UART,是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),既然是“器”,显然,它就是个设备而已,要完成一个特定的功能的硬件,它本身并不是协议。那么它要完成什么功能呢?它的最基本功能,是串行数据和并行数据之间的转换。我们知道,计算机中的数据以Byte为基本单位,对一个Byte的存取是并行的,即,同时取得/写入8个bit。而串行通信,需要把这个Byte“打碎”,按照时间顺序来收发以实现串行。
RS232/RS485,是两种不同的电气协议,也就是说,是对电气特性以及物理特性的规定,作用于数据的传输通路上,它并不内含对数据的处理方式。比如,最显著的特征是:RS232使用3-15v有效电平,而UART,因为对电气特性并没有规定,所以直接使用CPU使用的电平,就是所谓的TTL电平(可能在0~3.3V之间)。更具体的,电气的特性也决定了线路的连接方式,比如RS232,规定用电平表示数据,因此线路就是单线路的,用两根线才能达到全双工的目的;而RS485, 使用差分电平表示数据,因此,必须用两根线才能达到传输数据的基本要求,要实现全双工,必需用4根线。但是,无论使用RS232还是RS485,它们与UART是相对独立的,但是由于电气特性的差别,必须要有专用的器件和UART接驳,才能完成数据在线路和UART之间的正常流动。
普通方式的串口
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(HAL_UART_Receive(&huart1, &c, sizeof(c), 1000) == HAL_OK)
{
if(c == '\r')
{
HAL_UART_Transmit(&huart1, (uint8_t*)"\n", sizeof("\n"), 1000);
}
HAL_UART_Transmit(&huart1, &c, sizeof(c), 1000);
}
}
/* USER CODE END 3 */
串口使用printf()
#include <stdio.h>
#ifdef __GNUC__
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100);
if(ch == '\n')
HAL_UART_Transmit(&huart1, (uint8_t*)"\r", 2, 100);
return ch;
}
#endif
中断方式UART
先在主函数中初始调用一次中断接收
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, &c, sizeof(c));
/* USER CODE END 2 */
注册接收完成的回调函数,这个函数是弱函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
if(c == '\r')
{
HAL_UART_Transmit_IT(huart, (uint8_t*)"\n\r", sizeof("\n\r"));
}
else
{
HAL_UART_Transmit_IT(huart, &c, sizeof(c));
}
}
HAL_UART_Receive_IT(huart, &c, sizeof(c));
}
HAL_UART_Transmit_IT只发送一次数据,下次发送需要等待下次中断
//第二行代码不会生效,只会发送"ab",而不会发生"abcde",或者被覆盖成"cde"
//这与中断的结构有关
HAL_UART_Transmit_IT(huart, (uint8_t*)"ab", sizeof("ab"));
HAL_UART_Transmit_IT(huart, (uint8_t*)"abc", sizeof("abc"));
DMA串口
以USART1为例
MX配置完DMA通道的代码
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}
HAL_UART_Transmit_DMA(&huart1, buffer, sizeof(buffer));