编程完成⼀个串口的收发数据程序。要求,单片机与 PC 机进行串口通 信,PC 机发送字符给单片机,单片机统计收到的'A'字符的个数,在数码 管上显示个数。当收到 10 个'A'时发送字 符串 Test OK。';当收到 20 个 'A'时发送字符串'Uart OK !'。通信速率为 4800bps,单片机外接晶振频 率为 11.0592MHz。
时间: 2024-02-09 18:11:12 浏览: 112
这里提供一个基于STC89C52单片机的串口收发数据程序,实现PC机向单片机发送字符,单片机统计'A'字符的个数并在数码管上显示,当收到10个'A'时发送字符串"Test OK",当收到20个'A'时发送字符串"Uart OK!"。通信速率为4800bps,单片机外接晶振频率为11.0592MHz。
```
#include <reg52.h>
#define FOSC 11059200L // 单片机外部晶振的频率
#define BAUD 4800 // 串口波特率
#define TIMER_1MS 1 // 定时器1定时1ms
#define MAX_A 20 // 最大统计的A字符个数
sbit LSA = P2 ^ 2; // 数码管控制位LSA
sbit LSB = P2 ^ 3; // 数码管控制位LSB
sbit LSC = P2 ^ 4; // 数码管控制位LSC
sbit led = P1 ^ 0; // LED指示灯
unsigned char num = 0; // 统计'A'字符个数
unsigned char receive; // 接收到的数据
unsigned char count = 0; // 数码管扫描计数器
unsigned char a[MAX_A]; // 存储接收到的'A'字符
/* 延时函数 */
void delay(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 120; j++);
}
}
/* 数码管扫描函数 */
void display(unsigned char num) {
unsigned char code table[] = {
// 0~9的BCD码
0xC0, 0xF9, 0xA4, 0xB0, 0x99,
0x92, 0x82, 0xF8, 0x80, 0x90
};
LSA = 0;
LSB = 0;
LSC = 0; // 全部关闭
P0 = table[num]; // 显示数码管
count++; // 扫描计数器加1
switch (count) {
case 1:
LSA = 1;
break;
case 2:
LSB = 1;
break;
case 3:
LSC = 1;
break;
default:
count = 0;
break;
}
}
/* 串口初始化函数 */
void Uart_Init() {
TMOD &= 0x0F;
TMOD |= 0x20; // 定时器1工作在8位自动重载模式
TH1 = TL1 = -(FOSC / 12 / 32 / BAUD);
TR1 = 1; // 启动定时器1
SM0 = 0;
SM1 = 1; // 设置串口为模式1(8位数据位,可变波特率)
REN = 1; // 允许串口接收数据
EA = 1;
ES = 1; // 打开总中断和串口中断
}
/* 串口发送函数 */
void Uart_Send(unsigned char ch) {
SBUF = ch;
while (!TI); // 等待发送完成
TI = 0; // 发送完成,清除标志位
}
/* 串口接收中断函数 */
void Uart_Isr() interrupt 4 {
if (RI) {
RI = 0; // 清除接收标志位
receive = SBUF; // 读取接收到的数据
if (receive == 'A') { // 统计A字符的个数
num++;
a[num - 1] = receive;
if (num == 10) { // 收到10个A字符,发送Test OK
Uart_Send('T');
Uart_Send('e');
Uart_Send('s');
Uart_Send('t');
Uart_Send(' ');
Uart_Send('O');
Uart_Send('K');
Uart_Send('\r'); // 发送回车符
num = 0; // 统计A字符的个数清零
} else if (num == 20) { // 收到20个A字符,发送Uart OK!
Uart_Send('U');
Uart_Send('a');
Uart_Send('r');
Uart_Send('t');
Uart_Send(' ');
Uart_Send('O');
Uart_Send('K');
Uart_Send('!');
Uart_Send('\r'); // 发送回车符
num = 0; // 统计A字符的个数清零
}
}
}
}
/* 定时器1中断函数 */
void Timer1_Isr() interrupt 3 {
static unsigned int cnt = 0;
TH1 = TL1 = -(FOSC / 12 / 32 / BAUD); // 重新加载计数值
cnt++;
if (cnt >= TIMER_1MS) { // 定时1ms
cnt = 0;
display(num); // 数码管扫描
}
}
/* 主函数 */
void main() {
Uart_Init();
while (1) {
if (num > MAX_A) { // 统计A字符的个数达到上限
led = ~led; // LED指示灯翻转
num = 0; // 统计A字符的个数清零
}
}
}
```
需要注意的是,上述代码中使用了定时器1来实现定时扫描数码管的功能,同时也使用了定时器1的中断来实现定时串口通信的功能。在使用定时器中断时,需要根据外部晶振频率、定时器工作模式和计数器初值来计算中断周期。在本例中,由于定时器1工作在8位自动重载模式,所以计数器初值为TH1=TL1=-FOSC/12/32/BAUD=0xFF-0x19=0xE6,中断周期为1ms。
阅读全文