编程完成⼀个串口的收发数据程序。要求,单片机与 PC 机进行串口通 信,PC 机发送字符给单片机,单片机统计收到的'A'字符的个数,在数码 管上显示个数。当收到 10 个'A'时发送字 符串 Test OK。';当收到 20 个 'A'时发送字符串'Uart OK !'。通信速率为 4800bps,单片机外接晶振频 率为 11.0592MHz。 扩展要求: 在上述程序的基础上,将对单个字符的判断增加为对一个字符串的判断。 用单片机统计收到的字符串是否正确,如果收到字符串'Test'时表示正 确,单片机回送字符串'Uart OK !'。
时间: 2024-01-22 10:20:21 浏览: 263
单片机接收PC发送的数据.zip_foundbrz_单片机 PC_单片机接收PC的数据
以下是基于STC89C52单片机的串口收发数据程序,同时包含了扩展要求的代码:
```
#include <reg52.h>
#include <stdio.h>
#define FOSC 11059200L // 单片机外部晶振的频率
#define BAUD 4800 // 串口波特率
#define TIMER_1MS_RELOAD_VALUE (65536UL - (FOSC/1000UL)) // 定时器1每1ms中断一次时的重载值
sbit LED = P1^0; // 数码管控制引脚
sbit DIO = P2^0; // 数码管数据引脚
sbit CLK = P2^1; // 数码管时钟引脚
sbit RXD = P3^0; // 串口接收引脚
sbit TXD = P3^1; // 串口发送引脚
unsigned char counter = 0; // 统计收到的'A'字符个数
unsigned char state = 0; // 状态标志,0表示正常接收,1表示接收到了'Test'字符串
unsigned char receive_buffer[5]; // 串口接收缓存区
unsigned char receive_index = 0; // 串口接收缓存区索引
void init_uart() {
TMOD &= 0x0F; // 设置定时器1为16位自动重载模式
TMOD |= 0x20;
TH1 = TL1 = TIMER_1MS_RELOAD_VALUE / BAUD; // 计算波特率重载值
TR1 = 1; // 启动定时器1
SCON = 0x50; // 设置串口为模式1,允许接收
ES = 1; // 允许串口中断
EA = 1; // 允许总中断
}
void init_timer() {
TMOD &= 0xF0; // 设置定时器0为16位定时模式
TMOD |= 0x01;
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
}
void display(unsigned char num) {
unsigned char i;
for (i = 0; i < 8; i++) {
CLK = 0;
DIO = num & 0x80;
num <<= 1;
CLK = 1;
}
}
void delay_ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 114; j++);
}
void main() {
init_uart();
init_timer();
while (1) {
display(counter);
delay_ms(10);
}
}
void uart_interrupt() interrupt 4 {
if (RI) {
RI = 0; // 清除接收中断标志位
receive_buffer[receive_index++] = SBUF; // 将接收到的字符存入缓存区
if (receive_index == 4) { // 接收到了4个字符,判断是否为'Test'
receive_index = 0;
if (strncmp(receive_buffer, "Test", 4) == 0) { // 接收到了'Test'字符串
state = 1;
SBUF = 'U'; // 回送'Uart OK !'字符串
}
} else if (state == 0 && SBUF == 'A') { // 正常接收状态,统计收到的'A'字符个数
counter++;
if (counter == 10) { // 收到了10个'A'字符,发送'Test OK'字符串
counter = 0;
SBUF = 'T';
delay_ms(1);
SBUF = 'e';
delay_ms(1);
SBUF = 's';
delay_ms(1);
SBUF = 't';
delay_ms(1);
SBUF = ' ';
delay_ms(1);
SBUF = 'O';
delay_ms(1);
SBUF = 'K';
} else if (counter == 20) { // 收到了20个'A'字符,发送'Uart OK !'字符串
counter = 0;
SBUF = 'U';
delay_ms(1);
SBUF = 'a';
delay_ms(1);
SBUF = 'r';
delay_ms(1);
SBUF = 't';
delay_ms(1);
SBUF = ' ';
delay_ms(1);
SBUF = 'O';
delay_ms(1);
SBUF = 'K';
delay_ms(1);
SBUF = '!';
}
}
}
}
void timer_interrupt() interrupt 1 {
static unsigned int count = 0;
TH0 = (65536 - (FOSC / 12 / 1000)) / 256; // 重新设置定时器0的重载值
TL0 = (65536 - (FOSC / 12 / 1000)) % 256;
if (++count == 500) { // 定时器0每500ms中断一次
count = 0;
LED = !LED; // LED闪烁,表示程序正在运行
}
}
```
其中,串口接收中断处理函数是`uart_interrupt()`,定时器0中断处理函数是`timer_interrupt()`。在串口接收中断处理函数中,如果接收到了'A'字符,则将计数器`counter`加1,并判断是否达到了10或20个,如果是则发送相应的字符串;如果接收到了4个字符,则判断是否为'Test'字符串,如果是则将状态标志`state`设为1,并回送'Uart OK !'字符串。在主循环中,通过`display()`函数在数码管上显示计数器的值。在定时器0中断处理函数中,LED闪烁,表示程序正在运行。
扩展要求的实现方法是,当接收到4个字符时,使用`strncmp()`函数判断是否为'Test'字符串,如果是则将状态标志`state`设为1,并回送'Uart OK !'字符串。在接收到字符时,需要首先判断当前状态是否为1,如果是则不再统计'A'字符的个数。
阅读全文