STM32F10x的USART有不少功能(例如LIN、irDA等),这里只用作普通串口。
STM32F10x最多有3组USART和2组UART。
1. USART和UART的区别
UART:Universal Asynchronous Receiver and Transmitter通用异步收发器。信号: RXD, TXD。
USART:Universal Synchronous Asynchronous Receiver and Transmitter通用同步异步收发器。信号:RXD,TXD,CK,其中CK为同步时钟信号。
这里只考虑UART的情况。
2. UART1/UART2/UART3的IO配置
IO采用默认的复用脚。这里只列举了3个USART的IO配置
RCC->APB2ENR |= RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB;
//A9: TX1, A10: RX1
GPIOA->CRH &= ~(0x000000FF << ((9 % 8) * 4));
GPIOA->CRH |= (0x0000008B << ((9 % 8) * 4));
GPIOA->BSRR = ((uint32_t)1 << 10);
//A2: TX2, A3: RX2
GPIOA->CRL &= ~(0x000000FF << ((2 % 8) * 4));
GPIOA->CRL |= (0x0000008B << ((2 % 8) * 4));
GPIOA->BSRR = ((uint32_t)1 << 3);
//B10: TX3, B11: RX3
GPIOB->CRH &= ~(0x000000FF << ((10 % 8) * 4));
GPIOB->CRH |= (0x0000008B << ((10 % 8) * 4));
GPIOB->BSRR = ((uint32_t)1 << 11);
3. 全局变量
首先定义需要用到的全局变量:
USART_TypeDef* const USARTxGroup[] = {USART1, USART2, USART3};
用于对应STM32的USART寄存器结构。
EXTERN volatile uint8_t gUart0RecvBuf[UART0_RECV_BUFSIZE];
EXTERN volatile uint8_t gUart1RecvBuf[UART1_RECV_BUFSIZE];
EXTERN volatile uint8_t gUart2RecvBuf[UART2_RECV_BUFSIZE];
各个USART接收缓冲,如果不使用则设置大小为0。
static volatile uint16_t gUartRecvIn[] = {0, 0, 0};
static volatile uint16_t gUartRecvRd[] = {0, 0, 0};
USART读写接收缓冲的位置,gUartRecvIn表示写入位置,gUartRecvRd表示读出位置。
4. UART初始化
程序采用数字来表示不同的Uart,port 0表示USART1,port 1表示USART2,以此类推。
UART初始化的API函数原型如下:
void uartInit(uint8_t port, uint32_t baudrate,
uartparity_e parity, uartStop_e stopBit, uint8_t datBit)
参数说明:
port - UART端口号,有效值0 – n,具体根据MCU和应用设计对应的端口定义。这里有效值是0到2.
baudrate - UART的波特率。
parity - UART的奇偶校验位设置。定义其枚举类型如下:
typedef enum eUartParity
{
UART_PARITY_NONE = 0,
UART_PARITY_EVEN,
UART_PARITY_ODD,
}uartparity_e;
stopBit - UART的停止位设置。定义其枚举类型如下:
typedef enum eUartStop
{
UART_STOP_1 = 0,
UART_STOP_0_5,
UART_STOP_1_5,
UART_STOP_2,
}uartStop_e;
4.1 使能USART的RCC并DeInit USART
switch(port)
{
case HW_UART0:
RCC->APB2ENR |= RCC_APB2Periph_USART1;
RCC->APB2RSTR |= RCC_APB2Periph_USART1; //DeInit
RCC->APB2RSTR &= ~RCC_APB2Periph_USART1;
break;
case HW_UART1:
RCC->APB1ENR |= RCC_APB1Periph_USART2;
RCC->APB1RSTR |= RCC_APB1Periph_USART2; //DeInit
RCC->APB1RSTR &= ~RCC_APB1Periph_USART2;
break;
case HW_UART2:
RCC->APB1ENR |= RCC_APB1Periph_USART3;
RCC->APB1RSTR |= RCC_APB1Periph_USART3; //DeInit
RCC->APB1RSTR &= ~RCC_APB1Periph_USART3;
break;
default:
return;
}
4.2 中断初始化
void uartNVICInit(USART_TypeDef *USARTx, uint8_t priority)
{
NVIC_InitTypeDef NVIC_InitStructure;
if(USARTx == USART1)
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
else if(USARTx == USART2)
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
else if(USARTx == USART3)
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
}
使能RXNE中断。
优先级为0:
USART_TypeDef *USARTx;
USARTx = USARTxGroup[port];
uartNVICInit(USARTx, 0);
4.3 配置USART
USART_InitStructure.USART_BaudRate = baudrate;
switch(datBit)
{
case 8:
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
break;
case 9:
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
break;
default:
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
break;
}
switch(stopBit)
{
case UART_STOP_1:
USART_InitStructure.USART_StopBits = USART_StopBits_1;
break;
case UART_STOP_0_5:
USART_InitStructure.USART_StopBits = USART_StopBits_0_5;
break;
case UART_STOP_1_5:
USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
break;
case UART_STOP_2:
USART_InitStructure.USART_StopBits = USART_StopBits_2;
break;
default:
USART_InitStructure.USART_StopBits = USART_StopBits_1;
break;
}
switch(parity)
{
case UART_PARITY_NONE:
default:
USART_InitStructure.USART_Parity = USART_Parity_No;
break;
case UART_PARITY_EVEN:
USART_InitStructure.USART_Parity = USART_Parity_Even;
break;
case UART_PARITY_ODD:
USART_InitStructure.USART_Parity = USART_Parity_Odd;
break;
}
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USARTx, &USART_InitStructure);
5. 中断处理程序
void USART1_IRQHandler(void)
{
USART_IRQHandler(0);
}
void USART2_IRQHandler(void)
{
USART_IRQHandler(1);
}
void USART3_IRQHandler(void)
{
USART_IRQHandler(2);
}
void USART_IRQHandler(uint8_t port)
{
USART_TypeDef *USARTx = USARTxGroup[port];
volatile uint8_t *pUartRecvBuf[] = {gUart0RecvBuf, gUart1RecvBuf, gUart2RecvBuf};
uint16_t bufSize;
switch(port)
{
case HW_UART0:
bufSize = sizeof(gUart0RecvBuf);
break;
case HW_UART1:
bufSize = sizeof(gUart1RecvBuf);
break;
case HW_UART2:
bufSize = sizeof(gUart2RecvBuf);
break;
}
if (USART_GetFlagStatus(USARTx, USART_FLAG_ORE) != RESET)
{
pUartRecvBuf[port][gUartRecvIn[port]] = (uint8_t)(USART_ReceiveData(USARTx) & 0xff);
gUartRecvIn[port] %= bufSize;
USART_ClearITPendingBit(USARTx, USART_FLAG_ORE);
}
else if (USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET)
{
pUartRecvBuf[port][gUartRecvIn[port]++] = (uint8_t)(USART_ReceiveData(USARTx) & 0xff);
gUartRecvIn[port] %= bufSize;
USART_ClearITPendingBit(USARTx, USART_IT_RXNE);
}
}
接收到的数据只保存在接收缓冲中,Circle的方式,数据如果没有被及时取走会被覆盖。
6. 写数据
void uartSendByte(USART_TypeDef *USARTx, uint8_t dat)
{
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET)
{
}
USART_SendData(USARTx, dat);
}
bool_t uartWriteBytes(uint8_t port, uint8_t *buf, uint16_t len)
{
if(port >= HW_UART_MAX)
return FALSE;
while(len)
{
uartSendByte(USARTxGroup[port], *buf);
buf++;
len--;
}
return TRUE;
}
STM32F10x的USART有不少功能(例如LIN、irDA等),这里只用作普通串口。
STM32F10x最多有3组USART和2组UART。
1. USART和UART的区别
UART:Universal Asynchronous Receiver and Transmitter通用异步收发器。信号: RXD, TXD。
USART:Universal Synchronous Asynchronous Receiver and Transmitter通用同步异步收发器。信号:RXD,TXD,CK,其中CK为同步时钟信号。
这里只考虑UART的情况。
2. UART1/UART2/UART3的IO配置
IO采用默认的复用脚。这里只列举了3个USART的IO配置
RCC->APB2ENR |= RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB;
//A9: TX1, A10: RX1
GPIOA->CRH &= ~(0x000000FF << ((9 % 8) * 4));
GPIOA->CRH |= (0x0000008B << ((9 % 8) * 4));
GPIOA->BSRR = ((uint32_t)1 << 10);
//A2: TX2, A3: RX2
GPIOA->CRL &= ~(0x000000FF << ((2 % 8) * 4));
GPIOA->CRL |= (0x0000008B << ((2 % 8) * 4));
GPIOA->BSRR = ((uint32_t)1 << 3);
//B10: TX3, B11: RX3
GPIOB->CRH &= ~(0x000000FF << ((10 % 8) * 4));
GPIOB->CRH |= (0x0000008B << ((10 % 8) * 4));
GPIOB->BSRR = ((uint32_t)1 << 11);
3. 全局变量
首先定义需要用到的全局变量:
USART_TypeDef* const USARTxGroup[] = {USART1, USART2, USART3};
用于对应STM32的USART寄存器结构。
EXTERN volatile uint8_t gUart0RecvBuf[UART0_RECV_BUFSIZE];
EXTERN volatile uint8_t gUart1RecvBuf[UART1_RECV_BUFSIZE];
EXTERN volatile uint8_t gUart2RecvBuf[UART2_RECV_BUFSIZE];
各个USART接收缓冲,如果不使用则设置大小为0。
static volatile uint16_t gUartRecvIn[] = {0, 0, 0};
static volatile uint16_t gUartRecvRd[] = {0, 0, 0};
USART读写接收缓冲的位置,gUartRecvIn表示写入位置,gUartRecvRd表示读出位置。
4. UART初始化
程序采用数字来表示不同的Uart,port 0表示USART1,port 1表示USART2,以此类推。
UART初始化的API函数原型如下:
void uartInit(uint8_t port, uint32_t baudrate,
uartparity_e parity, uartStop_e stopBit, uint8_t datBit)
参数说明:
port - UART端口号,有效值0 – n,具体根据MCU和应用设计对应的端口定义。这里有效值是0到2.
baudrate - UART的波特率。
parity - UART的奇偶校验位设置。定义其枚举类型如下:
typedef enum eUartParity
{
UART_PARITY_NONE = 0,
UART_PARITY_EVEN,
UART_PARITY_ODD,
}uartparity_e;
stopBit - UART的停止位设置。定义其枚举类型如下:
typedef enum eUartStop
{
UART_STOP_1 = 0,
UART_STOP_0_5,
UART_STOP_1_5,
UART_STOP_2,
}uartStop_e;
4.1 使能USART的RCC并DeInit USART
switch(port)
{
case HW_UART0:
RCC->APB2ENR |= RCC_APB2Periph_USART1;
RCC->APB2RSTR |= RCC_APB2Periph_USART1; //DeInit
RCC->APB2RSTR &= ~RCC_APB2Periph_USART1;
break;
case HW_UART1:
RCC->APB1ENR |= RCC_APB1Periph_USART2;
RCC->APB1RSTR |= RCC_APB1Periph_USART2; //DeInit
RCC->APB1RSTR &= ~RCC_APB1Periph_USART2;
break;
case HW_UART2:
RCC->APB1ENR |= RCC_APB1Periph_USART3;
RCC->APB1RSTR |= RCC_APB1Periph_USART3; //DeInit
RCC->APB1RSTR &= ~RCC_APB1Periph_USART3;
break;
default:
return;
}
4.2 中断初始化
void uartNVICInit(USART_TypeDef *USARTx, uint8_t priority)
{
NVIC_InitTypeDef NVIC_InitStructure;
if(USARTx == USART1)
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
else if(USARTx == USART2)
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
else if(USARTx == USART3)
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE);
}
使能RXNE中断。
优先级为0:
USART_TypeDef *USARTx;
USARTx = USARTxGroup[port];
uartNVICInit(USARTx, 0);
4.3 配置USART
USART_InitStructure.USART_BaudRate = baudrate;
switch(datBit)
{
case 8:
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
break;
case 9:
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
break;
default:
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
break;
}
switch(stopBit)
{
case UART_STOP_1:
USART_InitStructure.USART_StopBits = USART_StopBits_1;
break;
case UART_STOP_0_5:
USART_InitStructure.USART_StopBits = USART_StopBits_0_5;
break;
case UART_STOP_1_5:
USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
break;
case UART_STOP_2:
USART_InitStructure.USART_StopBits = USART_StopBits_2;
break;
default:
USART_InitStructure.USART_StopBits = USART_StopBits_1;
break;
}
switch(parity)
{
case UART_PARITY_NONE:
default:
USART_InitStructure.USART_Parity = USART_Parity_No;
break;
case UART_PARITY_EVEN:
USART_InitStructure.USART_Parity = USART_Parity_Even;
break;
case UART_PARITY_ODD:
USART_InitStructure.USART_Parity = USART_Parity_Odd;
break;
}
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USARTx, &USART_InitStructure);
5. 中断处理程序
void USART1_IRQHandler(void)
{
USART_IRQHandler(0);
}
void USART2_IRQHandler(void)
{
USART_IRQHandler(1);
}
void USART3_IRQHandler(void)
{
USART_IRQHandler(2);
}
void USART_IRQHandler(uint8_t port)
{
USART_TypeDef *USARTx = USARTxGroup[port];
volatile uint8_t *pUartRecvBuf[] = {gUart0RecvBuf, gUart1RecvBuf, gUart2RecvBuf};
uint16_t bufSize;
switch(port)
{
case HW_UART0:
bufSize = sizeof(gUart0RecvBuf);
break;
case HW_UART1:
bufSize = sizeof(gUart1RecvBuf);
break;
case HW_UART2:
bufSize = sizeof(gUart2RecvBuf);
break;
}
if (USART_GetFlagStatus(USARTx, USART_FLAG_ORE) != RESET)
{
pUartRecvBuf[port][gUartRecvIn[port]] = (uint8_t)(USART_ReceiveData(USARTx) & 0xff);
gUartRecvIn[port] %= bufSize;
USART_ClearITPendingBit(USARTx, USART_FLAG_ORE);
}
else if (USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET)
{
pUartRecvBuf[port][gUartRecvIn[port]++] = (uint8_t)(USART_ReceiveData(USARTx) & 0xff);
gUartRecvIn[port] %= bufSize;
USART_ClearITPendingBit(USARTx, USART_IT_RXNE);
}
}
接收到的数据只保存在接收缓冲中,Circle的方式,数据如果没有被及时取走会被覆盖。
6. 写数据
void uartSendByte(USART_TypeDef *USARTx, uint8_t dat)
{
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET)
{
}
USART_SendData(USARTx, dat);
}
bool_t uartWriteBytes(uint8_t port, uint8_t *buf, uint16_t len)
{
if(port >= HW_UART_MAX)
return FALSE;
while(len)
{
uartSendByte(USARTxGroup[port], *buf);
buf++;
len--;
}
return TRUE;
}
举报