您的位置:首页 > 编程语言

串口收发处理——编程方法(原创)

2016-02-29 18:09 190 查看
对于通信相关代码编程,保证 及时、稳定、处理效率高,是很关键的。所以通常采用中断接收方式,并且中断处理函数尽量简短。
然而在我的工作中看到些:在中断中做很多工作,比如处理包的错误处理,解析,最终又将正确的有用信息拷贝到全局变量中,甚至还处理其他应用层的东西。
其实这样对于裸跑的mcu来说,main中的主循环就不高效了。
下面代码,将只对串口接收处理接收操作哦,在main的主循环去解析接收的内容;
comm_deal() 中以状态机的方式处理:等待接收(包头判断)、接收中(长度符合或有包尾、加接收超时)、接收处理(对包的正确性判断,以及应用处理、错误提示等);这样看是不是方便、高效很多呢!而且逻辑清晰!
对于包长固定的通讯格式,可以从接收长度上判断有没有收发完成;而对于多种格式的数据包结构,往往还是加个接收超时 T_WAST 判断较好(虽然这要求发送短包之间的间隔 T_WAST至少)
其实发送也可以采用中断的发送: 开启发送中断,讲发送内容放在buff_send[]中,在发送第一个字节。再跳到中断,在中断中发送其他内容。

#define  MAX_CHAR_NUM    1064

struct USART{
volatile unsigned short haveAcceptedLen;//接收字符数
unsigned short conIndex;//消费指针
unsigned short proIndex;//生产指针
unsigned long  acceptTimer;
unsigned long  readTimer;
unsigned char bufOverErr;
unsigned char acceptBuf[MAX_CHAR_NUM];
};
extern struct USART  m1USART;//串口1的结构

/*------------------------
brif:从接收缓存内读取一个字节
input: none
output: none
--------------------------*/
struct USART  m1USART;//串口的结构
unsigned char UartROneData(USART_TypeDef* USARTx,struct USART* pUSART )
{
unsigned char val;
val=pUSART->acceptBuf[pUSART->conIndex];
pUSART->conIndex =(pUSART->conIndex+1)%(MAX_CHAR_NUM);
/* Disable the USART0 Receive interrupt */
USART_ITConfig(USARTx, USART_IT_RXNE, DISABLE);
pUSART->haveAcceptedLen =pUSART->haveAcceptedLen -1;
/* ENABLE the USART0 Receive interrupt */
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
return val;
}
unsigned char UartRData(USART_TypeDef* USARTx ,struct USART* pUSART,unsigned char *mRBuf,unsigned short needRNum)// unsigned char needRNum
{
unsigned short rlen;

pUSART->readTimer = Tick_1ms;
rlen = 0;
while(1)
{
if(pUSART->haveAcceptedLen)
{
*(mRBuf+rlen) =UartROneData(USARTx,pUSART);
rlen++;
if(rlen>=needRNum)
break;
}
if((Tick_1ms-pUSART->readTimer)>100)
{//超时,发送超时错误
return 1;//err
}
}
return 0;
}
void UART_ClearRxBuf(struct USART *pUSART)
{
pUSART->haveAcceptedLen=0;
pUSART->proIndex=0;
pUSART->conIndex=0;
}

/**
* @brief  This function handles USART1 interrupt request.
* @param  None
* @retval None
*/
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
m1USART.acceptBuf[m1USART.proIndex] = (uint8_t)USART_ReceiveData(USART1);
m1USART.proIndex =(m1USART.proIndex+1)%MAX_CHAR_NUM;
m1USART.haveAcceptedLen = m1USART.haveAcceptedLen+1;
if(m1USART.haveAcceptedLen> MAX_CHAR_NUM)
{
m1USART.bufOverErr = 1;
m1USART.haveAcceptedLen = 0;
m1USART.conIndex = m1USART.proIndex;
}
m1USART.acceptTimer=Tick_1ms;
}
}

/************应用部分 main.c*************/
KeyData g_keydatabuf[MAX_KEY_NUM]={0};
u8 CMD_status=CMD_WAIT;
u32 CMD_delay;
u8 bufData[MAX_CHAR_NUM];// 用于中转
u16 g_len;
void comm_deal(void)
{
u16 i;
u8 n,cmd1,cmd2;
u16 sum;
u16 tmp16;
u8 pool[4]={0};
char Pstr[6]="\0";
switch(CMD_status)
{
case CMD_WAIT:
if(m1USART.haveAcceptedLen>=2)
{
cmd1=UartROneData(USART1, &m1USART);
cmd2=UartROneData(USART1, &m1USART);
if(cmd1==HEAD1&&cmd2==HEAD2)
{
CMD_status=CMD_RECV;
CMD_delay=Tick_1ms;
//?    Usart1_SendByte(0xDD);
}
else
{
UART_ClearRxBuf( &m1USART);
//? Usart1_SendByte(0xEE);
}
}
break;
case CMD_RECV:
if((m1USART.haveAcceptedLen+2)>=4)
{
g_len=m1USART.acceptBuf[m1USART.conIndex+1];//高8bit
g_len=(g_len<<8)+m1USART.acceptBuf[m1USART.conIndex];//低8bit
if((m1USART.haveAcceptedLen+2)>=g_len)
{
UartRData(USART1, &m1USART, bufData, g_len-2);//从包长度开始读取
CMD_status=CMD_DEAL;
}
}
else if(Tick_1ms-m1USART.acceptTimer>150)//超过50Ms, 没有接收,清空重新接收
{
UART_ClearRxBuf( &m1USART);
CMD_status=CMD_WAIT;
//?    Usart1_SendByte(0xAA);
}
break;
case CMD_DEAL:
sum = GetSum(bufData,(g_len-4));
sum=0xFFFF-(sum + HEAD1 +HEAD2);
tmp16 = (bufData[g_len-3]<<8) + bufData[g_len-4];
if(sum==tmp16)//校验和正确
{
switch(bufData[2])
{
case CMD_READ:                    //? Usart1_SendByte(0xBB);                     break;
case CMD_SET:                  //?   Usart1_SendByte(0xCC);                     setting_save();
break;
case CMD_ERR://错误码, 表示上控收到错误的下控包
if(bufData[3]==E_CMD)//下控发送包错误
{
//?    Usart1_SendByte(0xEF);
my_memset(pool, 0, 4);
setting_sendback(CMD_READ, (u8 *)pool, 4);
}
else ;
break;
default:
break;
}
}
else//校验和错误,上控包错误
{
//?    Usart1_SendByte(0xED);
my_memset(pool, 0, 4);
setting_sendback(CMD_ERR, (u8 *)pool, 4);
}
UART_ClearRxBuf(&m1USART);
CMD_status=CMD_WAIT;
break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: