串口通信介绍
串口通信(Serial Communication)是嵌入式系统中常用的通信方式之一,广泛应用于微控制器与计算机、微控制器与微控制器之间的数据传输。51单片机(如STC89C51或AT89C51)内置了串口模块(USART),可以方便地实现串口通信。
1. 串口通信的基本概念
串口通信:数据一位一位地按顺序传输,适合长距离、低速率的数据传输。
波特率:每秒传输的位数,常见的波特率有9600、115200等。
帧格式:通常包括起始位(0)、数据位(8位)、校验位(可选)和停止位(1位)。
全双工:同时支持发送和接收数据。
半双工:同一时刻只能发送或接收数据。
2. 51单片机的串口模块
51单片机的串口模块(USART)支持多种工作模式,包括:
模式0:同步移位寄存器模式,波特率固定。
模式1:8位可变波特率模式。
模式2:9位固定波特率模式。
模式3:9位可变波特率模式。
3. 串口通信的硬件连接
TXD:发送引脚,通常连接到P3.1。
RXD:接收引脚,通常连接到P3.0。
GND:地线。
VCC:电源正极。
实现目标
1、乙单片机串口发送数据给甲单片机。
2、甲单片机收到乙单片机串口发送数据,并在八位数码管上显示
甲单片机代码实现
#include <REGX52.H>
#include <intrins.h>//包含移位函数的头文件
#define uint unsigned int
#define uchar unsigned char
//数码管段码表 要展示的数据 0-F 共阴极 和tab[]一一对应
uchar code dp[] = {
0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c,
0x39, 0x5e, 0x79, 0x71};
// 延迟函数
void delay(uint xms)
{
uint i, j;
for (i = xms; i > 0; i--)
for (j = 110; j > 0; j--);
}
//延时函数
//显示位置和数字
void Nixie(uchar Location,Number)
{
switch(Location) //位码输出
{
case 1:P2=0xfe;break;//p20=0 其它是1 ,1111 1110 =0xfe
case 2:P2=0xfd;break;//p21=0 其它是1 ,1111 1101=fd
case 3:P2=0xfb;break;//p22=0 其它是1 ,1111 1011=fd
case 4:P2=0xf7;break;//p23=0 其它是1 ,1111 0111=f7
case 5:P2=0xef;break;//p24=0 其它是1 ,1110 1111=fd
case 6:P2=0xdf;break;//p25=0 其它是1 ,1101 1111=f7
}
//P1=NixieTable[Number]; //段码输出
if(Number ==16){ //显示等号 dpgfe dcba
P1 = 0x40;// dpgfe dcba = 0100 0000 =0x48;
}else{
P1=dp[Number];
}
delay(50);
}
// 显示函数
void DisplayChar(uchar c) {
//P1 = dp[c & 0x0F]; // 显示接收到的字符或'-'
if(c>=16)
{
Nixie(1,16);
delay(50);
}else{
Nixie(1,c& 0x0F);
}
}
// 串口初始化函数
void UartInit() {
SCON = 0x50; // 设置串口工作模式1
TMOD |= 0x20; // 定时器1工作在模式2
TH1 = 0xFD; // 设置波特率为9600
TL1 = 0xFD;
TR1 = 1; // 启动定时器1
ES = 1; // 开启串口中断
EA = 1; // 开启总中断
}
//// 发送函数
//void SendChar(uchar c) {
// SBUF = c; // 发送数据
// while(!TI); // 等待发送完成
// TI = 0; // 清除发送中断标志
//}
void main()
{
UartInit();// 串口初始化函数
while(1)
{
}
}
// 串口中断服务程序
void Serial_ISR() interrupt 4
{
char received_char;
if(RI) {
RI = 0; // 清除接收中断标志
received_char = SBUF; // 读取接收到的数据
if(received_char >= '0' && received_char <= 'F') {
uchar hex_value = received_char - '0';
if(hex_value > 15) { // 如果是'F',加一后变为16
//hex_value = 0;
DisplayChar(16); // 显示'-'符号
} else {
hex_value++;
}
SBUF = hex_value + '0'; // 发送加一后的数据
while(!TI); // 等待发送完成
TI = 0; // 清除发送中断标志
DisplayChar(hex_value); // 显示接收到的字符
} else {
DisplayChar(16); // 显示'-'符号
}
}
}
乙单片机代码实现
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 延时函数
void DelayMS(uint ms) {
uchar i;
while(ms--)
for(i = 0; i < 120; i++);
}
// 串口初始化函数
void UartInit() {
SCON = 0x50; // 设置串口工作模式1
TMOD |= 0x20; // 定时器1工作在模式2
TH1 = 0xFD; // 设置波特率为9600
TL1 = 0xFD;
TR1 = 1; // 启动定时器1
}
// 发送函数
void SendChar(uchar c) {
SBUF = c; // 发送数据
while(!TI); // 等待发送完成
TI = 0; // 清除发送中断标志
}
void main()
{
uchar i=0;
UartInit(); // 初始化串口
while(1) {
//SendChar(9+ '0');//乙主机发送9,甲主机,加+1,显示十进制10对应的16进制A
SendChar(i+ '0');//乙主机发送4,甲主机,加+1,数码管显示7
//SendChar(4+ '0');//乙主机发送4,甲主机,加+1,数码管显示5
//SendChar(0+ '0');//乙主机发送0,甲主机,加+1,数码管显示1
//SendChar(15+ '0');//乙主机发送15,甲主机,加+1,大于0到F,显示-号
i++;
DelayMS(1500);
if(i>16)
{
i=0;
}
}
}
void Serial_ISR() interrupt 4
{
uchar receivedData;
if (RI) {
RI = 0; // 清除接收中断标志
receivedData = SBUF; // 读取接收到的数据
// 处理接收到的数据
// 例如:将其回显回去
SBUF = receivedData+1;
while (!TI); // 等待发送完成
TI = 0; // 清除发送中断标志
}
}
proteus 仿真电路图

实验现象
当甲单片机收到乙单片机的串口发送数据后,再数码管显示。


8880

被折叠的 条评论
为什么被折叠?



