“本以为数字电路相关的0和1是绝对精准的。现在我有了更多的体会。” ——我
Table of Contents
4天4夜的电子设计大赛结束了。今年是省级比赛,明年是国赛,每两年一反复,全名即大学生电子设计竞赛,本届由TI公司赞助。 一般来讲,省赛的题目相对基础,更容易上手。对于专业学电工电子类同学来说,是不可错过的大事,同时省赛能很好地练手,以应对明年的国赛。我和宸爷、fandy有幸作为三个外行人参加了这次比赛。 若是让我总结这次比赛的全过程,那么我得将它形容为“奇妙冒险”。 首先,是高强度的补充知识。作为机械狗,虽然提前熟悉了一些基础实验,但是还是极其需要根据需求大量、高强度地学习知识,以应对项目的进展和开发。整个比赛过程中,一直都是高强度的工作。我也不知道专业和电赛经历丰富的同学大概是什么感受,总之这几天我的基础知识得到了极大的提高,工作量比较大。 其次,是一种气氛上、情绪上的感受。每次程序遇到迷之恶性bug、和逐步目标达成后的喜悦和激励。不光是自己,以他人视角和同赛的其他组视角,看到其他组遇到顽固困难时候,解决问题的态度、处理问题的情绪,都会从侧面思考自己,是怎么做的呢,应该怎么做呢。 最后,是我和我的队友们。我们在短时间完整经历了一个比赛作品从 策划 设计 到 制作 排错 提交 审核 评比 的全过程。我多么希望机械学院多一些在相对低年级就能参与的大型竞赛,这种经历真是太奇妙了。事实上,队伍的气氛和目标有关。然而我们组的气氛就是比较诙谐的。 比赛结果其实无所谓,尤其对我这种非电类专业的人。但是最后还是祝愿我们能取得不错的成绩。 SPtuan 2016.8.3 补写写在前面
事实上……我后来才反应过来,ti即Texas Instruments,大名鼎鼎的德州仪器。就我这个外行人来看,这次比赛真是ti秀肌肉的机会,因为购买的,不论是高精度AD转换芯片、DCDC、放大器IC等都少不了TI的身影。尤其是本次小车题目,必备ti的电感探测器LDC1314 或者LDC1000是金属探测识别不可或缺的模块。同时,提供了一堆迷之launchpad开发板,是各种低能耗先进mcu的代表和一些根本不能手焊的ic。总之,我以之为吊。
↓以下绝对不是little gay speech
以下为流水
2016.7.25
Day 01
今天上午8点准时发布了题。
队长sama宸爷来自求是学部,实验室自然也是求是学部队员们聚集在一起,大约有5队。不过我很庆幸没有和电信等学院的许多队伍在三次元实验室相遇,因为我目测在我还在看文档的时候,他们就已经做完商量去哪里玩儿了。
不得不吐槽,啊,TI的发题页面——
http://www.deyisupport.com/universityprogram/b/announcements/archive/2016/07/18/2016-ti.aspx
先不吐槽这个冗长的链接。这个东西其实是通过德州仪器的支持社区发布的,百度是搜不到的,然而却在某404网站的搜索结果第一条。起初我搜索这个结果,乍一看,还以为TI的社区帖子讨论。
以下为题目
其中小车的题涉及到使用独一无二的贵德州仪器的IC,而我们并没有准备。据说这次比赛TI不会提供样片。
最终我们选择了G题,简易传感器设计。
我想我大概是这一堆做电设里的、唯一学过材料力学、做过材料力学专有的测主应力和应变实验的人了,虽然不知道为何优越,但还是有一丝迷之优越的。
搜索了几篇论文大致理清了思路。我来提供材料力学相关的应变实验信息、单片机功能实现。fandy和宸爷负责放大电路、AD转换和相关的blabla。
在大家查阅资料的同时,我直接从之前博客的库里扒下来点预设代码。
外面的雨下的飞起,可是还是要去实体电子元器件店购买必要材料。不得不说这个淘宝天猫的元器件店,你明明没发货点了发货,一耽误耽误好几天,这波坑得比较惨。
去了一家fandy亲戚推荐的电子元器件店。我觉得,fandy的这个“我一个亲戚”就和敖厂长的“我一哥们”原理差不多。后来还快马加鞭为我们找来了一些现成的电阻应变传感器,感谢。赛题要求铁质悬臂梁,遗憾,这些虽然不能直接用,但还是可以作为一个前期的测试的。
中午:勤奋的队友们和勤奋写基础框架代码的我。
下午,让宸爷火急火燎地加订传感器。但是后来发现是铝合金的。(PS后来在五金城采购时候了解,一般小型传感器都是铝制的,因为铁质会因为磁性产生偏移和误差。)大概是出题组故意设置的。看来这个桥是非自己贴不可了。
后来顺丰加订了350,120Ω箔式电阻应变贴片。
fandy和宸爷貌似进行了放大器的文档阅读和初步试验。
今日没有通宵,起居正常。
今天觉得是四处奔走初步买料了,他们的部分我不懂就不多说了,我的初步代码框架如下(也算是思考笔记了)
/**************************
2016.7.25工程
要求:
(1)电子秤可以数字显示被称物体的重量,单位克(g); ?0分)
(2)电子秤称重范围5.00g~500g;重量小于50g,称重误差小于0.5g;重量在50g及以上,称重误差小于1g; (50分)
(3)电子秤可以设置单价(元/克),可计算物品金额并实现金额累加;
(4)电子秤具有去皮功能,去皮范围不超过100g;
(5)其他。
实现功能,由上位模数转换模块TLC1542接受数字信号,完成
功能1.数字信号的标定
显示数字信号,和温度、挂载重量比较,为得到线性拟合做准备
组件1.输入:矩阵键盘
123456789 ABCD 0 * # 12键位的矩阵键盘
组件2.方案1 输出Max7219数码管模块
方案2 1602液晶屏显示,已经集成,等待使用时查询用户手册
组件3.按键设计
分析功能1:重量(其实是在其他功能下复位重量)
分析功能2:单价:
输入每g价格后按*,实现自动计价
分析功能3:累加
分析功能4:去皮
AD思路,采样;按照论文
***************************/
#include <reg52.h>
//快速定义uchar uint
#define uchar unsigned char
#define uint unsigned int
//IO未分配P0:LCD P3 矩阵键盘
#define LCD_DATA P2
//定义Max7219数码管端口
sbit Max7219_pinCLK = P1^2;
sbit Max7219_pinCS = P1^1;
sbit Max7219_pinDIN = P1^0;
//定义LCD1602端口
sbit rs = P0^7;
sbit rw = P0^6;
sbit en = P0^5;
//全局中间变量寄存处
uchar temp;
uchar tempH[8];
int i;
//通用延时函数
void Delay_xms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<112;j++);
}
//--------------------------------------------
//功能:向MAX7219(U3)写入字节
//入口参数:DATA
//出口参数:无
//说明:
void Write_Max7219_byte(uchar DATA)
{
uchar i;
Max7219_pinCS=0;
for(i=8;i>=1;i--)
{
Max7219_pinCLK=0;
Max7219_pinDIN=DATA&0x80;
DATA=DATA<<1;
Max7219_pinCLK=1;
}
}
//-------------------------------------------
//功能:向MAX7219写入数据
//入口参数:address、dat
//出口参数:无
//说明:
void Write_Max7219(uchar address,uchar dat)
{
Max7219_pinCS=0;
Write_Max7219_byte(address); //写入地址,即数码管编号
Write_Max7219_byte(dat); //写入数据,即数码管显示数字
Max7219_pinCS=1;
}
//初始化Max7219
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0xff); //译码方式:BCD码
Write_Max7219(0x0a, 0x03); //亮度
Write_Max7219(0x0b, 0x07); //扫描界限;4个数码管显示
Write_Max7219(0x0c, 0x01); //掉电模式:0,普通模式:1
Write_Max7219(0x0f, 0x01); //显示测试:1;测试结束,正常显示:0
}
//矩阵键盘扫描-未完成,本函数中矩阵键盘使用P3 IO口
unsigned char keyscan()
{
unsigned char key_x, key_y;//坐标变量
P3 =0xf0;//初始化,等待行线全为1,列线全为0。1111 0000
if((P3 & 0xf0) != 0xf0) //若发生变化
{
Delay_xms(5); //软件消抖
if((P3 & 0xf0) != 0xf0) //仍然按下
{
key_y = (P3 & 0xf0); //保存列坐标(y坐标)
P3 = 0x0f;
key_x = (P3 & 0x0f); //保存行坐标(x坐标)
while((P3 & 0x0f) != 0x0f);//松手检测
return (key_x+key_y); //返回键值
}
}
return temp;
}
//write系列函数为1602操作函数
void write_cmd (uchar cmd)
{
rs = 0;
rw = 0;
LCD_DATA = cmd;
Delay_xms(5);
en = 1;
Delay_xms(5);
en = 0;
}
void write_data (uchar dat)
{
rs = 1;
rw = 0;
LCD_DATA = dat;
Delay_xms(5);
en = 1;
Delay_xms(5);
en = 0;
}
void lcd_init (void)
{
write_cmd(0x02);
write_cmd(0x06);
write_cmd(0x0c);
write_cmd(0x38);
write_cmd(0x01);
}
void main(void)
{
Delay_xms(50);
Init_MAX7219();
Delay_xms(2000);
Write_Max7219(0x0f, 0x00); //显示测试:1;测试结束,正常显示:0
rw = 0;
rs = 0;
en = 0;
lcd_init();
write_cmd(0xc0);
temp=0;
do
{
temp=keyscan();
for(i=0;i<8;i++)
{
Write_Max7219(i+1,(temp>>i)%2);
write_cmd((temp>>i)%2+48);
}
}while(1);
/*
write_data('2');
Delay_xms(300);
for(i=0;i<10;i++)
{
write_data('3');
Delay_xms(3);
}
Delay_xms(3000);
write_cmd(0x01);
}while(1);
*/
}
测试了新的矩阵键盘键码,一些手稿如下;
2016.7.26
Day 2
上午去五金城(确实很大,门口可是写着“华北第一五金城”)进行采购。
5km路程在uber上生堵了一个小时。
这是我第4次到这里来买一堆破玩意儿。只不过没想到电设还是得到这里买破玩意儿。
这种地方,一般来讲热心的店家会因为看你像学生买散件,会多问问,多告诉你一些人生的经验让你学习一个,一般还好,确实能学到一些买东西的技巧。这个节能减排的数次采购也有经历,另讲。
买货架的姐姐也太认真的,非要精确尺寸才给制作。这个我理解,因为尺寸这种东西对做生意非常重要,一不留神因为尺寸问题,几天活就会白干。最后还是在隔壁一家年龄大的老板那里买了一套不要求具体尺寸的架子。
看了一堆适合当悬臂梁的材料,比如这两标准件。最后还是看到这种钢板。老板说这个是拿来做弹性振动测试的。
回来之后我开始怀疑人生。不过看到tb上这个,令我比较心安。
我的结论就是,现在淘宝上的信息都要比百度准确、有效。
今天简单调了一调代码
我还是不习惯库的写法,先这么着
/**************************
2016.7.25工程
要求:
(1)电子秤可以数字显示被称物体的重量,单位克(g); ?0分)
(2)电子秤称重范围5.00g~500g;重量小于50g,称重误差小于0.5g;重量在50g及以上,称重误差小于1g; (50分)
(3)电子秤可以设置单价(元/克),可计算物品金额并实现金额累加;
(4)电子秤具有去皮功能,去皮范围不超过100g;
(5)其他。
实现功能,由上位模数转换模块TLC1542接受数字信号,完成
功能1.数字信号的标定
显示数字信号,和温度、挂载重量比较,为得到线性拟合做准备
组件1.输入:矩阵键盘
123456789 ABCD 0 * # 12键位的矩阵键盘
组件2.方案1 输出Max7219数码管模块
方案2 1602液晶屏显示,已经集成,等待使用时查询用户手册
组件3.按键设计
分析功能1:重量(其实是在其他功能下复位重量)
分析功能2:单价:
输入每g价格后按*,实现自动计价
分析功能3:累加
分析功能4:去皮
AD思路,采样;按照论文
***************************/
#include <reg52.h>
#include "LCD1602.h"
#include "delay.h"
//快速定义uchar uint
#define uchar unsigned char
#define uint unsigned int
//IO未分配P0:LCD P3 矩阵键盘
#define LCD_DATA P2
sbit rs = P0^7;
sbit rw = P0^6;
sbit en = P0^5;
//定义Max7219数码管端口
sbit Max7219_pinCLK = P1^2;
sbit Max7219_pinCS = P1^1;
sbit Max7219_pinDIN = P1^0;
//全局中间变量寄存处
uchar temp;
uchar tempH[8];
int i;
/****************延时函数部分****************/
//通用延时函数
void Delay_xms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<112;j++);
}
//细致划分延时函数
void delayms(unsigned int x) // 延时 (x) ms
{
unsigned char j;
while(x--){
for(j=0;j<123;j++){;}
}
}
void delayus(unsigned char x) // 延时 (x*2+5) us
{
while(--x);
}
//------------------MAX7219相关函数----------
//功能:向MAX7219(U3)写入字节
//入口参数:DATA
//出口参数:无
//说明:
void Write_Max7219_byte(uchar DATA)
{
uchar i;
Max7219_pinCS=0;
for(i=8;i>=1;i--)
{
Max7219_pinCLK=0;
Max7219_pinDIN=DATA&0x80;
DATA=DATA<<1;
Max7219_pinCLK=1;
}
}
//-------------------------------------------
//功能:向MAX7219写入数据
//入口参数:address、dat
//出口参数:无
//说明:
void Write_Max7219(uchar address,uchar dat)
{
Max7219_pinCS=0;
Write_Max7219_byte(address); //写入地址,即数码管编号
Write_Max7219_byte(dat); //写入数据,即数码管显示数字
Max7219_pinCS=1;
}
//初始化Max7219
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0xff); //译码方式:BCD码
Write_Max7219(0x0a, 0x03); //亮度
Write_Max7219(0x0b, 0x07); //扫描界限;4个数码管显示
Write_Max7219(0x0c, 0x01); //掉电模式:0,普通模式:1
Write_Max7219(0x0f, 0x01); //显示测试:1;测试结束,正常显示:0
}
//矩阵键盘扫描-未完成,本函数中矩阵键盘使用P3 IO口
unsigned char keyscan()
{
unsigned char key_x, key_y;//坐标变量
P3 =0xf0;//初始化,等待行线全为1,列线全为0。1111 0000
if((P3 & 0xf0) != 0xf0) //若发生变化
{
Delay_xms(5); //软件消抖
if((P3 & 0xf0) != 0xf0) //仍然按下
{
key_y = (P3 & 0xf0); //保存列坐标(y坐标)
P3 = 0x0f;
key_x = (P3 & 0x0f); //保存行坐标(x坐标)
while((P3 & 0x0f) != 0x0f);//松手检测
return (key_x+key_y); //返回键值
}
}
return temp;
}
//1602液晶屏操作函数
// LCD1602上电后初使化
void LCD1602_Init(void)
{
delayms(50); // 上电延时50ms.
write1602_byte(0x3c,0); // 功能设置:双行、8位数据接口、5*10点阵字符.
while(Read1602_BF()); // 读取1602的繁忙状态(Busy Flag),直至空闲。
write1602_byte(0x0c,0); // 显示开关:开;光标显示:关;闪烁控制:关;
while(Read1602_BF()); // 读取1602的繁忙状态(Busy Flag),直至空闲。
write1602_byte(0x06,0); // 操作后,AC自增,画面不动。
while(Read1602_BF()); // 读取1602的繁忙状态(Busy Flag),直至空闲。
write1602_clear();
CursorRST_1602(); // 光标复位,但DDRAM内容不变
}
/*----Function Description----
- Function Name : write1602_byte(uchar dat,bit RorS)
- Description : 发送一个字节数据
- Return Code : None
- Parameters/Arguments : dat 是一个字节数据,RorS 指定 dat 是数据还是指令
- Global Variable : None
- static Variable : None
-------------------------------------------------------------------------*/
void write1602_byte(uchar dat,bit RorS)
{
RW_1602 = 0; // 写
EN_1602 = 0;
delayus(10); // 数据建立时间,需大于1us.这里延时25us.
if(RorS) RS_1602 = 1; // dat is a data.
else RS_1602 = 0; // dat is a command.
EN_1602 = 1; // 使能脉冲需大于450ns。
DP_1602 = dat; // 整个使能周期需大于1ms。
delayus(10); // 延时25us
EN_1602 = 0;
delayms(1); // 指令执行时间,需大于40us.这里延时1ms.
}
/*----Function Description----
- Function Name : bit Read1602_BF(void)
- Description : 判断1602指令执行状态。
- Return Code : BF(busy flag),BF = 1 : busy.
- Parameters/Arguments : None
- Global Variable : None
- static Variable : None
-------------------------------------------------------------------------*/
bit Read1602_BF(void) // 读取1602的空闲状态(Busy Flag)
{
RW_1602 = 1; // 读
RS_1602 = 0;
delayus(50); // 延时100us,这里的延时需大于
DP_1602 <<= 1; // 读指令最大执行时间40us.
return CY; // 将BF位移至CY位并返回.
}
void write1602_clear(void)
{
write1602_byte(CLRLCD1602,0); // 发送清屏指令。
delayms(50); // 延时需大于15.2ms,这里延时50ms
}
void CursorRST_1602(void) // 光标复位,但DDRAM内容不变
{
write1602_byte(CURRST1602,0); // 发送清屏指令。
delayms(50); // 延时需大于15.2ms,这里延时50ms
}
/*----Function Description----
- Function Name : write1602_DDRAM_pos(uchar px,uchar py)
- Description : DDRAM 为显示数据存储器。本函数更改指向DDRAM
的指针AC。
- Return Code : None
- Parameters/Arguments : py : row . 0 : First row . 1 : Second row .
px : 从左至右分别为 0 ~ 15 .
- Global Variable : None
- static Variable : None
-------------------------------------------------------------------------*/
void write1602_DDRAM_pos(uchar px,uchar py)
{
if(py){
write1602_byte( px|0x80 + 0x40 , 0 );
}else{
write1602_byte( px|0x80 , 0 );
}
}
/*----Function Description----
- Function Name : write1602_CGRAM(uchar dat[8],uchar add)
- Description : 将一个字符(8个字节的数组)写入 CGRAM。
- Return Code : None
- Parameters/Arguments : uchar dat[8]为字符数组。
uchar add 为自定义字符的访问地址,取值应在 0~7.
- Global Variable : None
- static Variable : None
-------------------------------------------------------------------------*/
void write1602_CGRAM(uchar dat[8],uchar add)
{
uchar temp;
add %= 8; // 数据有效性处理
for(temp=0;temp<8;temp++)
{
write1602_byte( add<<3|0x40+temp , 0 ); // 写 CGRAM 地址。
write1602_byte( dat[temp] , 1 ); // 写 CGRAM 字符数据。
}
}
void draw1602_basic(void)
{
uchar temp;
for(temp=0;temp<8;temp++) // 装载8个自定义符号
write1602_CGRAM(dat1602[temp],temp);
write1602_DDRAM_pos(0,0);
write1602_byte(4,1); // 显示8个自定义符号
write1602_DDRAM_pos(15,0);
write1602_byte(5,1); // 显示8个自定义符号
write1602_DDRAM_pos(0,1);
write1602_byte(6,1); // 显示8个自定义符号
write1602_DDRAM_pos(15,1);
write1602_byte(7,1); // 显示8个自定义符号
write1602_DDRAM_pos(5,0);
write1602_byte('m',1);
write1602_byte('a',1);
write1602_byte('s',1);
write1602_byte('o',1);
write1602_byte('n',1);
write1602_DDRAM_pos(2,1);
write1602_byte('v',1);
write1602_byte('o',1);
write1602_byte('l',1);
write1602_byte('t',1);
write1602_byte(':',1);
}
void write_cmd (uchar cmd)
{
rs = 0;
rw = 0;
LCD_DATA = cmd;
Delay_xms(5);
en = 1;
Delay_xms(5);
en = 0;
}
void write_data (uchar dat)
{
rs = 1;
rw = 0;
LCD_DATA = dat;
Delay_xms(5);
en = 1;
Delay_xms(5);
en = 0;
}
void lcd_init (void)
{
write_cmd(0x02);
write_cmd(0x06);
write_cmd(0x0c);
write_cmd(0x38);
write_cmd(0x01);
}
void main(void)
{
rw = 0;
rs = 0;
en = 0;
lcd_init();
write_cmd(0xc0);
write_data('I');
write_data(' ');
write_data(0x26);
write_data(' ');
write_data('U');
while(1);
//Delay_xms(50);
//Init_MAX7219();
//Delay_xms(2000);
//Write_Max7219(0x0f, 0x00); //显示测试:1;测试结束,正常显示:0
/*
write_data('2');
Delay_xms(300);
for(i=0;i<10;i++)
{
write_data('3');
Delay_xms(3);
}
Delay_xms(3000);
write_cmd(0x01);
}while(1);
*/
}
@2016年7月27日02:27:33 抱着破笔记本更新
Day3~Day4
这几天就相对单调了,而且住在了实验室。做的主要工作还是继续推进。
期间也收获了好多见闻。比如典型的金属循迹小车题,由于本比赛给出的轨道长度相对飞思卡尔比赛的赛道小,导致现成的车架过大,差速转向无法顺利循迹。有的组决定把特别漂亮的小车锯开。令我印象深刻的还是听到了一句“做了一个学期的小车说锯就锯了”。仔细想想,也是比较痛心的。
在Day4时候,电源组的pcb板洗出来了,开始装件。这个真是相对玄学,在仿真软件上好好的电路,洗出来按上后就会迷之不正常。上百个零件想想也是让人头大。在day4,遇到玄学问题要么直接放弃,要么通宵抢救一下。
最终,我们的称作在了精确度3g左右。怎么说呢,这种题目相对来说实物好出,精确度和各种功能的实现就不一样了。电源类没办法,最终调试失败,实物也没有了意义。
写整个51程序我简直要疯掉了。因为之前做的都是小实验,我根本没形成建立分文件、统筹整个工程代码的意识,最后整个人好像都被掏空一样。
最后遗留了好多问题。最令我发癫的是——最后一旦在程序段里加任意一个回车,最后就会发生蜜汁bug,整个显示数据都不正常。
还有最没令我料到的是,我没有考虑到浮点数的问题。最后用多位整数处理。
除皮功能异常= =囧
#include <reg52.h>
//快速定义uchar uint
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//P0:LCD P3 矩阵键盘
#define LCD_DATA P2
sbit rs = P0^7;
sbit rw = P0^6;
sbit en = P0^5;
//ad
sbit clk = P1^3; //输入输出时钟端
sbit address = P1^1; //串行地址输入端
sbit dataout = P1^0; //三态串行数据输出端
sbit cs = P1^2;
float K1;
float K1avr[8];
uchar K1avrnum=0;
uchar flag=0;
uchar avrflag;
//全局中间变量寄存处
uchar temp;
int i;
int j=0;
uchar sum;
int key_flag;
uchar key_code;
uchar key_data;
uchar key_temp;
unsigned long price_temp;
uchar input_temp[5];
unsigned long price_temp2;
//前期调试变量,AD转换输出变量处理后数据:重量(g)
float mass=40;
float massout=40;
float massavr[8];
/****************延时函数部分****************/
//通用延时函数
void Delay_xms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<112;j++);
}
void delay(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<112;j++);
}
//细致划分延时函数
void delayms(unsigned int x) // 延时 (x) ms
{
unsigned char j;
while(x--){
for(j=0;j<123;j++){;}
}
}
void delayus(unsigned char x) // 延时 (x*2+5) us
{
while(--x);
}
//ad
uint read1543(uchar port) //从TLC1543读取采样值,形参port是采样的通道号
{
uint ad;
uint i;
uchar al=0,ah=0;
clk = 0; //将时钟信号置低
cs = 0; //片选低电平有效
port <<= 4; //通道号左移四位
for (i=0;i<4;i++) //把通道号打入1543
{
address = (bit)(port&0x80);
clk = 1; //上升沿一到,读走数据
delay(1);
clk = 0; //将时钟置于下降沿,等待上升沿的到来
port <<= 1; //通道号左移一位
}
cs = 1;
delay(10);
cs=0; //等待AD转换
delay(2);
for (i=0;i<2;i++) //取D9,D8
{
dataout = 1; //可删除
clk = 1;
ah <<= 1;
if (dataout)
ah |= 0x01;
clk = 0;
delay(10);
}
for (i=0;i<8;i++) //取D7--D0
{
dataout = 1;
clk = 1;
al <<= 1;
if (dataout)
al |= 0x01;
clk = 0;
delay(10);
}
cs = 1;
ad = ah;
ad <<= 8;
ad += al; //得到AD值
K1avr[avrflag]=ad;
if(avrflag<8) avrflag++;
else avrflag=0;
return (ad);
}
//矩阵键盘扫描,本函数中矩阵键盘使用P3 IO口
unsigned char key_code_scan()
{
unsigned char key_x, key_y;//坐标变量
P3 =0xf0;//初始化,等待行线全为1,列线全为0。1111 0000
if((P3 & 0xf0) != 0xf0) //若发生变化
{
Delay_xms(5); //软件消抖
if((P3 & 0xf0) != 0xf0) //仍然按下
{
key_y = (P3 & 0xf0); //保存列坐标(y坐标)
P3 = 0x0f;
key_x = (P3 & 0x0f); //保存行坐标(x坐标)
while((P3 & 0x0f) != 0x0f);//松手检测
key_flag=1;
return (key_x+key_y); //返回键值
}
}
key_flag=0;
return temp;
}
unsigned char key_data_scan()
{
temp=key_code_scan();
if(key_flag==1)
{
switch(temp)
{
case 238:
key_code=1;
break;
case 222:
key_code=2;
break;
case 190:
key_code=3;
break;
case 237:
key_code=4;
break;
case 221:
key_code=5;
break;
case 189:
key_code=6;
break;
case 235:
key_code=7;
break;
case 219:
key_code=8;
break;
case 187:
key_code=9;
break;
case 215:
key_code=10;
break;
case 126:
key_code=11;
break;
case 125:
key_code=12;
break;
case 123:
key_code=13;
break;
case 119:
key_code=14;
break;
case 231:
key_code=15;
break;
case 183:
key_code=16;
break;
}
key_flag=0;
return key_code;
}
return 0;
}
//1602液晶屏操作函数
void write_cmd (uchar cmd)
{
rs = 0;
rw = 0;
LCD_DATA = cmd;
Delay_xms(5);
en = 1;
Delay_xms(5);
en = 0;
}
void write_data (uchar dat)
{
rs = 1;
rw = 0;
LCD_DATA = dat;
Delay_xms(5);
en = 1;
Delay_xms(5);
en = 0;
}
void lcd_init (void)
{
rw = 0;
rs = 0;
en = 0;
write_cmd(0x02);
write_cmd(0x06);
write_cmd(0x0c);
write_cmd(0x38);
write_cmd(0x01);
}
/*固定显示字符代码串*/
uchar code table_mass_lcd_line1[]="Weight(g):" ;
uchar code table_price_lcd_line1[]="Type in Price(g)";
uchar code table_net_weight_lcd_line1[]="Net Weight(g)";
uchar code table_value_lcd_line1[]="value is";
/*以下为电子秤功能实现函数*/
void show_value_lcd_line1()
{
write_cmd(0x01); //清屏
write_cmd(0x80); //1line
for(j=0;j<8;j++)
{
write_data(table_value_lcd_line1[j]);
Delay_xms(5);
}
}
void show_mass_lcd_line1()
{
write_cmd(0x01); //清屏
write_cmd(0x80); //1line
for(j=0;j<10;j++)
{
write_data(table_mass_lcd_line1[j]);
Delay_xms(5);
}
}
void show_data_lcd_line2(unsigned long data_line2) //通用第二行显示
{
uchar data_line2_0,data_line2_1,data_line2_2,data_line2_3,data_line2_4;
data_line2_0=(data_line2%10);
data_line2_1=((data_line2)/10%10);
data_line2_2=((data_line2)/100%10);
data_line2_3=((data_line2)/1000%10);
data_line2_4=((data_line2)/10000%10);
write_cmd(0x80+0x40);//2line
write_data(data_line2_4+48);
Delay_xms(5);
write_data(data_line2_3+48);
Delay_xms(5);
write_data(data_line2_2+48);
Delay_xms(5);
write_data(data_line2_1+48);
Delay_xms(5);
write_data(data_line2_0+48);
Delay_xms(5);
}
uchar data_line2_0,data_line2_1,data_line2_2,data_line2_3,data_line2_4,data_line2_5,data_line2_6;
void show_point_data_lcd_line2(long data_line2) //浮点数第二行显示
{
write_cmd(0x80+0x40);//2line
if(data_line2<0)
{ write_data(45);
data_line2=-data_line2;
}
data_line2_0=((data_line2)%10);
data_line2_1=((data_line2)/10%10);
data_line2_2=((data_line2)/100%10);
data_line2_3=((data_line2)/1000%10);
data_line2_4=((data_line2)/10000%10);
data_line2_5=((data_line2)/100000%10);
data_line2_6=((data_line2)/1000000%10);
write_data(data_line2_6+48);
Delay_xms(2);
write_data(data_line2_5+48);
Delay_xms(2);
write_data(data_line2_4+48);
Delay_xms(2);
write_data(data_line2_3+48);
Delay_xms(2);
write_data(data_line2_2+48);
Delay_xms(2);
write_data(46);
Delay_xms(2);
write_data(data_line2_1+48);
Delay_xms(2);
write_data(data_line2_0+48);
Delay_xms(2);
}
void show_price_lcd_line1()
{
write_cmd(0x01); //清屏
write_cmd(0x80); //1line
for(j=0;j<16;j++)
{
write_data(table_price_lcd_line1[j]);
Delay_xms(5);
}
}
void show_net_weight_lcd_line1()
{
write_cmd(0x01); //清屏
write_cmd(0x80); //1line
for(j=0;j<13;j++)
{
write_data(table_net_weight_lcd_line1[j]);
Delay_xms(5);
}
}
int price(void)
{
show_price_lcd_line1();
write_cmd(0x80+0x40);
j=0;
price_temp2=0;
do
{
key_temp=key_data_scan();
if(key_temp==14) return 0;
if(key_temp!=0&&(key_temp!=16))
{
if(key_temp!=10)
write_data(key_temp+48);
else
write_data(0+48);
input_temp[j]=key_temp;
j++;
}
}while((key_temp!=16)&&(j<5));
for(i=0;i<j;i++)
price_temp2=price_temp2*10+input_temp[i];
show_value_lcd_line1() ;
price_temp2=price_temp2*(mass-massout);
show_data_lcd_line2(price_temp2);
return 1;
}
float avr_K1()
{
float avrtemp;
for(K1avrnum=0;K1avrnum<8;K1avrnum++)
avrtemp+=K1avr[K1avrnum];
return avrtemp;
}
long result_temp;
long result(ulong datain)
{
return((datain*100-74866)*100/793);
}
void domassout()
{
massout=result(avr_K1());
}
void key_circle()
{
if(flag==0)
{
K1=read1543(0x00);
show_point_data_lcd_line2(result(avr_K1())-massout+9793);
mass=avr_K1();
delay(400);
}
if(flag==1)
{
price();
do{
key_temp=key_data_scan();
}while(key_temp!=14);
show_mass_lcd_line1();
flag=0;
}
key_temp=key_data_scan();
if(key_temp==11)
{
flag=0;
show_mass_lcd_line1();
}
if(key_temp==12)
{
domassout();
}
if(key_temp==13)
{
flag=1;
}
}
void main(void)
{
lcd_init(); //必须初始化lcd显示屏
show_mass_lcd_line1() ;
delay(300);
delay(300);
key_circle();
delay(300);
key_circle();
delay(300);
key_circle();
delay(300);
do
{
key_circle();
delay(5);}
while(1);
}
Day5(评审)
挺多地方和想象的不一样……可以使用整版单片机实验板,可以自带ADDA= =!虽然我们有的那个精度高一些,但是我觉得实验板内置的AD也足够了!
最令我没想到的地方是……给了半个小时进行调试= =那我们还尝试做什么温度补偿,写一个输入接口直接零点标定甚至直接用标准砝码现场线性标定都行……
最后也得到一些信息,许多大学的老师都是帮学生干,统一买铝材提供基础架构(我们都是自己去五金市场买的货架= =!),老师和同学通宵在实验室干。
这个和比赛规则和精神我就不多评价了…其实和结果回馈的大小很有关系。
作为一个机械狗,我只是觉得,当今机电一体化,学到了好多东西,就足够了。
辛苦着,快乐着,收获着
说好的加图呢,说好的更新呢
@fandy 你个ctrl cv的伸手党就不要来这里自爆了
@fandy 我更新完了,你来吧
@SPtuan 狠,是不是节能减排你也准备写一个
@fandy 节能减排还是发一些比赛的图就得了…如果想写那可太多了不知道该写什么
@SPtuan 233333(为什么评论必须包含汉字导致我必须写这句毫无意义的话)
@fandy 不开这个就等着每天5000的垃圾评论轰炸吧
狠
@cola60 还行,一般狠
狠