这个通用的方法,其实原理就是传输两个字节间是否超过了指定时间,如果超过了一定的时间,就认为是接收完一帧数据了。首先我们要知道,串口是接收一个字节,就会发生一次中断,如果一帧数据包含10个字节,就会发生10次中断。在接收一个字节以后,会紧跟着接收下一个字节,如果时间超了一定值,就代表一帧数据已经发完了
比如.波特率为9600,8位(数据位)+2位(开始位+停止位)=10位 :每个串口中断时间为10位 *(1000/9600),那么传一个字节1MS左右,
/*----------------------------------*/
/*-------- 定时器3 操作函数 --------*/
/*----------------------------------*/
void t3int() interrupt 19 using 1 //中断入口
{
if(uart2Ri_start){
uart2Ri_start_time++;
if(uart2Ri_start_time>12){
uart2Ri_start=0;
uart2Ri_start_time=0;
uart2Ri_frame_flat=1;
uart2Ri_cnt=0;
}
}
time_ms_pwm++;
time500ms_tmp1++;
//时间点切换计时
//脉冲宽度调制
if(time_ms_pwm <= pwm){
OE =0;
}else{
OE =1;
if(time_ms_pwm >= 14 ){
time_ms_pwm =0;
OE =1;
}
}
RunLed++;
if(RunLed>200){
RunLed=0;
RunState=~RunState;
}
}
/*----------------------------
串口中断2 中断服务程序
-----------------------------*/
#define S2RI 0x01 //S2CON.0
#define S2TI 0x02 //S2CON.1
#define S2RB8 0x04 //S2CON.2
#define S2TB8 0x08 //S2CON.3
char Count=0;
int uart1TimeOut=0;
char data1;
void Uart2() interrupt 8 using 1
{
unsigned char dat =0; //暂存接收的数据
//接收操作
if (S2CON & S2RI){
S2CON &= 0xfe;
uart2Ri_start=1; //串口接收开始计时
if(uart2Ri_cnt<uart2Ri_maxCnt){
rxd_buf[uart2Ri_cnt++]=S2BUF;
}
else
{
uart2Ri_cnt=uart2Ri_maxCnt;
}
uart2Ri_start_time=0;
}
if (S2CON & S2TI)
{
S2CON &= ~S2TI; //清除S2TI位
busy = 0; //清忙标志
}
}
unsigned char time_ms =9;
/*******************************************************************
* 函数名 : timer0_init
* 描述 : 1毫秒的中断。
* 参数 : ALL_INT_Enable -- 使能总中断
********************************************************************/
void tm0_isr() interrupt 1 using 1
{
time_ms++;
if(USART2_RX_STA & 0x40){
uart_time_sta++; //接收超时计时
if( uart_time_sta >=12){
// rx_cnt =0;
USART2_RX_STA =0x80; //这里也清0了允许接收位
// USART2_485_Status_Rx_Tx=1;//接收发送标记位。
}
}
}
以下是串口的部分,串口接收发送部分的调用过
#include "main.h"
#include "uart.h"
#include "protocol_process.h"
#include "stdio.h"
#define FOSC 11059200L //系统频率
#define BAUD 115200 //串口波特率
//#define FOSC 11059200L //系统频率
//#define BAUD 115200 //串口波特率
#define NONE_PARITY 0 //无校验
#define ODD_PARITY 1 //奇校验
#define EVEN_PARITY 2 //偶校验
#define MARK_PARITY 3 //标记校验
#define SPACE_PARITY 4 //空白校验
#define PARITYBIT EVEN_PARITY //定义校验位
#define S2RI 0x01 //S2CON.0
#define S2TI 0x02 //S2CON.1
#define S2RB8 0x04 //S2CON.2
#define S2TB8 0x08 //S2CON.3
#define S2_S0 0x01 //P_SW2.0
bit busy;
//dong 2019-03-19
//unsigned char rx_max_len =256;
xdata unsigned char USART2_RX_BUF_test[ rx_max_len ];
xdata unsigned char USART2_RX_BUF[ rx_max_len ];
xdata unsigned char USART2_TX_BUF[ rx_max_len ];
unsigned char USART2_485_Status_Rx_Tx=0;
unsigned char USART2_RX_STA =0; //位[7]-接收成功标志,位[6]-允许接收数据标志(包头正确标志)
unsigned char uart_time_sta =0; //用于串口接收计时
unsigned char rx_cnt =0;
void uart2_init(char ALL_INT_Enable)
{
P_SW2 &= ~S2_S0; //S2_S0=0 (P1.0/RxD2, P1.1/TxD2)
//P_SW2 |= S2_S0; //S2_S0=1 (P4.6/RxD2_2, P4.7/TxD2_2)
S2CON = 0x50; //8位可变波特率
T2L = (65536 - (FOSC/4/BAUD)); //设置波特率及重装值
T2H = (65536 - (FOSC/4/BAUD))>>8;
AUXR |= 0x14; //T2为1T模式, 并启动定时器2
IE2 = 0x01; //使能串口2中断
if(ALL_INT_Enable){
EA = 1;
}else{
EA = 0;
}
}
void UartInit(void) //9600bps@11.0592MHz
{
P_SW2 &= ~S2_S0; //S2_S0=0 (P1.0/RxD2, P1.1/TxD2)
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xE0; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
}
void SendData(unsigned char dat)
{
while (busy); //等待前面的数据发送完成
busy = 1;
S2BUF = dat; //写数据到UART2数据寄存器
}
void SendString(unsigned char *s, unsigned char len)
{
unsigned char i =0;
for(i=0; i<len; i++){
SendData(*s++); //发送当前字符
}
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData2(char dat)
{
while (busy); //等待前面的数据发送完成
// ACC = dat; //获取校验位P (PSW.0)
S2BUF = dat; //写数据到UART2数据寄存器
busy = 1;
}
/*----------------------------
发送字符串
----------------------------*/
void SendString2(char *s)
{
while (*s) //检测字符串结束标志
{
SendData2(*s++); //发送当前字符
}
}
//重写putchar函数
char putchar(char c)
{
SendData2(c);
return c;
}
//用于485接收完成数据后再发送数据
void Uart2() interrupt 8 using 1 /* UART2 中断服务程序 */
{
unsigned char dat =0; //暂存接收的数据
unsigned char checksum =0;
unsigned char offset =0;
//接收操作
if ( (S2CON & S2RI) && (USART2_485_Status_Rx_Tx==0 )){ //当USART2_STA_RX_TX:0时为485数据线空闲状态。
// if ( (S2CON & S2RI) ){ //当USART2_STA_RX_TX:0时为485数据线空闲状态。
USART2_485_Status_Rx_Tx=1;
//S2CON &= ~S2RI; //清除S2RI位
S2CON &= 0xfe; //清除S2RI位
dat = S2BUF;
//数据包接收是否允许标志位检测
USART2_RX_STA |= 0x40;
//完成时不接收,清0了才能接收数据,主函数查询处理完成后置1,并将接收数据缓存清空掉待下次接收。
if( !(USART2_RX_STA & 0x80) ){
uart_time_sta =0x00; //连续每来一字节间隔时间清0,达到不过超时时间,过了超时时间置1
//USART2_RX_STA的第二个位允许接收数据标志检测
if(USART2_RX_STA & 0x40){
if(rx_cnt < rx_max_len){
USART2_RX_BUF[rx_cnt++] =dat;
}
else
{
//数据包接收完成
// rx_cnt =0;
// USART2_485_Status_Rx_Tx=1; //大于最大长度退出时接收标志位为0:空闲
USART2_RX_STA =0x80;
uart_time_sta =12;
}
}
}
}
//发送操作
if (S2CON & S2TI){
// S2CON &= ~S2TI; //清除S2TI位
S2CON &= 0xfd; //清除S2TI位
// S2BUF=checksum;
busy = 0; //清忙标志
}
}
void clear_rx_buf()
{
unsigned char i =0;
for(i=0; i<rx_max_len; i++){
USART2_RX_BUF[i] =0;
}
}