失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > AutoLeaders控制组——C51单片机学习笔记--定时器串口通信LED点阵屏

AutoLeaders控制组——C51单片机学习笔记--定时器串口通信LED点阵屏

时间:2019-07-05 10:19:33

相关推荐

AutoLeaders控制组——C51单片机学习笔记--定时器串口通信LED点阵屏

目录

1. 中断系统介绍

2. 定时器工作原理

3. 定时器实验

4. 串口相关寄存器

5. 串口工作原理

6. 串口收发数据实验

7. 移位寄存器74HC595

8. 点阵屏工作原理

9. 点阵屏实验

1. 中断系统介绍

中断系统是CPU工作中必不可少的一部分,它为CPU计算处理多任务提供了更高的可靠性,提高了CPU利用效率。

简单来说,我们可以将中断系统理解成一个紧急情报员,当CPU在处理程序时,外界突然通过中断系统发来紧急处理请求,这时CPU就会转向处理优先级高的程序接着在处理优先级低的程序,最后回到中断点来处理刚刚没处理完的程序。

STC89C52系列单片机提供了8个中断请求源,它们分别是:外部中断 O(INTO)、外部中断1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定时器0中断、定时器 1 中断、定时器 2 中断、串口(UART)中断。

上述原理图中INT0和INT1外部中断可分别由IT0和IT1来选择是低电平还是下降沿有效,当CPU检测到对应的P3_2或P3_3引脚的有效信号,IE0或IE1就会置1然后向CPU申请中断,CPU会通过判断优先级来处理中断请求。

2. 定时器工作原理

上述图片简单地展现了定时器和中断系统的连接原理,单片机内有两个可编程的定时器T0和T1。定时器的实质是一个自加1的计数器,定时器通过自加1的脉冲来计时,脉冲时间与晶振的频率有关,定时器不断加1直到最后溢出,溢出时中断系统会相应标志位置1,然后向CPU发送中断请求,同时定时器会归零然后再次循环。

定时器中有一些寄存器来控制定时器,寄存器是一种特殊的RAM存储器,它不仅可以储存读取数据,也可以作为单片机电路的控制器。

通过配置特殊功能的寄存器,我们就可以来控制定时器并通过定时器计时来实现一些好玩的功能了。

3. 定时器实验

我们需要利用中断系统来计数,并利用LCD液晶屏来作为定时器的显示屏。

# include <REGX52.H># include <stdio.h># include <intrins.h># include "LCD1602.h"void Timer0Init(void)//定时器0初始化{TMOD &= 0xF0;TMOD |= 0x01;TL0 = 0x18;TH0 = 0xFC;TF0 = 0;TR0 = 1;ET0=1;EA=1;PT0=0;}unsigned int Num=0,count,s=0,m=0,h=0;void main(){ Timer0Init();LCD_Init();LCD_ShowString(1,1,"Clock:");LCD_ShowString(2,4,":");LCD_ShowString(2,7,":");while (1){LCD_ShowNum(2,2,h,2);LCD_ShowNum(2,5,m,2);LCD_ShowNum(2,8,s,2);}}void Timer0Routine() interrupt 1{static unsigned int count=0;TL0 = 0x18;TH0 = 0xFC;count++;if(count>=1000){s++;count=0;if(s>=60){m++;s=0;if(m>=60){h++;m=0;if(h>=24){h=0;}}}}}

通过配置几个特殊功能寄存器和赋予优先级就可以实现定时的功能了,写程序时可以用stc软件里的定时器计算器会自动生成定时器代码,在软件里设置定时器参数要注意波特率的大小、定时器的工作模式和定时器时,最后记得在中断函数里初始化TH0和TL0状态与定时器里一样。

4. 串口相关寄存器

单片机内与串口有关的主要寄存器:串行控制寄存器SCON、波特率选择特殊功能寄存器PCON、数据缓冲寄存器SBUF、中断相关寄存器IE、IPH和IP。

串行控制寄存器SCON:

通过控制寄存器SCON中的位REN来允许或禁止单片机接收端RXD接收信息,其中REN=1为允许接受状态,而REN=0为禁止接受状态。

通过控制寄存器SCON中的发送中断标志位TI实现中断请求,TI=1为向CPU申请中断,响应后令TI=0来实现复位。

通过控制寄存器SCON中的接收中断标志位RI实现中断请求,TI=1为向CPU申请中断,响应后令TI=0来实现复位。

波特率特殊功能寄存器PCON:

通过控制寄存器PCON中的波特率选择位SMOD来选择波特率是否加倍,SMOD=1则波特率加倍,SMOD=0则波特率不加倍,令SMOD=0来实现复位。

数据缓冲寄存器SBUF:

通过给寄存器SBUF赋16进制值来实现数据的输入和输出,输入时可以通过串口来控制单片机的外设。

中断相关寄存器IE、IPH、IP:

通过控制寄存器IE中的CPU总中断允许控制位EA实现CPU中断,EA=1则CPU开放中断申请,EA=0则CPU禁止中断申请。

通过控制寄存器IE中的串口中断允许控制位ES实现串口中断,ES=1则允许串口中断,ES=0则禁止串口中断。

5. 串口工作原理

发送开始时,先把起始位0输出到TXD引脚,然后发送移位寄存器的输出位D0到TXD引脚,每一个移位脉冲都使输出移位寄存器的各位向右移一位,并由TXD引脚输出。第一次移位时,停止位"1"移入输出移位寄存器的第9位,以后每次移位左边都移入0。当停止位移至输出位时,左边其余位全为0,当检测到这一条件时,控制电路进行最后一次移位并置TI=1,请求中断。

接收数据时,数据从右边移入输入移位寄存器,在起始位0移到最左边时,控制电路进行最后一次移位。当RI=0且SM2=0(或接收到的第9位数据为1)时,接收到的数据装入接收缓冲器SBUF和RB8(接收数据的第9位),置RI=1,向CPU请求中断。如果条件不满足,则数据丢失且不置位RI,继续搜索RXD引脚的负跳变。

6. 串口收发数据实验

首先我们要配置好定时器和中断系统,接着配置串口有关的寄存器即可,还要定义两个子函数用于数据的收发。

# include <REGX52.H># include <stdio.h># include <intrins.h># include "delay.h"sfr AUXR = 0x8e;void UartInit(void)//9600bps@12.000MHz{PCON &= 0x7F;//波特率不倍速SCON = 0x50;//8位数据,可变波特率AUXR &= 0xBF;//定时器时钟12T模式AUXR &= 0xFE;//串口1选择定时器1为波特率发生器TMOD &= 0x0F;//设置定时器模式TMOD |= 0x20;//设置定时器模式TL1 = 0xFD;//设置定时初始值TH1 = 0xFD;//设置定时重载值ET1 = 0;//禁止定时器%d中断TR1 = 1;//定时器1开始计时EA = 1;ES = 1;}void Uart_Send(unsigned char a){SBUF=a;while(TI==0);TI=0;}void main(){UartInit();while(1){}}void Uart_Routine() interrupt 4{if (RI==1){P2=SBUF;RI=0;}}

上述程序中UART是串行异步通信接口标准,Uart_Send子函数通过配置SBUF寄存器来实现数据通过电脑发到单片机上,Uart_Routine子函数则通过读取电脑写入到SBUF寄存器里的数据利用中断来使LED点亮。

上述程序实现了串口收发数据,其中记得在头文件处用sfr声明可位寻址的AUXR,因为在头文件<REGX52.H>里并没有声明该特殊功能寄存器地址。

7. 移位寄存器74HC595

移位寄存器74HC595是一个串行转并行的寄存器,主要是用来控制LED点阵屏的哪一列亮,点阵屏原理有点类似矩阵键盘和数码管,74HC595实现了控制三个引脚来实现数据的输入。

每个数据1或0从串行数据口SER端进入,当SERCLK=1即给高电平触发上升沿时,数据就会进入到寄存器内部,接着SECLK=0即给低电平触发下降沿来储存数据。每次以此类推,每8个0或1就会沿着QA-->QB-->QC-->...-->QH的方向进入并储存到寄存器内,最后RCLK=1即给高电平触发上升沿进行数据锁存,从D0到D7引脚输入到LED点阵屏内。

8. 点阵屏工作原理

点阵屏与数码管一样是共阴极连接,所以需要给高电平即1来点亮,将高低电平的二进制数转化为16进制数后直接赋值给可位寻址的P0引脚即可点亮每一列对应的LED灯了。

需要注意的是为了实现LED点阵屏的动态显示效果,我们需要进行与数码管类似操作,利用人眼余晖和快速扫描的原理,还要利用封装好的delay模块来防止点阵屏出现上次扫描后的显示留存。

9. 点阵屏实验

