目录
一、串口介绍
1、双向串口通信
2、电平标准
3、常用通信协议
4、时序图
二、串口收发数据(模式1)
1、串行控制(模式选择)寄存器SCON(可位寻址)
2、串行口数据缓冲寄存器SBUF
3、电源控制(波特率配置)寄存器PCON(不可位寻址)
4、串行口中断相关寄存器IE、IPH、IP
5、串口通信的模式选择/定时器的模式选择
6、单片机每隔1秒向电脑发送数据
7、电脑向单片机发送数据控制LED,单片机回传相同文本
三、LED点阵
1、LED点阵的原理
2、LED点阵的消影
3、使用LED点阵绘制爱心
4、使用LED点阵播放流水文字
一、串口介绍
串口是一种应用广泛的通讯接口,成本低廉,可以实现两个设备之间的互相通信。
单片机的串口可以使单片机与单片机、电脑、各式模块进行互相通信。
51单片机内部自带UART(通用异步收发器),实现单片机串口通信功能。
1、双向串口通信
1、简单的双向串口通信必须要有TXD、RXD、GND,而VCC看情况,如果是模块设备,则需要VCC;
2、TXD与RXD交叉链接;
3、仅需单向数据传输时,可以仅使用一根通信线;
4、当电平标准不一致时,需要加电平转换芯片(比如设备1串口输出电压12V,而设备2的串口标准电压为5V,会烧坏设备2)
2、电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系。
串口常用的电平标有三种:
TTL电平 | 低电平 | 输出电平小于0.8V或输入电平小于1.2V |
高电平 | 输出电平大于2.4V或输入电平高于2V | |
RS232 | 低电平 | 0V |
高电平 | -3~-15V | |
RS485 | 低电平 | 两线压差-2~-6V(差分信号) |
高电平 | 两线压差+2~+6V(差分信号) |
3、常用通信协议
常见通信接口还有CAN和USB等。
全双工(双行道) | 通信双方可以在同一时刻互相传输数据 |
半双工(单行道) | 通信双方可以互相传输数据,但必须分时复用一根数据线 |
单工 (单向道) | 只能单向传输 |
异步(近似同步) | 通信双方各自约定好通信速率 |
同步 | 通信双方靠一根时钟线来约定通信速率 |
总线 | 连接各个设备的数据传输线路(类似马路,连接路边住户,使用户交流) |
4、时序图
检验位有奇校验、偶校验、0校验、1校验等。例如发送数据位0000 0011,进行偶校验,那么发送数据位0000 0011 1,发送时从低位到高位进行发送,对方接收数据后拿着这个校验位进行校验,如果1的个数为奇数,那么传输的数据有误。当然这种方式是检测不出接收数据为0000 0101 1的错误的(这种方法1的数量为偶数,但是所处位置不同,是测不出异常的)。
二、串口收发数据(模式1)
串行口相关寄存器:
1、串行控制(模式选择)寄存器SCON(可位寻址)
51系列单片机UART的工作模式:
模式0 | SM0、SM1 | 00 | 同步移位寄存器 |
模式1 | 01 | 8位UART,波特率可变(发送和接收各数据位的时间间隔)(常用) | |
模式2 | 10 | 9位UART,波特率固定 | |
模式3 | 11 | 9位UART,波特率可变 |
2、串行口数据缓冲寄存器SBUF
SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器。
3、电源控制(波特率配置)寄存器PCON(不可位寻址)
PCON本质是电源控制寄存器,因为比特位还有空余,放了两个和串口通信有关系的位SMOD和SMOD0。对于串口通信来说,PCON是波特率配置寄存器。
4、串行口中断相关寄存器IE、IPH、IP
PS | PSH | 优先级 |
0 | 0 | 串口1中断为最低优先级中断(优先级0) |
1 | 0 | 串口1中断为较低优先级中断(优先级1) |
0 | 1 | 串口1中断为较高优先级中断(优先级2) |
1 | 1 | 串口1中断为最高优先级中断(优先级3) |
5、串口通信的模式选择/定时器的模式选择
此处串口使用模式1。
注意51系列单片机不能使用定时器0进行定时。这里使用定时器1+模式二:8位自动重装模式实现串口通信。
8位自动重装模式只有低8位TL1参与计数(定时范围0~255)。当TL1溢出时,单片机自动把存在TH1中的值赋给TL1,继续进行定时计数。该模式与模式一:16为定时器/计数器相比,不需要在中断程序中重新对TH1和TL1重新赋值,减少了中断程序的代码条数,使时间更加精准。
6、单片机每隔1秒向电脑发送数据
void UART_Init()
{
SCON=0X40;//模式配置
PCON|=0;//波特率配置,波特率不加倍
TMOD&=0X0F;
TMOD|=0X20;//设置定时器模式为8位自动重装
TL1=0XFA;//设置定时器初值
TH1=0XFA;//设置自动重装值,自动重装值和波特率有关
ET1=0;//禁止定时器1中断
TR1=1;//允许定时器开始计数
}
//发送函数
void UART_SendByte(unsigned char byte)
{
SBUF=byte;//SUBF在等号左边,表示写入,这个SBUF表示发送寄存器
while(TI==0);//TI是SCON的一位,空循环直到TI等于1,说明发送结束
TI=0;//需要软件置0
}
unsigned char num;
void main()
{
UART_Init();
while(1)
{
UART_SendByte(num++);//如果在循环中发送的数据有误差,可以延时
delay_ms(1000);//如果延时太短,发送的数据会有误差
}
}
7、电脑向单片机发送数据控制LED,单片机回传相同文本
void UART_Init()
{
SCON=0X50;//模式配置,需要打开接收
PCON|=0;//波特率配置,波特率不加倍
TMOD&=0X0F;
TMOD|=0X20;//设置定时器模式为8位自动重装
TL1=0XFA;//设置定时器初值
TH1=0XFA;
ET1=0;//禁止定时器1中断
TR1=1;//允许定时器开始计数
EA=1;//配置电路中断打开
ES=1;
PS=0;
}
//发送函数
void UART_SendByte(unsigned char byte)
{
SBUF=byte;//SUBF在等号左边,表示写入,这个SBUF表示发送寄存器
while(TI==0);//TI是SCON的一位,空循环直到TI等于1,说明发送结束
TI=0;//需要软件置0
}
void main()
{
UART_Init();
while(1)
{
}
}
//中断服务函数
void UART_Routine() interrupt 4
{
if(RI==1)//RI是SCON的一位,RI等于1,说明是发送中断
{
P2=~SBUF;
UART_SendByte(SBUF);
RI=0;//需要软件置0
}
}
1、使用串口时,需要禁止定时器中断;
2、当TI或RI等于1时,进入中断服务函数;
3、在中断函数中,如果RI等于1,说明电脑有发送数据给单片机,那么就会进入if循环,执行if循环中代码。
三、LED点阵
1、LED点阵的原理
LED点阵结构类似数码管,有共阴和共阳两种接法,使用时进行逐行或逐列扫描,才能使所有LED同时显示。当然,点阵也需要消影。
SEC是数据排队的入口。SERCLK给高电平,一个bit数据就会进入左侧,当左侧存满时,先进来的数据会被送入QH’,QH’连接在下一个74HC595上。RCLK是接收时钟,会将各个级联的数据从左侧数据传入右侧。
74HC595是串行输入并行输出的移位寄存器,可用3根线输入串行数据,8根线输出并行数据,多片级联后,可输出16位、32位等常用于IO口的扩展。
2、LED点阵的消影
和数码管一样,LED点阵也存在残影问题。在不断“段选位选、段选位选、段选位选”的过程中,下一次的段选完毕后,由于位选代码还没有执行,所以会出现位已变,而段还没来得及改变的鬼影现象。所以可以采用“段选位选延时位清零、段选位选延时位清零、段选位选延时位清零”的方法。(因为位已经清零了,窜位也没事)
3、使用LED点阵绘制爱心
#include <REGX52.H>
#include "delay.h"
#define MXTRIX_LED_PORT P0
sbit RCK=P3^5;//RCLK,高电平将数据搬到引脚
sbit SRCLK=P3^6;//SRCLK,给高电平进一个bit数据
sbit SER=P3^4;//SER,数据进入的地方
//将字节数据写入引脚
void _74HC595_WriteByte(unsigned char byte)
{
unsigned char i=0;
for(;i<8;++i)
{
SER=(byte>>(7-i))&0X01;//高位先进SER,取出高位
SRCLK=1;//进数据
SRCLK=0;//重新置为0
}
RCK=1;//将数据送入IO口
RCK=0;
}
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Data)
{
_74HC595_WriteByte(Data);//把数据放进来,填充引脚
MXTRIX_LED_PORT=~(0x80>>Column);//选择哪一列LED,P0中引脚只要是低电平,就有机会亮,高电平肯定不亮
delay_ms(1);//延时
MXTRIX_LED_PORT=0XFF;//位清零
}
void main()
{
SRCLK=0;//初始是高电平,需要先置0
RCK=0;//初始是高电平,需要先置0
while(1)
{
MatrixLED_ShowColumn(0,0X38);
MatrixLED_ShowColumn(1,0X44);
MatrixLED_ShowColumn(2,0X82);
MatrixLED_ShowColumn(3,0X61);
MatrixLED_ShowColumn(4,0X61);
MatrixLED_ShowColumn(5,0X82);
MatrixLED_ShowColumn(6,0X44);
MatrixLED_ShowColumn(7,0X38);
}
}
4、使用LED点阵播放流水文字
unsigned char code Animation[]={//加code变为只读存储,但是储存量大
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0x10,0x10,0x10,0x10,0xFF,0x00,0x00,
0xFF,0x91,0x91,0x91,0x91,0x00,0x00,0xFF,
0x01,0x01,0x01,0x01,0x00,0x00,0xFF,0x01,
0x01,0x01,0x01,0x00,0x00,0x7E,0x81,0x81,
0x81,0x7E,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//加0X00是为了对齐
};
void main()
{
unsigned char i=0,flag=0,count=0;
unsigned char num=sizeof(Animation);
SRCLK=0;//初始是高电平,需要先置0
RCK=0;//初始是高电平,需要先置0
while(1)
{
while(flag+7<num)
{
for(i=0;i<8;++i)
{
MatrixLED_ShowColumn(i,Animation[flag+i]);
}
++count;
if(count==10)
{
count=0;
flag+=1;
}
}
flag=0;
}
}