第十八集 串口的高级应用 校验位 奇偶校验: 串口的奇偶校验是数据8位+一个校验位总共9位中的1的个数 奇校验 数据中如果有双数个1 那么校验位=1 如果数据单但数个1 校验位=0 偶校验 数据中如果有双数个1 那么校验位=0 如果数据单但数个1 校验位=1 因为校验位会占用一位,通常使用校验的话会使用串口为波特率9位的模式 串口在发送或者接收时候 TB8 RB8就是第九位校验位 吧收到的数据交给acc就可以得到P的校验值 然后放到校验位就可以了 奇校验需要取反, #include "usart.h" u8 rec[50], len = 0; void usart_date_send(u8 *str) { u8 dat; for (; *str != 0; str++) { dat = *str; ACC = dat; //数据交给acc得到p 这里采用奇校验 if (P) { S2TB8 = 0; //判断p=1 就给校验位=0 } else { S2TB8 = 1; //判断p=0 就给校验位=1 } S2BUF = dat; //吧数据发出去 while (!S2TI) ; } } u8 usart_date_handle(void) { if (len > 5 && rec[len - 1] == '\n' && rec[len - 2] == '\r') { if (rec[len - 6] == 'o' && rec[len - 5] == 'p' && rec[len - 4] == 'e' && rec[len - 3] == 'n') { P21 = 0; len = 0; usart_date_send("P21_open \r\n"); } else if (rec[len - 7] == 'c' && rec[len - 6] == 'l' && rec[len - 5] == 'o' && rec[len - 4] == 's' && rec[len - 3] == 'e') { P21 = 1; len = 0; usart_date_send("P21_close \r\n"); } } return 0; } void Uart2_Isr(void) interrupt 8 { u8 dat; if (S2CON & 0x02) // 检测串口2发送中断 { S2CON &= ~0x02; // 清除串口2发送中断请求位 } if (S2CON & 0x01) // 检测串口2接收中断 { dat = S2BUF; ACC = dat; // 给到累加器得到P值 if (S2RB8 == !P) // 奇校验部分 rec[len++] = dat; S2CON &= ~0x01; // 清除串口2接收中断请求位 } } void PortSwitch(void) { P_SW2 |= 0x01; // UART2/USART2: RxD2(P4.2), TxD2(P4.3) } { PortSwitch(); //S2CON = 0x50; // 8位数据,可变波特率 S2CON = 0xD0; //9位数据,可变波特率 有校验位了 AUXR |= 0x04; // 定时器时钟1T模式 T2L = 0xEE; // 设置定时初始值 T2H = 0xFB; // 设置定时初始值 AUXR |= 0x10; // 定时器2开始计时 IE2 |= 0x01; // 使能串口2中断 } 串口超时寄存器UR2TOCR 串口2接收超时寄存器
#include "usart.h" u8 rec[50], len = 0, rx_timeout = 0; void usart_date_send(u8 *str) { u8 dat; for (; *str != 0; str++) { dat = *str; ACC = dat; // 数据交给acc得到p 这里采用奇校验 if (P) { S2TB8 = 0; // 判断p=1 就给校验位=0 } else { S2TB8 = 1; // 判断p=0 就给校验位=1 } S2BUF = dat; // 吧数据发出去 while (!S2TI) ; } } u8 usart_date_handle(void) { if (len > 5 && rec[len - 1] == '\n' && rec[len - 2] == '\r') { if (rec[len - 6] == 'o' && rec[len - 5] == 'p' && rec[len - 4] == 'e' && rec[len - 3] == 'n') { P21 = 0; len = 0; usart_date_send("P21_open \r\n"); } else if (rec[len - 7] == 'c' && rec[len - 6] == 'l' && rec[len - 5] == 'o' && rec[len - 4] == 's' && rec[len - 3] == 'e') { P21 = 1; len = 0; usart_date_send("P21_close \r\n"); } } if (rx_timeout==1) { usart_date_send("usart2 received timeout! \r\n"); rx_timeout=0; } return 0; } void Uart2_Isr(void) interrupt 8 { u8 dat; if (S2CON & 0x02) // 检测串口2发送中断 { S2CON &= ~0x02; // 清除串口2发送中断请求位 } if (S2CON & 0x01) // 检测串口2接收中断 { dat = S2BUF; ACC = dat; // 给到累加器得到P值 if (S2RB8 == !P) // 奇校验部分 rec[len++] = dat; S2CON &= ~0x01; // 清除串口2接收中断请求位 UR2TOCR = 0xe0; // 开启接受超市中断 } if (UR2TOSR & 0x01) // 检测是不是接收超时中断触发的 { UR2TOSR = 0x00; // 清除超时中断标志位 UR2TOCR = 0x00; // 关闭超时中断 也就是用的时候开 不用的时候关掉 rx_timeout = 1; // 整一个全局变量作为标志,在handle中可以用作判断是不是很久没有接收到数据了 } } void PortSwitch(void) { P_SW2 |= 0x01; // UART2/USART2: RxD2(P4.2), TxD2(P4.3) } { PortSwitch(); UR2TOCR = 0x00; // 关闭超时接受功能 UR2TOTL = 0x04; // 超时的计数时长 UR2TOTH = 0x3b; UR2TOTE = 0x01; // S2CON = 0x50; // 8位数据,可变波特率 S2CON = 0xD0; // 9位数据,可变波特率 有校验位了 AUXR |= 0x04; // 定时器时钟1T模式 T2L = 0xEE; // 设置定时初始值 T2H = 0xFB; // 设置定时初始值 AUXR |= 0x10; // 定时器2开始计时 IE2 |= 0x01; // 使能串口2中断 }
|