协议解码的时候,如果上位机发送数据不完整或者有错误,通过定时器中断将之接收的不完整数据清楚。定时的时间长短可有定时器觉得,ms为单位。
//初始化位毫秒单位
void Timer_Init(){
TIM1_PSCRH = (unsigned char) ( ( (F_CPU / 1000) - 1) >> 8); /* 16M系统时钟经预分频f=fck/(PSCR+1) */
TIM1_PSCRL = (unsigned char) ( (F_CPU / 1000) - 1); /* PSCR=0x3E7F,f=16M/(0x3E7F+1)=1000Hz,每个计数周期1ms */
TIM1_ARRH = 0; /* 这三行不知道为什么要先初始化,如果不定时第一次用时将不正常 */
TIM1_ARRL = 1; /* */
TIM1_CR1 = 0x01; /* 计数器使能,开始计数 */
}
void ClearTimeOut( void )
{
TIM1_IER_UIE = 0; /* Turn off the interrupts. */
TIM1_CR1 = 0x00; /* 计数器停止计数 */
TIM1_SR1 = 0; /* 清除定时器0标志 */
}
/*
* -----------------------------------------------------------------------------
* timeout ()
* -----------------------------------------------------------------------------
*/
void SetTimeOut( unsigned int ticks )
{
TIM1_CR1 = 0x00; /* 计数器关闭 */
TIM1_SR1 = 0; /* 清除更新中断标记 */
TIM1_CNTRH = 0;
TIM1_CNTRL = 0; /* 清零计数器 */
TIM1_ARRH = (ticks >> 8); /* 自动重载寄存器ARR=0x01F4=500 */
TIM1_ARRL = ticks; /* 每记数ticks=500次产生一次中断,即500ms ;ARR设置可看作一个门限值, CNT由0增加到ARR值,自动清零,并置位事件标志 */
TIM1_IER_UIE = 1; /* Turn on the interrupts. */
TIM1_CR1 = 0x01; /* 计数器使能,开始向上计数 */
}
#pragma vector = TIM1_OVR_UIF_vector
__interrupt void TIM1_UPD_OVF_IRQHandler( void )
{
unsigned char i;
for ( i = 0; i < 30; i++ )
m_ucData[i] = 0;
state_machine = 0;
retFlag = 0;
TIM1_IER_UIE = 0; /* Turn off the interrupts. */
TIM1_CR1 = 0; /* 计数器停止计数 */
TIM1_SR1 = 0; /* 清除定时器0标志 */
}
void uart_init( void )
{
UART2_CR2_TEN = 1;
UART2_CR2_REN = 1;
UART2_CR2_RIEN = 1;
UART2_BRR2 = ( (unsigned char) ( (F_CPU / BAUD_RATE) & 0x0f) ) + ( ( (unsigned char) ( (F_CPU / BAUD_RATE) >> 8) ) & 0xf0);
UART2_BRR1 = ( (unsigned char) ( (F_CPU / BAUD_RATE) >> 4) );
}
/*
* ******************************************************************************
*
* ******************************************************************************
*/
#pragma vector = UART2_R_RXNE_vector
__interrupt void UART2_IRQHandler( void )
{
unsigned char rcvcount;
unsigned char lencnt;
unsigned char xorchkm;
unsigned char rcvdat;
if ( UART2_SR_RXNE == 1 )
{
UART2_SR_RXNE = 0;
rcvdat = UART2_DR;
/* uart_tx_byte(rcvdat); */
/* 如下是协议解析情况 ,全协议不超过30字节
* 位机发送数据的时候,两个接收数据包之间不少于100毫秒。
*/
if ( state_machine == 0 ) /* 协议解析状态机 */
{
if ( rcvdat == 0x55 ) /* 接收到帧头第一个数据 */
{
SetTimeOut( 100 ); /* 9600bps,一秒钟1200字节。25毫秒为30字节 */
lencnt = 0; /* 接收数据计数器 */
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
state_machine = 1;
}else
state_machine = 0; /* 状态机复位 / */
}else if ( state_machine == 1 )
{
xorchkm = rcvdat; /* 开始计算异或校验和 / */
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
state_machine = 2;
}else if ( state_machine == 2 )
{
xorchkm ^= rcvdat;
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
state_machine = 3;
}else if ( state_machine == 3 )
{
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
rcvcount = rcvdat; /* 接收数据长度 */
xorchkm ^= rcvdat;
if(rcvcount>=24) //数据长度不能超过24个字节
state_machine = 0;
else
state_machine = 4;
}else if ( state_machine == 4 || state_machine == 5 )
{
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
xorchkm ^= rcvdat;
if ( (lencnt - 4) == rcvcount ) /* 判断数据是否接收完毕 */
state_machine = 6;
else
state_machine = 5;
}else if ( state_machine == 6 )
{
if ( xorchkm == rcvdat ) /* 判断异或校验和是否相等 */
{
state_machine = 7;
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
}else
state_machine = 0;
}else if ( state_machine == 7 )
{
if ( 0xAA == rcvdat ) /* 判断是否接收到帧尾结束符 / */
{
m_ucData[lencnt++] = rcvdat; /* 数据保存 */
ClearTimeOut();
retFlag = 0x01; /* 置标志,表示一个数据包接收到 / */
}
state_machine = 0; /* 复位状态 / */
}
}
}