首先我们先构建一个点阵屏扫描显示模块,然后在主函数中调用该模块并利用数组储存一些动态显示动画,可以利用软件来生成动画的相应点阵来给P0赋值。

# include <REGX52.H># include <stdio.h># include "delay.h"sbit RCK=P3^5;sbit SCK=P3^6;sbit SER=P3^4;unsigned int i;void LEDMatrix_Init(){SCK=0;RCK=0;}void LEDMatrix_Show(unsigned char column,unsigned char Num){for (i=0;i<8;i++){SER=column&(0x80>>i);SCK=1;SCK=0;}RCK=1;RCK=0;P0=~(0x80>>Num);delay(1);}

以上是封装好的点阵屏扫描显示模块,需要在头文件处声明几个不可寻址位,就是我们上面说的与74CH595有关的位用于实现数据移位和锁存,接着按原先讲过的步骤分别给位赋高低电平,然后再写for循环来扫描点阵屏的每一列,最后再把每一列的点阵赋给P0,这样LED点阵屏就可以按我们想要的效果发光。

# include <REGX52.H># include <stdio.h># include "delay.h"# include "LEDMatrix.h"sbit RCK=P3^5;sbit SCK=P3^6;sbit SER=P3^4;unsigned char j=0,count=0,set=0;void main(){unsigned char code Data0[48]={0x00,0x42,0x42,0x7E,0x42,0x42,0x00,0x00,0x00,0x30,0x48,0x44,0x22,0x44,0x48,0x30,0x00,0x00,0x00,0x00,0x40,0x60,0x30,0x1E,0x30,0x60,0x40,0x00,0x18,0x24,0x42,0x42,0x42,0x24,0x18,0x00,0x00,0x7C,0x02,0x02,0x02,0x7C,0x00,0x00,0x7A,0x00,0x00,0x00,};unsigned char code Data1[80]={0x00,0x00,0x40,0x60,0x30,0x1F,0x30,0x60,0x46,0x09,0x09,0x06,0x00,0x0E,0x01,0x01,0x0E,0x00,0x00,0x00,0x00,0x00,0x0E,0x11,0x11,0x0E,0x02,0x08,0x1F,0x10,0x10,0x00,0x0E,0x15,0x15,0x0C,0x00,0x00,0x00,0x00,0x08,0x1F,0x09,0x00,0x7F,0x10,0x0F,0x00,0x0E,0x15,0x15,0x0C,0x00,0x00,0x00,0x00,0x06,0x09,0x09,0x06,0x00,0x0F,0x04,0x08,0x0F,0x00,0x3F,0x01,0x00,0x19,0x05,0x1F,0x00,0x00,0x00,0x7D,0x00,0x00,0x00,0x00,};unsigned char code Data2[5][8]={{0x78,0x84,0x82,0x41,0x41,0x82,0x84,0x78},{0x00,0x38,0x44,0x22,0x22,0x44,0x38,0x00},{0x00,0x00,0x10,0x28,0x28,0x10,0x00,0x00},{0x00,0x38,0x44,0x22,0x22,0x44,0x38,0x00},{0x78,0x84,0x82,0x41,0x41,0x82,0x84,0x78},};LEDMatrix_Init();while(1){if(P3_1==0){delay(20);while(P3_1==0);delay(20);count=0;set=0;while(P3_0!=0&&P3_2!=0&&P3_3!=0){for (j=0;j<8;j++){LEDMatrix_Show(Data0[j+set],j);}count++;if (count>10){count=0;set++;if(set>40){set=0;}}}} if(P3_0==0){delay(20);while(P3_0==0);delay(20);count=0;set=0;while(P3_1!=0&&P3_2!=0&&P3_3!=0){for (j=0;j<8;j++){LEDMatrix_Show(Data1[j+set],j);}count++;if (count>10){count=0;set++;if(set>72){set=0;}}}}if(P3_2==0){delay(20);while(P3_2==0);delay(20);count=0;set=0;while(P3_0!=0&&P3_1!=0&&P3_3!=0){for (j=0;j<8;j++){LEDMatrix_Show(Data2[set][j],j);}count++;if (count>30){count=0;set++;if(set>=5){set=0;}}}}}}

上述程序展示的是主函数,主函数通过调用点阵屏扫描显示模块来实现既定的动画显示效果,

这里我结合独立按键做了一个更好玩的小实验,仅供参考。

C51单片机LED点阵屏实验

如果觉得《AutoLeaders控制组——C51单片机学习笔记--定时器串口通信LED点阵屏》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。