打印

STM8的UART接收中断遇到0x00出现溢出错误

[复制链接]
1289|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 crystal1987 于 2020-3-17 16:52 编辑

使用STM8的UART与485芯片进行通信。STM8的UART接收中断没有接收0X00数据时,通信数据正常,数据也不会丢失;当接收数据中含有0X00时,就会进入数据溢出中断,而且接收的数据也会丢失,如果发送八个数据,很多时候只能接收到6个;网上的很多方法都试过,也没效果;代码发出来,大神帮忙看看。

void ALL_GPIO_Config(void)
{
    /////////////////////////////// LED //////////////////////////////////////////////
    GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_Init(GPIOC, GPIO_PIN_7, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);
    LED_G_OFF;LED_R_OFF;LED_Y_OFF;
    /////////////////////////////// UART //////////////////////////////////////////////
    GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);   //RS485接收转换使能
    GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);
    GPIO_Init(GPIOD, GPIO_PIN_6, GPIO_MODE_IN_PU_IT);

}


void UART1_Config(void)
{

      CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);
    //初始化UART中的所有寄存器
      UART1_DeInit();

      //UART的参数初始化
      UART1_Init(9600, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);      
      UART1_ITConfig(UART1_IT_TXE,DISABLE);//关闭串口发送中断  
      UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE);//打开串口接收中断   

      //使能UART
      UART1_Cmd(ENABLE);

    //中断使能
    enableInterrupts();  
}



/************************************************************************************************
**     @function   UART1_RX_IRQHandler
**     @author      
**     @version     V1.0
**     @date          接收中断
************************************************************************************************/
unsigned char IT_States[4]= {0};
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
        unsigned char kk = 0;
        unsigned char  status=UART1->SR;

        if(UART1_GetFlagStatus(UART1_FLAG_OR) == SET)//stm8 uart?生溢出??的原因
        {
                 UART1->SR &= 0xDF;
                 UART1_ClearFlag(UART1_FLAG_OR); //清除ORE
                 kk = UART1_ReceiveData8();
                 LED_G_ON;
        }
        else  if(UART1_GetFlagStatus(UART1_FLAG_RXNE) != RESET)          //查看UART1中?是否?生
        {            
//                TIM2_SetCounter(0);
//                TIM2_Cmd(ENABLE);

                LED_R_ON_OFF;
                USART1_RECEIVE_BUFF[rec_len] = UART1_ReceiveData8();  
                rec_len++;
                if(rec_len>=100)  rec_len = 0;
                UART1_ClearITPendingBit(UART1_IT_RXNE);            //清除UART1挂起?志
        }
}


/************************************************************************************************
**     @function   UART1_TX_IRQHandler
**     @author      
**     @version     V1.0
**     @date         发送中断
************************************************************************************************/
INTERRUPT_HANDLER(UART1_TX_IRQHandler, 17)
{
       if( (RESET != UART1_SR_TC) && (RESET != UART1_CR2_TCIEN) )   //if(UART1_SR & 0x80)  //
      {
                if(uart_len != 0)
                {
                        UART1_SendData8(*uart_buf);
                        uart_buf++;
                        uart_len--;
                }
                else
                {
                        UART1_ITConfig(UART1_IT_TXE, DISABLE);  //close send interrupt
                        RX485;
                }
      }
}






使用特权

评论回复
评论
xch 2020-3-18 19:11 回复TA
这个代码写得不好。 接收中断入口,应该立刻读状态和数据两寄存器,得到快照。清除需要清除的标记。 然后,后续一堆代码仅对快照的数据进行处理。特别是状态寄存器应避免多次读取。 

相关帖子

沙发
crystal1987|  楼主 | 2020-3-18 09:38 | 只看该作者
补充一下:用示波器测量通信信号,进入STM8之前的信号都是正常的(没有缺少数据的信号),但STM8收到的数据出错时,就进入数据溢出中断;也不是每次带0x00就进入溢出中断,偶尔也能收到完整的数据帧(带0x00)。

使用特权

评论回复
板凳
crystal1987|  楼主 | 2020-3-18 16:50 | 只看该作者
补充一下:目前的问题,不知道是软件还是硬件问题(软件的可能性大),借了一块开发板和例程测试,也存在同样的问题。难道是STM8单片机在这种情况下,对数据00敏感???

使用特权

评论回复
地板
xch| | 2020-3-18 19:02 | 只看该作者
可能是发送端漏了00,

不少人把数据当作字符串输出处理,字符串中0x0 会被认为是字符串结束,不发送。

使用特权

评论回复
5
crystal1987|  楼主 | 2020-3-18 19:28 | 只看该作者
xch 发表于 2020-3-18 19:02
可能是发送端漏了00,

不少人把数据当作字符串输出处理,字符串中0x0 会被认为是字符串结束,不发送。

谢谢,回复。用示波器监测到发送的00数据,应该不是这个问题。

使用特权

评论回复
6
crystal1987|  楼主 | 2020-3-18 19:33 | 只看该作者
问题解决。说一下解决方法,便于以后程序设计大家参考。 将通信IO口初始化删除,也就是UART通信的IO口不用初始化,使用系统默认的。
如下:

void ALL_GPIO_Config(void)
{
    /////////////////////////////// LED //////////////////////////////////////////////
    GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_Init(GPIOC, GPIO_PIN_7, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST);
    LED_G_OFF;LED_R_OFF;LED_Y_OFF;
    /////////////////////////////// UART //////////////////////////////////////////////
    GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);   //RS485接收转换使能
//    GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);
//    GPIO_Init(GPIOD, GPIO_PIN_6, GPIO_MODE_IN_PU_IT);

}

使用特权

评论回复
7
crystal1987|  楼主 | 2020-3-18 19:35 | 只看该作者
本帖最后由 crystal1987 于 2020-3-18 19:36 编辑

953155e7207592cb5f.png (16.3 KB )

953155e7207592cb5f.png

520875e7207737808d.png (16.3 KB )

520875e7207737808d.png

使用特权

评论回复
8
milk0510| | 2020-4-6 22:19 | 只看该作者
学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:不会是因为你懒

17

主题

349

帖子

5

粉丝