UART
1> UART硬件框图
2> 通信协议
位段 | 内容 |
---|---|
空闲位 | TX保持高电平 |
起始位 | TX由高变低,保持=1bit位宽 |
数据为 | 5~8位ASCII的编码数据 |
校验位 | 校验方式:奇校验 / 偶校验 |
停止位 | TX由低变高,保持>=0.5bit位宽 |
常用配置:115200, 8N1
波特率为115200,
数据位:8位;
奇偶校验:无;
停止位:1位;
3> 硬件设计
PA9:USART1_TX;
PA10: USART1_RX
4> 发送1Byte数据_轮询方式
bsp_uart.c:
#include "bsp_uart.h"
// USART1_TX - PA9
// USART1_RX - PA10
void USART1_Init(void)
{
/* configures GPIO ports */
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE);
/* USART1_TX PA9 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1_RX PA10 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* configures USART1: 115200baud, 8N1 */
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
}
void UART_Putchar(uint8_t c)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) /*Wait*/;
USART_SendData(USART1,c);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) /*Wait*/;
}
配置规律, 分模块,顺序配置,井井有条
1-【时钟】模块 -> 2-【GPIO】模块 -> 3-【UART】模块
5> 发送字符串_轮询方式
/**
* @brief UART put string
* @str Pointer to string
*/
void UART_Puts(uint8_t *str)
{
uint8_t i = 0;
while(str[i] != '\0') {
if (str[i] == '\n') {
UART_Putchar('\r');
}
UART_Putchar(str[i]);
i++;
}
}
有了底层的UART_Putchar()其他都是花活了
6> printf()重定向
重写 fputc()
/**
* @brief for printf function
*/
int fputc(int ch, FILE *f)
{
if (ch == '\n')
UART_Putchar('\r');
UART_Putchar((uint8_t)ch);
return ch;
}
注意:
1> 包含头文件 #include <stdio.h>
2> 【Target】选项中,勾选【Use MicroLIB】;
7> USART接收中断_图解
8> USART接收程序_中断方式
bsp_uart.h:
void USART1_Init(void)
{
/* configures GPIO ports */
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE);
/* USART1_TX PA9 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1_RX PA10 */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* configures USART1: 115200baud, 8N1 */
USART_InitStruct.USART_BaudRate = 115200;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
/* Configures USART1 RXNE interrupt enable */
USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
/* Configures NVIC */
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
/* USART enable, UE */
USART_Cmd(USART1, ENABLE);
}
stm32f10x_usart.h:
// USART1总中断处理函数
void USART1_IRQHandler(void)
{
uint8_t c;
c = USART_ReceiveData(USART1);
UART_Putchar(c);
}
RXNEIE位描述:
读USART_DR就可以清除RXNE位,这招可以;