8.3.1 电子秤技术指标和功能要求
1. 预存10组储单重值,方便调出。
2. 计数:能已知单重求个数,已知个数求得单重再计数。
3. 去皮:已知皮重扣除指定的皮,一次性扣除秤上的皮。
4. 零点:偶尔会发生零点漂移现象,可按零点回零。
5. 累计:个数,重量。
6. 预先设定个数上下限值,重量上下值。超过上下限自动报警
7. 单位转换:千克,英磅,盎司,金衡盎司,克拉,英钱,克。
8. 开关背光,蜂鸣器。
9. 外部进行校正(在秤发生漂移时,可以进行校正)。
10. 精度可达0.1,0.2,0.5,1,2,5,10,20,50g等可调(通过调软件,换传感器达到)。
11. 外码可达60000(通过软件设置,可达几十种不同规格的量程和精度的电子秤)。
12. 电源检测
13. 当电池电压下降至5.25 0.1V,电源指示灯红灯亮,则表示要充电。若此时不充电,将有可能因电压太低而出现称量不准或不稳定。如继续使用超过2小时,电子天平将自动关机,进入保护模式。
14. 传感器:电阻应变式秤重传感器。
15. 额定电压:
16. 交流 AC 220V(+10%-15%)50Hz 1Hz;
17. 直流 DC6V/4AH充电电池(充电式)。
18. 贮藏:-40~60 19. 工作:5~40 20. 湿度:
21. 贮藏:<=70%RH无结露;
22. 工作:<=90%RH无结露。
23. 内部采用20位专用AD。
8.3.2 功能详细说明
1. 单重(个数)预设
(1) 如何预设单重(个数)
1) 利用数字键0~9输入单重值(个数)。
2) 按“单重预设”键。个数栏显示“PrSET”。
3) 按“单重预设”键。重量栏显示“SET”。
4) 按0~9任何一键,即可将单重(个数)存入此键。
(2) 如何叫出所预设之单重(个数)
1) 按“单重预设”键。个数栏显示“PrSET”。
2) 按0~9任何一键,即可将此键内之单重(个数)叫出。
说明:个数最多为65545个以下,重量的小数最多为两位。
2. 计数
在计算数量前,必须先作取样步骤以求得待称物品之单重。取样方法有下列2种。
(1) 待秤物品之单重未知
1) 将一取样物品置于天平盘上。
2) 输入天平上取样物品之数量。
3) 按“个数设定”键。
4) 当电子秤稳定后,即取样完成进入计数模式。
(2) 待秤物品之单重已知
1) 输入已知的待秤物品之单重 ,进入计数模式。
2) 取样之数量愈大,所计算出之单重愈精确。
3. 扣除包装物品之重量
(1) 包装物品置于天平盘上。
(2) 按“去皮”键。重量栏显示“tArE”。
(3) 当电子秤稳定后,即进入计数模式。
将天平上物品与包装一并移开后,重量栏将显示包装物品重量之负值,此时再按一次“去皮”键,即可取消去皮,使重量归零且去皮符号“p”消失。
4. 零点
电子秤在工作过程中,偶尔会发生零点漂移现象,(即重量栏之重量有微小变动)此时按“零点”键可使重量回复。
5. 累计
(1) 将物品置于天平盘上。
(2) 按“累计”键。
(3) 当电子秤稳定后。重量栏显示总重量,个数栏显示出总个数,单重栏显示总笔数。
(4) 约3秒后,电子秤回复计数模式。
累计笔数最多为99笔,但位数为6位。
按“累计清除”键,即可将记忆中之累计值清除且累计符号“p”消失。
6. 数量预设(括号中为下限值)
计数时可预先设定数量之上(下)限值,以后每次计算数量,若超过(少于)此数值即有警告声且单重栏有—o.ty—(—SLX--)字样闪动。
7. 如何预设数量之上(下)限值
(1) 天平盘上有无物品皆可,请按“数量预设”键。个数栏出现“SLYS”
(2) 按数字键“1”(“3”),重量栏出现“SZ---1”(“SZ---3)。
(3) 输入欲设定之上(下)限值。(可利用“清除”键修改所输入之数值)
(4) 按“个数设定”键。(可利用“清除”键修改所输入之数值。
(5) 按“数量预设”键。电子秤回复计数模式。
8. 重量预设
可预先设定重量之上(下)限值,以后每次秤重时,若超过(少于)此数值即有警告声且单重栏有uuPST字样闪动。
9. 如何预设数量之上(下)限值
(1) 秤盘上有无物品皆可,请按“数量预设”键。个数栏出现“SLYS”
(2) 按数字键“2”(“4”),重量栏出现“SZ---2”(“SZ---4)。
(3) 输入欲设定之上(下)限值。(可利用“清除”键修改所输入之数值)
(4) 按“单重设定”键。(可利用“清除”键修改所输入之数值。
(5) 按“数量预设”键。电子秤回复计数模式。
10. 清除所预设之上(下)限值
欲清除所设数量或重量之上(下)限值,请依上述预设步骤操作,在输入预设时,则输入“0”即可。
说明:所设定的数字为重量栏所要出现的数字,不包括小数点,如:量程为3千克,精度为0.1,(3000.0),设定上限值为2000克,即输入20000即可。
11. 单位切换
先按长按“清除”键,直到出现CENTR,接着再按“0”,接着按“.”键,会在“Kg,ct,lb,oz,ozt,dwt,g”之间切换,确认好所选单位后,按“去皮”键确认。
12. 背光
13. 自动背光模式
先按长按“清除”键,直到出现CENTR,接着再按“5”
当天平盘上放置物品时,背光点亮,按按键时,(背光亦点亮,待归零后约5秒背光熄灭。)
14. 一般背光模式
先按长按“清除”键,直到出现CENTR,接着再按“4”,背光一直点亮。
15. 取消背光
先按长按“清除”键,直到出现CENTR,接着再按“6”,开机后电子秤将记忆住所选用之背光模式,待下次开机后,(维持相同之背光模式。)
16. 蜂鸣器
先按长按“清除”键,直到出现CENTR,按“2”,表示按键也有声音发出。如是按“3”,表示按键没有声音发出。
开机后电子秤将记忆住所选用之蜂鸣模式, 待下次开机后,(维持相同之蜂鸣模式。)
17. 外部校正
(1) 按长按“清除”键,直到出现CENTR,按“8”,个数栏出现“CAL”,个数栏出现“999”。
(2) 按“去皮”确认进入标定零点状态,(按“清零”键退出零点标定。)红灯亮。在单重栏会出现当前的内码值。内码确定好以后,绿灯亮,个数栏出现“989”,按“去皮”键确认,进入上限标定状态。按“清零”键放弃存入内码值,进入上限标定状态。
(3) 显示“000000”,按“累计”切换闪炫的位,按“.”闪炫位加一。注意:标定时,砝码不能大于最大量程,最小不能小于分度数。设定好后,按“去皮”进入取码状态,红灯亮。内码确定好后,绿灯亮,个数栏出现“888”。按“去皮”确认,自动重新初始化。(也可按“清零”键取消退出或放弃存入内码值。
18. 调入出厂之校正值
按长按“清除”键,直到出现CENTR,按“8”,即可,标定好以后,自动重新初始化。
19. 标定与调试
在显示启动画面时,打开标定开关,可进入标定与调试状态。
(1) 分度数选择:显示[N ****]
按“.”键,显示的****字为,3000, 6000,7500,10000,12000,15000,20000,30000,60000,100000循环改变,选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入 下一步骤。
(2) 分度值选择:显示[E *]
按“.”键,显示的*字为,1,2,5,10,20,50循环改变,选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入下一步骤。
(3) 小数点选择:显示[D 0.0]
按“.”键,显示的数字为,0,0.0,0.00,0.000,0.0000循环改变,选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入 下一步骤。
(4) 满量程显示:显示[***.**]
将上面确认的分度数(例如:3000)乘以分度值(例如:5),再配以小数点(例如:0.00),使用户确认是否要高置的满量程值(例如:150.00),如不是,把标定开关关上再打开即可重新标定上述三步。如是,则按“清除”键进入下一步骤。
(5) 零跟踪范围的确定:显示[01 *.*]
按“.”键,显示的*.*字为,0 .5,1 .0,2 .0循环改变,表示范围为:0 .5,1E,2E,选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入下一步骤。
(6) 开机判零范围:显示[02 ***]
按“.”键,显示的*.*字为,0 .10,0 .20,1.00循环改变,表示当零位不要保存时(后面的步骤8中期4设为0),开机时称量值如在上述设定的10%FS,20%FS,100%FS范围内,称量值置零,否则以原来储存的零位作为开机时的零位。选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入下一步骤。
(7) 手动置零范围选择:显示[05 .**]
按“.”键,数字在0.02,0.04,0.08,1.00循环,表示范围为2%,4%,8%,100%F.S。选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入 下一步骤。
(8) 滤波常数的选择:显示为[LB *]
按“.”键,数字在1,2,3,4,5 ,6, 7, 8, 9, 10循环,分别表示滤波常数为40,60,80,100,120数字越大,刷新速度越慢,但稳定性愈好。选择其中一项,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入下一步骤。
(9) 零位的确定:显示[CAL ]两秒钟,再显示[NOLOAD]
检查秤上是否空,显示“999”,稍等十秒钟左右,让秤加零稳定,显示“989”,按“去皮”键确认,自动进入下一步骤。如该项不要改变,则按“清除”键进入 下一步骤。
(10) 满值的标定(标定的砝码越接近或等于满值越好)。显示加数砝码为[000000](此处应说明以什么为单位输入),最左一位闪烁。
按“累计”键可向右循环改变闪烁位。按“.”键闪烁位加1。逐位打入实际加载的砝码数。按“去皮”键确认,显示“898”,稍等10秒~20秒钟左右,让秤加零稳定,显示“888”,(如重量值太小,则显示[END ]约3秒钟,再重复上述过程),最后显示为[END]。如该项不做,则按“清除”也可。
(11) 关上标定开关,标定结束。(我们用的不是标定开关而是跳线,标定时跳线在ADJ,不标定时跳线在LOCK)
8.3.3 详细设计
1. 硬件设计
(1) 主要原器件
89C52、CS5513、OPA2277、CSI93C46、HT1622等
(2) 硬件原理图
1) 键盘原理图:
按键分布与键面文字:
2) LCD部分原理图及MCU部分电路:
2. 程序代码
(1) 软件初始化与LCD
LCD驱动芯片HT1622介绍:
其它读写时序可以到网上下载相应资料。
#include "head.h"
const UINT8 Number[20]=
{0xbe,0x06,0x7c,0x5e,0xc6,0xda,0xfa,0x0e,0xfe,0xde,0xbf,0x07,0x7d,
0x5f,0xc7,0xdb,0xfb,0x0f,0xff,0xdf};
data UINT8 LcdRam[18];
data char Slsdcs; //计录“数量设定次数?
data uchar Dzz; //计录“单重值”
data char Wpsl; //计录“物品数量?
data char Ljcs; //计录“累计次数”
data char Dssl; //计录“定数数量”
data uchar Dszl; //计录“定数重量”
data uchar Qpz; //计录“去皮值”
//data float zl[10]; 用来存放“单重预设”值
/*
LcdDATSet1(13,0x01);
LcdDATSet1(13,0x02);
LcdDATSet1(13,0x04);
LcdDATSet1(13,0x08);
LcdDATSet1(14,0x04);
LcdDATSet1(14,0x08); 显示 每个数字底下的“▽”
LcdDATSet1(14,0x02); 显示 “k”
LcdDATSet1(14,0x01); 显示 “g”
LcdDATSet1(15,0x08); 显示 “oz"
LcdDATSet1(14,0x04); 显示 “t"
LcdDATSet1(14,0x02); 显示 "lb"
LcdDATSet1(14,0x01); 显示 "dwt"
LcdDATSet1(15,0x08); 显示 "ct"
LcdDATSet1(14,0x04); 显示 "wot"
LcdDATSet1(14,0x02); 显示 "tl"
LcdDATSet1(14,0x01); 显示 "pcs"
LcdDATSet1(14,0x08); 显示 "%"
LcdDATSet1(14,0x04); 显示 " "
LcdDATSet1(14,0x02); 显示 "-"
LcdDATSet1(14,0x01); 显示 "◎"
LcdDATSet1(7,0x0b);
LcdDATSet1(8,0x0e);
LcdDATSet1(9,0x0e);
LcdDATSet1(10,0x08); 显示 ”off"
*/
//const UINT8 a[5]={0xec,0x60,0xc6,0xf8,0xf0}; //显示 "pnset",按“单重预设”所出现的
//const UINT8 b[5]={0xc6,0xee,0x62,0x62,0xec}; //显示 "5annp",按“个数设定”所出现的
//const UINT8 c[4]={0xf0,0xee,0x60,0xf8}; //显示 "tane",按“去皮”所出现的
//const UINT8 d[5]={0xec,0x60,0xf8,0xf0,0xee}; //显示 "pneta",按“去皮”所出现的
void LcdInit(void)
{
LcdCmdSet1(0x01);
LcdCmdSet1(0x03);
Delay1(100);
ClearScreen();
Delay1(50);
}
void ClearScreen(void)
{
LcdDATSet1(1,0x00);
LcdDATSet1(2,0x00);
LcdDATSet1(3,0x00);
LcdDATSet1(4,0x00);
LcdDATSet1(5,0x00);
LcdDATSet1(6,0x00);
LcdDATSet1(7,0x00);
LcdDATSet1(8,0x00);
LcdDATSet1(9,0x00);
LcdDATSet1(10,0x00);
LcdDATSet1(11,0x00);
LcdDATSet1(12,0x00);
LcdRam[1]=0x00;
LcdRam[2]=0x00;
LcdRam[3]=0x00;
LcdRam[4]=0x00;
LcdRam[5]=0x00;
LcdRam[6]=0x00;
LcdRam[7]=0x00;
LcdRam[8]=0x00;
LcdRam[9]=0x00;
LcdRam[10]=0x00;
LcdRam[11]=0x00;
}
void DisplayNumber(UINT8 who,float num)
{
char temp1;
char j;
char l;
int sss=30000;
float temppara;
char n[11];
temppara=num;
sss=(int)temppara;
if(temppara>0)
{
for (j=6;j>0;j--)
{
temp1=(sss%Pow(10,j))/Pow(10,j-1);
l=abs(j-6);
n[l]=temp1;
}
for (j=1;j<6;j++)
{
temp1=((sss*Pow(10,j))%10)/1;
l=abs(6+j);
n[l]=temp1;
}
j=-1;
while (n[++j]!=0)
{
}
for (temp1=j;temp1
{
}
}
else if(temppara==0)
{
switch (who)
{
case 1:
{
LcdDATSet1(11,0x0b);
LcdDATSet1(12,0x0e);
}
case 2:
{
LcdDATSet1(11,0xb0);
LcdDATSet1(12,0xe0);
}
case 3:
{
LcdDATSet1(28,0x0b);
LcdDATSet1(29,0x0e);
}
}
}
}
void LcdDATSet1(UINT8 addr,UINT8 dat)
{
UINT8 i,temp;
LCD_CS = 0;
LCD_SD = 1;
LCD_CD = 0;
LCD_CD = 1;
LCD_SD = 0;
LCD_CD = 0;
LCD_CD = 1;
LCD_SD = 1;
LCD_CD = 0;
LCD_CD = 1;
temp=(addr-1)*2;
temp=temp<<2;
for(i=0;i<6;i++)
{
if (temp & 0x80)
LCD_SD = 1;
else
LCD_SD = 0;
LCD_CD = 0;
LCD_CD = 1;
temp = temp << 1;
}
for (i = 0; i < 8; i++) {
if (dat & 0x80) LCD_SD = 1;
else LCD_SD = 0;
LCD_CD = 0;
LCD_CD = 1;
dat = dat << 1;
}
LCD_SD=1;
LCD_CD=0;
LCD_CD=1;
LCD_CS= 1;
}
void LcdCmdSet1(UINT8 cmd)
{
UINT8 i;
LCD_CD = 1;
LCD_CS = 0;
LCD_SD = 1;
LCD_CD = 0;
LCD_CD = 1;
LCD_SD = 0;
LCD_CD = 0;
LCD_CD = 1;
LCD_SD = 0;
LCD_CD = 0;
LCD_CD = 1;
for (i = 0; i < 8; i++) {
if (cmd & 0x80) LCD_SD = 1;
else LCD_SD = 0;
LCD_CD = 0;
LCD_CD = 1;
cmd = cmd << 1;
}
LCD_SD=0;
LCD_CD=0;
LCD_CD=1;
LCD_CS= 1;
}
void disp(UINT8 who,UINT8 n,UINT8 num)
{
UINT8 who1,i,dd;
i=num;
who1=who;
dd=n;
if (who1==1)
{
LcdRam[dd*2-2]=(Number[i]>>4)|(LcdRam[dd*2-2]&0xf0);
LcdRam[dd*2-1]=0x0f&Number[i]|(LcdRam[dd*2-1]&0xf0);
LcdDATSet1(dd*2-1,LcdRam[dd*2-2]);//(Number[i]>>4)|(LcdRam[dd*2-2]&0xf0));
LcdDATSet1(dd*2,LcdRam[dd*2-1]);//(0x0f&Number[i])|(LcdRam[dd*2-1]&0xf0));
}
if(who1==2)
{
LcdRam[dd*2-2]=0xf0&Number[i]|(LcdRam[dd*2-2]&0x0f);
LcdRam[dd*2-1]=((Number[i]<<4))|(LcdRam[dd*2-1]&0x0f);
LcdDATSet1(dd*2-1,LcdRam[dd*2-2]);//(0xf0&Number[i])|(LcdRam[dd*2-2]&0x0f));
LcdDATSet1(dd*2,LcdRam[dd*2-1]);//(0xf0&(Number[i]*16))|(LcdRam[dd*2-1]&0x0f));
}
if (who1==3)
{
LcdDATSet1(dd*2+16,(Number[i]>>4));
LcdDATSet1(dd*2+17,(0x0f&Number[i]));
}
}
void Disp9to0(void)
{
int i=0,j=0,k=0;
for (k=0;k<10;k++)
{
Delay1(800000);
for (i=1;i<7;i++)
{
disp(2,i,k+10);
Delay1(80);
disp(1,i,k+10);
}
}
}
UINT32 Pow(int n,int m) //n的m次方计算函数
{
UINT32 result=1;
int x,y;
int i;
x=n;
y=m;
if (y==0)
return (1);
else
{
for(i=0;i
result=x*result;
return (result);
}
}
(2) A/D CS5513
1) 读数据时序:
UINT32 CS5513READDATA(void)
{
idata UINT8 i;
idata UINT32 CS5513DATA;
AD_CS=0;
AD_CLK=0;
CS5513DATA=0;
Delay1(10);
while(AD_SD !=0) //等待数据转换完成
{
}
for (i=0;i<24;i++)
{
CS5513DATA <<=1;
AD_CLK=1;
Delay1(10);
if(AD_SD==1)
CS5513DATA |= 0x01;
AD_CLK=0;
Delay1(10);
}
CS5513DATA &=0XFFFFF; //取20位有效数据
AD_CS=1;
return(CS5513DATA);
}
(3) SPI总线及93C46
1) SPI总线工作原理
① 概述
CSI93C46/56/57/66/86 是一种存储器,可以定义为16 位ORG 引脚接Vcc, 或者定义为8 位ORG 引脚接GND 的1K/2K/2K/4K/16K 位的串行E2PROM 。每一个的存储器都可以通过DI 引脚或DO 引脚,进行写入或读出。每一片CSI93C46/56/57/66/86 都是采用CSIalyst 公司先进的CMOS E2PROM 浮动门工艺。加工器件可以经受1,000,000 次的写入/擦除操作,片内数据保存寿命达到100 年。器件可提供的封装有DIP-8 SOIC-8 TSSOP-8。
② 管脚配置及其方框图
管脚说明
说明:当ORG 接Vcc 时存储器为16 位结构
当ORG 接GND ,是存储器为8 位结构。
当ORG引脚悬空时,内部的上拉电阻把存储器选择为16 位结构。
管脚名称功能
CS 片选信号
SK 时钟输入
DI 串行数据输入
DO 串行数据输出
Vcc 电源+1.8 伏到6 伏
GND 接地
ORG 存储器结构选择
NC 不用连接
PE* 写入保护
图示:数据传输同步时序
void EEPROMByteWrite0(UINT8 addr,UINT8 value)//写一个字节内容
{
EwenROM();
WriteRom(addr,value);
EwdsROM();
SCKPIN=0;
Delay1(20);
}
void EwdsROM(void) //写停止
{
SCKPIN=0;
_nop_();
CSPIN=1;
_nop_();
SDIPIN=1;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
WR_3wire(0x00);
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
CSPIN=0;
_nop_();
_nop_();
}
void WriteRom(UINT8 addr,UINT8 value) //写数据value到地址addr
{
UINT16 i;
SCKPIN=0;
_nop_();
CSPIN = 1;
_nop_();
_nop_();
SDIPIN=1;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=1;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
WR_3wire(addr);
WR_3wire(value);
_nop_();
CSPIN=0;
_nop_();
SDOPIN=1;
_nop_();
CSPIN=0;
_nop_();
CSPIN=1;
_nop_();
for(i=0;i<1000;i++)
{
if(SDOPIN || i>=1000)
break;
}
SDIPIN=0;
CSPIN=0;
}
void EwenROM(void) //写允许
{
SCKPIN=0;
_nop_();
CSPIN=1;
_nop_();
SDIPIN=1;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
WR_3wire(0xc0);
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
CSPIN=0;
_nop_();
_nop_();
}
void WR_3wire(UINT8 value)
{
UINT8 i;
for(i=0;i<8;i++)
{
if(value&0x80)
SDIPIN=1;
else
SDIPIN=0;
value<<=1;
_nop_();
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
_nop_();
}
}
UINT8 EEPROMByteRead0(UINT8 addr) //读ADDR中的内容
{
UINT8 value;
SCKPIN=0;
_nop_();
CSPIN=1;
_nop_();
SDIPIN=1;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=1;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
SDIPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
SCKPIN=0;
_nop_();
WR_3wire(addr);
Delay1(1);
value=ReceiveByte();
SCKPIN=0;
CSPIN=0;
Delay1(20);
return value;
}
UINT8 ReceiveByte(void)
{
UINT8 i;
UINT8 value=0;
SDOPIN=1;
for(i=0;i<8;i++)
{
SCKPIN=0;
_nop_();
SCKPIN=1;
_nop_();
_nop_();
value<<=1;
if(SDOPIN) value|=0x01;
SCKPIN=0;
}
_nop_();
_nop_();
return value;
}
(4) 键盘扫描
UINT8 Scankey(void)
{
UINT8 ee=0,temp1,j;
Keyval=0;
temp1=0xff;
j=0;
ET0=0;
sum=0;
longtime=0;
while(temp1==0xff)
{
j=0;
temp1=0xff;
KEY_IN1=0;
KEY_IN2=0;
KEY_IN3=0;
KEY_IN4=0;
KEY_IN5=0;
Delay1(1);
if (KEY_OUT1==0)
temp1=1;
if (KEY_OUT2==0)
temp1=2;
if (KEY_OUT3==0)
temp1=3;
if (KEY_OUT4==0)
temp1=4;
KEY_IN1=1;
KEY_IN2=1;
KEY_IN3=1;
KEY_IN4=1;
KEY_IN5=0;
Delay1(1);
if (KEY_OUT1==0 || KEY_OUT2==0 || KEY_OUT3==0 || KEY_OUT4==0)
j=1;
KEY_IN1=1;
KEY_IN2=1;
KEY_IN3=1;
KEY_IN4=0;
KEY_IN5=1;
Delay1(1);
if (KEY_OUT1==0 || KEY_OUT2==0 || KEY_OUT3==0 || KEY_OUT4==0)
j=2;
KEY_IN1=1;
KEY_IN2=1;
KEY_IN3=0;
KEY_IN4=1;
KEY_IN5=1;
Delay1(1);
if (KEY_OUT1==0 || KEY_OUT2==0 || KEY_OUT3==0 || KEY_OUT4==0)
j=3;
KEY_IN1=1;
KEY_IN2=0;
KEY_IN3=1;
KEY_IN4=1;
KEY_IN5=1;
Delay1(1);
if (KEY_OUT1==0 || KEY_OUT2==0 || KEY_OUT3==0 || KEY_OUT4==0)
j=4;
KEY_IN1=0;
KEY_IN2=1;
KEY_IN3=1;
KEY_IN4=1;
KEY_IN5=1;
Delay1(1);
if (KEY_OUT1==0 || KEY_OUT2==0 || KEY_OUT3==0 || KEY_OUT4==0)
j=5;
if (temp1!=0xff && j!=0 && ee==0)
{
Keyval=temp1*5+j;
j=0;
temp1=0xff;
ee++;
}
else if (temp1!=0xff && j!=0 && ee==1)
{
if (Keyval!=temp1*5+j)
{
j=0;
Keyval=0;
temp1=0xff;
ee=0;
}
else
{
ee++;
temp1=0xff;
}
}
else if(ee==2 && temp1!=0xff)
temp1=0xff;
else if(ee==2 && temp1==0xff && j==0)
break;
else if(ee==0 && temp1==0xff && j==0)
break;
if(sum==120)
{
longtime=1;
sum=0;
break;
}
}
if(slys==0)
ET0=1;
switch (Keyval)
{
case 22:
if (Once==0)
Once++;
break;
case 21: //数字0
Keyval=30;
if (Once>0)
Once++;
break;
case 16: //数字1
Keyval=31;
if (Once>0)
Once++;
break;
case 17: //数字2
Keyval=32;
if (Once>0)
Once++;
break;
case 18: //数字3
Keyval=33;
if (Once>0)
Once++;
break;
case 11: //数字4
Keyval=34;
if (Once>0)
Once++;
break;
case 12: //数字5
Keyval=35;
if (Once>0)
Once++;
break;
case 13: //数字6
Keyval=36;
if (Once>0)
Once++;
break;
case 6: //数字7
Keyval=37;
if (Once>0)
Once++;
break;
case 7: //数字8
Keyval=38;
if (Once>0)
Once++;
break;
case 8: //数字9
Keyval=39;
if (Once>0)
Once++;
break;
default:
break;
}
if(Speakflag==1)
{
if(Keyval!=0 && Keyval!=19)
{
Speak=0;
Delay1(100);
Speak=1;
}
}
return(Keyval);
}