51单片机串口通信代码
时间: 2023-11-07 08:05:01 浏览: 38
以下是基于51单片机的串口通信代码,可以实现发送和接收数据:
```c
#include <reg51.h>
// 定义波特率为9600
#define BAUDRATE 9600
// 定义计算波特率所需的常量
#define DIVISOR (256 - (11059200 / (32 * BAUDRATE)))
// 定义发送和接收缓冲区的大小
#define TX_BUFFER_SIZE 64
#define RX_BUFFER_SIZE 64
// 定义发送和接收缓冲区
unsigned char tx_buffer[TX_BUFFER_SIZE];
unsigned char rx_buffer[RX_BUFFER_SIZE];
// 定义发送和接收缓冲区的头尾指针
unsigned char tx_head, tx_tail, rx_head, rx_tail;
// 初始化串口
void init_serial()
{
// 设置波特率
TMOD &= 0xF0;
TMOD |= 0x20;
TH1 = DIVISOR;
TL1 = DIVISOR;
TR1 = 1;
// 设置串口工作模式
SCON = 0x50;
// 清空发送和接收缓冲区的头尾指针
tx_head = tx_tail = 0;
rx_head = rx_tail = 0;
}
// 发送一个字符
void send_char(unsigned char c)
{
// 如果发送缓冲区已满,则等待
while ((tx_tail + 1) % TX_BUFFER_SIZE == tx_head);
// 将字符存入发送缓冲区
tx_buffer[tx_tail] = c;
tx_tail = (tx_tail + 1) % TX_BUFFER_SIZE;
// 打开发送中断
TI = 1;
}
// 发送一个字符串
void send_string(unsigned char *s)
{
while (*s != '\0') {
send_char(*s++);
}
}
// 接收一个字符
unsigned char receive_char()
{
// 如果接收缓冲区为空,则等待
while (rx_head == rx_tail);
// 从接收缓冲区取出一个字符
unsigned char c = rx_buffer[rx_head];
rx_head = (rx_head + 1) % RX_BUFFER_SIZE;
return c;
}
// 清空接收缓冲区
void clear_receive_buffer()
{
rx_head = rx_tail = 0;
}
// 串口中断服务程序
void serial_isr() interrupt 4
{
// 发送中断
if (TI) {
// 如果发送缓冲区非空,则继续发送下一个字符
if (tx_head != tx_tail) {
SBUF = tx_buffer[tx_head];
tx_head = (tx_head + 1) % TX_BUFFER_SIZE;
}
// 如果发送缓冲区已空,则关闭发送中断
else {
TI = 0;
}
}
// 接收中断
if (RI) {
// 如果接收缓冲区未满,则存入一个字符
if ((rx_tail + 1) % RX_BUFFER_SIZE != rx_head) {
rx_buffer[rx_tail] = SBUF;
rx_tail = (rx_tail + 1) % RX_BUFFER_SIZE;
}
// 如果接收缓冲区已满,则清空接收缓冲区
else {
clear_receive_buffer();
}
// 清除接收中断标志
RI = 0;
}
}
void main()
{
// 初始化串口
init_serial();
// 发送一个字符串
send_string("Hello, world!\r\n");
// 接收一个字符并发送回去
while (1) {
unsigned char c = receive_char();
send_char(c);
}
}
```
在上面的代码中,向串口发送数据时,首先将数据存入发送缓冲区,并打开发送中断。当发送中断触发时,从发送缓冲区取出一个字符发送出去,直到发送缓冲区为空,关闭发送中断。
接收数据时,当有数据到达串口时,将数据存入接收缓冲区,并清除接收中断标志。从接收缓冲区取出数据时,先判断接收缓冲区是否为空,如果非空,则取出一个字符并返回。如果接收缓冲区已满,则清空接收缓冲区。