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

STM32F072在跑UCOS时UART中断服务程序只进去第一次

[复制链接]
haihuang-402384 提问时间:2014-12-17 18:54 /
我跑裸机的时候在中断里面接收到数据就马上发送出来没有问题,但是在Ucos系统下只有第一次进了UART中断服务程序,ucos其它任务照常运行。这是怎么回事?(备注:接收的是GPS模块传过来的数据,然后在任务中串口输出是没问题的,就是中断接收有问题)
中断服务程序如下:
void USART1_IRQHandler(void)
{
        INT8U i = 0;
        OS_CPU_SR  cpu_sr;

       OS_ENTER_CRITICAL();                        
       OSIntNesting++;
       OS_EXIT_CRITICAL();

       while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
        {
        }
        i = USART_ReceiveData(USART1);
        printf("%c",i);
        OSIntExit();
}
初始化那些应该没问题,跑裸机是可以的
下面是初始化程序:
void NvicInit(void)
{
        
      NVIC_InitTypeDef  NVIC_InitStructure;

      NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
      NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPriority = 0x03;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
}

void UartInit(void)
{
                INT8U i;

        GPIO_InitTypeDef  GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA   , ENABLE);   // 使能GPIOA端口
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1   , ENABLE); // 使能串口1时钟
   
        GPIO_PinAFConfig(GPIOA ,GPIO_PinSource9, GPIO_AF_1);
        GPIO_PinAFConfig(GPIOA ,GPIO_Pin_10, GPIO_AF_1);                           
/////////////////////////////////////////////////////////////////////////////////////        
        /* PA9==TX PA10-RX  */  

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

        GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10 ;
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;        
        GPIO_Init(GPIOA , &GPIO_InitStructure);
/////////////////////////////////////////////////////////////////////////////////////

        USART_InitStructure.USART_BaudRate = 9600;                                       
        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;               
        USART_Init(USART1, &USART_InitStructure);         //串口配置

        USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);//打开中断        
                                
        USART_Cmd(USART1, ENABLE);//使能串口1
        USART_ClearFlag(USART1, USART_FLAG_TC);  
        
}


收藏 评论29 发布时间:2014-12-17 18:54

举报

29个回答
haihuang-402384 回答时间:2014-12-18 08:54:35
自己顶一下
回答时间:2014-12-18 09:45:18
中断中不要写死循环,用if来判断,并且要清除串口标志位。

OSIntEnter();   
              
  if(USART_GetITStatus(USART1, USART_IT_RXNE) !=RESET)
  {
    ch =USART_ReceiveData(USART1);
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);  
  }
   OSIntExit();  
haihuang-402384 回答时间:2014-12-18 10:51:02
安 发表于 2014-12-18 09:45
中断中不要写死循环,用if来判断,并且要清除串口标志位。

OSIntEnter();   

F0系列好像跟其他系列不一样,我都是先在裸机上测试的,裸机下情况:一开始我也是用if来判断标志位,if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
{
      i = USART_ReceiveData(USART1);
      printf("%c",i);
}
至于清除标志位数据手册上面是这么说的:In single buffer mode, clearing the RXNE bit is performed by a software read to the USARTx_RDR register. 那么我读完寄存器标志位也就清除了。然而上述程序跑裸机状态下是不行的,然后我看了摩尔吧枫叶老师的例程是这么写的:
while(USART_GetFlagStatus(F072RB_COM, USART_FLAG_RXNE) == RESET);//等待接收为空
     Uart_buf[0] = (unsigned char)(USART_ReceiveData(F072RB_COM)); // 接收单个字符
他用一个while阻塞到数据接收完,但是我看数据手册并没有说接受完RENE位会被清除,但我试着用他的方法,还真成功接收然后发送出来了。这点我百思不得其解,F0怎么跟其他的有这样的差别。但是移植到操作系统下就出现问题了,只进去一次中断
haihuang-402384 回答时间:2014-12-18 10:53:44
安 发表于 2014-12-18 09:45
中断中不要写死循环,用if来判断,并且要清除串口标志位。

OSIntEnter();   

测试表明那个while并不是死循环,状态位会被清除,然后往下执行
回答时间:2014-12-18 11:29:22
这里就怕会产生死循环,是个隐性问题。下次再接收时,发生什么情况?退出中断以后,对应的寄存器是否发生了变化?
小贾-370388 回答时间:2014-12-18 11:55:00
In single buffer mode, clearing the RXNE bit is performed by a software read to the USARTx_RDR register,说的是在single buffer 模式 是在软件读USARTx_RDR 的时候产生的清楚RXNE 位,while(USART_GetFlagStatus(F072RB_COM, USART_FLAG_RXNE) == RESET);//这句话应该是当有数据的时候RXNE置位1这时才读取读取完自动会清除 USART_FLAG_RXNE,就会跳出循环,并不是循环等待接受,跟IF 是一个意思。为什么你上面写的是!= RESET啊,只是没有接收到数据的意思啊
haihuang-402384 回答时间:2014-12-18 13:55:40
安 发表于 2014-12-18 11:29
这里就怕会产生死循环,是个隐性问题。下次再接收时,发生什么情况?退出中断以后,对应的寄存器是否发生了 ...

下次不会再进中断了,系统的几个任务都还正常运行,看寄存器RX使能位开着没问题,但是RXNE中断标志位一直没置位,RDR寄存器也一直是0。还有我定义了一个全局数组变量,然后如果用这个数组来存数据的话会发生段错误,所以后来就用了个i来接收,然后调试的时候会看到那个全局变量数组里面的值一直在变化,除了初始化一次后,我又没对它进行操作,这是怎么回事
rdr.png
rxie.png
rxne.png
haihuang-402384 回答时间:2014-12-18 13:58:03
小贾-370388 发表于 2014-12-18 11:55
In single buffer mode, clearing the RXNE bit is performed by a software read to the USARTx_RDR regis ...

之前逻辑乱了,是寄存器接收完数据后才会往下执行,我刚用if来接收,在裸机状态下也可以了,就是跑操作系统时不行
wambob 回答时间:2014-12-18 14:08:39
中断服务程序中,前后加上OSIntEnter();OSIntExit();
如果不行,是不是中断任务切换程序出错.
123下一页

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版