注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

时间记录器

记录我的Linux、Android学习之路

 
 
 

日志

 
 

STM32 串口 USART1 轮询方式发送、接收都正常,但反复中断的解决  

2010-08-03 21:54:45|  分类: STM32 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
楼主位: 问题贴               (问题解决在7楼,结束贴)

我的STM32F103ZET小板的 USART1 中断进不去,查了很久,没找到原因。 

USART1 向电脑端发送数据已经可以了(轮询方式),就是发送或接收完一个字符好像没有进中断。(整个系统已经跑起来了) 
下面是我的相关程序片段,请各位大侠帮忙分析一下。万分感谢! 

void RCC_Config(void)//初始化时钟     
{   . 

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1  
                         | RCC_APB2Periph_GPIOA  
 | RCC_APB2Periph_GPIOB   
                         | RCC_APB2Periph_AFIO, ENABLE); 



void GPIO_Config(void)//引脚初始化 

    GPIO_InitTypeDef GPIO_InitStructure; 
     . 
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */ 
    /* Configure USART1 Rx (PA.10) as input floating */ 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
     . 

void InterruptConfig(void)//中断初始化 

    NVIC_InitTypeDef NVIC_InitStructure; 
    EXTI_InitTypeDef EXTI_InitStructure; 

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); 

    NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick,0,0); 
     . 
    /* Enable the USART1 Interrupt */ 
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure); 
     .      

void USART_Config(void)//串口初始化 

    USART_InitTypeDef USART_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; 
   
    /* Configure USART1 */ 
    USART_Init(USART1, &USART_InitStructure); 
     
    /* Enable USART1 Receive and Transmit interrupts */ 
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE); 
     
     /* Enable the USART1 */ 
    USART_Cmd(USART1, ENABLE); 
     


void USART1_IRQHandler(void

    u16 data; 

    GPIO_ResetBits(GPIOG,GPIO_Pin_14);//要是进了中断,这里应该会把LED灯点亮,实际没有 

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//中断是由接收到字符产生的 
  {    
      data = USART_ReceiveData(USART1);  
  } 
   
  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)//发送一个字符完成产生中断 
  {    
    /* Write one byte to the transmit data register */ 
 GPIO_ResetBits(GPIOG,GPIO_Pin_13); 
  } 



按理无论是发送还是接收产生中断的话都应该把灯点亮的,实际没有。 

4楼:

按参考例程,现在加了清中断函数,修改后的ISR如下。问题依然没有解决,用示波器观察,确定是不断进入中断了。 

void USART1_IRQHandler(void

  u16 data; 

  if(led1==0)//示波器观察,看到方波了 
  { 
    led1=1
    GPIO_ResetBits(GPIOG,GPIO_Pin_14); 
  } 
  else  
  { 
    led1=0
    GPIO_SetBits(GPIOG,GPIO_Pin_14); 
  } 

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//中断是由接收到字符产生的 
  {    
    data = USART_ReceiveData(USART1);  
    USART_ClearITPendingBit(USART1 ,USART_IT_RXNE);//清接收中断 
      ... 
  } 
   
  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)//发送一个字符完成产生中断 
  {    
    USART_ClearITPendingBit(USART1 ,USART_IT_TXE);//清发送中断 
      ... 
  } 


并且也确定问题出在 
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure);//问题出在这里 

我继续跟下去,发现 NVIC_Init()函数中 
  if(NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) 
  {    
    ... 
    NVIC->ISER[(NVIC_InitStruct->NVIC_IRQChannel >> 0x05)] = 
      (u32)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (u8)0x1F);//这里触发了一次中断 
  } 
  else 
  { 
    ... 
  } 

从此,中断就不返回了。永无止尽的中断.... 

7楼: 结束贴
问题的分析: 

