目前我知道的断帧的方式有两种:
1、通过判断特殊字符0x0d 0x0a或者自定义字符如0x5a 0xa5(起始),0xfa,0xaf(结束)
其串口程序可以为:
void USART3_4_IRQHandler(void)
{
unsigned char Res3;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
Res3 =USART_ReceiveData(USART3);//(USART3->DR);
USART_ClearITPendingBit(USART3,USART_IT_RXNE);
Usart3_Buff[Usart3_Data_Number]=Res3 ;
Usart3_Data_Number++;
if(Usart3_Buff[0]!=0x5A) Usart3_Data_Number=0;
if(Usart3_Data_Number>=Usart_Max_Recive_Data-2) Usart3_Data_Number=0;
if((Usart3_Buff[Usart3_Data_Number-2] == 0xfa)&&(Res3 == 0xaf))
{
usart3_data_len=Usart3_Data_Number;
Usart3_Recive_flag=1;
Usart3_Data_Number=0;
}
}
if(( USART_GetITStatus(USART3, USART_IT_ORE) != RESET ) || ( USART_GetFlagStatus(USART3, USART_FLAG_ORE) != RESET ) )
{
USART_ReceiveData(USART3);
USART_ClearITPendingBit(USART3,USART_IT_RXNE);
}
}
方式2:通过定时器断帧
void USART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //串口接收中断
{
USART_ClearITPendingBit(USART3, USART_IT_RXNE); //清除空闲中断标志
USART3_RBuf[USART3_RBuf_CNT]=USART_ReceiveData(USART3);
USART3_RBuf_CNT++;
if(USART3_RBuf_CNT>=100) USART3_RBuf_CNT=0;
MBMasterTimersEnable(1); //开启定时器断帧
}
if(USART_GetFlagStatus(USART3, USART_FLAG_ORE) != RESET)
{
USART_ClearFlag(USART3,USART_FLAG_ORE); //读SR
USART_ReceiveData(USART3);//清除ORE中断(先读SR 再读DR)
}
}
void DMA_TIMER_Config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
u16 PrescalerValue = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
PrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1; // 1/20000=50us
TIM_TimeBaseStruct.TIM_Period = (USART3_Baud>19200?35:500000/(USART3_Baud)); //定时器计数值 count much n_50us
TIM_TimeBaseStruct.TIM_Prescaler = PrescalerValue; //定时器分频系数
TIM_TimeBaseStruct.TIM_ClockDivision = 0; //设置时钟分割
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up; //定时器计数模式向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);
TIM_ARRPreloadConfig(TIM3, ENABLE); //使能ARR上的预装载寄存器
}
void MBMasterTimersEnable(u8 Timer_EN)
{
if (1 == Timer_EN)
{
TIM_SetCounter(TIM3,0x0000); //复位定时器计数值为0
TIM_Cmd(TIM3, ENABLE); //使能定时器
TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清除定时器更新标志
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //使能定时器中断
}
else
{
TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE); //关闭定时器中断
TIM_Cmd(TIM3, DISABLE); //关闭定时器
}
}
void TIM3_IRQHandler(void)
{
if (RESET != TIM_GetITStatus(TIM3, TIM_IT_Update))
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除定时器中断标志
MBMasterTimersEnable(0); //关闭定时器
mb_rtu_Fram.MB_CNT=USART3_RBuf_CNT; //获取接收到的数据
USART3_RBuf_CNT=0; //清零
mb_rtu_Fram.MB_PORT_STA = 1; //串口接收到数据置位
}
}
代码贴上来了 代码是经过测试的 可以直接使用