[计算机软件及应用]嵌入式系统讲义.doc
嵌入式系统讲义目录ATMage16基础编程部分3一、认识ATMega163(一)、ATmega16 引脚功能4二、AVR开发工具5(一)、开发软件系统5(二)、硬件开发板5(三)、ISP下载6(四)、Jtag调试工具6三、I/O 引脚使用12(一)、I/O 口引脚配置12(二)、I/O 口的输出操作让发光二极管闪动13(三)、引脚的输出操作让发光二极管流动14(四)、引脚的输入操作按键控制发光二极管的亮灭15四、键盘18(一)、矩阵键盘1波峰法18(二)、矩阵键盘2翻转法22五、数字的显示23(一)、单数字的显示23(二)、数字的显示多数字动态显示27(三)、数字的显示多数字静态显示29六、中断判断电机的转向33七、定时/计数器039(一)、认识定时/计数器39(二)、定时/计数器0的计数功能应用40、定时/计数器0PWM应用43、定时/计数器0精确定时闪动的发光二极管46、定时/计数器0产生可变频率矩形波47八、定时/计数器148(一)、定时功能使用产生报警声48(二)、定时/计数器1频率计49(三)、定时/计数器1输出两路PWM信号50九、简易温度计设计50十、串行通讯52(一)、认识串行通讯52(二)、查询方式进行串行数据发送52(三)、查询方式进行串行数据接收52(四)、中断方式进行串行数据发送、接收52十一、AD转换52十二、DA转换53十三、spi接口53(一)、spi接口用途及认识53(二)、非中断方式使用spi接口53(三)、中断方式使用spi接口53十四、液晶模块使用53十五、SD卡使用53十六、红外遥控54(一)、红外遥控接收识别54(二)、红外遥控发射54ATMega16嵌入式应用部分54一、电池充电器设计54二、示波器设计54三、便携收录机设计54附录:知识点索引54参考文献55ATMage16基础编程部分一、认识ATMega16ATmega16是基于增强的AVR RISC结构的低功耗8位CMOS微控制器。由于其先进的指令集以及单时钟周期指令执行时间,ATmega16的数据吞吐率高达1 MIPS/MHz,从而可以缓减系统在功耗和处理速度之间的矛盾。ATmega16 AVR内核具有丰富的指令集和32个通用工作寄存器。所有的寄存器都直接与算逻单元(ALU)相连接,使得一条指令可以在一个时钟周期内同时访问两个独立的寄存器。这种结构大大提高了代码效率,并且具有比普通的CISC微控制器最高至10倍的数据吞吐率。ATmega16有如下特点:16K字节的系统内可编程Flash(具有同时读写的能力,即RWW),512字节EEPROM,1K字节SRAM,32个通用I/O口线,32个通用工作寄存器,用于边界扫描的JTAG接口,支持片内调试与编程,三个具有比较模式的灵活的定时器/计数器(T/C),片内/外中断,可编程串行USART,有起始条件检测器的通用串行接口,8路10位具有可选差分输入级可编程增益的ADC,具有片内振荡器的可编程看门狗定时器,一个SPI串行端口,以及六个可以通过软件进行选择的省电模式。工作于空闲模式时CPU停止工作,而USART、两线接口、A/D 转换器、SRAM、T/C、SPI 端口以及中断系统继续工作;掉电模式时晶体振荡器停止振荡,所有功能除了中断和硬件复位之外都停止工作;在省电模式下,异步定时器继续运行,允许用户保持一个时间基准,而其余功能模块处于休眠状态;ADC噪声抑制模式时终止CPU和除了异步定时器与ADC以外所有I/O模块的工作,以降低ADC转换时的开关噪声;Standby模式下只有晶体或谐振振荡器运行,其余功能模块处于休眠状态,使得器件只消耗极少的电流,同时具有快速启动能力;扩展Standby模式下则允许振荡器和异步定时器继续工作。(一)、ATmega16 引脚功能ATmega16有4个8位的双向I/O端口PA、PB、PC、PD,他们对外对应32个I/O引脚,每一位都可以独立地用于逻辑信号的输入和输出。在5V工作电压下,输出高点平时,每个引脚可输出达20mA的驱动电流;而输出低电平时,每个引脚可吸收最大为40mA的电流,可以直接驱动发光二极管(一般的发光二极管的驱动电流为10mA)和小型继电器等小功率器件。AVR大部分的I/O端口都具备双重功能(有的还有第三功能)。其中第一功能是作为数字通用I/O接口使用,而复用的功能可分别与片内的各种不同功能的外围接口电路组合成一些可以完成特殊功能的I/O口,如定时器、计数器、串行接口、模拟比较器、捕捉器、USART、SPI等。引脚名称引脚功能说明VCC电源正GND电源地端口A(PA7.PA0)端口A做为A/D转换器的模拟输入端。端口A为8位双向I/O口,具有可编程的内部上拉电阻。其输出缓冲器具有对称的驱动特性,可以输出和吸收大电流。作为输入使用时,若内部上拉电阻使能,端口被外部电路拉低时将输出电流。在复位过程中,即使系统时钟还未起振,端口A处于高阻状态。端口B(PB7.PB0)端口B为8位双向I/O口,具有可编程的内部上拉电阻。其输出缓冲器具有对称的驱动特性,可以输出和吸收大电流。作为输入使用时,若内部上拉电阻使能,端口被外部电路拉低时将输出电流。在复位过程中,即使系统时钟还未起振,端口B处于高阻状态。如果ISP接口使能,引脚PB5至PB7输入输出功能失效。端口C(PC7.PC0)端口C为8位双向I/O口,具有可编程的内部上拉电阻。其输出缓冲器具有对称的驱动特性,可以输出和吸收大电流。作为输入使用时,若内部上拉电阻使能,端口被外部电路拉低时将输出电流。在复位过程中,即使系统时钟还未起振,端口C处于高阻状态。如果JTAG接口使能,引脚PC5(TDI)、PC3(TMS) 、PC2(TCK) 与PC3(TDO)做调试使用,输入输出功能失效。端口D(PD7.PD0)端口D为8位双向I/O口,具有可编程的内部上拉电阻。其输出缓冲器具有对称的驱动特性,可以输出和吸收大电流。作为输入使用时,若内部上拉电阻使能,则端口被外部电路拉低时将输出电流。在复位过程中,即使系统时钟还未起振,端口D处于高阻状态。端口D也可以用做其他不同的特殊功能RESET复位输入引脚。持续时间超过最小门限时间的低电平将引起系统复位。XTAL1反向振荡放大器与片内时钟信号电路的输入端。XTAL2反向振荡放大器与片内时钟信号电路的输出端。AVCCAVCC是A/D转换器的电源。不使用ADC时,该引脚应直接与VCC连接。使用ADC时应通过一个低通滤波器与VCC连接。AREFA/D 的基准电压输入引脚二、AVR开发工具AVR开发工具由开发软件系统、硬件开发板、Jtag调试工具、和ISP下载工具四部分组成。(一)、开发软件系统开发软件系统常用有ICCAVR和AVRGCC两类,ICCAVR是付费软件,而AVRGCC是免费软件,在版权意识日益增加的今天,我们使用AVRGCC。AVRGCC同AVR Studio配合可以进行软件在线调试、下载,是AVR开发工具由开发软件系统的首选。AVR Studio是AVR生产商ATmel公司免费提供的开发环境,可以进行下载和在线调试,缺点是只支持汇编不支持C语言,而AVRGCC支持C语言,两者配合,可以用C语言开发AVR。依次缺省安装AVR Studio及AVRGCC后就可以进行AVR的学习和开发。(二)、硬件开发板(三)、ISP下载(四)、Jtag调试工具第一部:硬件连接。第二步:使用AVRstudio打开*.cof文件如果你没有自己写AVR程序,你可以使用本站的新手入门第一个程序。AVR_first,实现红绿灯不断闪烁的例子。程序启动时候的样子如下图:程序启动界面:打开main.cof文件工程文件存为main_cof.aps方便下次打开 选择相关硬件配置(端口的选择参见下图) 使用JTAG&SIP默认会是COM3。端口的选择(说明:这个画面可以在:右击我的电脑>-管理>-设备管理器里面找到。)端口频率设置 运行程序 直接运行你可以看到红绿灯闪动的效果。点击看大图你还可以通过Debug里面的命令进行在线调试。 好了,现在你已经进入AVR的精彩世界了。 三、调试命令的使用调试快捷键,具体可以通过DEBUG菜单项查看,按照相应的指令就可以进行调试操作了。观察窗口的说明:使用以下窗口可以即时查看寄存器,变量,以及数据地址的值,更多内容大家自己摸索吧。 三、I/O 引脚使用(一)、I/O 口引脚配置AVR单片机的每组I/O口都配备有三个8为寄存器,分别是:方向控制寄存器DDRx、数据寄存器PORTx、输入引脚寄存器PINx(x=A/B/C/D).I/O口的工作方式和表现特征由这三个I/O寄存器控制。方向控制寄存器DDRx用于控制I/O口的输入输出方向,及控制I/O口的工作方式为输出方式还是输入方式。DDRx=1时,I/O口处于输出工作方式;此时数据寄存器PORTx中的数据输出到外部引脚。DDRx=0时,I/O口处于输入工作方式;此时输入引脚寄存器PINx中的数据就是外部引脚的实际电平,通过读I/O指令可将物理引脚的真实数据读入MCU。此外,当I/O口定义为输入时(DDRx=0),通过PORTx的控制,可使用或不使用内部的上拉电阻。I/O 口引脚配置表AVR I/O 口引脚配置表DDRXn PORTXn PUD I/O 方式 内部上拉电阻 引脚状态说明 0 0 X 输入 无效 三态(高阻) 0 1 0 输入 有效 外部引脚拉低时输出电流 (uA) 0 1 1 输入 无效 三态(高阻) 1 0 X 输出 无效 推挽 0 输出,吸收电流 (20mA) 1 1 X 输出 无效 推挽 1 输出,输出电流 (20mA) (二)、I/O 口的输出操作让发光二极管闪动任务:通过AVR端口,控制发光二极管,在制定时间内进行亮、灭状态转换。知识点:AVR端口的输出设置、延时库函数使用(一)、电路SIP8接I/O 口,输出高电平时,发光二极管处于灭状态;输出低电平时,发光二极管处于亮状态。在每个状态之间,插入延时,可以轻松实现让发光二极管闪动的效果。虽然AVR的I/O口单独输出“1”时,可输出较大电流足已点亮一LED,但AVR总的I/O输出毕竟是有限的,所以,可将AVR的I/O口设计为输出“0”时点灯,输出“1”时熄灯。这种接法亦叫“灌电流接法”。 (二)、程序#include<avr/io.h>#include<util/delay.h>int main()DDRD=0xff;PORTD=0xff;while(1) PORTD=0x00; _delay_ms(500.0); PORTD=0xff; _delay_ms(500.0);io.h完成端口的定义,delay.h实现延时。DDRD=0xff设置PORTD为输出口,在死循环while(1)内,PORTD=0x00,点亮二极管,_delay_ms(500.0)延时半秒;再熄灭二极管,延时半秒,如此循环,实现发光二极管闪动的效果。(三)、引脚的输出操作让发光二极管流动任务:通过AVR引脚操作,控制发光二极管,在制定时间内进行亮、灭状态转换。知识点:AV引脚的输出设置,与、或运算的应用(一)、电路让发光二极管流动,一般称为流水灯,电路同前一个试验采用同一个电路。实现方法可以在前一个程序基础上进行简单的改进,将循环体内容改为: PORTD=0x7f; _delay_ms(500.0); PORTD=0xbf; _delay_ms(500.0); PORTD=0xdf; _delay_ms(500.0); PORTD=0xef; _delay_ms(500.0); PORTD=0xf7; _delay_ms(500.0); PORTD=0xfb; _delay_ms(500.0); PORTD=0xfd; _delay_ms(500.0); PORTD=0xfe; _delay_ms(500.0); (二)、程序本例采用引脚操作的方法,利用逻辑操作每次只改变一个引脚的输出值,我们看下面两个操作:PORTD|=(1<<i); (1)PORTD&=(1<<i); (2)式(1)的操作结果仅使PORTD的第i位为1;式(2)的操作结果仅使PORTD的第i位为0。如果改变i值就可以任意改变某位的使。实现流水灯的程序如下:#include<avr/io.h>#include<util/delay.h>int main()DDRD=0xff;PORTD=0xff;unsigned char i;while(1) for(i=0;i<=7;i+) PORTD&=(1<<i); /点亮第i个二极管 _delay_ms(500.0); PORTD|=(1<<i); /熄灭第i个二极管 在死循环while(1)内,i值从0变化为7,每次变化时,PORTD&=(1<<i);点亮第i个二极管,后演示半秒,保持二极管点亮;PORTD|=(1<<i);熄灭第i个二极管,结束本次循环。(四)、引脚的输入操作按键控制发光二极管的亮灭任务:通过AVR引脚接按钮,控制发光二极管的亮、灭状态转换。按下时亮,不按时灭。知识点:AV引脚的输入设置,与运算的应用,按键去抖。(一)、电路按键是基本方便的输入手段,在本例中,通过介绍利用按键开关控制发光二极管的亮灭来了解AVR单片机的端口检测外部信号的功能和方法。1、单按键的电路典型的单按键的电路如图71所示,在按键没有按下时,PA5引脚信号为高电平,当按键按下时PA5引脚信号为低电平。通过检测引脚的电平会方便的知道按键的状态。图71 按键电路我们日常所说的按键,外观如图72所示,有四个脚。按键两侧的脚是连通的,之所以做成四个脚,是为了安装牢固。图72 按键开关2、按键的响应过程理想的按键的闭合和断开时,接触点的电压应该立即变高或者变低,但是由于机械触点的弹性以及按键按动时电压突变等原因,在触点闭合或断开的瞬间会出现电压抖动现象,如图72所示。在发生抖动的时间一般在5-10ms。一次按键处理过程如下:当按键按下之后,相应的按键接触点的电压以高低电平的方式输入到单片机的I/O口。按键的闭合与断开是有一定时间的,一般为0.1-1S。而AVR单片机的机器周期一般为1us甚至更短,在0.1-1S的时间段内,程序会检测很多次按键的输入电平,这样单片机可能会认为按键被按下了多次,从而出现误判。 图73 按键闭合断开时的电压波动示意图3、按键去抖动的方法和原理为了去除按键的抖动,保证单片机对按键的一次输入只响应一次,可以采用硬件和软件两种方法:硬件电路去抖动是在外围电路中加入去抖动电路(如R-S触发器);软件去抖动是在程序中加入延时程序以跳过抖动时间,等待信号稳定后再次判断按键的输入电平,如果信号电平保持不变,则可以确认一次按键按下。硬件去抖动电路的原理用R-S触发器形成去抖电路是单片机外围电路设计中常用的方法,这种方法可以减少单片机软件对按键动作的延时和计算。典型的硬件去抖动电路如图74,74LS02构成一个R-S触发器电路实现按键的消抖电路。 图74 74LS02实现的硬件消抖电路软件消抖的原理和实现软件消抖的基本原理是在软件中对按键进行两次检测确认,记载第一次检测到按键按下后,间隔10ms左右再次检测按键是否按下,只有在两次都检测到按键按下时才最终确认有键按下,这样就避开了按键的抖动时间,从而消除了抖动的影响。 在按键接口软件的设计中,除了要考虑按键消抖外,一般还要判别按键的释放,只有检测到按键释放后,才能确定为一次完整的按键动作。通用的案件检测程序如下:1. Keyscan()2. 3. if(PINA&0X20)=0) /判断按键是否按下,等于0表示按键按下4. 5. delayms(20); /延时20ms。避开按键抖动时间6. if(PINA&0X20)=0) /再次判断按键是否按下,7. 8. /按键按下的处理程序9. 10. 11. While(PINA&0X20)=0); /判断按键是否放开,不等于表示按键释放,退出处理函数12. (二)、程序程序通过检测连接在PA5引脚上按键状态,控制连接PD口的八个二极管的亮灭。按键按下时二极管处于亮的状态,按键抬起,二极管处于熄灭的状态。1. #include<avr/io.h>2. #include<util/delay.h>3. int main()4. 5. DDRD=0xff;6. PORTD=0xff;7. DDRA=0x00;8. PORTA=0x0;9. unsigned char i;10. while(1)11. 12. if(PINA&0X20)=0) /判断按键是否按下,等于0表示按键按下13. 14. _delay_ms(20); /延时20ms。避开按键抖动时间15. if(PINA&0X20)=0) /再次判断按键是否按下,16. 17. PORTD=0X0;18. while(PINA&0X20)=0); /判断按键是否放开,不等于表示按键释放,退出处理函数19. 20. 21. PORTD=0Xff;22. 23. 四、键盘(一)、矩阵键盘1波峰法任务:构造矩阵键盘,识别按键,并将按键值在数码管上显示。知识点:非运算的应用,按键去抖,矩阵键盘结构及识别程序演变。(一)、电路矩阵键盘是输入数字的最简介的方式,4X4矩阵键盘有16个键,满足10个数字和其他字符输入的需要。电路结果如下图。电路下方的数码管是为学习方便而放置的,输入BCD码给数码管就会看到对应的数字,使用起来很方便,但这种数码管没有实际的产品和实物,仅是为仿真方便而构造的理想数码管。这两个数码管负责显示各种输出。 (二)、程序1、某行按键的识别 下面程序仅可以识别第一行的四个键的按下,并分别显示0、1、2、3。程序执行PORTA =0x7f后,PA7为低电平,其他为高电平,如果第一个键按下,PINA的电平是0X77,执行temp = PINA&0X0f后,temp等于0X7。如果第二个键按下,temp等于0Xb。如果第一个键按下,temp等于0Xd。如果第一个键按下,temp等于0Xe。具体代码如下:1. #include<avr/io.h>2. #include<util/delay.h>3. unsigned char keyscan();4. int main()5. 6. unsigned char keyv;7. DDRB=0xff;8. PORTB=0x00;9. while(1)10. 11. keyv=keyscan();12. PORTB=keyv;13. 14. 15. unsigned char keyscan()16. 17. unsigned char keycode,temp;18. DDRA=0xf0;/高四位输出,低四位输入19. PORTA=0x00;20. keycode=0x10;21. PORTA=0x7f;/第一行为低电平,其他为高电平22. temp=PINA&0X0f;/只看低四位值23. if(temp!=0x0f) /判断按键是否按下,等于0表示按键按下24. 25. _delay_ms(20); /延时20ms。避开按键抖动时间26. temp=PINA&0X0f;27. if(temp!=0x0f)28. 29. switch(temp)30. 31. case 0x0e: keycode=3;break;32. case 0x0d: keycode=2;break;33. case 0x0b: keycode=1;break;34. case 0x07: keycode=0;break;35. 36. 37. 38. return keycode;39. 程序中语句PORTA=0x7f负责选择识别那行的按键,如果将0x7f改为0xbf、0xdf或0xef。高四位为零十对应的行,就是要识别那行的按键,试试对吗?2、全部按键的识别在上面程序基础上进行简单修改,可以得到识别全部按键的程序。将2137行重复三次,每次将21行赋值修改对应的0xbf、0xdf或0xef,再将3134指定为想要的键值。采用此方案最大的缺点是程序太长。为了进行优化要对子程序keyscan()做部分修改,具体如下:1. unsigned char keyscan()2. 3. unsigned char keycode,temp,line;4. DDRA=0xf0;/高四位输出,低四位输入5. PORTA=0x00;6. keycode=0x10;7. line=0x80;8. PORTA=line;/第一行为低电平,其他为高电平9. temp=PINA&0X0f;/只看低四位值10. if(temp!=0x0f) /判断按键是否按下,等于0表示按键按下11. 12. _delay_ms(20); /延时20ms。避开按键抖动时间13. temp=PINA&0X0f;14. if(temp!=0x0f)15. 16. switch(temp)17. 18. case 0x0e: keycode=3;break;19. case 0x0d: keycode=2;break;20. case 0x0b: keycode=1;break;21. case 0x07: keycode=0;break;22. 23. 24. 25. return keycode;26. 第7行取0X40、0X20、0X10可以识别其他行按键。上面子程序仍很长,可以再进行优化,代码如下:1. unsigned char keyscan()2. 3. unsigned char keycode,temp,line,lcode;4. DDRA=0xf0;/高四位输出,低四位输入5. PORTA=0x00;6. keycode=0x10;7. for(line=0;line<=3;line+)8. 9. lcode=(0x80>>line);10. PORTA=lcode;/第一行为低电平,其他为高电平11. temp=PINA&0X0f;/只看低四位值12. if(temp!=0x0f) /判断按键是否按下,等于0表示按键按下13. 14. _delay_ms(20); /延时20ms。避开按键抖动时间15. temp=PINA&0X0f;16. if(temp!=0x0f)17. 18. switch(temp)19. 20. case 0x0e: keycode=3+line*4;break;21. case 0x0d: keycode=2+line*4;break;22. case 0x0b: keycode=1+line*4;break;23. case 0x07: keycode=0+line*4;break;24. 25. 26. 27. 28. return keycode;29. 最后得到的子程序较短,可以作为最终优化结果。我们采用的方法也称为扫描法,那行为零,就检测这行是否有键按下,零值一行一行反复,就像水的波浪一样,故也称为波峰法。波峰法的优点是:好理解,缺点是:如果行很多,扫描时间会拉长,浪费机时。解决方法是采用翻转法,请见下一部分。(三)、作业1、如果采用列扫描,重新书写程序。2、如果矩阵键盘的行线接PC03或PC47,重新书写程序。3、如果2X4矩阵键盘,自己设计它们的接线,并书写对应按键识别程序。(二)、矩阵键盘2翻转法任务:构造矩阵键盘,识别按键,并将按键值在数码管上显示。知识点:与运算的应用,按键去抖,矩阵键盘翻转法编程。(一)、电路翻转法的电路结构同波峰法完全一致,区别只是如何识别按键。(二)、程序翻转法的键盘识别程序法分为两部分:scan_key和key_num。scan_key是翻转法的主体,scan_key将矩阵键盘按下的位置变成数,既2843行case后数,可以称这些数为扫描码,如果没有键按下变成的数是0XFF。key_num将扫描码变成需要的键码,本例键码为015。1. unsigned char scan_key(void) 2. 3. unsigned char i; 4. PORTA=0x00; 5. DDRA =0xf0; /设置端口高4位输出,低四位输入 6. PORTA=0x0f;/低四位内部上拉 7. _delay_ms(1);/短暂延时 8. i=PINA&0x0f;/读取端口电平 9. if(i!=0x0f)/判断是否有键按下 10. 11. PORTA=0x00; 12. DDRA =0x0f;/设置端口低4位输出,高四位输入 13. PORTA=0xf0;/高四位内部上拉 14. _delay_ms(6);/短暂延时,去抖 15. if(PINA&0xf0)!=0xf0)/再次判断是否有键按下 16. 17. i+=(PINA&0xf0);/读取端口电平 18. while(PINA&0xf0)!=0xf0);/等待按键释放 19. return i;/返回键值 20. 21. 22. return 0xff; /无按键按下返回null 23. 24. unsigned char key_num(unsigned char key) 25. 26. switch(key) 27. 28. case 0xe7:return 0; /按键0 29. case 0xd7:return 1;/按键1 30. case 0xb7:return 2;/按键2 31. case 0x77:return 3;/按键3 32. case 0xeb:return 4;/按键4 33. case 0xdb:return 5;/按键5 34. case 0xbb:return 6;/按键6 35. case 0x7b:return 7;/按键7 36. case 0xed:return 8;/按键8 37. case 0xdd:return 9;/按键9 38. case 0xbd:return 10;/按键A 39. case 0x7d:return 11;/按键B 40. case 0xee:return 12;/按键C 41. case 0xde:return 13;/按键D 42. case 0xbe:return 14;/按键E 43. case 0x7e:return 15;/按键F 44. default: return 16;/无按键按下 45. 46. 翻转法的48行获得按键的行值,1117行获得按键的列值,按键的行、列值为零表示对应位置按键被按下,如0xe7对应二进制为1110 0111,高四位有一个0,低四位一个0,按照接线可以确定按键的位置。通过key_num中return语句可以灵活改变按键代表的键值。(三)、作业1、如果矩阵键盘的行线接PC03或PC47,重新书写程序。五、数字的显示(一)、单数字的显示任务:通过数码管循环显示数字09。知识点:数码管结构、显示驱动,flashrom区数据操作。(一)、数码管及电路1、数码管的外观 图101、数码管的外观 图102、5011系列数码管的引脚排列一个“8”字型的显示模块用“a、b、c、d、e、f、g、dp” 8 个发光二极管组合而成。每个发光二极管称为一字段。其内部电原理图如图103、104,分别是共阴极和共阳极LED数码管两种结构形式。 图103、共阴极数码管 图104、共阳极数码管以共阴极数码管为例,由图中可以看出:如果要点亮数码管的某一段,只需将该段加上高电平,然后使数码管的公共端3、8脚为低电平,那么该段就会点亮。2、单个数码管的电路连接 单个数码管的电路连接可以直接同AVR单片机的某个口连接。在图105中,PC0接A段对应引脚,PC1接B段对应引脚, PC7接dp段对应引脚,采用的是共阳极数码管。图105单个数码管的电路连接为了获得“0”“9”10 个不同的数字,数码管各段所加的也电平不同,因此首先要建立一个字型与字段的编码表,见表101。 端口段字型PC7dpPC6gPC5fPC4ePC3dPC2cPC1bPC0aPC值0110000000xc01111110010xf92101001000xa43101100000xb04100110010x995100100100x926100000100x827111110000xf88100000000x809100110000x98(二)、程序1、单数字的显示单数字的显示通过PC端口输出数字对应字段的编码,在数码管上就可显示对应数字。程序如下:1. #include<avr/io.h>2. #include<util/delay.h>3. unsigned char seg=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98,i;4. int main()5. 6. DDRC=0xff;7. PORTC=0xff;8. while(1)9. 10. for(i=0;i<=9;i+)11. 12. PORTC=segi;13. _delay_ms(2000.0);14. 15. 16. 程序的关键是字形编码的书写,不同的字形编码会得到不同的符号。在字形编码众多时,字形编码会占用大量的内存空间,字形编码这类数据的特点是:我们只需要读取它们的内容,而不会修改其内容,即只进行读操作不进行写操作。这种特点的数据,可以看成常数,对于常数可以保存在程序区。2、字形数据保存在Flash我们首先观察前面程序的Build OutPut区的提示信息:Program: 3546 bytes (21.6% Full) 表示程序占用3546字节的flash rom。Data: 19 bytes (1.9% Full) 表示程序占用19字节的ram。将数据保存在程序区的程序如下:1. #include<avr/io.h>2. #include<util/delay.h>3. #include<avr/pgmspace.h>4. const prog_uchar seg=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98;5. unsigned char i;6. int main()7. 8. DDRC=0xff;9. PORTC=0xff;10. while(1)11. 12. for(i=0;i<=9;i+)13. 14. PORTC=pgm_read_byte(seg+i);15. _delay_ms(2000.0);16. 17. 18. 我们再观察此程序的Build OutPut区的提示信息:flash rom区占用空间多了10个字节,而Ram区的占用空间少了10个字节。说明字形数组seg被保存在flash rom区。要将数据保存在flash rom区,先添加头文件avr/pgmspace.h;在数组前加const prog_uchar,在读数组内容时用函数pgm_read_byte读取。pgm_read_byte参数是数组的首地址加上数据的偏移量。prog_char、prog_uchar 分别指定在FLASH内的8 位有符号整数和8 位无符号整数。(二)、数字的显示多数字动态显示任务:通过数码管实现多数字的显示。知识点:显示时间分配。