1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,任务一 认识单片机C语言,一、,C语言特点,目前单片机C语言已非常流行,绝大部分单片机应用系统可直接用C语言来编写,与汇编语言相比,用C语言开发单片机具有如下特点:,1、开发速度优于汇编语言;,2、软件的可读性和可维护性显著改善;,3、提供了库函数包含许多标准子程序,具有较强的数据处理能力;,4、关键字及控制转移方式更接近人的思维方式;,5、方便进行多人联合开发,进行模块化软件设计;,6、C语言本身并不依赖于机器硬件系统,移植方便;,7、适合运行嵌入式实时操作系统。,二、C51的数据类型,我们用变量去描述
2、一个现实中的数据时,应根据需要选择变量类型。对于C51来讲,不管采用哪一种数据类型,虽然源程序看起来是一样的,但最终形成目标代码的长度和运行速度相差非常大。,三、C51的数据存储类型与8051存储器结构,MCS-51系列单片机将程序存储器(ROM)和数据存储器(RAM)分开,并有各自的寻址机构和寻址方式。8051单片机在物理上有四个存储空间:,片内程序存储器空间:0000H-0FFFH,片外程序存储器空间:1000H-FFFFH(/EA=1),0000H-FFFFH(/EA=0),片内数据存储器空间:,00H-1FH:通用工作寄存器区,20H-2FH:位寻址空间,30H-7FH:用户RAM区,
3、80H-FFH:特殊功能寄存器区/间接寻址区,片外数据存储器空间:0000H-FFFFH,C51中变量定义的格式,:,数据类型 存储类型 变量名1,变量名2,变量名n,;,例:,char data temp;,bit bdata flags;,uchar bdata speed;,uchar idata len;,uchar code seg=0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d;,如果变量定义时省去存储类型说明,编译时会自动选择默认的存储类型,而默认的存储类型由存储模式确定。在C51中有SMALL、COMPACT、LARGE三种存储模式,在KEI
4、L环境中,可以通过目标工具选项设置选择所需的存储模式。,四、定义8051特殊功能寄存器及I/O口,1、定义8051特殊功能寄存器,(1)、对特殊功能寄存器的访问,sfr SFR名=SFR地址;,例:sfr TMOD=0 x89;,(2)、对于SFR的16位数据的访问,sfr16 16位SFR名=低8位SFR地址;,例:sfr16 DPTR=0 x82;,(3)、SFR中的某位进行访问,sbit SFR位名=SFR名i;,例:,sbit TR0=TCON4;,sbit SFR位名 =SFR地址i;,例:sbit TR0=0 x884;,sbit SFR位名 =位地址;,例:sbit TR0=0
5、x8C;,(4)、可位寻址对象的定义,可位寻址对象指既可以字节寻址,又可位寻址的对象,位于片内RAM的20H2FH中。,一般先定义变量的数据类型,数据类型可以是字符型、整型、长整型等,其存储器类型必须定义为bdata,然后使用sbit定义该变量中可单独寻址访问的位。,例:,char bdata state;,sbit state_7=state 7;,main(),state=5;,state_7=1;,2、定义8051并行接口,(1)、片内并行口的定义,8051单片机带有4个8位并行口,即SFR中的P0、P1、P2、P3口,对它的定义在reg51.h已存在,可直接对其引用。,例:P2=0 x
6、FE;,Key=P1;,如果要单独对某位进行操作,可在程序的开头加上位寄存器定义。,例如:sbit P1_0=P10;,在随后的程序中即可对这些位进行访问。,例如:while(P1_0=1);,(2)、定义片外并行口,对于MCS-51单片机外扩展的I/O口,例8255、8155等,则根据其硬件译码地址,将其视为片外数据存储器的一个单元,使用#define 语句定义格式:,#define I/O口名称 XBYTEI/O口地址,其中,XBYTE表示绝对存储器访问的宏,在文件absacc.h中定义,方括号中中是存储器的绝对地址。在使用这种格式定义之前,应加上语句:,#include,例如:在系统中扩
7、充的USB接口芯片,其命令口地址为0 xBDF1,数据口地址为0 xBDF0,可以这样定义:,#include,#define CMDPORT XBYTE0 xBDF1,#define DATPORT XBYTE0 xBDF0,五、认识C51的内部函数及常用的宏,C51运行库提供了100多个预定义函数和宏,用户可以在自己的C程序中使用这些函数和宏,。,1、内部函数,c51编译器支持许多内部库函数,内部函数产生的在线嵌入代码与调用函数产生的代码相比,执行速度快,效率高。常用的内部函数如下:,_crol_(v,n):将无符号字符变量v循环左移n位.,_cror_(v,n):将无符号字符变量v循环右
8、移n位.,_irol_(v,n):将无符号整型变量v循环左移n位.,_iror_(v,n):将无符号整型变量v循环右移n位.,_nop_():延时一个机器周期,相当于NOP指,令。,2、绝对存储器访问宏,C51标准库包含了可以访问显式存储地址的宏,可以像使用数组一样使用这些宏:,1、CBYTE,允许用户访问程序存储器中指定地址单元。例:id=CBYTE0X200;,2、XBYTE,允许用户访问外部数据存储器中指定地址单元。例:XBYTE0X100=d;,3、DBYTE,允许用户访问片内数据存储器中指定地址单元。,以上宏在ABSACC.H文件中定义,为了使用这些宏,必须在程序开始时加上:,#in
9、clude,任务二、P0P3口应用举例,1、硬件电路,案例1 设计一电路,监视开关S0-S3的状态,当某开关闭合时,对应的发光二极管点亮,如开关断开时,发光二极管熄灭。,P0口作为输出口,P1口作为输入口,for(i=0;i200;i+),state_7=1;,K14按下,修改当前速度等级,为此需进行去抖动处理。,二、MCS-51单片机的中断系统(一)中断源,动态显示方式是应用最为广泛的一种显示方式,其接口电路是把所有数码管的8个字段ag、dp的同名端并联在一起,由一个8位的字段输出口控制;,while(S1=0),delay(100);,当CPU正在执行某段程序时,外部发生了某一事件请求CP
10、U迅速去处理,于是CPU暂时中断当前程序的执行,转去处理发生的事件,处理完成后,再回到原来被中断的地方,继续执行被中断的程序,这一过程称为中断。,using m:定义中断函数使用的工作寄存器组,m的取值范围为0-3,可以默认。,void disp(void),延时由speed指定的时间,从表面上看,主程序和中断服务程序似乎没有关系,当按下PLUSE键时,将产生中断请求,由于中断号为0,当前中断又是开放的,CPU自动会找到属性为“interrupt 0”的函数运行,即进入外部中断0的服务程序,将变量dir(设进入中断前取值为0)取反,当CPU回到主程序再次检测dir时,其值已变为1,D1-D8因
11、此开始左移。,1、定义8051特殊功能寄存器,for(m=0;m200;m+),2、设计思想,将开关S0-S3接在P1.0-P1.3引脚,当某个开关Si接通时,对应的引脚P1.i为低电平,如果我们向P0.i引脚输出低电平,发光二极管Di就能被点亮;当开关Ki断开时,由于P1口内部具有上拉电阻,对应引脚P1.i为高电平,如果我们向P0.i引脚输出高电平,发光二极管Di熄灭。,因此我们只要读取P1口低四位的状态并传送给P0口即可。,3、程序清单,#include,sbit P10=P10;,sbit P03=P03;,void main(void),P1=P1|0 x0f;,while(1),P0
12、0=P10;,P01=P11;,P02=P12;,P03=P13;,定义所用的I/O口引脚,将P1口置1,作输入口使用,案例2 如图所示,由P0口控制发光二极管D1-D8,首先点亮D1,延时0.5秒后,熄灭D1点亮D2,到D8点亮并熄灭后,再点亮D1,这样不断循环。,2、程序清单,#include,#include,#define uchar unsigned char,void delay(uchar n),void main(void),uchar led=0 xfe;,while(1),P0=led;,delay(100);,led=_crol_(led,1);,延时程序,n:入口参数,
13、单位:2毫秒左右。,首先点亮LED1。,将led左循环移位一次。,延时。,led送P0口。,案例3如图所示,用P1.0输出1KHz和500Hz的音频信号驱动扬声器,作为报警信号,要求1KHz的信号响100ms,500Hz的信号响200ms,两种信号交替产生,P1.1接一个控制开关,当开关合上时产生报警,当开关断开时停止报警。,1、,设计思想,500Hz的信号周期为2ms,信号电平为每1ms变反一次;1KHz的信号周期为1ms,信号电平为500us取反一次。,因此只要编写一个延时程序,当入口参数n=1时,延时时间为500us,n=2时,延时时间为1000us。每次调用延时函数后就对P1.0求反,
14、即可产生频率为1KHz或500Hz的方波。以上过程连续循环200次,就能使1KHz的声音持续100ms,500Hz的声音持续200ms。,2、程序清单,sbit S1=P11;,sbit SPK=P10;,void main(void),uchar m,n;,S1=1;,while(1),while(S1=0),for(n=1;n=2;n+),for(m=0;m200;m+),delay(n);,SPK=SPK;,S1控制是否产生报警声,用来产生方波,只有S1接通时,才产生报警,n=1:1KHz;n=2:500Hz,循环200次,,,延时500us或1ms,,,P1.0求反,产生方波,,案例4
15、 设计一个流水灯控制器,发光管的变化方式、变化速度各有四档,可用按钮K13、K14进行选择。,1、,设计思想,如图所示,开关K13、K14分别接到P2.4、P2.5引脚,当有键被按下时,对应引脚为低电平,按键释放时,又恢复为高电平,因此通过检测该引脚电平的高低就能判别当前是否有键被按下。,根据要求,我们可以设计如表2-4所示四种方式的控制字。变量mode用来选择当前的工作方式,其值在0-3之间,受按钮K13控制;变量i用来记录当前的输出位置,其值在0-7之间,每次输出后自动指向下一位置。,为了控制发光管移动速度,我们定义一个表示速度等级的变量speed,取值范围在0-3之间,受按钮K14控制。
16、2、程序清单,void main(void),uchar i=0;,uchar mode=0;,uchar speed=0;,while(1),for(i=0;i8;i+),P0=tabmodei;,if(K13=0),mode=mode+;,mode=mode,else if(K14=0),speed=speed+;,speed=speed,delay(50+speed*50);,通电后的默认方式为0、,默认速度等级0,每种方式有8个控制字,从当前模式中取控制字输出,K13按下,修改当前工作模式,K14按下,修改当前速度等级,延时由speed指定的时间,任务五 认识MCS-51单片机的中断
17、系统,一、中断的概念,当CPU正在执行某段程序时,外部发生了某一事件请求CPU迅速去处理,于是CPU暂时中断当前程序的执行,转去处理发生的事件,处理完成后,再回到原来被中断的地方,继续执行被中断的程序,这一过程称为中断。,在中断系统中,把引起中断的设备或事件称为,中断源,;,由中断源向CPU发出的中断请求称为,中断请求信号,;,CPU接收中断请求而暂停现行程序的执行,转去为服务,对象服务称为,中断响应,;,为服务对象服务的程序称为,中断服务程序,;,现行程序暂停时的PC值称为,断点,;,从中断服务程序返回到断点处称为,中断返回,;,当有多个中断源同时向CPU申请中断时,CPU优先响应最,紧急的
18、中断请求,处理完毕再响应优先级别较低的中断,请求,这种预先安排的响应次序称为,中断优先级,。,1、,使CPU的工作效率大为提高,CPU和外部设备通过中断方式交换信息,可以避免不必要的等待和查询,CPU可启动多个外设与它并行工作,对各个外设实行统一管理,分时服务,从而大大提高了CPU的工作效率。,计算机采用中断技术后的优点,2、增强了实时控制及应急处理能力,在实时控制系统中,被控制对象的参数变化必须 及时采集、处理,并转化为相应的控制动作,对系统进行调节;数据的越限、系统的故障信息也必须被计算机及时发现,以便报警。有了中断功能后,系统的失常和故障都可通过中断立刻通知CPU,使它能够迅速采集实时数
19、据和故障信息,并对系统做出应急处理。,二、MCS-51单片机的中断系统,(一)中断源,MCS-51系列单片机中,基本型8XX51有5个中断源,增强型8XX52有6个中断源,它们在程序存储器中各有固定的中断服务程序入口地址(又称中断向量地址),当CPU响应中断时,硬件自动形成各自的入口地址,由此进入中断服务程序,从而实现正确的转移。,(二)中断控制寄存器,1、中断的允许和禁止中断控制寄存器IE,8XX51/52的每个中断源对应于IE寄存器的一位,如果允许该中断源中断,则该位置1,禁止该中断源中断,则该位清0。另外还有一位CPU是否响应中断的总控位。,ES:串行口中断允许位,ES=1,允许;ES=
20、0,禁止。,ET0/ET1/ET2:定时器中断允许位,为1,允许;为0,禁止。,EX0/EX1:外部中断允许位,为1,允许;为0,禁止。,EA:中断总控开关。EA=1,CPU开中断;EA=0,CPU关中断。,2、,中断请求标志及外部中断方式选择寄存器TCON,TF1、TF0、IE1、IE0分别为中断源T1、T0、/INT1、/INT0的中断请求标志,如果中断源有中断请求,相应的中断标志置1;没有中断请求,相应标志位为0。,IT0、IT1分别为外部中断/INT0、/INT1的中断触发方式选择,如果选择下降沿触发IT应设置为1;如果选择低电平触发,IT应设置为0。,TR1、TR0为定时器T1、T0
21、工作的启动和停止位,与中断无关,请参阅项目三,。,3、中断优先级管理寄存器IP,8XX51/52中断源优先级由IP寄存器管理,一个中断源对应一位,如果对应位置1,该中断源为高优先级;如果对应位为0,则为低优先级。,当某一时刻有多个中断源提出中断请求时,CPU首先响应高优先级的请求;一个低优先级的中断可能被高优先级的中断所中断,但不能被另一个低优先级的中断所中断。一个高优先级的中断不能被其他中断所中断。,当某几个中断源在IP寄存器中的相应位同为1或同为0时,CPU的查询顺序为:,/INT0定时器T0/INT1定时器T1串行口定时器T2,(三)中断的响应过程,单片机在每个机器周期顺序采样每个中断源
22、在下一个机器周期按优先级顺序检测中断标志,如果发现某个中断标志为1,将在接下来的机器周期按优先级进行处理。中断系统通过硬件自动将当前的PC值压入堆栈,以保护断点,再将相应的中断服务程序的入口地址装入PC,使CPU转到中断服务程序的入口处开始执行程序。,中断服务程序从向量地址开始,一直到返回指令RETI为止,RETI指令一方面告诉中断系统该中断服务程序已执行完毕,另一方面把压入堆栈的断点地址从堆栈中弹出,装入程序计数器PC,使程序返回到被中断的程序的断点处继续执行。,(四)中断程序的设计,用户对中断的控制和管理,实际是围绕寄存器IE、TCON、IP、SCON进行的,这几个寄存器在单片机复位时是
23、清零的,因此必须根据需要对这几个寄存器的相关位进行设置。,编写中断服务程序时应注意,:,(1)开中断总控开关EA,置位中断源的中断允许位;,(2)根据外部中断请求信号/INT0、/INT1的特性选择,中断触发方式,是低电平触发还是下降沿触发;,(3)如果有多个中断源中断,应设置中断优先级,预,置IP。,使用C51可以编写出高效的中断服务程序,中断服务程序定义为函数,函数的定义如下:,void 函数名(void),interrupt n,using m,其中,,interrupt n,表示将函数声明为中断服务函数,n为中断号,通常取以下值:,0:外中断0 1:定时/计数器T0中断,2:外中断 3
24、定时/计数器T1中断,4:串行口发送与接收中断,5:定时/计数器T2中断,using m:,定义中断函数使用的工作寄存器组,m的取值范围为0-3,可以默认。它对目标代码的影响是:函数的入口处将切换到m指定的寄存器组,函数退出时,原寄存器组恢复,选不同的工作寄存器组,可方便实现寄存器组的现场保护。,案例1 如图所示,P0口控制发光二极管D1D8每隔一段时间左移或右移一位,当单脉冲按钮PLUSE按下时,单脉冲电路将产生一个负脉冲作为中断请求信号,控制发光二极管的移动方向。,void main(void),uchar led;,EX0=1;,IT0=1;,EA=1;,led=0 xfe;,whil
25、e(1),P0=led;,delay(250);,if(dir)led=_crol_(led,1);,else,led=_cror_(led,1);,void chdir(void)interrupt 0,dir=dir;,允许外部中断0中断,负跳变触发,CPU开中断,如果dir标志为1,左移,否则右移,外部中断0服务程序,每次中断,将方向标志求反,从表面上看,主程序和中断服务程序似乎没有关系,当按下PLUSE键时,将产生中断请求,由于中断号为0,当前中断又是开放的,CPU自动会找到属性为“interrupt 0”的函数运行,即进入外部中断0的服务程序,将变量dir(设进入中断前取值为0)取反
26、当CPU回到主程序再次检测dir时,其值已变为1,D1-D8因此开始左移。,任务六 设计动态LED显示器,一、认识LED显示器,在单片机应用系统中,常用的显示器主要有LED数码管显示器及LCD液晶显示器。LED显示器由于亮度高、价格低、寿命长、对电流、电压要求低,与单片机的连接方便等优点,得到了非常广泛的应用。,LED显示器由7个条形发光二极管及一个小圆点发光二极管组成,每个发光二极管又称为字段,根据各字段的亮暗组合成相应的字符。,根据内部的连接方式可分成共阳极型和共阴极型。,共阴极LED数码管的阴极连在一起接地,当某个发光二极管的阳极为高电平时,对应字段被点亮。,共阳极LED数码管的阳极连
27、在一起,接正电压,当某个发光二极管的阴极为低电平时,该二极管所表示的字段被点亮。,数码管不同的亮暗组合就能形成不同的字形,这种组合称之为字形码,共阳极和共阴极的字形码是不同的,对应的字形码如表2-7所示。,二、动态显示方式,动态显示方式是应用最为广泛的一种显示方式,其接口电路是把所有数码管的8个字段ag、dp的同名端并联在一起,由一个8位的字段输出口控制;而每一个数码管的公共极(位选线)各自独立地受位选口控制,实现各位的分时点亮。,案例2 在4位动态LED显示器上显示“1234”,想要在显示屏上显示1234,可先通过P0口送出“4”的字形码0 x99,并向P2.3P2.0引脚送出1110B,使
28、三极管Q1导通,从而在最右侧的共阳数码管LED1上显示“4”,然后向P0口送出“3”的字形码0 xb0,并向P2.3P2.0引脚送出1101B,将数字“3”显示在LED2上,依次类推,“2”、“1”可分别显示在LED3、LED4上。,由此可知,每次只有一个数码管被点亮,但由于人眼有视觉暂留现象,只要以较快的速度令4个数码管依次轮流点亮,看起来会觉得4个数码管同时被点亮了,这种显示方法称为动态扫描显示法。,uchar code segtab=,0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90,0 x88,0 x83,0 xc6
29、0 xa1,0 x86,0 x8e,0 x89,0 x8c;,uchar dbuf4=4,3,2,1;,void disp(void),uchar n,bsel;,bsel=0 xfe;,for(n=0;n4;n+),P2=bsel;,P0=segtabdbufn;,bsel=_crol_(bsel,1);,delay();,P0=0 xff;,字符0F的字形码表,显示缓存,存放要显示的字符,首先点亮最低位,bsel送位选口,根据显示缓冲单元的数据查出字形码,准备显示下一位,延时1ms,熄灭数码管,任务七 电子计数器的设计,设计一个计数器,其计数范围为-999,+999,通电后4位LED显示
30、000,如果K13键按下,计数器加1,K14键按下,计数器减1。,上图中的按键为机械弹性开关,由于机械触点的弹性及电压突跳等原因,在触点闭合或断开的瞬间,会出现电压抖动,如下图所示。,为了保证按键识别的正确、可靠,在电压信号抖动的情况下不能认为按键已闭合。为此需进行去抖动处理。去抖动有硬件与软件两种方法。,硬件去抖动,就是加去抖动电路,从根本上避免抖动的产生;,软件去抖动,则采用时间延迟以躲过抖动阶段,等信号稳定后再进行检测。,为了简化设计、降低成本,单片机应用系统一般采用软件方法。程序一旦检测到按键输入端口为低电平,随即延时10ms-20ms左右,避开抖动阶段,再检测输入端口是否仍然为低电平
31、如果为高,则认为无键被按下,否则说明有键按下,进一步判断是哪一个键被按下,并作相应的处理。,电子计数器的流程图,void main(void),uchar i;,int count=0;,unsigned int t;,while(1),disp();,if(P2&0 x30)!=0 x30),for(i=0;i999)count=-999;,else count-;,if(count=0)dbuf3=0 x10;,t=count;,else dbuf3=0 x11;,t=-count;,dbuf2=t/100;,dbuf1=(t%100)/10;,dbuf0=t%10;,while(P2,
32、如果计数值大于等于0,最高位+号不显示,最高位显示-,求出计数值的绝对值,将计数值转换成三位BCD码送显示缓存,等待按键释放,如果计数值小于0,2、抢答器的软件设计,系统上电后,首先完成初始化,在数码管上显示P,然后等待PLUSE的按下,PLUSE按下后,数码管显示0,并等待K13-K16的按下,只要P2.4-P2.7有一个引脚为低电平,则逐位扫描出按键的键号,送数码管显示,同时控制蜂鸣器发出500ms的提示音,然后再等待PLUSE按下,重新开始下一轮抢答。,void main(void),uchar key;,uchar i;,P2=P2|0 xf0;,P2=P2,P0=segtab0 x1
33、0;,start=0;,EX0=1;,IT0=1;,EA=1;,P2口高四位置1,设置为输入方式,允许最低位数码管显示,数码管显示P,当前PLUSE键按下标志清0,允许外部中断0中断,触发方式为负跳变,单片机开中断,while(1),while(start=0);,start=0;,P0=segtab0;,while(P2,key=P2,for(i=1;i1;,P0=segtabi;,for(i=0;i200;i+),delay();,SPK=SPK;,等待按下PLUSE键,start标志清0,为下次抢答作准备,按下PLUSE键后,数码管显示0,等待K13K15抢答键按下,读取P2口高四位的状
34、态,逐位检测所按键的键号,数码管显示按键的键号,产生100个周期为2ms左右的方波,延时1ms,产生方波,void int0(void)interrupt 0 /中断函数,start=1;/start标志置1,3、调试方法与步骤,编译后进入调试方式全速运行程序,如果不能实现抢答器的预定功能,可按以下步骤检查:,(1)如果运行后数码管无显示或显示的不是P,应检查数码管电路及字形码表及相关程序。,(2)如果数码管显示P后,按下PLUSE键,不能显示0,应检查外部中断初始化程序及中断服务程序是否有问题。,(3)当数码管显示0时,按下K13-K16后显示的键号不对,应检查相关的检测程序。,(4)如果蜂鸣器无提示音产生,应检查产生方波的程序及相关的线路。,






