USART作为一种标准接口在应用中十分常见。本文着重分析其作为UART的配置和应用方法。
1、STM32固件库使用外围设备的主要思路
在STM32中,外围设备的配置思路比较固定。首先是使能相关的时钟,一方面是设备本身的时钟,另一方面如果设备通过IO口输出还需要使能IO口的时钟;最后如果对应的IO口是复用功能的IO口,则还必须使能AFIO的时钟。
其次是配置GPIO,GPIO的各种属性由硬件手册的AFIO一章详细规定,较为简单。
接着相关设备需要如果需要使用中断功能,必须先配置中断优先级,后文详述。
然后是配置外围设备的相关属性,视具体设备而定,如果设备需要使用中断方式,必须使能相应设备的中断,之后需要使能相关设备。
最后如果设备使用了中断功能,则还需要填写相应的中断服务程序,在服务程序中进行相应操作。
2、UART的配置步骤
2.1、打开时钟
由于UART的TX和RX和AFIO都挂在APB2桥上,因此采用固件库函数RCC_APB2PeriphClockCmd()进行初始化。UARTx需要分情况讨论,如果是UART1,则挂在APB2桥上,因此采用RCC_APB2PeriphClockCmd()进行初始化,其余的UART2~5均挂在APB1上。
2.2、GPIO初始化
GPIO的属性包含在结构体GPIO_InitTypeDef,其中对于TX引脚,GPIO_Mode字段设置为GPIO_Mode_AF_PP(复用推挽输出),GPIO_Speed切换速率设置为GPIO_Speed_50MHz;对于RX引脚,GPIO_Mode字段设置为GPIO_Mode_IN_FLOATING(浮空输入),不需要设置切换速率。最后通过GPIO_Init()使能IO口。
以下是TX引脚设置的实例代码:
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = UART_TX_PIN[COM];
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(UART_TX_PORT[COM], &GPIO_InitStructure);
2.3、中断优先级的配置
这是STM32比较奇怪的地方,在只有一个中断的情况下,仍然需要配置优先级,其作用是使能某条中断的触发通道。STM32的中断有至多两个层次,分别是先占优先级和从优先级,而整个优先级设置参数的长度为4位,因此需要首先划分先占优先级位数和从优先级位数,通过NVIC_PriorityGroupConfig()实现;
特定设备的中断优先级NVIC的属性包含在结构体NVIC_InitTypeDef中,其中字段NVIC_IRQChannel包含了设备的中断向量,保存在启动代码中;字段NVIC_IRQChannelPreemptionPriority为主优先级,NVIC_IRQChannelSubPriority为从优先级,取值的范围应根据位数划分的情况而定;最后NVIC_IRQChannelCmd字段是是否使能,一般定位ENABLE。最后通过NVIC_Init()来使能这一中断向量。实例代码如下:
/* Configure theNVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
2.4、配置UART相关属性
通过结构体USART_InitTypeDef来确定。UART模式下的字段如下
USART_BaudRate:波特率,视具体设备而定
USART_WordLength:字长
USART_StopBits:停止位
USART_Parity:校验方式
USART_HardwareFlowControl:硬件流控制
USART_Mode:单/双工
最后通过USART_Init()来设置。实例代码为:
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_Cmd()来启动设备UART。
2.5、中断的服务程序的设计
目前使用了UART的两个中断USART_IT_RXNE(接收缓存补空中断)和USART_IT_TXE(发送缓存空中断),前一个中断保证了一旦有数据接收到就进入中断以接收特定长度的数据,后一个中断表示一旦发完一个数据就进入中断函数,保证连续发送一段数据。一个设备的所有中断都包含在一个中断服务程序中,因此必须首先分清楚这次响应的是哪一个中断,使用USART_GetITStatus()函数确定;采用USART_ReceiveData()函数接收一个字节数据,采用USART_SendData()函数发送一个字节数据,当关闭中断时采用USART_ITConfig()失能响应的中断。实例程序:
voidUART4_IRQHandler(void)
{
if(USART_GetITStatus(UART4,USART_IT_RXNE) != RESET)
{//当检测掉读入中断
RxBuffer[RxCounter++] = USART_ReceiveData(UART4);
if (RxCounter ==NbrOfDataToRead)
{
USART_ITConfig(UART4, USART_IT_RXNE, DISABLE); //禁止中断
}
}
if(USART_GetITStatus(UART4, USART_IT_TXE) != RESET)
{
/* Write one byte to the transmit data register */
USART_SendData(UART4, TxBuffer[TxCounter++]);
if(TxCounter ==NbrOfDataToTransfer)
{
//TxCounter = 0;
/* Disable the USARTy Transmit interrupt */
USART_ITConfig(UART4, USART_IT_TXE, DISABLE);
}
}
}
其中主程序与中断服务程序通过全局变量来通信,这也是一种多进程共享存储区的体现形式。