用c51 实现带奇偶校验的串行通信
时间: 2023-05-23 20:04:41 浏览: 276
在使用C51实现串行通信时,可以通过添加奇偶校验来提高通信的可靠性。奇偶校验是通过在每个数据字节中添加一个校验位来实现的,这个校验位表示这个数据字节中1的个数是奇数还是偶数。
以下是一个简单的C51程序,用于实现带奇偶校验的串行通信:
```
#include <reg51.h>
#define BUFFER_SIZE 10 // 缓冲区大小
#define EVEN_PARITY 0 // 偶校验
#define ODD_PARITY 1 // 奇校验
unsigned char buffer[BUFFER_SIZE]; // 缓冲区
unsigned char rx_count = 0; // 接收计数器
/* 串口接收中断处理函数 */
void UART_ISR () interrupt 4 {
unsigned char c;
if (RI) { // 接收到数据
RI = 0;
c = SBUF;
/* 检查奇偶校验,如果校验错误则丢弃这个数据 */
if (check_parity(c)) {
buffer[rx_count++] = c;
if (rx_count >= BUFFER_SIZE) {
rx_count = 0;
}
}
}
}
/* 发送一个字节 */
void UART_send_byte (unsigned char b) {
ES = 0; // 关闭串口接收中断
/* 计算奇偶校验位 */
b = (b & 0x7f) ^ ((b & 0x3f) >> 1) ^ ((b & 0x1f) >> 2) ^ ((b & 0x0f) >> 3) ^ ((b & 0x07) >> 4) ^ ((b & 0x03) >> 5) ^ ((b & 0x01) >> 6);
/* 添加奇偶校验位 */
if (parity == EVEN_PARITY) {
b &= 0xfe; // 把奇偶校验位设为偶数
} else {
b |= 0x01; // 把奇偶校验位设为奇数
}
/* 发送数据 */
SBUF = b;
while (!TI); // 等待发送完成
TI = 0;
ES = 1; // 打开串口接收中断
}
/* 检查奇偶校验 */
unsigned char check_parity (unsigned char b) {
unsigned char parity = b & 0x80; // 保存奇偶校验位
b &= 0x7f; // 去掉奇偶校验位
/* 计算奇偶校验 */
b = b ^ (b >> 4);
b = b ^ (b >> 2);
b = b ^ (b >> 1);
/* 检查奇偶校验是否正确 */
if ((b & 0x01) == parity) {
return 1; // 校验正确
} else {
return 0; // 校验错误
}
}
/* 主函数 */
void main () {
unsigned char i;
/* 初始化串口 */
TMOD = 0x20; // 设定计数器1工作模式2(自动重装载)
TH1 = 0xfd; // 设定计数器1的重载值,用于产生波特率为9600的波特率发生器
TL1 = TH1;
TR1 = 1; // 启动计数器1
SM0 = 0; // 设置串口工作方式为8位数据位,无校验位,1位停止位
SM1 = 1;
EA = 1; // 打开总中断
ES = 1; // 打开串口接收中断
while (1) {
/* 发送数据 */
for (i = 0; i < BUFFER_SIZE; i++) {
UART_send_byte(buffer[i]);
}
}
}
```
在这个程序中,我们首先定义了一个缓冲区来保存接收到的数据。接着定义了一个中断处理函数,用于处理串口接收中断。在这个中断处理函数中,我们首先检查接收到的数据的奇偶校验位是否正确,如果正确,就把这个数据存放到缓冲区中。在发送数据时,我们先计算出每个数据字节的奇偶校验位,并添加到数据字节中。然后再把数据发送出去。
需要注意的是,在本程序中我们采用的是计算奇偶校验位的一种简单方法,实际上在工业控制系统中通常采用更复杂的方法来计算奇偶校验位。因此,如果你在实际应用中使用本程序,请仔细检查奇偶校验的实现方法是否符合你的要求。
阅读全文