




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十章单片机典型模块应用1、任务:点亮LED灯在Keil软件编辑窗口输入以下程序:#include<AT89x51.H>sbitP3_0=P3^0;voidmain(void){while(1){P3_0=0;}}2、AT89S51单片机最小系统介绍单片机要工作必须具备以下条件:(1)+5V电源;(2)起振电路;(3)复位电路;(4)一块正常的单片机。注意:另外P0口要加上拉电阻,才有足够的驱动能力驱动外围器件工作;EA接高电平,表示单片机使用的是片内FLASHROM。3、任务:闪烁灯#include<AT89X51.H>voiddelay02s(void){unsignedchari,j,k;for(i=20;i>0;i--)for(j=20;j>0;j--)for(k=248;k>0;k--);}voidmain(void){while(1){P3_0=0;delay02s();P3_0=1;delay02s();}}要求:前面例子是让LED灯亮,现在实现LED灯的闪烁。4、任务:流水灯要求:做广告灯的左移右移,八个发光二极管分别接在单片机的P3.0-P3.7接口上,输出“0”时,发光二极管亮,左移右移按D1→D2→D3→D4→┅→D8→D7→D6→┅→D1亮,重复循环。4、任务:流水灯程序:#include<AT89X52.H>unsignedchari;unsignedchartemp;voiddelay(void)//延时子程序{ unsignedcharm,n,s; for(m=20;m>0;m--) for(n=20;n>0;n--) for(s=248;s>0;s--);}voidmain(void)//主程序{ while(1)//循环条件永远为真,以下程序一直执行下去。 {
续前页:temp=0x7f; P3=temp;//直接对I/O口P3赋值,使P3.7输出低点平。 delay();//延时 for(i=1;i<8;i++)//实现广告灯的从D1到D7移动 { temp=(temp>>1)|0x80; P3=temp; delay(); } temp=0xfe; P3=temp; delay(); for(i=1;i<8;i++)//实现广告灯的从D7到D1移动 { temp=(temp<<1)|0x01; P3=temp; delay(); } }}
思考:如何实现更为复杂的花样灯?参考程序:#include"reg51.h"#defineucharunsignedcharconstuchartab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,//下移0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,//上移 0xef,0xbd,0xdb,0xfe,//两边向中间移 0xdb,0xbd,0xef,//中间向两边移 0xaa,0x55,0xaa,0x55,0xaa,0x55,//1357,2468交替3次 0xf0,0x0f,0xf0,0x0f,//1234,5678交替2次 0x33,0xcc,0x33,0xcc,0x33,0xcc,//1256,3478交替3次 0x00};//结束码
uchart=0;////以下初始化子函数////voidsys_init(void){TMOD=0x01;TH0=0xd8;续前页:TL0=0xef;ET0=1;EA=1;TR0=1;}////以下主函数////voidmain(void){uchari=0;P3=tab[i];i++;sys_init();while(1){while(t<100);t=0;if(tab[i]==0x00){i=0;}P3=tab[i];i++;}}续左页:////以下定时器0中断函数////voidtimer0(void)interrupt1{TR0=0;TH0=0xd8;TL0=0xef;t++;TR0=1;}5、任务:按键识别要求:通过按下一次按键INT0,使小灯D1亮灭交替变换。实验原理:只要判断P3.2的电平就可以知道按键是否被按下;而在按键按下的过程中,由于机械抖动,将产生干扰,电平高低变化。可以采用软件滤波的方法去除这些干扰信号,在程序设计时,一旦发现P3.2为低电平,进入按键判断状态,软件延时10-20ms,从而避开了干扰信号区域,再重新检测P3.2状态,看按键是否真的已经按下。参考程序:include<AT89X52.H>sbitINT_0=P3^2;//定义按键的输入端sbitD1=P3^0;
//D1小灯定义voiddelay10ms(void)//延时程序{
unsignedchari,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);}key(
)
//按键判断程序{ if(INT_0==0)//判断是否按下键盘 { delay10ms(
);//延时,软件去干扰 if(INT_0==0)//确认按键按下 {
D1=!D1;//D1亮灭交替变化 }
while(INT_0==0);//按键锁定,每按一次D1只变化一次 }续前页:}main(){while(1)
//永远循环,扫描判断按键是否按下 { key();
//对于此处CPU只按键判断一直扫描; }}
课后请实践:1.用两个按键来控制D1的亮灭;2.使用一个按键,控制小灯亮的顺序D1→D2→D3→D4→┅→D8→D7→→┅D0亮重复循环;6、任务:数码管静态显示要求:用数码管LED的个位,静态显示数字“4”字样;注意:因采用共阴数码显示管,故此图P0口还应接1K或10K的排阻作为上拉电阻。参考程序:#include<AT89X52.H>sbitGE=P1^3;codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//显示段码main(){ unsignedchardisplay_date=4;//定义并赋值要显示的数据 while(1) { P0=seg7code[display_date];
//查表,输出 GE=0;//P1^3为低电平,相当于把数码管的4H端接地 }}课后请实践:1.让显示的数据动起来,比如做一个0到9的秒表(用软件延时);2.和按键判断程序结合,用按键控制数字变化;7、任务:数码管动态显示要求:用数码管LED的显示四位数据,比如显示数字“1234”;参考程序:#include<AT89X52.H>sbitqian=P1^0;sbitbai=P1^1;sbitshi=P1^2;sbitge=P1^3;codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示段码voidDelay(unsignedinttc)//延时程序{ while(tc!=0) //如果tc为0则终止延时 { unsignedinti; //局部正整数变量i for(i=0;i<100;i++); //执行400次将耗时1毫秒 tc--; //tc计数减一 }}续前页:voidLed(intdate)//显示函数{ qian=0;//P1.0输出低电平,选通千位数 P0=seg7code[date/1000];//取出千位数,查表,输出。 Delay(10);//延时 qian=1;//销隐 bai=0;//P1.1输出低电平,选通百位数 P0=seg7code[date%1000/100];//取出百位数,查表,输出。 Delay(10);//延时 bai=1;//销隐 shi=0;//P1.2输出低电平,选通十位数 P0=seg7code[date%100/10];//取出十位数,查表,输出。 Delay(10);//延时 shi=1;//销隐 ge=0; //P1.3输出低电平,选通十位数 P0=seg7code[date%10];//取出个位数,查表,输出。 Delay(10); ge=1;}
续前页:main(){intdisplay_date=1234;//定义并赋值要显示的数据while(1){Led(display_date);//调用显示函数显示数据display_date}}
上述数码管动态显示程序的另一种写法参考程序:#include<AT89X51.H>unsignedchardatebit[]={0xfe,0xfd,0xfb,0xf7};//存储数码管的位选值unsignedchartvdate[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,};unsignedintdisdata;//定义要显示的数据unsignedchardisdat[4];//存储要显示的四位数据voiddelay(time){unsignedchari,j;for(j=0;j<time;j++)for(i=0;i<250;i++);}display(void){ unsignedchark; disdata=1234;//显示1234
续前页:
disdat[0]=disdat/1000; //取出千位 disdat[1]=disdat%1000/100;
//取出百位 disdat[2]=disdat%100/10; //取出十位 disdat[3]=disdat%10; //取出个位 for(k=0;k<4;k++)
//显示四位数据 { P0=tvdate[disdat[k]];
//送出要显示数据的段码 P1=datebit[k]; //P2位选 delay(10); //延时 }}main(){while(1){display();}}
这种写法比上一种复杂,占用空间要多一些.但是使用方便,可以在此基础上方便的加上比如显示小数点,指定某位数码管闪烁等。课后思考:如何用软件延时来做一个0到60秒的计数器吗?8、任务:4X4矩阵键盘识别要求:用AT89S51的并行口P2接4×4矩阵键盘,以P3.0-P3.3作输入线,以P3.4-P3.7作输出线;在每一个数码管上显示每个按键的“0-F”序号。[实验原理]每个按键有它的行值和列值,行值和列值的组合就是识别这个按键的编码。矩阵的行线和列线分别通过两并行接口和CPU通信。键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。键盘识别的两种方法逐行扫描法:(1)首先判断有无键按下:令矩阵行线输出全0信号,检测列线状态,若有一列电平为低,则有键按下。(2)确定闭合键位置:依次将各行线置为低电平,逐行检测各列线的电平状态,若某列为低,则该行线和列线交叉处按键就是闭合键。线反转法:(1)令矩阵键盘列线输出全0信号,行线作为输入接口接收信号,可判断按键处于哪一行。(2)令矩阵键盘行线输出全0信号,列线作为输入接口接收信号,可判断按键处于哪一列。(3)将输入信号相或后形成键盘的唯一键码。程序:(线反转法)#include<reg52.h>unsignedcharcodeseg7code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsignedchark;voiddelay10ms(void)//延时程序{ unsignedchari,j; for(i=20;i>0;i--) for(j=248;j>0;j--);}voidGetch(){ unsignedcharX,Y,Z;
P2=0xff;
P2=0x0f;
//先对P2置数行扫描 if(P2!=0x0f)//判断是否有键按下 {
delay10ms();//延时,软件去干扰
if(P2!=0x0f)
//确认按键按下X=P2;
{
续前页:
X=P2;//保存行扫描时有键按下时状态 P2=0xf0;//列扫描 Y=P2;//保存列扫描时有键按下时状态 Z=X|Y;//取出键值 switch(Z)//判断键值(那一个键按下) { case0x77:k=0;break;//对键值赋值 case0x7b:k=1;break; case0x7d:k=2;break; case0x7e:k=3;break; case0xb7:k=4;break; case0xbb:k=5;break; case0xbd:k=6;break; case0xbe:k=7;break; case0xd7:k=8;break; case0xdb:k=9;break; case0xdd:k=10;break; case0xde:k=11;break; case0xe7:k=12;break; case0xeb:k=13;break; 续前页:
case0xed:k=14;break;
case0xee:k=15;break; } } }}voidmain(void){while(1){P2=0xff;Getch(
);P0=seg7code[k];//查表LED输出P1=0xf0;//输出相同的四位数据。}}
9、任务:按键中断识别要求:采用中断技术,每按一下按键,计数器加1,并用LED显示出来,注意只显示2位十进制数。原理:以上的两个关于按键识别的实验的程序都是采用扫描的方式来实现的,CPU的利用率比较低;按键判断还可以用中断方式来判断。中断方式可以满足快速响应的要求。程序:#include<AT89X51.H>unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsignedchardispcount=0;//计数sbitgewei=P1^3;//个位选通定义sbitshiwei=P1^2;//十位选通定义voidDelay(unsignedinttc)//延时程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}voidExtInt0()interrupt0//中断服务程序{续前页:dispcount++;//每按一次中断按键,计数加一if(dispcount==100)//计数范围0-99{dispcount=0;}}voidLED()//LED显示函数{if(dispcount>=10)//显示两位数{shiwei=0;P0=table[dispcount/10];Delay(8);shiwei=1;gewei=0;P0=table[dispcount%10];Delay(5);gewei=1;}else//显示一位数{
续前页:shiwei=1;gewei=0;P0=table[dispcount];Delay(8);}}
voidmain(){TCON=0x01;
//下降沿触发
IE=0x81;
//开总中断和允许外部中断
while(1)
//循环执行{LED(
);}
//调用显示函数}/*******************************************************************课后思考:在程序在硬件运行过程中,有时候按一下键会加几个数,是因为没有去除按键干扰请您想一想怎么消除抖动./***************************************************************************************/
10、任务:定时器T0的应用——9.9秒计时设计要求:开始时,显示“00”,第1次按下INT0后就开始计时。第2次按INT0后,计时停止。第3次按INT0后,计时归零。程序:#include<AT89X51.H>unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,};unsignedcharsec;//定义计数值,每过1/10秒,sec加一unsignedcharkeycnt=1;//键值判断unsignedinttcnt;//中断次数计数器
sbitgewei=P1^3;//个位选通定义sbitshiwei=P1^2;//十位选通定义sbitINT_0=P3^2;//按键定义位voidDelay(unsignedinttc)//延时程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}续前页:voidLED(
)//LED显示函数{shiwei=0;P0=table[sec/10]|0x80;//十位加上小数点Delay(5);shiwei=1;gewei=0;P0=table[sec%10];Delay(5);gewei=1;}voidKEY()//按键扫描程序{unsignedchari,j;if(INT_0==0){for(i=20;i>0;i--)//延时去干扰for(j=248;j>0;j--);续前页:if(INT_0==0){switch(keycnt)
//按下次数判断{case1:
//第一次按下TH0=0x06;
//对TH0TL0赋值TL0=0x06;TR0=1;
//开始定时keycnt=2;
//为第二次做准备break;case2:
//第二次按下TR0=0;
//定时结束keycnt=3;
//为第三次按下做准备break;case3:
//第三次按下keycnt=1;
//重新开始判断键值sec=0;
//计数重新从零开始break;}
续前页:while(INT_0==0);}}}voidt0(void)interrupt1using0//定时中断服务函数{tcnt++;//每过250us,tcnt加一if(tcnt==400)//计满400次(0.1秒)时{tcnt=0;//重新再计sec++;if(sec==100)//定时10秒,在从零开始计时{sec=0;}}}续前页:voidmain(void){TMOD=0x02;//定时器工作在方式2自动重装方式ET0=1;//允许T0产生中断EA=1;//开总中断sec=0;while(1){KEY();LED();}}11、任务:PC机与单片机通信要求:单片机串口通信的应用,通过串口,电脑和单片机系统进行通信。电脑作为上位机,向下位机单片机系统发送十六进制或者ASCLL码,单片机系统接收后,用LED显示接收到的数据和向上位机发回原样数据。单片机串口相关知识回顾(1)MCS-51串行口的原理结构图
单片机串口相关知识回顾(2)串行口控制寄存器SCON
SM0SM1SM2RENTB8RB8TIRID7D6D5D4D3D2D1D0
SMODGF1GF0PDIDLD7D6D5D4D3D2D1D0
(3)特殊功能寄存器PCON
单片机串口相关知识回顾(4)串口通信的波特率
对于方式0,波特率是固定的,为单片机时钟的1/12,即fosc/12。对于方式2,波特率有两种可供选择,即fosc/32和fosc/64。对应于以下公式:
波特率=fosc×(2^SMOD)/64对于方式1和方式3,波特率都由定时器T1的溢出率来决定,对应于以下公式:
波特率=(2^SMOD/32)×(定时器T1的溢出率)
而定时器T1的溢出率则和所采用的定时器工作方式有关,并可用以下公式表示:
定时器T1的溢出率=fosc/12×(2^n-X)程序:#include<AT89X51.H>unsignedchardat;//用于存储单片机接收发送缓冲寄存器SBUF里面的内容sbitgewei=P1^3;//个位选通定义sbitshiwei=P1^2;//十位选通定义unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};voidDelay(unsignedinttc)//延时程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}voidLED()//LED显示接收到的数据(十进制){shiwei=0;P0=table[dat/10];Delay(5);续前页:shiwei=1;gewei=0;P0=table[dat%10];Delay(5);gewei=1;}voidInit_Com(void)//功能:串口初始化,波特率9600,方式1{TMOD=0x20;PCON=0x00;SCON=0x50;TH1=0xFd;TL1=0xFd;TR1=1;}续前页:voidmain()//实现接收数据并把接收到的数据原样发送回去///////{Init_Com();//串口初始化while(1){if(RI)//扫描判断是否接收到数据,{dat=SBUF;//接收数据SBUF赋与datRI=0;//RI清零(必须用软件清零)SBUF=dat;//再原样把数据发送回去}LED();//显示接收到的数据}}12、任务:数模转换器ADC0804的应用(扩展)要求:从ADC0804的通道IN+输入0-5V之间的模拟量,通过ADC0804转换成数字量在数码管上以十进制形成显示出来。程序:#include<reg52.h>codeunsignedcharseg7code[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示段码sbitint1=P3^3;//定义管脚功能sbitcs=P3^2;sbitwr=P3^6;sbitrd=P3^7;voidDelay(unsignedinttc)//显示延时程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}unsignedcharadc0804(void)//读AD0804子程序{unsignedcharaddata,i;rd=1;wr=1;int1=1;//读ADC0804前准备P1=0xff;//P1全部置一准备cs=0;wr=0;wr=1;//启动ADC0804开始测电压while(int1==1);//查询等待A/D转换完毕产生的INT(低电平有效)信号rd=0;//开始读转换后数据续前页:i=i;i=i;//无意义语句,用于延时等待ADC0804读数完毕addata=P1;//读出的数据赋与addatard=1;cs=1;//读数完毕return(addata);//返回最后读出的数据}unsignedintdatpro(void)
//ADC0804读出的数据处理{unsignedcharx;unsignedintdianyah,dianyal;
//用于存储读出数据的高字节和低字节unsignedintdianya=0;
//存储最后处理完的结果注意数据类型for(x=0;x<10;x++)
//将10次测得的结果存储在dianya中{dianya=adc0804()+dianya;}dianya=dianya/10;
//求平均值dianyah=dianya&0xf0;
//屏蔽低四位dianyah=dianyah>>4;
//右移四位取出高四位dianyal=dianya&0x0f;
//屏蔽高四位取出低四位dianya=dianyal*20+dianyah*320;
//最后的结果是一个四位数,便于显示return(dianya);//返回最后处理结果}续前页:voidLed(){unsignedintdate;date=datpro();//调用数据处理最后结果P2=P2&0xef;P0=seg7code[date/1000]|0x80;//输出个位数和小数点Delay(8);P2=P2|0xf0;P2=P2&0xdf;P0=seg7code[date%1000/100];//输出小数点后第一位Delay(8);P2=P2|0xf0;P2=P2&0xbf;P0=seg7code[date%100/10];//输出小数点后第二位Delay(8);P2=P2|0xf0;P2=P2&0x7f;P0=seg7code[date%10];//输出小数点后第三位Delay(8);P2=P2|0xf0;}main(){while(1){Led();//只需调用显示函数}}13、任务:模数转换器DAC0832的应用要求:用两个按键通过单片机控制DAC0832的输出,使OUT端可以输出0—5V的幅值,频率为1KHZ的锯齿波和三角波两种波形。通上电源后;按下INT1则输出三角波,再按下INT0输出锯齿波。[实验原理]DAC0832是8位全MOS中速D/A转换器,采用R—2RT形电阻解码网络,转换结果为一对差动电流输出,转换时间大约为1us。使用单电源+5V―+15V供电。参考电压为-10V-+10V。在此我们直接选择+5V作为参考电压。DAC0832有三种工作方式:直通方式,单缓冲方式,双缓冲方式;在此我们选择直通的工作方式,将XFER、WR1、WR2和CS管脚全部接数字地。管脚8接参考电压,在此我们接的参考电压是+5V。那么经过第一级运放后,输出电压将是-5V-0V,在经过第二级运放反相放大1倍以后将可以输出0V—5V了。再控制P1口输出数据有规律的变化将可以产生三角波,锯齿波,梯型波等波形了。程序:#include<AT89X51.H>unsignedcharkeycnt=0;//波形标志unsignedchartcnt=0;//键值判断bitsjz=0;//产生三角波时上升、下降用到的标志voiddelayl()
//延时子程序{unsignedchari,j;for(i=20;i>0;i--)for(j=248;j>0;j--);}voidKEY()
//按键扫描程序{if(P3_2==0){delayl();//延时跳过按下时的抖动if(P3_2==0){keycnt=0;
//定时器产生锯齿波标志TR0=0;
//暂时停止波形输出TH0=0x256-40;
//对TH0TL0赋值TL0=0x256-40;TR0=1;
//开始定时,产生锯齿波续前页:while(P3_2==0);//如果一直按着键,则等待键松开delayl();//延时跳过松开后的抖动}}if(P3_3==0){delayl();//延时跳过按下时的抖动if(P3_3==0){keycnt=1;//定时器产生三角波标志TR0=0;//暂时停止波形输出TH0=0x256-40;//对TH0、TL0赋值TL0=0x256-40;TR0=1;//开始定时产生三角波}while(P3_2==0);//如果一直按着键,则等待松键开delayl();//延时跳过松开后的抖动}}续前页:voidt0(void)interrupt1using0//定时中断服务函数{if(keycnt==0)//产生锯齿波{P0=tcnt;tcnt=+0x0a;//步进0.2V/一次中断if(tcnt==0xfb){tcnt=0;}}if(keycnt==1)//产生三角波{if(sjz==0){P0=tcnt;tcnt=+0x0a;//步进0.2V/一次中断if(tcnt==0xfa){sjz=1;}}if(sjz==1)续前页:{P0=tcnt;Tcnt-=0x0a;if(tcnt==0){sjz=0;}}}}voidmain(void){TMOD=0x02;//定时器工作在方式2ET0=1;EA=1;while(1){KEY();}}14、任务:24C08的读写操作要求:利用24C08断电以后存储的数据不消失的特点,可以做一个断电保护装置。首先利用单片机做一个0—99秒的自动计时器。然后随机关断电源,在通电以后计时器接着断电前的状态继续计时。[实验原理——引脚图][实验原理——总线协议][实验原理——写周期时序和起始、停止时序][实验原理——器件寻址][实验原理——器件寻址][实验原理——写操作]注意:I2C总线数据都是高位在前,低位在后!![实验原理——写操作][实验原理——读操作][实验原理——读操作][实验原理——读操作]程序:#include<AT89X52.H>#include<stdio.h>#include<absacc.h>unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsignedcharsec;//定义计数值,每过1秒,sec加1unsignedinttcnt;//定时中断次数bitwrite=0;//写24C08的标志;sbitgewei=P1^3;//个位选通定义sbitshiwei=P1^2;//十位选通定义/////////24C08读写驱动程序开始////////////////////sbitscl=P3^6;//24c08SCLsbitsda=P3^7;//24c08SDAvoiddelay1(unsignedcharx){unsignedinti;for(i=0;i<x;i++);;}voidflash()
//延时2us{;;}voidx24c08_init()//24c08初始化子程序{scl=1;flash();sda=1;flash();}voidstart()//启动I2C总线{sda=1;flash();scl=1;flash();sda=0;flash();scl=0;flash();}voidstop()//停止I2C总线{sda=0;flash();scl=1;flash();sda=1;flash();}voidwritex(unsignedcharj)//写一个字节{unsignedchari,temp;temp=j;for(i=0;i<8;i++){temp=temp<<1;scl=0;flash();sda=CY;flash();scl=1;flash();}scl=0;flash();sda=1;flash();}unsignedcharreadx()//读一个字节{unsignedchari,j,k=0;scl=0;flash();sda=1;for(i=0;i<8;i++){flash();scl=1;flash();if(sda==1)j=1;elsej=0;k=(k<<1)|j;scl=0;}flash();return(k);}voidclock()//I2C总线时钟,确认应答信号{unsignedchari=0;scl=1;flash();while((sda==1)&&(i<255))i++;scl=0;flash();}////////从24c08的地址address中读取一个字节数据/////unsignedcharx24c08_read(unsignedcharaddress){unsignedchari;//先发写命令、写地址start();writex(0xa0);clock();writex(address);clock();//再发读命令,读数据start();writex(0xa1);clock();i=readx();stop();delay1(10);return(i);}//////向24c08的address地址中写入一字节数据info/////voidx24c08_write(unsignedcharaddress,unsignedcharinfo){EA=0;start();writex(0xa0);clock();writex(address);clock();writex(info);clock();stop();EA=1;delay1(50);}/////////////以上24C08读写驱动程序完/////////////////////voidDelay(unsignedinttc)
//延时程序{while(tc!=0){unsignedinti;for(i=0;i<100;i++);tc--;}}voidLED()//LED显示函数{shiwei=0;P0=table[sec/10];Delay(5);shiwei=1;gewei=0;P0=table[sec%10];Delay(5);gewei=1;}voidt0(void)interrupt1using0//定时中断服务函数{TH0=(65536-50000)/256;//对TH0TL0赋值TL0=(65536-50000)%256;//重装计数初值tcnt++;//每过250usttcnt加一if(tcnt==20)//计满20次(1秒)时{tcnt=0;sec++;write=1;//1秒写一次24C08if(sec==100)//定时100秒,在从零开始计时{sec=0;}}}voidmain(void){TMOD=0x01;//定时器工作在方式1ET0=1;EA=1;x24c08_init();//初始化24C08sec=x24c08_read(2);//读出保存的数据赋于secTH0=(65536-50000)/256;//对TH0TL0赋值TL0=(65536-50000)%256;//使定时器0.05秒中断一次TR0=1;//开始计时while(1){LED();if(write==1)//判断计时器是否计时一秒{write=0;//清零x24c08_write(2,sec);//在24c08的地址2写入数据sec}}}15、任务:LCD1602液晶模块应用要求:LCD1602字符型液晶显示实验。在屏幕的第一行显示“224166320@”,第二行则显示“Tel:1308645xxxx”[实验原理——LCD基础知识]LCD显示器是一种利用液晶的扭曲/向列效应制成的新型显示器。具有体积小、重量轻、功耗低、抗干扰能力强等优点,因而在单片机系统中被广泛应用。[实验原理——LCD结构及工作原理]LCD本身不发光,是通过借助外界光线照射液晶材料而实现显示的被动显示器件。向列型液晶材料被封装在上、下两片导电玻璃电极之间,液晶分子平行排列,上下扭曲90度,外部入射光线通过上偏振片后形成偏振光,该偏振光通过平行排列的液晶材料后被旋转90度,再通过与上偏振片垂直的下偏振片,被反射极反射过来,呈透明状态。若在上、下电极之间加一定电压,在电场的作用下迫使加在电极部分的液晶分子转成垂直排列,其旋光作用也随之消失,致使从上偏振片入射的偏振光不旋转,光无法通过下偏振片返回,呈黑色。去掉电压后,液晶分子又恢复其扭转结构。实验原理——SMC1602A液晶模块引脚功能实验原理——液晶控制器接口说明实验原理——液晶控制器接口说明实验原理——液晶控制器接口说明实验原理——液晶控制器接口说明实验原理——1602液晶控制器自带标准字库每一个字符都有一个固定的代码,比如“A”的代码是41H,显示时模块把41H中的点阵字符图形显示出来,就能看到字母“A”。#include<AT89x52.h>#include<INTRINS.h>#defineucharunsignedchar#defineuintunsignedint#defineDOUTP0sbitrs=P2^0;sbitrw=P2^1;sbite=P2^7;codeuchartab1[]={0x32,0x32,0x34,0x31,0x36,0x36,0x33,0x32,0x30,0x40,0x71,0x71,0x2e,0x63,0x6f,0x6d,0xff,};codeuchartab2[]={0x54,0x65,0x6c,0x3a,0x20, 0X31,0X33,0x30,0x38,0x36,0x34,0x35,0x78,0x78,0x78,0x78,0xff,};//延时函数voiddelayms(unsignedintms){unsignedchari;while(ms--){for(i=0;i<120;i++);}}参考示例程序(LCD16021.0版)//以下为读忙状态的时序程序unsignedcharread_status(void){unsignedcharLCD_Status;DOUT=0xff;rs=0;rw=1;e=1;delayms(1);LCD_Status=DOUT;e=0;returnLCD_Status;}//以下为写命令的时序程序voidwrite_com(unsignedcharcmd){while((read_status()&0x80)==0x80);rs=0;rw=0;e=0;P0=cmd;e=1;delayms(1);e=0;}//以下为液晶初始化程序voidlcd_ini(void){write_com(0x38);delayms(1);write_com(0x01);delayms(1);write_com(0x06);delayms(1);write_com(0x0c);delayms(1);}//以下为写数据的时序程序voidwrite_dat(unsignedchardat){while((read_status()&0x80)==0x80);rs=1;rw=0;e=0;P0=dat;e=1;delayms(1);e=0;}//以下为主函数voidmain(void){uchari=0;lcd_ini();write_com(0x80);//设置第一行数据地址指针,为80H+地址码delayms(1);while(tab1[i]!=0xff){write_dat(tab1[i]);i++;delayms(1);}i=0;write_com(0xc0);//设置第二行数据地址指针,为80H+地址码delayms(1);while(tab2[i]!=0xff){write_dat(tab2[i]);i++;delayms(1);}i=0;while(1);}思考:如何利用总线控制方式显示字符?1、添加头文件包含语句:#include“absacc.h”2、添加宏定义语句:#defineLCD_W_COMXBYTE[0x7cff]#defineLCD_W_DATXBYTE[0X7dff]#defineLCD_R_COMXBYTE[0x7eff]3、修改读忙状态、写命令和写数据的时序程序。例:unsignedcharread_status(void){unsignedcharLCD_Status;LCD_Status=LCD_R_COM;returnLCD_Status;}重要提示:参考程序://LCD1602.C//液晶控制与显示程序#include<reg51.h>#include<intrins.h>sbitRS=P2^0;//寄存器选择位,将RS位定义为P2.0引脚sbitRW=P2^1;//读写选择位,将RW位定义为P2.1引脚sbitEN=P2^2;//使能信号位,将E位定义为P2.2引脚//延时函数voiddelayms(unsignedintms){unsignedchari;while(ms--){for(i=0;i<120;i++);}}该液晶显示程序的另一种写法(LCD16022.0版)//忙检测函数unsignedcharbusy_check(void){unsignedcharLCD_Status;//定义忙状态变量RS=0;RW=1;EN=1;delayms(1);LCD_Status=P0;//读取忙状态EN=0;returnLCD_Status;//返回忙状态}//写命令voidwrite_LCD_Command(unsignedcharcmd){while((busy_check()&0x80)==0x80);//等待忙状态结束RS=0;RW=0;EN=0;P0=cmd;EN=1;delayms(1);EN=0;}//写数据voidwrite_LCD_data(unsignedchardat){while((busy_check()&0x80)==0x80);RS=1;RW=0;EN=0;P0=dat;EN=1;delayms(1);EN=0;}//初始化voidinit_LCD(void){write_LCD_Command(0x38);//显示模式设置delayms(1);write_LCD_Command(0x01);//清屏delayms(1);write_LCD_Command(0x06);//字符进入模式:屏幕不动,字符后移delayms(1);write_LCD_Command(0x0c);//显示开,关光标delayms(1);}//显示字符串voidShowString(unsignedcharx,unsignedchary,unsignedchar*str){unsignedchari=0;//设置起始位置if(y==0){write_LCD_Command(0x80|x);}if(y==1){write_LCD_Command(0xc0|x);}//输出字符串for(i=0;i<16;i++){write_LCD_data(str[i]);}}//主函数voidmain(void){init_LCD();ShowString(0,0,"224166320@");ShowString(0,1,"Tel:1308645xxxx");while(1);}基本思路:将一个文件的程序按照其模块功能划分为两个或两个以上的文件,每个文件表示系统实现特定的功能。如本程序可分为主函数C文件、液晶显示C文件、液晶显示头文件、includes头文件。//main.c:#include"includes.h"voidmain(void){init_LCD();ShowString(0,0,"224166320@");ShowString(0,1,"Tel:1308645xxxx");while(1);}大型模块化程序的肇始(LCD16023.0版)//lcd1602test.c:#include<reg51.h>#include<LCD1602.h>voidShowString(unsignedcharx,unsignedchary,unsignedchar*str){unsignedchari=0;if(y==0){write_LCD_Command(0x80|x);}if(y==1){write_LCD_Command(0xc0|x);}for(i=0;i<16;i++){write_LCD_data(str[i]);}}大型模块化程序的肇始(LCD16023.0版)//includes.h:#ifndef__INCLUDES_H__#define__INCLUDES_H__#include<reg51.h>#include<intrins.h>voidShowString(unsignedcharx,unsignedchary,unsignedchar*str);init_LCD();#endif大型模块化程序的肇始(LCD16023.0版)//lcd1602.h:#ifndefLCD_CHAR_1602_2010_11_8#defineLCD_CHAR_1602_2010_11_8sbitRS=P2^0;//寄存器选择位,将RS位定义为P2.0引脚sbitRW=P2^1;//读写选择位,将RW位定义为P2.1引脚sbitEN=P2^2;//使能信号位,将E位定义为P2.2引脚voiddelayms(unsignedintms){unsignedchari;while(ms--){for(i=0;i<120;i++);}}大型模块化程序的肇始(LCD16023.0版)接上页://忙检测函数unsignedcharbusy_check(void){unsigne
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 代卖公司合同范本
- 产品抵押工资合同范本
- 内部购买服务合同范本
- 999玫瑰买卖合同范本
- 云南土地流转合同范本
- 04购房合同范例
- 无锡锦鲤池过滤器施工方案
- 主体盖房合同范本
- app监控合同范本
- 公司安全协议合同范本
- 接触网设备结构-接触网的组成
- 全国青少年机器人技术等级考试二级第一课-直升机课件
- 数学原来可以这样学:小学篇
- 建设用地报批服务投标方案(技术方案)
- 史赛克关节镜系统
- 大豆玉米带状复合种植技术
- 2024届高考语文一轮复习:现代诗歌 专练(含答案)
- 初中生物学七年级下册第四单元《生物圈中的人》 单元作业设计
- 《公路桥涵养护规范》(5120-2021)【可编辑】
- 2023年中国(安徽)大学生茶文化创新大赛试题库
- 锂离子电池简介课件
评论
0/150
提交评论