今天是自学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); //清除中断标志位,每个中断必备的,不然就出不来了。
}
}
好了,欢迎大家积极发言,让我们共同进步。