




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、基础知识:51单片机编程基础 第一节:单数码管按键显示 第二节:双数码管可调秒表 第三节:十字路口交通灯 第四节:数码管驱动 第五节:键盘驱动 第六节:低频频率计 第七节:电子表 第八节:串行口应用 基础知识:51单片机编程基础 单片机的外部结构: 1. DIP40双列直插; 2. P0,P1,P2,P3四个8位准双向I/O引脚;(作为I/O输入时,要先输出高电平) 3. 电源 VCC( PIN40 )和地线 GND ( PIN20); 4. 高电平复位RESET ( PIN9);( 10uF电容接VCC与RESET,即可实现上电复位) 5. 内置振荡电路,外部只要接晶体至 X1( PIN18
2、 )和X0(PIN19 );(频率为主频的12倍) 6. 程序配置EA(PIN31 )接高电平 VCC ;(运行单片机内部 ROM中的程序) 7. P3 支持第二功能: RXD、TXD、INT0、INT1、T0、T1 单片机内部I/O部件:(所为学习单片机,实际上就是编程控制以下I/O部件,完成指定任务) 1. 四个8位通用I/O端口,对应引脚 P0、P1、P2和P3; 2. 两个 16 位定时计数器;(TMOD,TCON,TL0,TH0,TL1,TH1) 3. 一个串行通信接口; ( SCON,SBUF) 4. 一个中断控制器;(IE,IP) 针对AT89C52单片机,头文件 AT89x52
3、.h给出了 SFR特殊功能寄存器所有端口的定义。 C语言编程基础: 1. 十六进制表示字节 0 x5a :二进制为 01011010B ; 0 x6E为01101110。 2. 如果将一个16位二进数赋给一个8位的字节变量,则自动截断为低8位,而丢掉高8位。 3. +var表示对变量 var先增一;var 表示对变量后减一。 4. x |= 0 x0f;表示为 x = x | 0 x0f; 5. TMOD = ( TMOD 表示给变量 TMOD的低四位赋值 0 x5,而不改变 TMOD的高 四位。 6. While( 1 );表示无限执行该语句,即死循环。语句后的分号表示空循环体,也就是; 在
4、某引脚输出高电平的编程方法:(比如P1.3 (PIN4 )引脚) 代码 1. #include II该头文档中有单片机内部资源的符号化定义,其中包含P1.3 2. void main( void ) I/void表示没有输入参数,也没有函数返值,这入单片机运行的复 位入口 3. 4. P1_3 = 1;II给P1_3赋值1,引脚P1.3就能输出高电平 VCC 5. While( 1 );II 死循环,相当 LOOP: goto LOOP; 6. 注意:P0的每个引脚要输出高电平时,必须外接上拉电阻(如 4K7)至VCC电源。 在某引脚输出低电平的编程方法:(比如P2.7引脚) 代码 1. #i
5、nclude II该头文档中有单片机内部资源的符号化定义,其中包含P2.7 2. void main( void ) IIvoid表示没有输入参数,也没有函数返值,这入单片机运行的复 位入口 3. 4. P2_7 = 0;II给P2_7赋值0,弓I脚P2.7就能输出低电平 GND 5. While( 1 );II 死循环,相当 LOOP: goto LOOP; 6. 在某引脚输出方波编程方法:(比如P3.1引脚) 代码 1. #include II该头文档中有单片机内部资源的符号化定义,其中包含P3.1 2. void main( void ) IIvoid表示没有输入参数,也没有函数返值,这
6、入单片机运行的复 位入口 3. 4. While( 1 )II非零表示真,如果为真则执行下面循环体的语句 5. I 6. P3_1 = 1;/给P3_1赋值1,弓I脚P3.1就能输出高电平 VCC 7. P3_1 = 0;/给P3_1赋值0,引脚P3.1就能输出低电平 GND 8. /由于一直为真,所以不断输出高、低、高、低-,从而形成方波 9. 将某引脚的输入电平取反后,从另一个引脚输出:(比如P0.4 = NOT( P1.1) 代码 1. #include / 该头文档中有单片机内部资源的符号化定义, 其中包含 P0.4 和 P1.1 2. void main( void ) IIvoid
7、表示没有输入参数,也没有函数返值, 这入单片机运行的复 3. 4. 5. 6. 7. 8. 9. 10. 11. 位入口 P1_1 = 1; While( 1 ) if ( P1_1 = 1 P0_4 = 0; else /初始化。P1.1作为输入,必须输出高电平 / II 非零表示真,如果为真则执行下面循环体的语句 /读取P1.1,就是认为P1.1为输入,如果P1.1 输入高电平VCC II给P0_4赋值0,引脚P0.4就能输出低电平 GND 否则P1.1输入为低电平GND / P0_4 = 0; II 给P0_4赋值0,引脚P0.4就能输出低电平 GND P0_4 = 1; II给P0_4
8、赋值1,引脚P0.4就能输出高电平 VCC 12. II由于一直为真,所以不断根据P1.1的输入情况,改变 P0.4的输出电平 13. 将某端口 8个引脚输入电平,低四位取反后,从另一个端口8个引脚输出:(比如P2 = NOT( P3 ) 代码 1. #include II 该头文档中有单片机内部资源的符号化定义, 其中包含P2和P 2. void main( void ) IIvoid表示没有输入参数,也没有函数返值, 这入单片机运行的复 3. 4. 5. 6. 位入口 P3 = 0 xff; 电平 While( 1 ) II II初始化。P3作为输入,必须输出高电平,同时给 P3 II非零
9、表示真,如果为真则执行下面循环体的语句 取反的方法是异或1,而不取反的方法则是异或0 口的8个引脚输岀高 7. P2 = P3A0 x0fII读取P3,就是认为P3为输入,低四位异或者1,即取反,然后输出 8. /由于一直为真,所以不断将P3取反输出到P2 9. 注意:一个字节的 8位D7、D6至DO,分别输出到 P3.7、P3.6至P3.0,比如P3=0 x0f ,_则P3.7、P3.6、 P3.5、P3.4四个引脚都输出低电平,而P3.3、P3.2、P3.1、P3.0四个引脚都输出高电平。同样,输入一 个端口 P2,即是将 P2.7、P2.6至P2.0,读入到一个字节的8位D7、D6至D0
10、。 共 9 页:上一页 1 2 3 4 5 6 7 8 9下一页 第一节:单数码管按键显示 单片机最小系统的硬件原理接线图: 1. 接电源:VCC (PIN40 )、GND(PIN20 )。加接退耦电容 0.1uF 2. 接晶体:X1 ( PIN18八 X2( PIN19 )。注意标出晶体频率(选用 12MHz ),还有辅助电容 30pF 3. 接复位:RES ( PIN9 )。接上电复位电路,以及手动复位电路,分析复位工作原理 4. 接配置:EA( PIN31 )。说明原因。 发光二极的控制:单片机I/O输出 将一发光二极管LED的正极邙日极)接P1.1 , LED的负极(阴极)接地GND。
11、只要P1.1输出高电平VCC, LED就正向导通(导通时 LED上的压降大于1V),有电流流过LED,至发LED发亮。实际上由于 P1.1 高电平输出电阻为10K,起到输出限流的作用,所以流过 LED的电流小于(5V-1V ) /10K = 0.4mA。只要 P1.1输出低电平GND,实际小于0.3V,LED就不能导通,结果LED不亮。 开关双键的输入:输入先输岀高 一个按键 KEY_ON 接在P1.6与GND之间,另一个按键 KEY_OFF 接P1.7与GND之间,按 KEY_ON 后LED亮,按KEY_OFF后LED灭。同时按下LED半亮,LED保持后松开键的状态,即 ON亮OFF灭。 1
12、. #include 2. #define LED P1A1 / 3. #define KEY_ON PM6 / 4. #define KEY_OFF PM7 / 5. void main( void ) 值 6. 代码 用符号LED代替P1_1 用符号 KEY_ON代替P1_6 用符号KEY_OFF代替P1_7 /单片机复位后的执行入口,void表示空,无输入参数,无返回 7. KEY_ON = 1;/作为输入,首先输出高,接下KEY_ON,P1.6则接地为0,否则输入为1 8. KEY_OFF = 1;/作为输入,首先输出高,接下KEY_OFF , P1.7则接地为0 ,否则输入 为1 9
13、. While( 1 )/永远为真,所以永远循环执行如下括号内所有语句 10. 11. if ( KEY_ON=0 ) LED=1;/ 是 KEY_ON 接下,所示 P1.1 输出高,LED 亮 12. if ( KEY_OFF=0 ) LED=0;/ 是 KEY_OFF 接下,所示 P1.1 输出低,LED 灭 13. /松开键后,都不给LED赋值,所以LED保持最后按键状态。 14. /同时按下时,LED不断亮灭,各占一半时间,交替频率很快,由于人眼惯性,看上去为半 亮态 15. 数码管的接法和驱动原理 一支七段数码管实际由8个发光二极管构成,其中7个组形构成数字8的七段笔画,所以称为七段
14、数码 管,而余下的1个发光二极管作为小数点。作为习惯,分别给 8个发光二极管标上记号:a,b,c,d,e,f,g,h。 对应8的顶上一画,按顺时针方向排,中间一画为g,小数点为h。 我们通常又将各二极与一个字节的8位对应,a(D0),b(D1),c(D2),d(D3),e(D4),f(D5),g(D6),h(D7) ,相应 8个发光二极管正好与单片机一个端口Pn的8个引脚连接,这样单片机就可以通过引脚输岀高低电平控制 8个发光二极的亮与灭,从而显示各种数字和符号;对应字节,引脚接法为:a(Pn.0),b(Pn.1),c(Pn.2), d(Pn.3),e(Pn.4),f(Pn.5),g(Pn.6
15、),h(Pn.7)。 如果将8个发光二极管的负极(阴极)内接在一起,作为数码管的一个引脚,这种数码管则被称为共阴 数码管,共同的引脚则称为共阴极,8个正极则为段极。否则,如果是将正极邙日极)内接在一起引岀的, 则称为共阳数码管,共同的引脚则称为共阳极,8个负极则为段极。 以单支共阴数码管为例,可将段极接到某端口Pn,共阴极接GND,则可编写岀对应十六进制码的七段 码表字节数据如右图: 显示宇需 共阴机段选码 共阳极段选码 显示字符 共阴根段选码 共阳极段逑码 0 3FH COH C 39H C6H 1 F9H D 5EH A1H 2 5EH A4H E 79H 86H 3 BOH F 71H
16、34H 4 66H 99H P 73H 32H 5 6DH 92H U 3EH C1H 6 7DH 82H r 31H CEH 7 07H F3H y 6EH 91H 8 7FH SOH 8 FFH OOH 9 6FK 90H OOH FFH A 77H 8SH B 7CH 3H 16键码显示的程序 我们在P1端口接一支共阴数码管 SLED,在P2、P3端口接16个按键,分别编号为 KEY_O、KEY_1到 KEY_F,操作时只能按一个键,按键后 SLED显示对应键编号。 代码 1. #include 2. #define SLED P1 3. #define KEY_O P2A0 4. #d
17、efine KEY_1 卩2人1 5. #define KEY_2 卩2人2 6. #define KEY_3 卩2人3 7. #define KEY_4 卩2人4 8. #define KEY_5 卩2人5 9. #define KEY_6 卩2人6 10. #define KEY_ 7 P2A7 11. #define KEY_ _8 P3A0 12. #define KEY_ _9 P3A1 13. #define KEY_ A P3A2 14. #define KEY_ _B P3A3 15. #define KEY_ _C P3A4 16. #define KEY_ _D P3A5
18、17. #define KEY E P3A6 18. #define KEY_F P3A7 19. Code unsignedchar Seg7Code16=/ 用十六进数作为数组下标,可直接取得对应的 七段编码字节 20. / / 0 1 2 34567 89 A b C d E F 21. 0 x3f, 0 x06, 0 x5b, 0 x4f, 0 x66, 0 x6d, 0 x7d, 0 x07, 0 x7f, 0 x6f, 0 x7 7, 0 x7c, 0 x39, 0 x5e, 0 x79, 0 x71; 22. void main( void ) 23. 24. unsigned
19、char i=0;/ 作为数组下标 25. P2 = 0 xff; /P2作为输入, 初始化输岀高 26. P3 = 0 xff; /P3作为输入,初始化输出高 27. While( 1 ) 28. 29. if ( KEY_ 0 = 0)i=0; if ( KEY_1 = 0 ) i=1; 30. if ( KEY_ 2 = 0 ) i=2; if ( KEY_3 = 0 ) i=3; 31. if ( KEY_ 4 = 0 ) i=4; if ( KEY_5 = 0 ) i=5; 32. if ( KEY_ _6 = 0 ) i=6; if ( KEY_7 = 0 ) i=7; 33. i
20、f ( KEY_ 8 = 0 ) i=8; if ( KEY_9 = 0 ) i=9; 34. if ( KEY_ A = 0 ) i=0 xA; if ( KEY_B =0 ) i=0 xB; 35. if ( KEY_ C = 0 ) i=0 xC; if ( KEY_D =0 ) i=0 xD; 36. if ( KEY_ E = 0 ) i=0 xE; if ( KEY_F =0 ) i=0 xF; 37. SLED = Seg7Code i ; /开始时显示i 0,根据i取应七段编码 38. 39. 共 9 页:上一页1 2 3 4 5 6 7 8 9下一页 第二节:双数码管可调秒表
21、 解:只要满足题目要求,方法越简单越好。由于单片机I/O资源足够,所以双数码管可接成静态显示方式, 两个共阴数码管分别接在 P1(秒十位)和P2(秒个位)口,它们的共阴极都接地,安排两个按键接在 P3.2 (十位数调整)和 P3.3 (个位数调整)上,为了方便计时,选用 12MHz的晶体。为了达到精确计时,选 用定时器方式2,每计数250重载一次,即250us,定义一整数变量计数重载次数,这样计数4000次即 为一秒。定义两个字节变量 S10和S1分别计算秒十位和秒个位。编得如下程序: 代码 1. #include 2. Code unsignedchar Seg7Code16=/用十六进数作
22、为数组下标,可直接取得对应的 七段编码字节 3. / / 012345678 9 A b C d E F 4. 0 x3f, 0 x06, 0 x5b, 0 x4f, 0 x66, 0 x6d, 0 x7d, 0 x07, 0 x7f, 0 x6f, 0 x77, 0 x7c, 0 x39, 0 x5e, 0 x79, 0 x71; 5. void main( void ) 6. 7. unsignedint us250 = 0; 8. unsignedchar s10 = 0; 9. unsignedchar s1 = 0; 10. unsignedchar key10 = 0; /记忆按键
23、状态,为 1按下 11. unsignedchar key1 = 0; /记忆按键状态,为 1按下 12. /初始化定时器Timer。 13. TMOD = (TMOD 14. TH1 = -250;/对于8位二进数来说,-250=6,也就是加250次1时为256,即为0 15. TR1 = 1; 16. while (1)/ -循环1 17. P1 = Seg7Code s10 ;/ 显示秒十位 18. P2 = Seg7Code s1 ;/ 显示秒个位 19. while ( 1 )/ -循环 2 20. /计时处理 21. if ( TF0 = 1 ) 22. TF0 = 0; 23.
24、if ( +us250 = 4000 ) 24. us250 = 0; 25. if ( +s1 = 10 ) 26. s1 = 0; 27. if ( +s10 = 6 ) s10 = 0; 28. 29. break ; /结束循环2”,修改显示 30. 31. 32. /按十位键处理 33. P3.2 = 1;/P3.2作为输入,先要输出高电平 34. if ( key10 = 1 )/ 等松键 35. if (P3.2 = 1 ) key10=0; 36. 37. else /未按键 38. if ( P3.2 = 0 ) 39. key10 = 1; 40. if (+s10 = 6
25、 ) s10 = 0; 41. break ; /结束循环2”,修改显示 42. 43. 44. /按个位键处理 45. P3.3 = 1;/P3.3作为输入,先要输出高电平 46. if ( key1 = 1 )/ 等松键 47. if (P3.3 = 1 ) key1=0; 48. else /未按键 49. if ( P3.3 = 0 ) key1 = 1; 50. if (+s1 = 10 ) s1 = 0; 51. break ; /结束循环2”,修改显示 52. 53. 54. / 循环 2 end 55. / 循环 1 end 56. /main end 共 9 页:上一页1 2
26、 3 4 5 6 7 8 9下一页 第三节:十字路口交通灯 如果一个单位时间为1秒,这里设定的十字路口交通灯按如下方式四个步骤循环工作: 60个单位时间,南北红,东西绿; 10个单位时间,南北红,东西黄; 60个单位时间,南北绿,东西红; 10个单位时间,南北黄,东西红; 解:用P1端口的6个引脚控制交通灯,高电平灯亮,低电平灯灭 代码 1. #include 2. /sbit 3. sbit SNRed =P1A0; 4. sbit SNYellow =PM1 5. sbit SNGreen =PM2; 6. sbit EWRed =PM3; 7. sbit EWYellow =PM4; 8
27、. sbit EWGreen =PM5; 9. /* 10. 11. 用来定义一个符号位地址,方便编程,提高可读性,和可移植性 /南北方向红灯 用软件产生延时一个单位时间 void Delay1Unit( void /南北方向黄灯 /南北方向绿灯 /东西方向红灯 /东西方向黄灯 /东西方向绿灯 */ 12. unsigned int i, j; 13. for ( i=0; i1000; i+ ) 14. for ( j0; j1000; j+ );/通过实测,调整j循环次数,产生1ms延时 1ms 15. /还可以通过生成汇编程序来计算指令周期数,结合晶体频率来调整j循环次数,接近 16.
28、17. /* 延时n个单位时间*/ 18. void Delay( unsignedint n ) for ( ; n!=0; n- ) Delay1Unit(); 19. void main( void ) 20. 21. while ( 1 ) 22. 23. SNRed=0; SNYellow=0; SNGreen=1; EWRed=1; EWYellow=0; EWGreen=0; D elay( 60 ); 24. SNRed=0; SNYellow=1; SNGreen=0; EWRed=1; EWYellow=0; EWGreen=0; D elay( 10 ); 25. SNR
29、ed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=0; EWGreen=1; D elay( 60 ); 26. SNRed=1; SNYellow=0; SNGreen=O; EWRed=O; EWYellow=1; EWGreen=O; D elay( 10 ); 27. 28. 共 9 页:上一页1 2 3 4 5 6 7 8 9下一页 第四节:数码管驱动 显示 “12345678 P1端口接8联共阴数码管SLED8的段极:P1.7接段h,,P1.0接段a P2端口接8联共阴数码管SLED8的段极:P2.7接左边的共阴极,P2.0接右边的共阴极
30、 方案说明:晶振频率fosc=12MHz,数码管采用动态刷新方式显示,在1ms定时断服务程序中实现 代码 1. #include 2. unsigned char DisBuf8;/ 全局显示缓冲区,DisBuf0 对应右 SLED ,DisBuf7 对应左SLED, 3. void DisplayBrush(void ) 4. code unsignedchar cathode8=0 xfe,0 xfd,0 xfb,0 xf7,0 xef,0 xdf,0 xbf, 0 x7f;/阴极控制码 5. Code unsigned char Seg7Code16= /用十六进数作为数组下标,可直接取
31、得对应的 七段编码字节 6. 0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d,0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x 5e,0 x79,0 x71; 7. static unsigned char i=0;/(0i = 8 ) i=0; 12. 13. void Timer0IntRoute( 14. 15. TL0 = -1000;/ 由于 TL0 只有 8bits ,所以将(-1000 )低 8 位赋给 TL0 16. TH0 = (-1000)8;/ 取(-1000 )的高 8 位赋给 TH0,重新定时 1ms
32、17. DisplayBrush(); 18. 19. void Timer0Init( void ) 20. TMOD=(TMOD /初始化,定时器T0,工作方式1 21. TL0 = -1000; /定时1ms 22. TH0 = (-1000)8; 23. TR0 = 1;/ 允许T0开始计数 24. ET0 = 1;/ 允许T0计数溢出时产生中断请求 25. 26. void Display( unsignedchar index, unsignedchar dataValue ) DisBu f index = dataValue; 27. void main( void ) 28.
33、 29. unsigned char i; 30. for ( i=0; i8; i+ ) Display。, 8-i); DisBuf0 为右,DisBuf7 为 左 31. Timer0lnit(); 32. EA = 1;/允许CPU响应中断请求 33. While(1); 34. 共 9 页:上一页1 2 3 4 5 6 7 8 9下一页 第五节:键盘驱动 指提供一些函数给任务调用,获取按键信息,或读取按键值。 定义一个头文档,描述可用函数,如下: 代码 1. #ifndef _KEY_H_ /防止重复引用该文档,如果没有定义过符号_KEY_H_,则编译下面 语句 2. #define
34、 _KEY_H_ /只要引用过一次, 即 #include ,则定义符号 _KEY_H_ 3. unsigned char keyHit( void );/如果按键,则返回非0,否则返回0 4. unsigned char keyGet( void );/读取按键值,如果没有按键则等待到按键为止 5. void keyPut( unsigned char ucKeyVal );/保存按键值ucKeyVal到按键缓冲队 列末 6. void keyBack( unsignedchar ucKeyVal );/退回键值ucKeyVal到按键缓冲队 I 列首 7. #endif 定义函数体文档 KE
35、Y.C,如下: 代码 1. #include key.h 2. #define KeyBufSize 16 / 定义按键缓冲队列字节数 3. unsigned char KeyBuf KeyBufSize ; /定义一个无符号字符数组作为按键缓冲队 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 列。该队列为先进 /先出,循环存取,下标从0到 KeyBufSize-1 unsigned char KeyBufWp=0; /作为数组下标变量,记录存入位置 unsigned char KeyBufRp=0; /作为数组下标变量,记录读出位置 /如果存入位置与读岀
36、位置相同,则表明队列中无按键数据 unsigned char keyHit( void ) if ( KeyBufWp = KeyBufRp ) unsigned char keyGet( unsigned char retVal; while ( keyHit()=O ); retVal = KeyBuf KeyBufRp ; void / / return ( 0 ); else return ( 1 ); 暂存读岀键值 等待按键,因为函数keyHit()的返回值为0表示无按键 /从数组中读岀键值 if ( +KeyBufRp = KeyBufSize ) KeyBufRp=0; /读位置
37、加1,超岀队列则循环回 22. 23./* 初始位置 16. return ( retVal ); 17. 18. 19. void keyPut( unsigned char ucKeyVal ) 20. KeyBuf KeyBufWp = ucKeyVal; /键值存入数组 21. if ( +KeyBufWp = KeyBufSize ) KeyBufWp=0; /存入位置加1,超出队列则 循环回初始位置 * 24.由于某种原因,读岀的按键,没有用,但其它任务要用该按键,但传送又不方便。此时可以退 回按键队列。就如取错了信件,有必要退回一样 25. * */ 26. void keyBa
38、ck( unsigned char ucKeyVal ) 27. 28. /* 9. 12. 29. 如果KeyBufRp=0; 减1后则为FFH,大于KeyBufSize,即从数组头退回到数组尾。或者 由于干扰使得KeyBufRp超出队列位置,也要调整回到正常位置, 30. */ 31. if ( -KeyBufRp = KeyBufSize ) KeyBufRp=KeyBufSize-1; 32. KeyBuf KeyBufRp = ucKeyVal; /回存键值 33. 下面渐进讲解键盘物理层的驱动。 电路共同点:P2端口接一共阴数码管,共阴极接 GND,P2.0 接 a 段、P2.1
39、接 b 段、P2.7 接 h 段。 是七段数码管共阴编码表。 软件共同点:code unsigned char Seg7Code10 Code unsigned char Seg7Code16= / 0123456789 0 x3f, 0 x06, 0 x5b, 0 x4f, 0 x66, 0 x6d, 0 x7d, 0 x07, 0 x7f, 0 x6f, 0 x77, 0 x7c, 0 x39, 0 x5e, 0 x79, 0 x71; 例一:P1.0接一按键到GND,键编号为6 显示按键。 代码 1. #include 2. #include “KEY.H 3. void main( v
40、oid ) 4. P1_0 = 1; /作为输入引脚,必须先输岀高电平 5. while ( 1 ) /永远为真,即死循环 6. if ( P1_0 = 0 ) /如果按键,则为低电平 7. keyPut( 6 ); / 保存按键编号值为按键队列 8. while ( P1_0 = 0 ); /如果一直按着键,则不停地执行该循环,实际是等待松键 10. if ( keyHit() != 0 ) /如果队列中有按键 11. P2=Seg7Code keyGet(); /从队列中取岀按键值,并显示在数码管上 13. 例二:在例一中考虑按键 20ms抖动问题 代码 1. #include 2. #i
41、nclude“KEY.H 3. void main( void ) 4. P1_0 = 1;/ 作为输入引脚,必须先输岀高电平 5. while ( 1 )/永远为真,即死循环 6. if ( P1_0 = 0 ) /如果按键,则为低电平 7. delay20ms(); /延时20ms,跳过接下抖动 8. keyPut( 6 );/ 保存按键编号值为按键队列 9. while ( P1_0 = 0 ) ;/如果一直按着键,则不停地执行该循环,实际是等待松键 10. delay20ms();/ 延时20ms,跳过松开抖动 11. 12. if ( keyHit() != 0 ) /如果队列中有按
42、键 13. P2=Seg7Code keyGet() ;/从队列中取出按键值,并显示在数码管上 14. 15. 例三:在例二中考虑干扰问题。即小于 20ms的负脉冲干扰。 代码 1. #include 2. #include “KEY.H 3. void main( void ) 4. P1_0 = 1;/作为输入引脚,必须先输出高电平 5. while ( 1 )/永远为真,即死循环 6. if ( P1_0 = 0 )/如果按键,则为低电平 7. delay20ms();/延时20ms,跳过接下抖动 8. if ( P1_0 = 1 )continue ; / 假按键 9. keyPut(
43、 6 );/保存按键编号值为按键队列 10. while ( P1_0 = 0 );/如果一直按着键,则不停地执行该循环,实际是等待松键 11. delay20ms(); /延时20ms,跳过松开抖动 12. 13. if ( keyHit() != 0 )/如果队列中有按键 14. P2=Seg7Code keyGet() ;/从队列中取出按键值,并显示在数码管上 15. 16. 例四:状态图编程法。通过 20ms周期中断,扫描按键。 代码 1. /* * 2. 采用晶体为12KHZ时,指令周期为1ms (即主频为1KHz),这样TO工作在定时器方式2,8 位自动重载。计数值为20,即可产生
44、20ms的周期性中断,在中断服务程序中实现按键扫描 3. * */ 4. #include 5. #include “KEY.H 6. void main( void ) 7. /不改变T1的工作方式,T0为定时器方式2 9. TH0 = -20; /计数周期为20个主频脉,即 10. TL0=TH0; /先软加载一次计数值 11. TR0=1; /允许T0开始计数 12. ET0=1; /允许T0计数溢出时产生中断请求 13. EA=1; /允许CPU响应中断请求 14. while ( 1 ) /永远为真,即死循环 15. 8. /如果队列中有按键 20ms TMOD =(TMOD 16.
45、 if ( keyHit() != 0 ) 17. P2=Seg7Code keyGet(); /从队列中取岀按键值,并显示在数码管上 20. void timer0int( void )interrupt 1 /20ms; T0的中断号为 1 21. static unsigned char sts=0; /作为输入引脚,必须先输岀高电平 22. P1_0 = 1; 23. switch ( sts ) 24. 25. case 0: if ( P1_0=0 ) sts=1;break ; / 按键则转入状态 1 26. case 1: 27. if ( P1_0=1 ) sts=0;/假按
46、错,或干扰,回状态 0 28. else sts=2; keyPut( 6 ); /确实按键,键值入队列,并转状态2 29. break ; 30. case 2: if ( P1_0=1 ) sts=3;break ; / 如果松键,则转状态 3 31. case 3: 32. if ( P1_0=0 ) sts=2;/ 假松键,回状态 2 33. else sts=0;/真松键,回状态0 ,等待下一次按键过程 34. 35. 例五:状态图编程法。 代码 1. * 2.如果采用晶体为12MHz时,指令周期为1us (即主频为1MHz),要产生20ms左右的计时, 则计数值达到20000,T0
47、工作必须为定时器方式1,16位非自动重载,即可产生 20ms的周 期性中断,在中断服务程序中实现按键扫描 3* */ 4. #include 5. #include “KEY.H 6. void main( void ) 7. 8. TMOD =( TMOD /不改变T1的工作方式,T0为定时器方式1 9. TL0 = -20000;/计数周期为20000个主频脉,自动取低 8位 10. TH0 = (-20000)8;/右移8位,实际上是取高 8位 11. TR0=1;/允许T0开始计数 12. ET0=1;/允许T0计数溢出时产生中断请求 13. EA=1;/允许CPU响应中断请求 14.
48、 while ( 1 )/永远为真,即死循环 15. 16. if ( keyHit() != 0 )/如果队列中有按键 17. P2=Seg7Code keyGet() ;/从队列中取出按键值,并显示在数码管上 18. 19. 20. void timerOint(void ) interrupt 1/20ms; TO 的中断号为 1 21. static unsigned char sts=O; 22. TL0 = -20000;/方式1为软件重载 23. TH0 = (-20000)8;/右移8位,实际上是取高 8位 24. P1_0 = 1;/作为输入引脚,必须先输出高电平 25. s
49、witch ( sts ) 26. 27. case 0: if ( P1_0=0 ) sts=1;break ; / 按键则转入状态 1 28. case 1: 29. if ( P1_0=1 ) sts=0;/假按错,或干扰,回状态 0 30. else sts=2; keyPut( 6 ); /确实按键,键值入队列,并转状态2 31. break ; 32. case 2: if ( P1_0=1 ) sts=3;break ; / 如果松键,则转状态 3 33. case 3: 34. if ( P1_0=0 ) sts=2;/ 假松键,回状态 2 35. else sts=0;/真松
50、键,回状态0 ,等待下一次按键过程 36. 37. 例六:4X4按键 Pl.O(OxE) Pl 1(0kD) P1.2(0 xB) Pl. 3(0 x7) 10 F E D C B A 9 8 7 6 5 4 3 2 1 Pl 4(E) P 1.5(D)Pl 6(B)Pl.7(7) 代码 1. 2. /* * 由P1端口的高4位和低4位构成4X4的矩阵键盘,本程序只认为单键操作为合法,同时按多 键时无效。 3. 这样下面的X,Y的合法值为0 x7, Oxb, Oxd, Oxe, Oxf ,通过表keyCode影射变换可得 4. 按键值 * */ 5. #include 6. #include
51、“KEY.H 7. unsigned char keyScan( void )/返回0表示无按键,或无效按键,其它值为按键编 码值 8. code unsigned char keyCode16= xD, 0 xE, 0 xF 10. 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 0 ; 11. unsignedchar x, y, retVal; 12. P仁 0 x0f;/ 低四位输入,高四位输出 0 13. x=P1 , /P1输入后,清高四位, 作为 X值 14. P仁 0 xf0;/ 高四位输入,低四位输出 0 15. y=(P1 4) /
52、P1输入后移位到低四位, 9. 并清高四位,作为Y值 /0 x0, 0 x1,0 x2, 0 x3, 0 x4, 0 x5, 0 x6, 0 x7, 0 x8, 0 x9, 0 xA, 0 xB, 0 xC, 0 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 16. retVal = keyCode x*4 + keyCodey; /根据本公式倒算按键编码 if ( retVal
53、=0 )return (0); else return ( retVal-4 ); /比如按键1,得X=0 x7 , Y=0 x7,算得retVal= 5 ,所以返回函数值1。 /双如按键7,得X=0 xb,Y=0 xd,算得retVal=11 ,所以返回函数值 7。 void main( void ) TMOD =( TMOD /不改变T1的工作方式,T0为定时器方式 1 TL0 = -20000;/计数周期为20000个主频脉,自动取低 8位 TH0 = (-20000)8;/右移8位,实际上是取高 8位 TR0=1;/允许T0开始计数 ET0=1;/允许T0计数溢出时产生中断请求 EA=
54、1;/允许CPU响应中断请求 while ( 1 )/永远为真,即死循环 if ( keyHit() != 0 )/如果队列中有按键 P2=Seg7Code keyGet() ;/从队列中取出按键值,并显示在数码管上 void timer0int(void ) interrupt 1/20ms; T0 的中断号为 1 static unsignedchar sts=0; TL0 = -20000;/方式1为软件重载 TH0 = (-20000)8;/右移8位,实际上是取高 8位 P1_0 = 1;/作为输入引脚,必须先输出高电平 switch ( sts ) case 0: if ( keyS
55、can()!=0 ) sts=1;break ; / 按键则转入状态 1 case 1: if ( keyScan()=0 ) sts=0;/假按错,或干扰,回状态 0 else sts=2; keyPut( keyScan() ); /确实按键,键值入队列,并转状态2 break ; case 2: if (keyScan()=0 ) sts=3; break ; /如果松键,则转状态 3 case 3: if ( keyScan()!=0 ) sts=2; /假松键,回状态2 50. else sts=0;/真松键,回状态0 ,等待下一次按键过程 51. 52. 共 9 页:上一页1 2
56、3 4 5 6 7 8 9下一页 第六节:低频频率计 实例目的:学时定时器、计数器、中断应用 说明:选用24MHz的晶体,主频可达 2MHz。用T1产生100us的时标,T0作信号脉冲计数器。假设晶 体频率没有误差,而且稳定不变(实际上可达万分之一);被测信号是周期性矩形波(正负脉冲宽度都不 能小于0.5us ),频率小于1MHz,大于1Hz。要求测量时标1S,测量精度为0.1%。 解:从测量精度要求来看,当频率超过1KHz时,可采用1S时标内计数信号脉冲个数来测量信号频,而 信号频率低于1KHz时,可以通过测量信号的周期来求岀信号频率。两种方法自动转换。 对于低于1KHz的信号,信号周期最小
57、为1ms,也就是说超过1000us,而我们用的定时器计时脉冲周期为 0.5us,如果定时多计或少计一个脉冲,误差为 1us,所以相对误差为1us/1000us=0.1% 。信号周期越大, 即信号频率越低,相对误差就越小。 从上面描述来看,当信号频率超过1KHz后,信号周期就少于1000us,显然采用上面的测量方法,不能达 到测量精度要求,这时我们采用1S单位时间计数信号的脉冲个数,最少能计到1000个脉冲,由于信号频 率不超过1MHz,而我们定时脉冲为 2MHz,最差多计或少计一个信号脉冲,这样相对误差为1/1000 ,可 见信号频率越高,相对误差越小。 信号除输入到T1 (P3.5 )夕卜,
58、还输入到INT1 ( P3.3 )。 代码 1. unsigned int us100; /对100us时间间隔单位计数, 即有多少个100us。 2. unsigned char Second; 3. unsigned int K64; /对64K单位计数,即有多少个 64K 4. unsigned char oldT0; 5. unsigned int oldus, oldK64, oldT1; 6. unsigned long fcy; /存放频率值,单位为 Hz 7. bit HighLow=1; /1 :表示信号超过1KHz ; 0 :表示信号低于1KHz。 8. void Init
59、ialHigh( void ) 9. 10. IE=0; IP=0; HighLow=1; 11. TMOD = (TMOD TH0=-200; TL0=TH0; PX0=1; T0=1; 12. TMOD = (TMOD TH1=0; TL1=0; T仁1; ET1=1; 13. Us100=0; Second=0; K64=0; 14. oldK64=0; oldT 仁0; / 同时置 TR0=1; TR1=1; 15. TCON |= 0 x50; 16. EA = 1; 17. 18. void lnitialLow(void ) 19. 20. IE=0; IP=0; HighLow
60、=0; 21. TMOD = (TMOD TH0=-200; TL0=TH0; ET0=1; TR0=1; 22. INT1 = 1; IT 仁1; EX1=1; 23. Us100=0; Second=0; K64=0; 24. oldK64=0; oldT 仁0; 25. EA = 1;| 26. 27. void T0intr( void ) interrupt 1| 28. if ( HighLow=0 ) +us100; 29. else | 30. if ( +us100 = 10000 )| 31. unsigned int tmp1, tmp2; 32. TR1=0; tmp1
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教育心理学在数学创新思维培养中的应用
- 肇庆市森林消防大队队员招聘笔试真题2024
- 陕西有色金属控股集团有限责任公司招聘笔试真题2024
- 2025年乳腺癌患者术后护理查房模板
- 2025年公务员制度测试题及答案
- 2025年公共营养师职业资格考试试卷及答案
- 村医高血压知识培训试题(附参考答案)
- 融资租赁咨询服务费协议
- 2025年高压化成箔项目发展计划
- 供热培训基础知识课件
- 投标项目设备培训方案(3篇)
- 2025年郑州转业士官考试题库
- 一级建造师《公路工程》备考试题及答案
- 2025年公务员考试时事政治试题【含答案详解】
- 劳动合同瑜伽馆(2025版)
- 工会内控管理办法
- 岗位职责管理办法
- 3.1.4 认识除法算式(课件) 人教版数学二年级上册
- 2025版保育员理论考试试题试题(附答案)
- 基于无人机的公路路面及设施状况智能检测技术研究采购服务方案投标文件(技术方案)
- 履约能力提升培训大纲
评论
0/150
提交评论