你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F030 串口 用IDLE中断 接收不定长度数据包,中断异常

[复制链接]
lps402 提问时间:2017-5-18 17:22 /
本帖最后由 lps402 于 2017-5-18 17:22 编辑

      如题,在使用IDLE中断接收不定长度的数据包,发现程序一直处于IDLE中断中。程序如下
串口配置程序
  1. void USART_Configuration(void)
  2. {
  3.   USART_InitTypeDef USART_InitStructure;
  4.   USART_InitStructure.USART_BaudRate = 9600;                       //设定波特率
  5.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;        //设定传输数据位
  6.   USART_InitStructure.USART_StopBits = USART_StopBits_1;             //设定停止位
  7.   USART_InitStructure.USART_Parity = USART_Parity_No ;               //不用校验位
  8.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不用流量控制
  9.   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //使用接收发送功能
  10.   USART_Init(USART1, &USART_InitStructure);                          //初始化USART1

  11.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                     //使能USART1 接收中断
  12.   USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);                     //使能USART1空闲中断

  13.   USART1->CR1=USART1->CR1&~(1<<4);                             //清除IDLE中断。特意加的,未添加时,上电后,设备一直处于IDLE中断,
  14.                                                                                                    无法执行主程序
  15.   USART_Cmd(USART1, ENABLE);                                            //使能USART1
  16. }
复制代码
中断程序
  1. void USART1_IRQHandler(void)
  2. {
  3. static uint8_t data[10]; //
  4. static uint8_t rxne_num; //
  5. if((USART1->ISR & USART_FLAG_RXNE) == USART_FLAG_RXNE)
  6. {
  7.    data[rxne_num]=USART_ReceiveData(USART1);
  8.    rxne_num=rxne_num+1;
  9.    if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)==SET)
  10.     {
  11.      USART1->CR1=USART1->CR1&~(1<<4); //清楚IDLE中断
  12.       rxne_num=0;
  13.      }
  14. }
复制代码
主程序
  1. int main(void)
  2. {
  3.   static uint8_t   data[10]={0,0,0,0,0,0,0,0,0,0}; //全局变量,接收缓存数组
  4.   static uint8_t          rxne_num=0;                             //全局变量,接收缓存数组序号
  5.   System_Initializes();

  6.         USART1_Printf((uint8_t*)"系统启动");     //打印输出
  7.   while(1)
  8.   {
  9.     LED_STA_TOGGLE;                                  //LED变化
  10. TIMDelay_Nms(500);                           //延时500ms
  11.   }
  12. }
复制代码
         该程序在STM32F103上调试过(串口配置程序,未添加清楚IDLE中断标志位),没有问题,可以正常接收多个字节数据。
STM32F030:当串口调试工具,发送E1E2E3E4数据时,接收到第一个E1时,程序直接进入IDLE中断
  1. /*IDLE中断*/
  2. if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)==SET)
  3. {
  4. USART1->CR1=USART1->CR1&~(1<<4); //清除IDLE中断
  5. rxne_num=0;
  6. }
复制代码
STM32F103:当串口调试工具,发送E1E2E3E4数据时,接收到第四个字节E4时,程序直接才进入IDLE中断。

       请问各位,STM32F030的IDLE这样使用是否有问题?STM32F030的IDLE是否有问题?
收藏 1 评论9 发布时间:2017-5-18 17:22

举报

9个回答
lps402 回答时间:2017-5-18 17:32:35
补充说明
串口GPIO配置
  1. void USART_GPIO_Configuration(void)
  2. {
  3.   GPIO_InitTypeDef GPIO_InitStructure;

  4.   GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
  5.   GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

  6.   /* 定义USART TX/ RX引脚为复用输出 */
  7.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;            //引脚
  8.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                       //复用模式
  9.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  //高速
  10.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                     //推挽输出
  11.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                       //上拉
  12.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  13. }
复制代码
yyq006 回答时间:2017-9-7 09:27:18
楼主问题解决了没有,我也遇到这个问题了。
wanyisq 回答时间:2017-12-29 17:22:00
我也遇到这个问题了
JiNian_04 回答时间:2018-3-24 08:59:42
IDLE清标志位不是通过写CR寄存器,而是一个软件序列,先读SR,再读DR,这样才能清中断,可以看下手册上关于IDLE的介绍
sdtazzf 回答时间:2019-5-15 18:03:01
楼主:IDLE中断为什么一上电就IDLE中断中断一次啊?没有数据也搞一次,怎么解决啊?
edmundlee 回答时间:2019-5-15 18:25:27
if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)==SET)
{
USART1->CR1=USART1->CR1&~(1<<4); //清除IDLE中断
USART1->DR;
rxne_num=0;
}
要加红色这一句
浅色调123 回答时间:2019-6-18 08:57:42
sdtazzf 发表于 2019-5-15 18:03
楼主:IDLE中断为什么一上电就IDLE中断中断一次啊?没有数据也搞一次,怎么解决啊?
...

看我的回复
浅色调123 回答时间:2019-6-18 09:03:44
多年已过,楼主肯定解决了,但是一直没有说一下怎么解决的,我说一下吧附上f030的代码1、初始化千万不要初始化就打开IDLE中断
2、在串口接收中断中打开IDLE中断
3、正确清楚IDLE中断。

void USART1_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStruct;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  //使能GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//使能USART的时钟
    /* USART1的端口配置 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);//配置PA9成第二功能引脚        TX
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);//配置PA10成第二功能引脚  RX

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);


    /* USART1的基本配置 */
    USART_InitStructure.USART_BaudRate = 115200;              //波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    /* USART1的NVIC中断配置 */
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0x02;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);


    USART_Init(USART, &USART_InitStructure);
    USART_ITConfig(USART, USART_IT_RXNE, ENABLE);         //使能接收中断      
//    USART_ITConfig(USART,USART_IT_IDLE,ENABLE);           //初始化的时候千万不要打开IDLE中断   
    USART_Cmd(USART, ENABLE);                             //使能USART1
}

void USART1_IRQHandler(void)
{
    uint8_t Res;
    if(USART_GetITStatus(USART, USART_IT_RXNE) != RESET) {        //接收中断
        if(!(USART->CR1 & USART_CR1_IDLEIE)) {         
            USART_ITConfig(USART,USART_IT_IDLE,ENABLE);//当没有开启IDLE中断的时候再开,不然上电会进去一次
            USART_ClearFlag(USART, USART_FLAG_IDLE);
        }
        Res = USART_ReceiveData(USART);        //读取接收到的数据
    }
    if(USART_GetFlagStatus(USART,USART_FLAG_IDLE) == SET) //空闲中断
    {        
        USART_ClearFlag(USART, USART_FLAG_IDLE);
        USART->RDR;   
        USART_ITConfig(USART,USART_IT_IDLE,DISABLE);//不用的时候关闭串口空闲中断,防止意外进入
        }
    }


lingdingyang 回答时间:2020-6-9 15:15:41
浅色调123 发表于 2019-6-18 09:03
多年已过,楼主肯定解决了,但是一直没有说一下怎么解决的,我说一下吧附上f030的代码1、初始化千万不要初 ...

——“多年已过,楼主肯定解决了”,其实也不一定,也可能是没解决,但是楼主已经死了,所以帖子才一直晾在这里。。。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版