我在void USART_Config(void)串口初始化函数中设置了USART_ITConfig(USART1, USART_IT_TXE, ENABLE);,对“发送数据寄存器空”中断进行了使能。 
其中TXE中断的描述是如下(STM32F10x微控制器参考手册(200812月第7版).pdf,P494) 
______________________________________________________________________________ 
|  TXE:发送数据寄存器空  
|     当TDR寄存器中的数据被硬件转移到移位寄存器的时候,该位被硬件置位。如果USART_CR1 
|     寄存器中的TXEIE为1,则产生中断。对USART_DR的写操作,将该位清零。  
|     0:数据还没有被转移到移位寄存器;  
|     1:数据已经被转移到移位寄存器。  
|  注意:单缓冲器传输中使用该位。 
|_____________________________________________________________________________ 
其中提到该位的清零只能由对对USART_DR的写操作来完成。而我在原来的程序里面使用了 
USART_ClearITPendingBit(USART1 ,USART_IT_TXE); 
这句话,本意是想在ISR中清除 发送数据寄存器空 中断,实际上只是一厢情愿,并不能达到清中断标志的目的。 
跟踪USART_ClearITPendingBit();函数,发现在函数说明中,这个函数并不能对USART_IT_TXE进行操作,原来的写法有误。 
/******************************************************************************* 
* Function Name  : USART_ClearITPendingBit 
* Description    : Clears the USARTx interrupt pending bits. 
* Input          : - USARTx: Select the USART or the UART peripheral.  
*                    This parameter can be one of the following values: 
*                     - USART1, USART2, USART3, UART4 or UART5. 
*                  - USART_IT: specifies the interrupt pending bit to clear. 
*                    This parameter can be one of the following values: 
*                       - USART_IT_CTS:  CTS change interrupt (not available for  
*                                        UART4 and UART5) 
*                       - USART_IT_LBD:  LIN Break detection interrupt 
*                       - USART_IT_TC:   Transmission complete interrupt.  
*                       - USART_IT_RXNE: Receive Data register not empty interrupt. 
*                       - USART_IT_IDLE: Idle line detection interrupt. 
*                       - USART_IT_ORE:  OverRun Error interrupt. 
*                       - USART_IT_NE:   Noise Error interrupt. 
*                       - USART_IT_FE:   Framing Error interrupt. 
*                       - USART_IT_PE:   Parity Error interrupt. 
*  可以看到,USART_IT_TXE并不能作为该函数的参数。 
*                    Note: - For IDLE, ORE, NE, FE and PE pending bits user has to  
*                            read the USART DR register after calling this function. 
*                          - TXE pending bit can't be cleared by this function, it's 
*                            cleared only by a write to the USART DR register. 
* Output         : None 
* Return         : None 
*******************************************************************************/
 
这就导致了上面提到的出现永无止尽的中断,因为 USART_DR 一直都是空的。 
这样看来,我在 4 楼提到的 NVIC_Init()函数中  
“NVIC->ISER[(NVIC_InitStruct->NVIC_IRQChannel >> 0x05)] = (u32)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (u8)0x1F);//这里触发了一次中断 ” 
这样的描述是不对的,并不是触发软中断,只是这句话刚打开中断,CPU发现 USART_DR 是空的,于是就进入响应中断了。 

解决办法: 

1. 因为发送的数据量不是很大,只是打印几个字符信息而已,所以干脆就把发送空中断关了 
2. 将原来发送一个字符的函数 
    void putch(u8 c) 
    { 
        if(c=='\n'
        { 
            USART_SendData(USART1, 0x0D); 
            while(!USART_GetITStatus(USART1, USART_IT_TXE)); //将要改这里 
            USART_SendData(USART1, 0x0A); 
            while(!USART_GetITStatus(USART1, USART_IT_TXE)); 
        } 
        else 
        { 
            USART_SendData(USART1, (unsigned char)c); 
            while(!USART_GetITStatus(USART1, USART_IT_TXE));  
        } 
    }//end of void putch(u8 c) 
改为 
    void putch(u8 c) 
    { 
        if(c=='\n'
        { 
            USART_SendData(USART1, 0x0D); 
            while (!(USART1->SR & USART_FLAG_TXE)); //这里改动 
            USART_SendData(USART1, 0x0A); 
            while (!(USART1->SR & USART_FLAG_TXE)); 
        } 
        else 
        { 
            USART_SendData(USART1, (unsigned char)c); 
            while (!(USART1->SR & USART_FLAG_TXE));  
        } 
    }//end of void putch(u8 c) 
  评论这张
 
阅读(7856)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017