[PIC单片机] 吴坚鸿单片机程序风格赏析【6】
- 格式:wps
- 大小:283.00 KB
- 文档页数:87
(一)按键行列扫描与蜂鸣器(1)技术体会:在行列式扫描结构的薄膜按键里,干扰很大,按键扫描程序非常讲究,尤其是去抖动的处理。
(2)功能需求:每按一个按键,蜂鸣器就响一次。
(3)硬件原理:(a)用4个IO来做2X2按键行列扫描,其中作为输入的2个IO口必须接上拉电阻20K左右。
(b)用1个IO经过8050三极管来驱动有源蜂鸣器,有源蜂鸣器通电就一直响,断电就停止。
而无源蜂鸣器是要靠断断续续的开关信号来驱动才能响,就是要频率来驱动。
(4)源码适合的单片机:PIC18F4620,晶振为22.1184MHz(5)源代码讲解如下:#include<pic18.h> //包含芯片相关头文件//补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr#define beep_dr LATA1 //蜂鸣器输出#define key_dr1 LATB3 //2X2按键行输出#define key_dr2 LATB4 //2X2按键行输出#define key_sr1 RB6 //2X2按键行输入#define key_sr2 RB7 //2X2按键行输入//补充说明:吴坚鸿程序风格是这样的,凡是做延时计数阀值的常量//前缀都用cnt_表示。
#define cnt_delay_cnt1 25 //按键去抖动延时阀值#define cnt_delay_cnt2 5 //按键行输出信号稳定的小延时阀值#define cnt_voice_time 60 //蜂鸣器响的声音长短的延时阀值void delay1(unsigned int de) ;//小延时程序,时间不宜太长,因为内部没有喂看门狗//补充说明:吴坚鸿程序风格是这样的,凡是按键扫描函数都放在定时中//断里,凡是按键服务程序都是放在main函数循环里。
有人说不应该把子程序//放在中断里,别听他们,信鸿哥无坎坷。
PIC12C5XX单片机使用和设计前言面向使用的嵌入式系统在我国方兴未艾微控制器,也就是单片机(MCU),在80年代进入中国。
由于微控制器容易学、容易用,倍受青眯。
这种把中央处理器、存储器、外设器件及I/O做在同一块芯片上的器件总是作为使用系统中的控制部件使用。
现在,做在微控制器芯片上的外设部件越来越多,功能不断增强。
针对具体的使用,利用微控制器可以设计出十分复杂的系统,这种系统称作嵌入式系统。
在杭州召开的’99全国单片微机学术交流会暨多国单片微机产品展览会上,许多专家呼吁要提高对嵌入式系统的认识。
目前,在全世界,嵌入式系统带来的工业年产值已超过1万亿美元。
预计在美国,单是使用嵌入式电脑的全数字电视产品每年将产生1500亿美元的新市场。
美国未来学家尼葛洛庞帝曾预言,四、五年后,嵌入式智能工具将是继PC和因特网后最伟大的发明。
就目前国内微控制器的使用状况,全国微机单片机学会理事长陈章龙教授说,从整体来讲,在中国,微控制器的使用水平还不高,主要是用8位微控制器,用量也不大,绝大多数是用于IC卡设备等仪器仪表和控制领域中。
嵌入式系统的核心部件是各种类型的嵌入式处理器,据不完全统计,全世界嵌入式处理器的品种已经过千,流行的结构有30多种,其中以我们熟悉的PIC系列结构的产品为最多。
据中国单片机公共实验室高级工程师吕京建介绍,嵌入式处理器分为两大类,一类是以通用计算机中的CPU为基础的嵌入式微控制器,另一类是微控制器。
和微处理器相比,微控制器具有单片化、体积小、功耗低、可靠性高、芯片上的个设资源丰富等特点,目前已成为嵌入式系统的主流器件。
嵌入式微处理器的软件是实现嵌入式系统功能的关键,为了提高执行速度和系统的可靠性,嵌入式系统中的软件一般都固化在存储器芯片或微控制器中。
嵌入式系统是面向使用的,因此它可以使用在现代化工业的各个领域,如:航天、航空、军事、家用消费商品、仪器仪表、各种控制系统及3C系统。
尤其在国内主要使用于家电消费类产品、通信和计算机外设等。
第五十五节:按键的花样技巧----双击按键的触发开场白:从这一节开始,我准备花几个章节来讲讲按键的几种常用花样技巧。
(1)功能需求:在规定的时间内,连续按两次按键则触发蜂鸣器发出“嘀”的短暂按键声。
类似于电脑鼠标的双击按键。
(2)硬件原理:独立按键和有源蜂鸣器的硬件原理请参考本连载文章的第二节。
(3)源码适合的单片机: PIC16F73,晶振为3.579545MHz。
(4)单片机的C语言源代码讲解:#include<pic.h>#define const_delay 1000 //连续按两次有效按键触发的时间单位。
当然此数据的大小我没仔细验证过,读者根据实际情况来调整.#define cnt_delay_cnt1 25 //按键去抖动延时阀值#define cnt_voice_time 60 //蜂鸣器响的声音长短的延时阀值//补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的IO后缀都是_sr#define beep_dr RB1 //蜂鸣器输出#define key_sr1 RB6 //独立按键输入启动按键//补充说明:吴坚鸿程序风格是这样的,按键扫描函数通常放在定时中//断里,按键服务程序通常放在main函数循环里。
有人说不应该把子程序放在中断里,别听他们,信鸿哥无坎坷。
void key_scan(); //按键扫描函数,放在定时中断里void key_service(); //按键服务函数,放在main函数循环里unsigned long time_cnt=0; //两次有效按键的时间计数器unsigned char key_lock1=0; //按键自锁标志unsigned int delay_cnt1=0; //按键去抖动的延时计数器的变量unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时unsigned char key_sec=0; //哪个按键被触发unsigned char key_touch_cnt=0; //按键触发的次数统计main() //主程序{ADCON0=0x41; //设置AD模式ADCON1=0x04; //RA0作为AD输入通道,本程序中没有用到AD,不用管它TRISB1=0; //蜂鸣器设置成输出beep_dr=0; //上电初始化蜂鸣器TRISB6=1; //独立按键设置成输入T1CON=0x24; //定时中断配置TMR1H=0xFE;TMR1L=0xEF;INTCON=0xC0;TMR1IF=0;TMR1IE=1;PEIE=1; //外围中断允许GIE=1; //开总中断TMR1ON=1; //启动定时器中断while(1){CLRWDT(); //喂单片机内部自带的看门狗,大家可以不管它key_service(); //按键服务}}void key_scan() //按键扫描函数{if(key_sr1==1) //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位{key_lock1=0; //按键自锁标志清零delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙,仔细品味,回味无穷,在按键去抖动期间,如果低电平掺杂了干扰的高电平,则计数器重新清零计数,极大增强了抗干扰的能力。
第一节:吴坚鸿谈初学单片机的误区。
(1)很难记住繁杂的寄存器?寄存器不用死记硬背,鸿哥我行走江湖多年,连一个寄存器都记不住。
需要配置寄存器的时候,直接在网上或者书本上参考别人现成的配置程序是上策,查找芯片数据手册是中策,死记硬背寄存器是最最下策。
(2)很难记住繁杂的汇编语言指令?除非是在校学生要应付考试或者少数工作中绕不开汇编,否则学汇编就是浪费时间。
鸿哥我行走江湖多年,从来就没有用汇编帮客户做过一个项目。
(3)C语言很难学?你不用学指针,你不用学带形参的函数,你不用学结构体,你不用学宏定义,你不用学文件操作,你也不用死记繁琐的数据类型。
你只要会:5条指令语句switch语句,if else语句,while语句,for语句,=赋值语句。
7个运算符+,-,*,/,|,&,!。
4个逻辑关系符||,&&,!=,==.3个数据类型unsigned char, unsigned int, unsigned long。
3个进制相互转化,二进制,十六进制,十进制。
1个void函数。
1个一维数组code(或const) unsigned char array[]。
那么世界上任何一种逻辑功能的单片机软件你都能做出来。
鸿哥我当年刚毕业出来工作的时候才知道可以用C语言开发单片机,一开始只用if 语句就把项目做出来了,没有用指针,没有用带形参的函数等复杂的功能。
再到后来才慢慢开始用C语言其他的高级功能,但是我发现C语言其他的高级功能,本质上都是用我前面列举出来的最基本功能集合而成,只是书写更加简单方便了一点,编译后的机器码都大同小异。
所以不会指针等高级功能你不用自卑,恰恰相反,当你会最简单的几个语句,就把这些高级功能的程序都做出来了,你才发现你对底层了解得更加透切,再学那些高级功能轻而易举。
当你裸机跑的程序都能够协调得很好的时候,你才发现所谓高深的操作系统也不过如此,只要给你时间和金钱你也可以写个操作系统来玩玩。
一文读懂PIC单片机的技术特性和优势对于电子工程师而言,PIC单片机是非常重要的一个产品。
PIC单片机是一种用来开发的去控制外围设备的集成电路,一种具有分散作用(多任务)功能的CPU,与人类相比,大脑就是CPU,PIC共享的部分相当于人的神经系统。
PIC单片机的特点PIC 单片机是一个小的计算机,PIC单片机有计算功能和记忆内存像CPU并由软件控制运行。
然而,处理能力—般,存储器容量也很有限,这取决于PIC的类型。
但是它们的最高操作频率大约都在20MHz 左右,存储器容量用做写程序的大约1K—4K字节。
时钟频率与扫描程序的时间和执行程序指令的时间有关系。
但不能仅以时钟频率来判断程序处理能力,它还随处理装置的体系结构改变。
如果是同样的体系结构,时钟频率较高的处理能力会较强。
因为PIC单片机可以把计算部分、内存、输入和输出等都做在一个芯片内。
所以它工作起来效率很高、功能也自由定义还可以灵活的适应不同的控制要求,而不必去更换不同的IC。
这样电路才有可能做的很小巧。
PIC单片机的优势PIC最大的特点是不搞单纯的功能堆积,而是从实际出发,重视产品的性能与价格比,靠发展多种型号来满足不同层次的应用要求。
就实际而言,不同的应用对单片机功能和资源的需求也是不同的。
比如一个摩托车的点火器需要一个I/O较少、RAM及程序存储空间不大、可靠性较高的小型单片机,若采用40脚且功能强大的单片机,投资大不说,使用起来也不方便。
PIC系列从低到高有几十个型号,可以满足各种需要。
其中,PIC12C508单片机仅有8个引脚,是世界上最小的单片机。
该型号有512字节ROM、25字节RAM、一个8位定时器、一根输入线、5根I/O线,市面售价在3-6元人人民币。
这样一款单片机在象摩托车点火器这样的应用无疑是非常适合。
PIC的高档型号,如PIC16C74(尚不是最高档型号)有40个引脚,其内部资源为ROM共4K、192字节RAM、8路A/D、3个8位定时器、2个CCP模块、三个串行口、1个并行口、11个中断源、33个I/O脚。
#in elude "REG52.H"#defi ne con st_se nd_size #defi ne con st_key_time1#defi ne con st_voice_short 40〃蜂鸣器短叫的持续时间void in itial_myself(void);void in itial_ perip heral(void);void delay_short (un sig ned int uiDelayshort);void delay_ long(un sig ned int uiDelay Ion g);void eusart_se nd(u nsig ned char ucSe ndData); //发送一个字节,内部自带每个字节之间的延时 void TO_time(void); // 定时中断函数 void usart_receive(void); // 串口接收中断函数void key_service(); //按键服务的应用程序void key_sca n(); //按键扫描函数 放在定时中断里sbit led_dr=卩1人5; //Led 的驱动 IO 口sbit beep_dr=卩2人5; //蜂鸣器的驱动IO 口sbit key_sr1=卩3人2; //对应朱兆祺学习板的 S1键 sbit key_gnd_dr= POM; //模拟独立按键的地 GND ,因此必须一直输出低电平 unsigned charucSendregBuf[const_send_size]; // 接收串口中断数据的缓冲区数组un sig ned int uiVoiceC nt=O;//蜂鸣器鸣叫的持续时间计数器 un sig ned char ucVoiceLock=0; 〃蜂鸣器鸣叫的原子锁un sig ned char ucKeySec=0;// 被触发的按键编号 unsigned int uiKeyTimeCnt1=O; //按键去抖动延时计数器 unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志 void mai n(){in itial_myself();delay_lo ng(100);in itial_ perip heral();while(1){key_service(); II 按键服务的应用程序} void eusart_se nd(un sig ned char ucSe ndData) {10 //串口发送数据的缓冲区数组大小20 〃按键去抖动延时的时间ES = 0; //关串口中断TI = 0; II 清零串口发送完成中断请求标志SBUF =ucSendData; II 发送一个字节I*注释一:*根据我个人的经验, 在发送一串数据中,每个字节之间必须添加一个延时, 用来等待串 口发送完成。
《谈学单片机有前途还是嵌入式系统有前途》一文吴坚鸿回复整理(1)六月初吴坚鸿发表了《吴坚鸿谈学单片机有前途还是嵌入式系统有前途》一文,后被andy1989转发至博客中,在发烧友中引起了很大的反响。
对于论坛上很多发烧友的评论,吴坚鸿一一作了答复,吴先生对于每个发烧友的评论都很认真的回复了,因此小编整理出来,供更多的发烧友们学习!稍稍啰嗦一下,吴坚鸿的回复可以解决很多单片机学者的疑问,如果有耐心看完的话,对大家会有极大的帮助的!谢谢版主的关注,没想到有那么多朋友关注,让我的虚荣心一下子得到极大的满足。
我决心对每个贴都回复。
无论有多忙,每天坚持抽一点时间来跟各位朋友交流。
(这是对于大家反映这么热烈的回复)好文章!很受启发——这个就是我分享心得的动力源泉。
嵌入式貌似学校没有怎么教——学校是学基础的地方,C语言,单片机,电子技术,数字技术,模拟技术,高等数学这些才是最重要的。
学校没教嵌入式,我认为是对的。
引用侯俊杰老师的一句话“勿在沙丘筑高台。
是啊脚踏实地最重要好高骛远到了最后一切都是浮云啊——共勉。
很感谢!—— 如果真要感谢我的话,就先感谢电子技术论坛的版主。
其中这句话我很赞同“我觉得单片机开发是艺术,我做的每一个作品都让我充满成就感。
”我比较偏爱自己独立开发自己喜欢的东西,这不为赚钱,只是自己个人对电子的爱好、热情!不过在工作中,个人的力量是有限的,团队合作也很重要!“英文阅读能力要好”这点很重要,不管是看参考资料还是软件开发寻求帮助对英语阅读能力都有很高的要求。
“掌握常用的不同厂家单片机,要掌握各种常用外围芯片,常用数字电路,模拟电路。
第22卷第6期 2003年12月实验室研究与探索R ESEAR CH A N D EXP L ORA T ION IN L A BO RA T ORYVol.22No.6 Dec.2003 PIC 单片机特点及应用时的注意事项吴正民(广州市广播电视大学番禺分校,广东广州511400)摘 要:比较了PIC 单片机与M CS -51系列单片机的不同,PIC 单片机的特点以及应用时的注意事项。
对中断、看门狗、程序跑飞等问题的进行了探讨。
关键词:PIC 单片机;精简指令集计算机;中断;看门狗;睡眠;唤醒中图分类号:TP 368.1文献标识码:B 文章编号:1006-7167(2003)06-0079-05Single Chip Micro -computer PIC :Characteristic and Application NotesWU Zheng -min(Panyu Radio and Television U niv .,Guang zhou 511400,China )Abstract :This paper compares the difference betw een the SCM (PIC kind)and SCM o f MSC-51,gives out the trait and the notice for application o f SCM (PIC kind ),and discusses the problems about terminal ,w atchdog ,the diso rder r unning of procedure and etc .Key words :PIC;RISC;terminal;w atchdog;sleep;w ake-up收稿日期:2001-12-101 问题的提出微控制器(M icro controller )的应用日益广泛,各个不同的公司推出了各自的产品。
第三十六节:EPROM篇--利用单片机内部自带EPROM存储数据开场白:这一节最有价值的可能不是我下面写的源代码讲解,而是我现在正在讲的开场白。
单片机内部自带EPROM存储数据,曾经是我去年一个挥之不去的噩梦。
去年我接了一个小项目,本来预计一个月内搞完的,结果因为小小的EPROM害得我阴沟里翻了船,拖了半年才验收通过。
事情是这样的,这个系统是工作在3.3V,利用单片机内部自带EPROM存储数据,我花了三个星期就交付给客户了,客户做了十几套样板在测试,发现数据偶尔会丢失,逼得我不得不想尽各种办法,比如备份数据等多种方法双管齐下,最终花了半年时间才弄好。
至于我是怎么弄好的我也不想多分享,因为这个系统有特殊性,我仅仅也是巧妙地利用它自身的特殊性才解决,这种解决问题的方法没有复制的价值。
不过从此之后我总结出了以下3条个人教训。
(a)凡是在低于5V电压工作的系统中,千万不要用单片机内部自带EPROM,宁可多花几毛钱也要用外挂的EPROM。
否则凶多吉少。
(b)在5V电压工作的系统中,如果要用单片机内部自带EPROM,那么这款单片机必须自带上电延时和掉电复位功能,同时烧录配置位时必须把这两项功能都打开。
因为单片机自带EPROM最容易丢失数据的时刻就是发生在掉电和上电那段“权力真空”的时间里。
(c)不管是工作在5V还是工作在低于5V的系统中,最保险的方法还是尽量选用外挂的EPROM。
因为去年那个项目给我留下了“成年阴影”,宁可错杀一千也不放过一个。
注:上电延时在PIC的烧录配置位是指power up timer掉电复位在PIC的烧录配置位是指brown out reset那个项目是去年年初开始弄,半年后才验收通过。
之后跟那个老总就几乎没什么联系了,到了年底的时候,突然有一天我接到了他的电话,他问我周末有没有空,他说想专门请我去酒楼吃海鲜,就我和他两个人。
我很开心地答应了,因为我想他肯定有什么大项目要跟我合作了。
到了周末,他真的专门从南山科技园那边开车到宝安西乡来接我去吃海鲜。
在吃饭的时候,我才知道,他找我真的没有什么“公事”,纯粹是因为“爱慕”我,年底了想跟我这个朋友聊聊天。
他夸我做事认真,沉得住气,遇到难题敢于迎难而上,颇有“帝王之气”,以后肯定有出息的。
同时他还点拨了我很多经验与方向。
他也很年轻,比我大两三年,09年才创业,我去过他公司,七八个人,环境还不错,每个月写字楼的租金五六千,不过他说这个负担也不重,因为他已经有批量的产品在出货。
他专门搞电脑方面的软件编程,用的是delphi,C#的开发工具。
他走的也是技术路线,不抽烟不喝酒,也不善于应酬,靠着诚信经营一个小公司,在圈内的朋友越来越多,口碑也越来越好,每两三个月都会跟一帮圈内的人自驾车到附近各地去旅游,他说他很知足了。
(1)功能需求:开机后两位数码管显示0到99之间的某一个数值,用一个按键可以不断的递增,用另外一个按键可以不断的递减。
断电后此数据可保存,下次通电开机的时候还是从那个保存的数据开始显示。
(2)硬件原理:(a)动态扫描两位数码管的电路请参考第二十一节。
(d) 独立按键的电路请参考第二节。
(c)烧录程序时记得把配置位PWRT和BOREN同时开打(Enable)。
(3)源码适合的单片机: PIC18f4520,晶振为3.579545MHz。
内部自带EPROM。
(4)单片机的C语言源代码讲解如下:#include<pic18.h> //包含芯片相关头文件#define cnt_delay_cnt1 25 //按键去抖动延时阀值#define cnt_voice_time 60 //蜂鸣器响的声音长短的延时阀值#define seg_0_dr LATB6 //任意7个IO口接数码管的seg引脚#define seg_1_dr LATB5#define seg_2_dr LATB4#define seg_3_dr LATB3#define seg_4_dr LATC7#define seg_5_dr LATB0#define seg_6_dr LATB1#define com_left_dr LATB2 //任意2个IO口接数码管的com引脚#define com_right_dr LATB7#define beep_dr LATA1 //蜂鸣器输出#define key_sr1 RD6 //独立按键输入#define key_sr2 RD7 //独立按键输入void eewrite(unsigned char ee_addr,unsigned char ee_data); //写入单片机内部eprom, unsigned char ee_read(unsigned char ee_addr); //从单片机内部eprom读取出数据void initial();//初始化void delay1(unsigned int de) ;//小延时程序,时间不宜太长,因为内部没有喂看门狗void display_drive(); //数码管驱动程序,放在定时中断里void display_seg(unsigned char seg); //编码转换程序,放在display_drive里//补充说明:吴坚鸿程序风格是这样的,凡是按键扫描函数都放在定时中//断里,凡是按键服务程序都是放在main函数循环里。
有人说不应该把子程序放在中断里,别听他们,信鸿哥无坎坷。
void key_scan(); //按键扫描函数,放在定时中断里void key_service(); //按键服务函数,放在main函数循环里//补充说明:吴坚鸿程序风格是这样的,凡是按键或者感应输入的自锁变量名//后缀都用_lock表示。
unsigned char key_lock1=0; //按键自锁标志unsigned char key_lock2=0; //按键自锁标志unsigned int delay_cnt1=0; //延时计数器的变量unsigned int delay_cnt2=0; //延时计数器的变量unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时unsigned char number_left=0; //左边数码管显示的内容unsigned char number_right=0; //右边数码管显示的内容unsigned char dis_step=1; //扫描的步骤unsigned char set_data; //显示,设置和保存的数unsigned char key_sec=0; //哪个按键被触发main() //主程序{initial(); //初始化while(1){CLRWDT();}}void eewrite(unsigned char ee_addr,unsigned char ee_data) //写入单片机内部eprom,{EEADR=ee_addr; //每种单片机都会有它固定的指令来配置相关的寄存器,来达到操作内部自带EPROM的目的,不必深究此时序EEDATA=ee_data;EEPGD=0;CFGS=0;WREN=1;GIE=0;EECON2=0x55;EECON2=0xaa;WR=1;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");GIE=1;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");WREN=0;WR=0;}unsigned char ee_read(unsigned char ee_addr) //从单片机内部eprom读取出数据{unsigned char ee_data;EEADR=ee_addr; //每种单片机都会有它固定的指令来配置相关的寄存器,来达到操作内部自带EPROM的目的,不必深究此时序EEPGD=0;CFGS=0;RD=1;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");ee_data=EEDATA;RD=0;return ee_data;}void key_scan() //按键扫描函数{if(key_sr1==1) //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位{key_lock1=0; //按键自锁标志清零delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙}else if(key_lock1==0) //有按键按下,且是第一次被按下{++delay_cnt1; //延时计数器if(delay_cnt1>cnt_delay_cnt1){delay_cnt1=0;key_lock1=1; //自锁按键置位,避免一直触发key_sec=1; //触发1号键}}if(key_sr2==1) //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位{key_lock2=0; //按键自锁标志清零delay_cnt2=0; //按键去抖动延时计数器清零,此行非常巧妙}else if(key_lock2==0) //有按键按下,且是第一次被按下{++delay_cnt2; //延时计数器if(delay_cnt2>cnt_delay_cnt1){delay_cnt2=0;key_lock2=1; //自锁按键置位,避免一直触发key_sec=2; //触发2号键}}}void key_service() //按键服务函数{switch(key_sec) //按键服务状态切换{case 1:// 1号键加// 补充说明:voice_time_cnt只要不为0蜂鸣器就会响,中断里判断voice_time_cnt不为0 //时,会不断自减,一直到它为0时,自动把蜂鸣器关闭++set_data;if(set_data>99){set_data=0;}eewrite(128,set_data); //把刚刚修改的数据保存进单片机内部自带的epromvoice_time_cnt= cnt_voice_time; //蜂鸣器响“滴”一声就停key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发break;case 2:// 2号键减--set_data;if(set_data>99) //字节类型的数据,当0减去1时会变成255(0xff),当然会比99大了。