3、UART的配置步骤(中断方式) 打开时钟、GPIO初始化、配置UART相关属性、重定向print()函数 与上面的相同。 3.1、中断优先级的配置 这是STM32比较奇怪的地方,在只有一个中断的情况下,仍然需要配置优先级,其作用是使能某条中断的触发通道。STM32的中断有至多两个层次,分别是先占优先级和从优先级,而整个优先级设置参数的长度为4位,因此需要首先划分先占优先级位数和从优先级位数,通过NVIC_PriorityGroupConfig()实现; 特定设备的中断优先级NVIC的属性包含在结构体NVIC_InitTypeDef中,其中字段NVIC_IRQChannel包含了设备的中断向量,保存在启动代码中;字段NVIC_IRQChannelPreemptionPriority为主优先级,NVIC_IRQChannelSubPriority为从优先级,取值的范围应根据位数划分的情况而定;最后NVIC_IRQChannelCmd字段是是否使能,一般定位ENABLE。最后通过NVIC_Init()来使能这一中断向量。实例代码如下: [url=][/url]
//配置UART1接收中断void NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the USARTy Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}[url=][/url]
3.2、中断的服务程序的设计 目前使用了UART的两个中断USART_IT_RXNE(接收缓存补空中断)和USART_IT_TXE(发送缓存空中断),前一个中断保证了一旦有数据接收到就进入中断以接收特定长度的数据,后一个中断表示一旦发完一个数据就进入中断函数,保证连续发送一段数据。一个设备的所有中断都包含在一个中断服务程序中,因此必须首先分清楚这次响应的是哪一个中断,使用USART_GetITStatus()函数确定;采用USART_ReceiveData()函数接收一个字节数据,采用USART_SendData()函数发送一个字节数据,当关闭中断时采用USART_ITConfig()失能响应的中断。实例程序: [url=][/url]
void USART1_IRQHandler(void){ uint8_t ch; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { //ch = USART1->DR; ch = USART_ReceiveData(USART1); //接受数据 printf( "%c", ch ); //返回打印 } }[url=][/url]
3.3、接收数据函数: [url=][/url]
//重定向scanf函数到USART1int fgetc(FILE *f){ /*等待串口1输入数据*/ while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(USART1);}[url=][/url]
4、 STM32串口在首次发送字符的时候,首字符丢失解决办法 网上关于发送字符的代码大多如下: USART_SendData(USART1, (uint8_t)ch);
while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); 其实咋一看是说的通的,但是在仔细看手册的时候发现 TC 和 TXE 标志位在复位的时候被置1 ,这样第一次while循环就是没有用的。这样导致了首次第一个字符还没有被输出,就被后面的字符覆盖掉,造成实际看到的丢失现象。解决办法就很简单:在前面加上一句 USART1->SR; 具体代码如下: USART1->SR;
USART_SendData(USART1, (uint8_t)ch);
while( USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); 下面我来说说原因: 第一句读取SR寄存器,第二句写DR寄存器 刚好清除了TC标志位 。第一次while循环就起作用了。 也可将USART1->SR;替换为USART_GetFlagStatus(USART1, USART_FLAG_TC)
本实验所有程序《STM32串口USART1的查询和中断方式程序》
补充:一直有一个疑问是关于接受和发送数据的问题:对于“hello”这样的字符串是一个一个接受还是整个接受显示,下面的实验可以验证是一个一个进行的。
|