您的位置:首页 > 其它

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

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

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: