STM32自学之串口中断模式

    今天是自学STM32的第7天了,之前的流水灯,按键,查询方式串口,PWM,计数器和红外有时间再补上来吧,先从今天调试的中断式串口写起吧。

    事先说明,写此博客只是为了记录自己的自学历程,由于水平极其有限,所以很多理解可能是错的,欢迎大家积极指出,让我们一起在嵌入式的开发上向前进。

   我所使用的是神舟三号学习开发板,芯片型号是STM32F103ZE。功能很齐全了,作为初期自学用绰绰有余。

   串口的printf在STM32程序调试过程中,确实可以起到实时跟踪程序进程的作用,但是经过昨天的红外和今天的中断式串口程序的坑爹BUG之后,深深感觉,没事还是不要加printf了,特别是在待处理事件的时间频率很高时,如昨天的红外调试时,信号的解码在ms级别,在加了printf和不加printf时,所解码的结果相差十万八千里。

  好了,回到正题,先上今天的中断式串口程序吧。

  以下是串口配置函数,我单独写了一个头文件,仅贴出核心部分。

void USART1_Configuration(void)
{
   //定义GPIO,,NVIC,USART结构体
   GPIO_InitTypeDef GPIO_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;
   USART_InitTypeDef USART_InitStructure;
   //初始化系统时钟
   SystemInit();
//   //调试用指示灯 
//   RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOF, ENABLE);   //首先是开调试用LED灯的GPIO口时钟
//   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
//   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;              //或者写成 GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2一直重复下去 
//   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
//   GPIO_Init(GPIOF,&GPIO_InitStructure);

//进行串口配置

//   RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);   //开串口和GPIOA的时钟
   //进行中断配置
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                         //中断优先组0
   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
   //配置PA9即USART1_TX_
   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
   GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
   GPIO_Init(GPIOA,&GPIO_InitStructure);
   //配置PA10即USART1_RX
   GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
   GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
   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_Mode=USART_Mode_Rx|USART_Mode_Tx;
   USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
   USART_Init(USART1,&USART_InitStructure);

/***************

      今天的一大坑点来了。在开中断使能时,不能开IT-TXE中断使能,因为 初始化时也会有TXE置位,

  原因就是此时发送数据寄存器为空。今天在这里被深深的坑了一下

                                                    **************************/

// USART_ITConfig(USART1,USART_TI_TXE,ENABLE);    //就是这句,千万不能要,不然马上进入中断
   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
   USART_Cmd(USART1,ENABLE);
   USART_ClearFlag(USART1,USART_FLAG_TC);
}

再就是中断处理函数了。

void USART1_IRQHandler(void)
{
   int i=0;      //中断内读取字符串组用
   flag=0;     //主函数中打印字符串组用,每进一次中断就清零。 
// GPIO_Write(GPIOF,0X340); //调试时用来判断进入中断否的LED灯标志
   if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)    //每个中断函数最好都加上这句,原因我也不知道,前辈说的。
   {
      while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET)    //如果接收数据寄存器非空,就不停地读
 {
              RxBuffer[i++]=USART_ReceiveData(USART1);

/********************

第二大坑点来了,这句本来是为了跟踪读取过程的,结果每次读了2个数据就跳出来了,

很是无语,开始怀疑是前面的配置有问题,一句句的核对了2个小时,实在没发现错误,

再拿出前几天调的查询时串口和这个作比较,发现唯一的不同是这里的printf多了一个\r\n。

其实也就是换行而已,结果我尝试性的把它去掉,一切正常。我嘞个去啊,坑了劳资一下午。

                                                                                 **************/
// printf("%c\r\n",RxBuffer[i-1]);  //调试用语句,为什么这里多一个\r\n就只能获取2个值便跳出中断??????????????
      }
 USART_ClearITPendingBit(USART1,USART_IT_RXNE);     //清除中断标志位,每个中断必备的,不然就出不来了。
   }
}

好了,欢迎大家积极发言,让我们共同进步。

你可能感兴趣的:(单片机,STM32自学)