资源简介 (共17张PPT)实例32 串口控制16个LED流水灯《单片机基础与应用(C语言版)》高等教育出版社实例要求实例分析采用串入并出移位寄存器74LSl64实现单片机串行口的I/O扩展,一片74LS164可以扩展8位并行输出口,系统需要2片74LS164级联实现16个LED的控制。利用单片机串行口扩展并行I/O口电路,驱动16个LED,使16个LED逐一点亮,实现16个LED流水灯效果。硬件电路控制程序设计//程序:ex35.c//功能:串口控制16个LED流水灯程序#include //包含头文件REGX51.H,定义了51单片机的所有SFR//函数名:sendbyte//函数功能:向串口发送一个字符,采用查询方式实现//形式参数:无符号整型变量i,定义发送的字符//返回值:无void sendbyte(unsigned char i){SBUF=i; //发送字符写入SBUFwhile(!TI); //查询TI是否由0变1TI=0; //软件给TI清0}//定义流水灯显示数据unsigned char dat[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};void main(){unsigned char i;unsigned int t;SCON=0x00; //设置串行口工作方式为方式0while(1){for(i=0;i<8;i++){//第2片74LS164连接的8个灯实现流水sendbyte(dat[i]); //发送第2片74LS164连接8个灯显示数据sendbyte(0xff); //第1片74LS164连接8个灯熄灭for(t=0;t<20000;t++); //延时}for(i=0;i<8;i++){//第1片74LS164连接的8个灯实现流水sendbyte(0xff); //第2片74LS164连接8个灯熄灭sendbyte(dat[i]);//第1片74LS164连接8个灯显示数据for(t=0;t<20000;t++); //延时}}}《单片机基础与应用(C语言版)》高等教育出版社实例33 单片机双机通信实例要求实例分析如果2个单片机共在一个电路板上或同处于一个机箱内,这时只要将2个单片机的TXD和RXD引出线交叉相连,并共地即可;如果2个单片机不在一个机箱内,距离较远,这时要采用 RS-232C接口进行连接。本系统假定两机处于一个机箱内。实现一个单片机串行口双机通信测试系统。系统中,发送与接收各用一套51单片机电路,称为甲机和乙机。甲机作为发送端,连接一个按键;乙机作为接收端,连接一个LED。将甲机按键次数(0~9,超过10次后又回到0)发送给乙机,并在乙机的LED上显示出来。硬件电路控制程序设计//程序:ex36.c//功能:甲机串行发送程序#include //包含头文件REGX51.H,定义了51单片机的所有SFRsbit S=P0^0; //定义P0.0引脚位名称为Sunsigned char count; //全局变量,用于存放按键次数//函数名:key//函数功能:检测按键S是否按下,如果按下count加1计数//形式参数:无//返回值:无void key(){ unsigned int k;if(S==0) //第1次判断S是否按下{for(k=0;k<1200;k++); //延时去抖if(S==0) { //再次判断S是否按下if(++count==10)count=0; //按键次数处理while(!S); //等待S释放} } }甲机发送通信程序如下。void main(){TMOD=0x20; //设置定时器T1为方式2TL1=0xfd; //波特率为9600BdTH1=0xfd;TR1=1;SCON=0x40; //定义串行口工作于方式1,不接收PCON=0x00; //SMOD=0count=0; //次数清0while(1){key(); //调用按键处理函数SBUF=count; //发送次数while(!TI); //查询TI是否由0变1TI=0; //软件给TI清0}}控制程序设计乙机发送通信程序如下。//程序:ex7-2.c//功能:乙机串行接收程序,采用查询方式实现#include //包含头文件REGX51.H,定义了51单片机的所有SFR//定义0~9共阳极显示字型码code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};void main() //主函数{unsigned char i;TMOD=0x20; //设置定时器T1为方式2TL1=0xfd; //波特率为9600BdTH1=0xfd;TR1=1;SCON=0x40; //定义串行口工作于方式1,不接收PCON=0x00; //SMOD=0while(1){REN=1; //接收允许while(RI==0); //查询等待接收标志为1,表示接收到数据i=SBUF; //接收数据P1=tab[i]; //显示接收数据RI=0; //RI由软件清0}}思考题:接收程序修改为中断方式,怎么修改程序。控制程序设计//程序:ex37.c//功能:乙机接收程序,中断方式实现#include //包含头文件REGX51.H,定义了51单片机的所有SFRcode unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//定义0~9共阳极显示字型码void main() //主函数{TMOD=0x20; //设置定时器T1为方式2TL1=0xfd; //波特率为9600BdTH1=0xfd;TR1=1;SCON=0x40; //定义串行口工作于方式1,不接收PCON=0x00; //SMOD=0ES=1; //开串行口中断EA=1; //开总中断允许位REN=1; //接收允许P1=tab[0]; //LED显示0while(1); //等待接收中断}//函数功能:串行口中断接收函数void serial()interrupt 4 //串口中断类型号为4{EA=0; //关中断RI=0; //软件清除中断标志位P1=tab[SBUF]; //显示接收数据EA=1;}《单片机基础与应用(C语言版)》高等教育出版社实例34 单片机与PC通信实例要求实例分析单片机通过一个电平转换电路MAX232芯片,与RS232-C插座连接,可以用一条串口线与PC的RS232_C口通信。单片机收到PC发送的字符后,回送给PC,同时用识别字符’A’和’B’来控制8个LED的显示,从而可以直接看到单片机与PC之间成功通信。PC上可以用“串口调试助手”软件来发送字符、显示接收到的单片机回送字符。通信协议如下:波特率9600Bd,1位起始位,8位数据位,无奇偶校验,1位停止位。实现一个单片机与PC之间的串行口通信测试系统。系统中,单片机通过串口与PC通信,同时连接8个LED。8个LED闪烁过程中,可以接收PC发送的字符,并回送给PC。如果接收的字符为’A’,则LED左移流水灯显示一遍,继续闪烁;如果接收的字符为’B’,则LED右移流水灯显示一遍,再返回闪烁状态。硬件电路控制程序设计//程序:ex38.c//功能:单片机通信程序,接收采用中断方式实现#include //包含头文件REGX51.H,定义了51单片机的所有SFR#include //包含头文件INTRINS.h,定义了移位函数unsigned char Recbyte; //全局变量,存放接收的字符//函数名:delay//函数功能:实现软件延时//形式参数:无符号整型变量i,控制空循环的循环次数//返回值:无void delay(unsigned int i){ while(i--); }//函数名:flash//函数功能:8个LED闪烁一次//形式参数:无//返回值:无void flash(){P1=0x00; //点亮8个LEDdelay(10000);P1=0xff; //熄灭8个LEDdelay(10000);}//函数名:lsd1//函数功能:8个LED逐一点亮一次,左移方向void lsd1(){unsigned char i,w;w=0xfe; //流水灯初值for(i=0;i<8;i++){P1=w;delay(10000);w=_crol_(w,1); //循环左移1位}}//函数名:lsd2//函数功能:8个LED逐一点亮一次,右移方向void lsd2(){unsigned char i,w;w=0x7f; //流水灯初值for(i=0;i<8;i++){P1=w;delay(10000);w=_cror_(w,1); //循环右移1位}}控制程序设计//函数名:sendbyte//函数功能:向串口发送一个字符,采用查询方式实现//形式参数:无符号整型变量i,定义发送的字符//返回值:无void sendbyte(unsigned char i){SBUF=i; //发送字符写入SBUFwhile(!TI); //查询TI是否由0变1TI=0; //软件给TI清0}void main() //主函数{TMOD=0x20; //设置定时器T1为方式2TL1=0xfd; //波特率为9600BdTH1=0xfd;TR1=1;SCON=0x40; //定义串行口工作于方式1,不接收PCON=0x00; //SMOD=0ES=1; //开串行口中断EA=1; //开总中断允许位REN=1; //接收允许Recbyte=0; //接收字符初值0while(1){switch(Recbyte){case 'A':lsd1(); Recbyte=0;break; //左移流水灯case 'B':lsd2(); Recbyte=0;break; //右移流水灯default: flash(); //闪烁}}}//函数名:serial//函数功能:串行口中断接收函数//形式参数:无//返回值:无void serial()interrupt 4 //串口中断类型号为4{EA=0; //关中断RI=0; //软件清除中断标志位Recbyte=SBUF ; //接收数据sendbyte(Recbyte); //再送回PCEA=1; //开中断}Thanks for your attention. 感谢您的观看(共14张PPT)《单片机基础与应用(C语言版)》高等教育出版社实例35 简易数字电压表实例要求实例分析系统需要将模拟信号转变为数字信号,再将数字信号转化为输入模拟信号的电压值,并进行显示,所以需要2次转换和一次显示操作。采用PCF8591实现A/D转换,采集0~5 V连续可变的模拟电压信号,用电位器调节来实现这个模拟信号。转变为8位二进制数字信号(0x00~0xFF)后,送单片机处理,并在4位LED上显示出0.000~5.000 V(小数点不用显示)。硬件电路主函数流程控制程序设计//程序:ex39.c//功能:0~5 V连续可变的模拟电压信号测量,并在4位LED上显示出0000~5000#include //包含头文件reg51.h,定义了51单片机的专用寄存器#include sbit SDA=P3^6; //定义P3.6引脚位名称为SDAsbit SCL=P3^7; //定义P3.7引脚位名称为SCL#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};//无符号字符型变量unsigned char code SEGTAB[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x83,0xF8,0x80,0x98};//定义共阳极7段LED显示字型码#define SEGDATA P2 //定义LED段选信号数据接口#define SEGSELT P0 //定义LED位选信号数据接口#define PCF8591_WRITE 0x90 //PCF8591器件写地址#define PCF8591_READ 0x91 //PCF8591器件读地址unsigned char disp[4]={0,0,0,0}; //定义全局变量disp[],存储4个显示LED对应的显示值bit SystemError;//函数名:delay_ms//函数功能:实现单位时间的延时,这个函数采用软件延时,//有一定的误差,在精度要求不高的情况下,人们习惯这种用法//形式参数:延时毫秒数//返回值:无void delay_ms(uint ms){unsigned int i,j;for(;ms>0; ms--){for(i=0;i<7;i++)for(j=0;j<210;j++);}}控制程序设计//函数名: data_process//函数功能:把ADC转换的8位数据转换为实际的电压值//形式参数:输入数据//返回值:无,实际电压值分离后存放在全局数组disp[]中void data_process(unsigned char value){unsigned int temp;temp = value *196; //0~255转换为0~50000disp[3]=temp/10000; //得到万位disp[2]=(temp/1000)%10; //得到千位disp[1]=(temp/100)%10; //得到百位disp[0]=(temp/10)%10; //得到十位,个位不需要,只显示高4位}//函数名: seg_display//函数功能:将全局数组变量的值动态显示在4个LED上//形式参数:引用全局数组变量disp//返回值:无void seg_display(void){unsigned char i,scan;scan=1;for(i=0;i<4;i++) //控制4位LED显示{SEGDATA=0xFF;SEGSELT=~scan; //送位选码SEGDATA= SEGTAB[disp[i]]; //送段选码delay_ms(5);scan<<=1; //位选码左移1位}}void main() //主函数{unsigned char voltage;iic_init(); //IIC初始化,参见8.3.2节while(1){voltage = ADC_PCF8591(0); //测0通道电压,参见8.3.3节data_process(voltage); //数据处理seg_display (); //数据显示delay_ms(10);}}要将一个数据显示在LED上,需要把这个数据的每位数值单独分离出来,因为只是显示高4位,程序中做了以下处理。disp[3]=temp/10000; //得到万位disp[2]=(temp/1000)%10; //得到千位disp[1]=(temp/100)%10; //得到百位disp[0]=(temp/10)%10; //得到十位《单片机基础与应用(C语言版)》高等教育出版社实例36 信号发生器实例要求实例分析锯齿波是一种常见的信号波形,先呈直线上升,随后陡落,再上升,再陡落,如此反复,实际上是一个线性波形。采用PCF8591实现简易波形发生器,产生锯齿波信号。通过软件调整波形设定参数,可用示波器观察输出波形的幅值、周期及频率的变化。硬件电路初始化开始输出数字量进行D/A转换输出电压值加1确定输出数字量初值0延时输出值=255?YN控制程序设计//程序:ex40.c//功能:锯齿波产生控制程序#include //包含头文件reg51.h,定义了51单片机的专用寄存器#include //包含头文件intrins.hsbit SDA=P2^7; // P2.7定义为IIC数据sbit SCL=P2^6; // P2.6定义为IIC时钟#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};bit bdata SystemError; // 从机错误标志位//------------PCF8591专用变量定义-----------------------------------#define PCF8591_WRITE 0x90 //器件写地址#define PCF8591_READ 0x91 //器件读地址//函数名:delay_ms//函数功能: 采用定时器T1延时t毫秒,工作方式1,定时器初值64536//形式参数:延时毫秒数//返回值:无void delay_ms(unsigned char t){unsigned char i;TMOD=0x10; //设置T1为工作方式1for(i=0;i{TH1=0xFC; //置定时器初值0xFC18=64536TL1=0x18;TR1=1; //启动定时器1while(!TF1); //查询计数是否溢出,即1ms定时时间到,TF1=1TF1=0; //1ms定时时间到,将定时器溢出标志位TF1清0}}控制程序设计void main() //主函数{unsigned char i;iic_init(); //参见8.3.2节while(1){for(i=0;i<=255;i++) //形成锯齿波输出值,最大255{DAC_PCF8591(0x40, i); //控制字为0100 0000,允许模拟量输出,参见8.3.4delay_ms(1);}}}Thanks for your attention. 感谢您的观看(共13张PPT)实例37 数字钟《单片机基础与应用(C语言版)》高等教育出版社实例要求数字钟设计要求如下。(1)显示当前的时间。(2)手动修改时间信息。(3)手动开启/关闭闹钟功能,且有闹钟状态指示灯。(4)手动设置闹钟,并且当达到设置好的时间点时报警,报警时间定时5s。实例分析51单片机核心模块包括51单片机最小系统模块,是设计应用系统的控制核心;显示模块用于显示时间和闹钟设置时间等时间信息;闹钟指示灯指示闹钟当前状态:开启或关闭;闹钟采用声音报警;键盘输入模块完成时间设置、闹钟开启或关闭、闹钟时间设置等。硬件电路(1)显示模块采用8个共阴极LED显示时间和闹钟时间,显示格式:hh-mm-ss(时-分-秒),单片机的P1口连接段选码,用8同相三态缓冲器/线驱动器74LS245驱动,P2口连接位选码。(2)闹钟指示灯一个LED作为闹钟指示灯,LED亮,表示闹钟功能开启;LED灭,表示闹钟功能关闭,由单片机的P3.1引脚控制。(3)闹钟报警闹钟报警采用蜂鸣器发声装置,由单片机的P3.0引脚控制。(4)键盘输入一般来说,当系统需要键盘数量超过8个时,采用矩阵键盘实现;否则,采用独立式按键实现。按照设计要求,数字钟需要5个按键,所以采用独立式按键连接方法,分别由单片机的P3.2~P3.6控制。按键功能定义见表9-1。序号 连接引脚 定义名称 功能1 P3.2 SWITCH 外部中断0,闹钟开关2 P3.3 SET 外部中断1,进入设置闹钟状态,进行闹铃设置,QUIT键按下则退出3 P3.4 INC_h 调节时钟和闹钟时,按一下小时加1,加到23后回到04 P3.5 INC_f 调节时钟和闹钟时,按一下分钟加1,加到59后回到05 P3.6 QUIT 退出设置闹钟表9-1 数字钟按键功能定义控制程序设计控制程序设计//程序名:ex41.c//功能:数字钟程序#include #define uint unsigned int#define uchar unsigned char//函数声明void tiaojie(); //调节时时间函数声明void naozhong(); //闹钟设置函数声明void alarm(); //闹铃函数声明//5个按键定义sbit SWITCH=P3^2; //外部中断0,闹钟功能切换键sbit SET=P3^3; //外部中断1,进入设置闹钟状态,进行闹铃设置,QUIT键按下则退出sbit INC_h=P3^4; //调节时钟和闹钟时,小时加1按键,加到59后回到0sbit INC_f=P3^5; //调节时钟和闹钟时,分钟加1按键,加到59后回到0sbit QUIT=P3^6; //退出设置闹钟//蜂鸣器和闹钟开关指示灯定义sbit BEEP=P3^0; //蜂鸣器端口sbit LED=P3^1; //闹钟开关指示灯,灯灭--闹钟关闭,灯亮--闹钟开启//定义全局变量uchar m,f,s,w; //w为累计50ms的次数,m为秒计数,f为分计数,h为时计数uchar f_nao,s_nao; //f_nao为闹钟分计数,s_nao为闹钟时计数bit flag_nao; //flag_nao=0,off,1--on控制程序设计//函数名:ledscan//函数功能:实现8位LED动态显示时-分-秒//形式参数:unsigned char h,unsigned char m,unsigned char s// 扫描的是h,m,s。分别对应时,分,秒。//返回值:无void ledscan(unsigned char h,unsigned char m,unsigned char s) reentrant{uchar led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9共阴极显示码表uint j;P1=led[s%10]; //第1位显示,显示秒个位并送入P1口P2=0x7f; //位选码01111111送入P2口for(j=0;j<100;j++); //小延时。以下同理P2=0xff; //关闭全部使能端,消影。以下同理P1=led[s/10]; //第2位显示,显示秒十位并送入P1口P2=0xbf; //位选码10111111送入P2口for(j=0;j<100;j++);P2=0xff;P1=0x40; //第3位显示,显示字符“-”并送入P1口P2=0xdf; //位选码11011111送入P2口for(j=0;j<100;j++);P2=0xff;P1=led[m%10]; //第4位显示,显示分个位并送入P1口P2=0xef; //位选码11101111送入P2口for(j=0;j<100;j++);P2=0xff;P1=led[m/10]; //第5位显示,显示分十位并送入P1口P2=0xf7; //位选码11110111送入P2口for(j=0;j<100;j++);P2=0xff;P1=0x40; //第6位显示,显示字符“-”并送入P1口P2=0xfb; //位选码11111011送入P2口for(j=0;j<100;j++);P2=0xff;P1=led[h%10]; //第7位显示,显示时个位并送入P1口P2=0xfd; //位选码11111101送入P2口for(j=0;j<100;j++);P2=0xff;P1=led[h/10]; //第8位显示,显示时十位并送入P1口P2=0xfe; //位选码11111110送入P2口for(j=0;j<100;j++);P2=0xff;}控制程序设计//函数名: tiaojie//函数功能:每次按INC_h实时时钟的小时就加1,每次按INC_f实时时钟的分钟就加1。// 用来调节实时时间//形式参数:无//返回值:无void tiaojie(){if(INC_h==0) //判断是否有键按下,按键延时去抖处理,以下同理{ledscan(s,f,m);if(INC_h==0) //调节小时,当按下INC_h:如果小时等于23,{ //则小时为0;否则小时加1if(s==23) s=0; else s++;while(!INC_h)ledscan(s,f,m);//判断键是否释放}}else if(INC_f==0) //调节分钟,当按下INC_f:如果分钟等于59,{ //则分钟为0ledscan(s,f,m);if(INC_f==0){ if(f==59)f=0;else f++;while(!INC_f)ledscan(s,f,m);}}}//函数名: alarm//函数功能:当时间和设置闹铃时间相等时,闹铃响5s。//形式参数:无//返回值:无void alarm(){if(flag_nao) //如果flag_nao为真,闹钟开启{if(f==f_nao&&s==s_nao) //判断实时时间和闹钟时间的分,时是否同时相等{while(m<=5&&flag_nao) //如果m<=5和flag_nao都为真,闹铃响5s{BEEP=!BEEP;ledscan(s,f,m);}}}}控制程序设计//函数名:t0//函数功能:T0中断服务函数,在T0的工作方式1,采用内部时钟定时实现实时时钟//形式参数:无//返回值:无void t0() interrupt 1 //内部定时T0中断服务函数{TH0=(65536-50000)/256;//重新设置T0计数初值高8位,定时时间50msTL0=(65536-50000)%256;//重新设置T0计数初值低8位,定时时间50msw++;if(w==20) //当w==20时,w为0,秒计数加一{w=0;m++;if(m==60) //当秒计数为60时,秒计数为0,分计数加一{f++;m=0;if(f==60) {s++;f=0;if(s==24)s=0;} //当分计数为60时,分计数为0,时计数加一} //当时计数为24时,时计数为0}}//函数名:guan_naozhong//函数功能:外部中断0中断服务函数,SWITCH按键控制flag_nao。当闹钟响时,按下此键立即关掉闹铃,同时关掉闹钟功能//形式参数:无//返回值:无void guan_naozhong() interrupt 0{flag_nao=~flag_nao; //flag_nao取反LED=~LED;while(!SWITCH)ledscan(s,f,m); //等待按键释放}控制程序设计//函数名:naozhong//函数功能:外部中断1中断服务函数,用来调节闹钟时间,实现每次按键INC_h时钟就加1,每次按键INC_f分钟就加1。void naozhong() interrupt 2{f_nao=f; //当前时间作为闹钟初始值s_nao=s;while(QUIT){ //等待按下QUIT退出,否则循环执行闹钟时间设置ledscan(s_nao,f_nao,0); //显示闹钟设置if(INC_h==0){ledscan(s_nao,f_nao,0);if(INC_h==0){if(s_nao==24) s_nao=0; //调节闹钟时间,当按下INC_h:如果闹钟小时等于23,else s_nao++; //则闹钟小时为0;否则闹钟小时加1}while(!INC_h)ledscan(s_nao,f_nao,0); //等待按键释放}else if(INC_f==0){ledscan(s_nao,f_nao,0);if(INC_f==0) //调节闹钟分钟,当按下INC_f:如果闹钟分钟等于59,{ //则闹钟分钟为0;否则闹钟时钟加1if(f_nao==59)f_nao=0;else f_nao++;}while(!INC_f)ledscan(s_nao,f_nao,0);}}}控制程序设计void main() //主函数{TMOD=0x01; //设置T0工作方式1TH0=(65536-50000)/256; //设置T0计数初值高8位,12MHz下定时时间50msTL0=(65536-50000)%256; //设置T0计数初值低8位,12MHz下定时时间50msTR0=1; //开启T0ET0=1; //打开外部中断1允许位IT1=1; //设置外部中断2为下降沿触发方式IT0=0; //设置外部中断0为低电平触发方式EX1=1; //打开外部中断2允许位EX0=1; //打开外部中断0允许位PT0=1; //设置内部定时中断优先级大于外部中断优先级EA=1; //打开中断总允许位f=0; //赋初值m=0;BEEP=0;flag_nao=0;while(1){ledscan(s,f,m); //不断扫描显示实时时钟(时-分-秒)tiaojie(); //调节实时时钟(调节时,分)alarm(); //判断闹钟}}感谢您的观看Thanks for your attention. (共18张PPT)《单片机基础与应用(C语言版)》高等教育出版社实例38 倒计时交通灯控制实例要求(1)要求南北方向车道和东西方向车道2条交叉道路上的车辆自动交替运行,东西和南北方向各有一组红、黄、绿灯用于指挥交通。(2)红灯的持续时间为55s,绿灯持续时间为50s,闪烁时间3s。(3)黄灯在绿灯转为红灯之前亮2s(4)东西方向、南北方向车道除了有红、黄、绿指示灯外,每一种灯亮的时间都用LED进行倒计时显示。(5)有紧急情况车辆要求通过时,系统要能禁止普通车辆通行,南北、东西方向都是红灯,时间持续20s,当紧急情况结束后,继续正常工作。(6)有特殊情况车辆要求通过时,系统要求南北方向通行10s,当特殊情况结束后,继续正常工作。实例分析硬件电路(1)交通灯显示电路采用6个LED模拟2个方向的红黄绿交通灯,采用单片机的P0口控制,采用灌电流控制方式,低电平点亮。(2)倒计时显示电路4个动态连接LED分别模拟2个方向的倒计时显示器,每个方向2位,P2.0~P2.3控制LED的段选,P1口连接LED的位选端,采用同相三态数据缓冲器74LS245驱动。(3)紧急和特殊情况按键输入按键S1、S2分别模拟紧急情况和特殊情况的发生,当S1、S2没有按下时,表示正常情况。当S1按下时,表示紧急情况,将S1信号接至 脚(P3.2)即可实现外部中断0中断申请。当S2按下时,表示特殊情况,将S2信号接至 脚(P3.3)即可实现外部中断1中断申请。控制程序设计南北方向 东西方向 P0口数据 交通灯状态红P0.5 黄P0.4 绿P0.3 倒计时 红P0.2 黄P0.1 绿P0.0 倒计时 1 1 0 50 0 1 1 55 F3H 状态1:南北绿灯,东西红灯1 1 0、1 3 0 1 1 F3H FBH 状态2:南北绿灯闪,东西红灯1 0 1 2 0 1 1 EBH 状态3:南北黄灯,东西红灯0 1 1 55 1 1 0 50 DEH 状态4:南北红灯,东西绿灯0 1 1 1 1 0、1 3 DEH DFH 状态5:南北红灯,东西绿灯闪0 1 1 1 0 1 2 DDH 状态6:南北红灯,东西黄灯控制程序设计控制程序设计//功能:倒计时交通灯控制程序#include #define uint unsigned int#define uchar unsigned char//全局变量定义uchar e_w,s_n; //e_w为东西方向倒计时,s_n为南北方向倒计时//函数名:ledscans//函数功能:实现4位LED动态显示扫描函数,分别显示东西和南北倒计时秒数void ledscans() reentrant{uchar led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uchar wei[]={0xfe,0xfd,0xfb,0xf7}; //位选码uchar b;P2=wei[0]; //第1位显示P1=led[e_w/10]; //显示东西倒计时高位for(b=0;b<100;b++); //延时P1=0x00; //关显示P2=wei[1]; //第2位显示P1=led[e_w%10]; //显示东西倒计时低位for(b=0;b<100;b++); //延时P1=0x00; //关显示P2=wei[2]; //第3位显示P1=led[s_n/10]; //显示南北倒计时高位for(b=0;b<100;b++); //延时P1=0x00; //关显示P2=wei[3]; //第4位显示P1=led[s_n%10]; //显示南北倒计时低位for(b=0;b<100;b++); //延时P1=0x00; //关显示}控制程序设计//函数名:time50ms//函数功能:在T1工作方式1下定时50ms,采用查询方式实现//形式参数:无符号整型变量i,控制定时时间,i*50ms//返回值:无void time50ms(uchar i) reentrant{uchar k;for(k=0;kTH1=(65536-50000)/256; //重新设置T1计数初值高8位,定时时间50msTL1=(65536-50000)%256; //重新设置T1计数初值低8位TR1=1; //启动T1while(!TF1)ledscans();//查询计数是否溢出,即定时50ms时间到,TF1=1TF1=0; //50ms定时时间到,将T1溢出标志位TF1清0}}//函数名:int_0//函数功能:外部中断0服务函数,紧急情况下2个方向红灯亮20s,高优先级//形式参数:无//返回值:无void int_0() interrupt 0 //外部中断0{uchar i,l,m,n,p;i=P0; //保护现场,暂存P1口、t0、t1、l=TH1;m=TL1;n=s_n;p=e_w;e_w=20;for(s_n=20;s_n>0;s_n--) //2个方向都倒计时计数20s{P0=0xdb; //2个方向红灯20stime50ms(20);e_w--;}P0=i; //恢复现场TH1=l;TL1=m;s_n=n;e_w=p;}控制程序设计//函数名:int_1//函数功能:外部中断1服务函数,特殊情况下南北方向通行10s,低优先级//形式参数:无//返回值:无void int_1() interrupt 2 //外部中断1{uchar i,l,m,n,p;EA=0; //关闭总中断i=P0; //保护现场l=TH1;m=TL1;n=s_n;p=e_w;EA=1; //开中断e_w=10; //2个方向倒计时计数都是10秒for(s_n=10;s_n>0;s_n--){P0=0xf3; //南北方向绿灯,东西方向红灯time50ms(20);e_w--;}EA=0; //关中断P0=i; //恢复现场TH1=l;TL1=m;s_n=n;e_w=p;EA=1;}void main() //主函数{TMOD=0x10; //设置T1工作于方式1IT0=1; //设置外部中断0为下降沿触发中断EX0=1; //允许外部中断0IT1=1; //设置外部中断1为下降沿触发中断EX1=1; //允许外部中断1PX0=1; //设置外部中断0(紧急情况)为高优先级)EA=1; //允许总中断while(1){ //南北方向绿灯50s,绿灯闪3s,黄灯2s;东西方向红灯,倒计时为55s,状态1-状态3e_w=55; //东西方向倒计时初值for(s_n=50;s_n>0;s_n--) //南北方向50s倒计时{P0=0xf3; //南北方向绿灯,东西方向红灯time50ms(20);e_w--; //东西方向同步倒计时}for(s_n=3;s_n>0;s_n--) //南北方向3s倒计时{P0=0xf3; //南北方向绿灯闪烁,东西方向红灯time50ms(10);P0=0xfb;time50ms(10);e_w--; //东西方向同步倒计时}控制程序设计for(s_n=2;s_n>0;s_n--) //南北方向2s倒计时{P0=0xeb; //南北方向黄灯,东西方向红灯time50ms(20);e_w--; //东西方向同步倒计时}//东西方向绿灯50s,绿灯闪3s,黄灯2s;南北方向红灯,倒计时为55s,状态4-状态6s_n=55;for(e_w=50;e_w>0;e_w--) //东西方向50s倒计时计数{P0=0xde; //东西方向绿灯,南北方向红灯time50ms(20);s_n--; //南北方向同步倒计时}for(e_w=3;e_w>0;e_w--) //东西方向3s倒计时{P0=0xde; //东西方向绿灯闪烁,南北方向红灯time50ms(10);P0=0xdf;time50ms(10);s_n--; //南北方向同步倒计时}for(e_w=2;e_w>0;e_w--) //东西方向2s倒计时{P0=0xdd; //东西方向黄灯,南北方向红灯time50ms(20);s_n--; //南北方向同步倒计时}}}《单片机基础与应用(C语言版)》高等教育出版社实例39 16×16点阵显示屏移动广告牌实例要求(1)将4个8×8点阵模块拼接成1个16×16点阵屏。(2)在16×16点阵屏上移动显示图形、汉字等广告内容。实例分析因为LED点阵大屏幕的尺寸增加,行数和列数也随之增加,而单片机往往不能提供足够的电流和足够多的I/O端口来控制每行或每列LED的扫描。所以,需要为大尺寸的LED点阵显示屏设计行驱动电路和列驱动电路硬件电路(1)16×16点阵显示屏由4片8×8 LED点阵组成的16×16 LED点阵显示屏如图9-13所示。将上面2片8×8 LED点阵模块的行并联在一起组成ROW0~ROW7,下面2片点阵模块的行并联在一起组成ROW8~ROW15,由此组成16根行扫描线;将左边上、下2片点阵模块的列并联在一起组成COL0~COL7,右边上、下2片点阵模块的列并联在一起组成COL8~COL15,由此组成16根列选线。(2)行驱动电路采用单片机的P2口和P3口共计16条I/O口线控制16条行线ROW0~ROW16,为了增强I/O口线的驱动能力,使用2片8位三态缓冲器74LS244驱动。(3)列驱动电路在列驱动电路设计中考虑采用译码器芯片来减少I/O端口的使用。选用2片3/8线译码器74LS138,生成16条列选通信号线,也可以采用1片4/16线译码器74LS154来实现16条列选通控制信号。控制程序设计//程序:ex43.c//功能:16×16点阵移动广告牌,移动显示“★课程设计★”,采用逐列扫描法#include#define uchar unsigned char#define uint unsigned intsbit U1=P1^3; //138控制端,高电平138工作sbit U2=P1^4; //138控制端,高电平138工作//P2口连接的8行显示数据uchar code tab1[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0x40,0x40,0xc0,0xc0,0xc0,0xe0,0xfc,0xff,0xfc,0xe0,0xc0,0xc0,0xc0,0x40,0x40,0x00,//★0x40,0x42,0xCC,0x00,0x00,0x00,0xFE,0x92,0x92,0xFE,0x92,0x92,0xFE,0x00,0x00,0x00,//课0x24,0x24,0xA4,0xFE,0x23,0x22,0x00,0x3E,0x22,0x22,0x22,0x22,0x22,0x3E,0x00,0x00,//程0x40,0x40,0x42,0xCC,0x00,0x40,0xA0,0x9E,0x82,0x82,0x82,0x9E,0xA0,0x20,0x20,0x00,//设0x40,0x40,0x42,0xCC,0x00,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x00,//计0x40,0x40,0xc0,0xc0,0xc0,0xe0,0xfc,0xff,0xfc,0xe0,0xc0,0xc0,0xc0,0x40,0x40,0x00,//★0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//P3口连接的8行显示数据uchar code tab2[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0x00,0x00,0x40,0x39,0x3f,0x1f,0x1f,0x0f,0x1f,0x1f,0x3f,0x39,0x40,0x00,0x00,0x00,//★0x00,0x00,0x3F,0x10,0x08,0x22,0x12,0x0A,0x06,0xFF,0x06,0x0A,0x12,0x22,0x20,0x00,//课0x08,0x06,0x01,0xFF,0x01,0x06,0x40,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x41,0x00,//程0x00,0x00,0x00,0x3F,0x90,0x88,0x40,0x43,0x2C,0x10,0x28,0x46,0x41,0x80,0x80,0x00,//设0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,//计0x00,0x00,0x40,0x39,0x3f,0x1f,0x1f,0x0f,0x1f,0x1f,0x3f,0x39,0x40,0x00,0x00,0x00,//★0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};控制程序设计void main() //主函数{uchar n,col;//n用于延时,col控制每屏16列扫描0-15uchar w,v; //w用于控制每屏扫描次数,可以控制移动,v控制移动,每次加1,控制逐列移动U1=0; //74LS138控制端清0,74LS138不工作U2=0; //74LS138控制端清0,74LS138不工作col=0; //col控制列v=0;while(1){for(v=0;v<=112;v++) //移动显示控制,16*7=112{for(w=0;w<=320;w++) //扫描列次计数器,一屏共扫描320列次,扫描一屏20次{P1=0; //P1控制列线,采用2片74LS138控制,预先清0P2=tab1[v+col]; //送P2口连接的8位行数据(低8位)v控制取数位置,即移动显示控制;col控制列P3=tab2[v+col]; //送P3口连接的8位行数据(高8位)P1=col&0x07; //把P1口的低3位取出来,选中列if(col<8){U1=1;U2=0;} //打开低7列的74LS138的控制口else{U2=1;U1=0;} //打开高7列的74LS138的控制口col++;if(col>15)col=0; //到15列,列清0for(n=0;n<80;n++); //延时}}}}Thanks for your attention. 感谢您的观看(共17张PPT)实例40 简易打字游戏机《单片机基础与应用(C语言版)》高等教育出版社实例要求1)设计并显示一个简单的游戏logo。(2)具有90s倒计时功能。(3)具有12个按键,包括10个(0~9)打字按键,1个开始键,1个退出键。(4)具有随机数(0~9)生成功能。(5)在90s内输入屏幕上显示的随机数,如果正确,得1分,时间到或按下退出键,游戏结束,显示分数2s,回到游戏开始画面;按下开始键,重新开始游戏。实例分析显示模块用于显示游戏logo和游戏各种画面等内容,是人机输出通道;键盘输入模块完成游戏开始、退出、打字等功能,是人机输入通道。硬件电路控制程序设计1)游戏logo设计与显示字符型LCD一般内置了160个5×7点阵字符图形,可以显示英文、日文及数字。除此之外,还可以通过自定义字符,在片内自定义8个字符,显示特殊字符甚至笔画比较少的汉字,一般LCD模块所提供的CGRAM能够自编8个5×7字符。设计一个游戏logo,并把它用6个自编字符显示。对LCD1602模块设置CGRAM地址以显示自编字符的命令字格式如下。A7 A6 A5 A4 A3 A2 A1 A00 1 AC5 AC4 AC3 AC2 AC1 AC0控制程序设计字模及CGRAM地址、CGRAM字模和DDRAM字符代码的关系DDRAM字符代码 A7A6A5 A4 A3 A2 A1 A0 CGRAM地址 P7P6 P5P4P3 P2 P1 P0 CGRAM字模0x00 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 0 1 0 0 0 1 1 1 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 ×××□ □ □ □ □ ×××□ □ □ □ □ ×××□ □ □ □■ ×××□ □ □ ■■ ×××□ □ □ ■■ ×××□ □ ■ ■■ ×××□ □ ■ ■■ ×××□ □ □ □ □ 0x000x000x010x030x030x070x070x000x01 0 1 0 0 10 0 0 0 1 0 0 10 0 1 0 1 0 0 10 1 0 0 1 0 0 10 1 1 0 1 0 0 11 0 0 0 1 0 0 11 0 1 0 1 0 0 11 1 0 0 1 0 0 11 1 1 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 0x4F ×××□ □ □ □ □ ×××■■ ■■ □ ×××■■ ■■ ■ ×××■■ ■■ ■ ×××■■ ■■ ■ ×××■■ □□□ ×××■□ □□□ ×××□ □ □ □ □ 0x000x1e0x1f0x1f0x1f0x180x100x000x02 0 1 0 100 0 0 0 1 0 100 0 1 0 1 0 100 1 0 0 1 0 100 1 1 0 1 0 101 0 0 0 1 0 101 0 1 0 1 0 101 1 0 0 1 0 101 1 1 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 ×××□ □ □ □ □ ×××□ □ □ □ □ ×××□ □ □ □ □ ×××■□ □ □ □ ×××■■□ □ □ ×××■■□ □ □ ×××□ ■□ □ □ ×××□ □ □ □ □ 0x000x000x000x100x180x180x080x00控制程序设计(2)随机数产生随机数产生一般有2种方法,一是采用C51函数库中的rand()和srand()函数;二是直接采用定时器/计数器的中断计数产生。本项目采用第2种方法,同时还利用按键等待时间的不确定性,在等待按键过程中进行计数,按下键后计数停止,从而产生1个随机数种子。(3)程序流程图控制程序设计lcd.h头文件内容如图1602LCD程序如下//程序:lcd.c//功能:提供1602LCD各种显示函数#include #include //定义控制引脚sbit RS=P3^0;sbit RW=P3^1;sbit E=P3^2;//函数名:delay//函数功能:实现软件延时//形式参数:无符号整型变量i,控制空循环的循环次数//返回值:无void delay(unsigned int i){while(i--); //i次空操作}控制程序设计//函数名:delay1//函数功能:采用软件实现延时,大约几个机器周期void delay1(){_nop_();_nop_();_nop_();}//函数名:lcd_r_start//函数功能:读状态字//形式参数:无//返回值:返回状态字,最高位D7=0,LCD控制器空闲;D7=1,LCD控制器忙unsigned char lcd_r_start(){unsigned char s;RW=1;delay1();RS=0;delay1();E=1;delay1();s=P1;delay1();E=0;delay1();RW=0;delay1();return(s);}//函数名:lcd_w_cmd//函数功能:写命令字//形式参数:命令字已存入com单元中//返回值:无void lcd_w_cmd(unsigned char com){unsigned char i;do{i=lcd_r_start();i=i&0x80;delay(100);}while(i!=0);RW=0;delay1();RS=0;delay1();E=1;delay1();P1=com;delay1();E=0;delay1();RW=1;delay(255);}控制程序设计//函数名:lcd_w_dat//函数功能:写数据//形式参数:数据已存入dat单元中//返回值:无void lcd_w_dat(unsigned char dat){unsigned char i;do{i=lcd_r_start();i=i&0x80;delay(100);}while(i!=0);RW=0;delay1();RS=1;delay1();E=1;delay1();P1=dat;delay1();E=0;delay1();RW=1;delay(255);}//函数名:lcd_init//函数功能:lcd初始化//形式参数:无//返回值:无void lcd_init(){lcd_w_cmd(0x3c);lcd_w_cmd(0x0e);lcd_w_cmd(0x01);lcd_w_cmd(0x06);lcd_w_cmd(0x80);}//函数名:puts//函数功能:在lcd上显示字符串函数//形式参数:待显示字符串的首地址//返回值:无void puts(unsigned char ch[]){unsigned char i;i=0;while(ch[i]!='\0') //字符串结束符 ‘/0’{lcd_w_dat(ch[i]);i++;}}控制程序设计//函数名:putdata//函数功能:显示数据函数(0-255)//形式参数:无符号字符型,待显示数据//返回值:无void putdata(unsigned char dbyte) reentrant{unsigned char b,s,g;b=dbyte/100; //分离百位s=(dbyte%100)/10; //分离十位g=dbyte%10; //分离个位if(b!=0) //百位不为0,显示3位{lcd_w_dat(b+0x30);lcd_w_dat(s+0x30);lcd_w_dat(g+0x30);}else if(s!=0) //百位为0,十位不为0,显示2位{lcd_w_dat(0x20);lcd_w_dat(s+0x30);lcd_w_dat(g+0x30);}else //百位为0,十位也为0,显示1位lcd_w_dat(0x20);lcd_w_dat(0x20);lcd_w_dat(g+0x30);}控制程序设计简易打字机游戏程序如下//程序:ex44.c//功能:简易打字游戏机程序,倒计时90秒,按照屏幕出现的随机数打字,(0~9),10号键是开始键,11号键为退出键#include #include //包含lcd.h头文件unsigned char code key_code[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b};// 3*4矩阵按键对应的扫描码表3*4矩阵接键unsigned int count250us; //250μs计数,用于定时和随机数产生unsigned char sec=90,score=0; //秒计数sec,分数scorebit flag=0; //时间到标志//游戏logo的字模生成数组,共6个5×7字符unsigned char code logo[6][8]={{0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x00}, //DDRAM:0x00{0x00,0x1e,0x1f,0x1f,0x1f,0x18,0x10,0x00}, //DDRAM:0x01{0x00,0x00,0x00,0x10,0x18,0x18,0x08,0x00}, //DDRAM:0x02{0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00}, //DDRAM:0x03{0x17,0x17,0x11,0x1f,0x1f,0x1f,0x0e,0x00}, //DDRAM:0x04{0x18,0x18,0x18,0x10,0x10,0x00,0x00,0x00}}; //DDRAM:0x05//函数名: delayms//函数功能:延时处理程序,单位毫秒//形式参数:无符号整型数,延时的毫秒数//返回值:无void delayms (unsigned int ms){unsigned int i;while(ms--){//for(i=0;i<112;i++) //11.0592M晶体for(i=0;i<120;i++); //12M晶体}}控制程序设计//函数名: CGRAM//函数功能:游戏logo字符生成程序,生成6个字符,拼成一个logo//形式参数:无//返回值:无void CGRAM(){ unsigned char i,w,c;w=0x40;for(i=0;i<6;i++){ //6个字符for(c=0;c<8;c++) { //每个字符8行lcd_w_cmd(w); //写入CGRAM地址lcd_w_dat(logo[i][c]); //写入CGRAM数据w++;}}}//函数名:display_logo//函数功能:在LCD中央显示游戏logo//形式参数:无//返回值:无void display_logo(){lcd_w_cmd(0x86); //第1行定位lcd_w_dat(0x00);lcd_w_dat(0x01);lcd_w_dat(0x02);lcd_w_cmd(0xc6); //第2行定位lcd_w_dat(0x03);lcd_w_dat(0x04);lcd_w_dat(0x05);}//函数名: keyscan//函数功能:判断是否有键按下,如果有键按下,行列反转法得到键值//形式参数:无//返回值:键值0~11,-1表示无键按下char keyscan(){char scan1,scan2,keycode,j,key;key=-1; //键值初值为-1,如果没有扫描到按键,函数返回-1P2=0xf0; //写:行为全1,列为全0scan1=P2; //读:行列值if(scan1!=0xf0) //如果读入的值不为0xf0,则表示有键按下{delayms(10); //延时去抖scan1=P2; //再次读入行列值if(scan1!=0xf0) //再次判断是否有键按下{P2=0x0f; //行列反转,写:行为全0,列为全1scan2=P2; //读入行列值keycode=scan1|scan2; //2次读入值按位或操作,合并在一起,得到扫描码for(j=0;j<12;j++) { //由扫描码表得到键值if(keycode==key_code[j]){key=j;break;}}}}return(key); //返回键值}控制程序设计//函数名:t0//函数功能:T0中断服务函数,倒计时90秒//形式参数:无//返回值:无void t0() interrupt 1{count250us++; //250μs计数器if(count250us==4000) //1s计时到{ count250us=0;sec--; //秒倒计时if(sec==0){flag=1;}//置时间到标志lcd_w_cmd(0x8c);putdata(sec); //显示秒}}//函数名:sys_init//函数功能:系统初始化,包括LCD、T0和中断等初始化//形式参数:无//返回值:无void sys_init(){lcd_init(); //LCD初始化TMOD=0x02; //定时器T0工作于方式2ET0=1; //允许T0中断TH0=0x06; // 250μs初值TL0=0x06;EA=1; //允许总中断sec=90; //90s倒计时初值score=0; //分数初值}//函数名:game_start//函数功能:游戏开始画面显示,包括倒计时时间和分数显示//形式参数:无//返回值:无void game_start(){lcd_w_cmd(0x01); //清屏lcd_w_cmd(0x8c);putdata(sec); //显示倒计时时间初值lcd_w_cmd(0xcc);putdata(score); //显示分数初值}//函数名:game_stop//函数功能:游戏停止画面显示,包括提示语和分数显示//形式参数:无//返回值:无void game_stop(){lcd_w_cmd(0x01); //清屏lcd_w_cmd(0x83);puts("Game over!");lcd_w_cmd(0xc5);puts("score="); //显示得分putdata(score);}控制程序设计void main(){ //主函数char key;unsigned char rdate; //存放随机数sys_init(); //系统初始化CGRAM(); //logo字模生成display_logo(); //显示logodelayms(3000); //持续3swhile(1){lcd_w_cmd(0x01); //清屏lcd_w_cmd(0x85);puts("START"); //显示START,然后等待按键while(1) //等待"10号"==>开始键{count250us++; //等待期间count250μs计数,因为按键时间的不确定性,可以得到随机数,作为250μs计数初值key=keyscan();if(key==10)break;}count250us%=10; //1个0-9的随机数作为250μs计数的初值,保证第1个随机数game_start(); //游戏开始画面显示TR0=1; //启动定时器EA=1;//游戏内容while(1){lcd_w_cmd(0xc0);rdate=count250us%10; //得到随机数0-9lcd_w_dat(rdate+0x30); //显示随机数控制程序设计while(1) //等待按键{key=keyscan();if(flag==1)break; //游戏时间到,退出按键if(key!=-1){while(keyscan()!=-1);break;} }//输入有效数字,等待按键释放并退出//按键处理if(key==rdate) //输入正确{score++; //分数增1lcd_w_cmd(0xcc);putdata(score); //显示分数}if(flag==1||key==11) //游戏时间结束或“11号键”==》退出键{flag=0;TR0=0; //T0停止计数EA=0;sec=90;game_stop(); //显示游戏结束画面score=0;delayms(2000); //持续2sbreak; //回到等待游戏开始画面}}}}Thanks for your attention. 感谢您的观看(共14张PPT)《单片机基础与应用(C语言版)》高等教育出版社实例41 智能温度测量实例要求(1)能够按照规定时间间隔(1s)自动检测环境温度。(2)能够在字符型LCD上显示温度值。(3)能够通过串口与PC通信,当收到PC命令时,上传温度值给PC。实例分析显示模块用于显示温度值;温度检测模块采用智能温度传感器DS18B20实现;电平转换模块实现单片机与RS-232C电平的转换。硬件电路温度检测电路采用Dallas公司生产的1-Wire接口数字温度传感器DSl8B20,如图所示,它采用3引脚TO-92封装,各引脚功能说明如下。GND(1):地信号。DQ(2):数据输入/输出引脚,开漏单总线接口引脚,需上拉电阻。VDD(3):电源引脚。DS18B20时序控制(1)初始化复位时序(2)DS18B20写时序(3)DS18B20读时序DS18B20的写入指令指 令 指令代码 操 作 说 明温度转换命令 44H 启动DS18B20进行温度转换读温度值命令 BEH 读暂存器中的温度值写暂存器命令 4EH 将数据写入暂存器的高8位TH和低8位TL中复制暂存器命令 48H 把暂存器TH、TL中的内容复制到E2RAM中重新调E2RAM命令 B8H 把E2RAM中的内容重新写回到暂存器TH、TL字节中读电源供电方式命令 B4H 启动DS18B20发送电源供电方式信号给单片机SKIP ROM操作命令 CCH 跳过ROM匹配,跳过读序列号的操作,可节省操作时间DS18B20的温度值转换控制程序设计DS18B20程序如下//程序:DS18b20.c//功能:提供DS18B20的初始化、读时序、写时序等函数#include "reg51.h"#include "intrins.h" //包含内部函数头文件intrins.h#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7; //温度采集//函数名:delay5us//函数功能:精确延时5μs//形式参数:延时时间参数i,无符号字符型//返回值:无void delay5us(uchar i){while(i--) {_nop_();_nop_();_nop_();}}//函数名:init_ds18b20//函数功能:总线初始化复位//形式参数:无//返回值:复位状态uchar init_ds18b20(void){uchar x=0;DQ=1;delay5us(10);DQ=0;delay5us(120); //低电平480-960sDQ=1;delay5us(15); //等待50-100sx=DQ;delay5us(80);DQ=1;return(x);}//函数名:readbyte//函数功能: 读取一个字节//形式参数:无//返回值:读取字节数据date, unsigned char 类型uchar readbyte(void){uchar i=0;uchar date=0;for(i=8;i>0;i--){DQ=0;delay5us(2);DQ=1; //15μs内释放总线date>>=1;if(DQ)date|=0x80;delay5us(9); }//读完需要45μs的等待return(date);}控制程序设计//函数名:writebyte//函数功能: 写一个字节//形式参数:写字节数据dat, unsigned char 类型//返回值:无void writebyte(uchar dat){uchar i=0;for(i=8;i>0;i--){DQ=0;DQ=dat&0x01; //写"1" 在15微秒内拉低delay5us(12); //写"0" 拉低60微秒等待写完DQ=1; //恢复高电平,至少保持1μsdat>>=1; //下次写作准备,移位数据delay5us(5); //延时25μs}}//函数名: readtemp//函数功能:读取温度//形式参数:无//返回值:单字节的温度值tt, unsigned char 类型uchar readtemp(void){uchar templ,temph,temp;uint temp_int;init_ds18b20();writebyte(0xCC);writebyte(0x44); //跳过ROM匹配,跳过读序列号的操作,可节省操作时间init_ds18b20(); //开始操作前需要复位writebyte(0xCC);writebyte(0xBE); //读暂存器中的温度值templ=readbyte(); //分别读取温度的低、高字节temph=readbyte();temp_int=temph;temp_int<<=8;temp_int|=templ;temp=temp_int*0.0625; //温度转换return(temp);}控制程序设计//程序:ds18b20.h//功能:ds18b20头文件,声明外部函数extern void delay5us(uchar n); //精确延时n*5μs子程序extern void init_ds18b20(void); //总线初始化复位extern uchar readbyte(void); //读取一个字节extern void writebyte(uchar); //写一个字节extern uchar readtemp(void); //读取温度DS18B20头文件如下。智能温度测量系统程序控制程序设计控制程序设计//功能:智能温度测量系统#include "reg51.h"#include "lcd.h"#include "ds18b20.h"//函数名:UartInit//函数功能:串口和定时器/计数器初始化设置//形式参数:无void UartInit(void){TMOD=0x21; //设置定时器T1为方式2,T0为方式1TL1=0xfd; //波特率为9600BdTH1=0xfd;TR1=1;SCON=0x40; //定义串行口工作于方式1,不接收PCON=0x00; //SMOD=0ES=1; //开串行口中断EA=1; //开总中断允许位REN=1; //接收允许}//函数名:UartSend//函数功能:串口发送数据//形式参数:待发送数据SendData,unsigned char数组类型//返回值: 无void UartSend(uchar SendData){SBUF=SendData; //发送第i个数据while(TI==0); //等待发送是否完成TI=0; //TI清0}//函数名:serial//函数功能:串行口中断接收函数void serial()interrupt 4 //串口中断类型号为4{uchar temp;EA=0; //关中断RI=0; //软件清除中断标志位temp=SBUF ; //接收数据UartSend(temp); //再送回PCif(temp=='A'){temp=readtemp(); //读取转换的温度UartSend(temp/10+0x30);//把温度值发送给PCUartSend(temp%10+0x30);}EA=1; //开中断}//函数名:time50ms//函数功能:在T0工作方式1下定时50ms,采用查询方式实现//形式参数:无符号整型变量i,控制定时时间,i*50ms//返回值:无void time50ms(uchar i) reentrant{uchar k;for(k=0;kTH0=(65536-50000)/256;//重新设置T0计数初值高8位,定时时间50msTL0=(65536-50000)%256; //重新设置T0计数初值低8位TR0=1; //启动T0while(!TF0);//查询计数是否溢出,即定时50ms时间到,TF0=1TF0=0; //50ms定时时间到,将T0溢出标志位TF0清0}}控制程序设计//函数名:lcd_wd//函数功能:显示温度值//形式参数:无符号字符型数据,温度值//返回值:无void lcd_wd(uchar temp){lcd_w_cmd(0x80);puts("Temprature is:");lcd_w_cmd(0xc0);putdata(temp);lcd_w_dat(0xdf);lcd_w_dat('C');}void main(void) //主函数{uchar temp;lcd_init(); //LCD初始化UartInit(); //串口和定时器/计数器初始化设置while(1){temp=readtemp(); //读取转换的温度lcd_wd(temp); //显示温度time50ms(20); //定时1s}}Thanks for your attention. 感谢您的观看 展开更多...... 收起↑ 资源列表 实例32 、实例33和实例34(课件) 《单片机基础与应用》(C语言版) 同步教学.pptx 实例35 简易数字电压表和实例36 信号发生器(课件) 《单片机基础与应用》(C语言版) 同步教学.pptx 实例37 数字钟(课件) 《单片机基础与应用》(C语言版) 同步教学.pptx 实例38 倒计时交通灯控制和实例39 16×16点阵显示屏移动广告牌(课件) 《单片机基础与应用》(C语言版) 同步教学.pptx 实例40 简易打字游戏机(课件) 《单片机基础与应用》(C语言版) 同步教学.pptx 实例41 智能温度测量(课件) 《单片机基础与应用》(C语言版) 同步教学.pptx