stm8 uart2 串口接收中断协议解码+定时器中断

时间:2022-06-29 19:15:46

协议解码的时候,如果上位机发送数据不完整或者有错误,通过定时器中断将之接收的不完整数据清楚。定时的时间长短可有定时器觉得,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;                              /* 复位状态 / */
}
}
}