一、前言
1、简介
在上一篇
UART详解中,已经有关于UART的介绍了,也有关于如何使用STM32CubeMX来配置UART的操作了,而在该篇博客,主要会演示一下如何实现UART的详细介绍
2、UART发送
简介
嵌入式中开发,UART通信通信协议是我们常用的协议之一,全称通用异步收发传输器(通用异步收发器)。
3、准备工作
在
UART详解中已经有详细的说明,这里就不说明了。
注:
建议每次编写好一个相关功能且测试功能成功使用后,保存并压缩成一份演示例程,方便日后有需要的时候可以直接使用。
例如:
二、CubeMx配置及函数说明
说明:
这篇用到的配置跟UART详解里的配置都相同,可以按照UART详解。来配置好时钟,UART即可
所以在进行下一步之前,先确保已经按照UART详解的配置步骤配置好了,然后再进行一次的操作。
1、CubeMx配置
按照上一篇
UART详解来配置
2、函数说明
1)CubeMX生成的UART初始化(在usart.c中)
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
USART init
说明:
该函数能够通过huart串口发送Size位pData数据。
参数说明:
- huart :选择用来发送的UART串口
- pData :指向将要发送的数据的指针
- Size :发送数据的大小
- Timeout:超时时间
/**
* @brief Sends an amount of data in blocking mode.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer
* @param Size Amount of data to be sent
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint16_t *tmp;
uint32_t tickstart = 0U;
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Init tickstart for timeout managment */
tickstart = HAL_GetTick();
huart->TxXferSize = Size;
huart->TxXferCount = Size;
while (huart->TxXferCount > 0U)
{
huart->TxXferCount--;
if (huart->Init.WordLength == UART_WORDLENGTH_9B)
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
tmp = (uint16_t *) pData;
huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
if (huart->Init.Parity == UART_PARITY_NONE)
{
pData += 2U;
}
else
{
pData += 1U;
}
}
else
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
}
}
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
/* At end of Tx process, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
HAL_UART_Transmit
三、代码部分:实现UART发送
1、直接发送
1)在主主函数中定义一个数组
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; //数组内十六进制代表“ABCDE”
/* USER CODE END 1 */
2)在主函数中的while循环中调用HAL库UART发送函数
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* UART发送 */
HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
整个主要函数如下:
int main(void)
{
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; //数组内十六进制代表“ABCDE”
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* UART发送 */
HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
3)编译、下载烧写
4)实现效果(在PC端串口助手中显示发送成功)
2、字符串发送
说明:
前面的发送方式,不仅要传入句柄参数,还有数组、长度、超时时间参数。
为了简便发送,我们可以专门写一个字符串发送函数,可以直接传入一个数组即可发送,可以更简便地实现字符串发送。
优点是,发送数据更简便,能够一次性发送很长的数据数组。
但缺点就是不能控制发送的长度,会将整个数据数组发出。
1)在Uart.c中添加vUser_UART_SendString函数
/* USER CODE BEGIN 1 */
void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData)
{
/* -1- 判断数据是否发送完毕 */
while(*uData) //若为空即发送完毕,若不为空则还有数据
{
/* -2- 发送1Byte */
HAL_UART_Transmit(uartHandle, uData, 1, 0xffff);
/* -3- 移至下1Byte */
uData++;
}
}
/* USER CODE END 1 */
2)在Uart.h中声明一下vUser_UART_SendString函数(声明后就可以在别的地方调用该函数)
/* USER CODE BEGIN Prototypes */
extern void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData);
/* USER CODE END Prototypes */
3)在main主函数中定义一个数组
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[] = "rn Hallo World! 你好,世界!";
/* USER CODE END 1 */
4)在main主函数的while循环中调用字符串发送函数
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* 字符串发送 */
vUser_UART_SendString(&huart1, uTx_Data);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
整个main函数如下:
int main(void)
{
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[] = "rn Hallo World! 你好,世界!";
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* UART发送 */
vUser_UART_SendString(&huart1, uTx_Data);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
5)编译、下载烧写
6)实现效果(在PC端串口助手显示发送成功)
3、printf发送
说明:
。这种发送方式就是相当于编写Ç语言的时候,在小黑框中打印自己想要打印的东西,也。我们可以在串口助手上实现一样的功能
由于篇幅长度有限,可能需要后续有空再补上这个发送方式,这里先不讲解了。
四、总结
1 、总结这篇
主要博客是上一篇
UART详解为基础,来实现使用UART来实现发送功能,快速讲解了两种发送方式,而在等有机会补上第三篇种
打印f发送方式的。如果大家还通过UART 通信协议的,可以看一下上一篇
UART 详解。若还有此篇博客看不懂,可在下方留言评论,我会尽快回复。
一、前言
1、简介
在上一篇
UART详解中,已经有关于UART的介绍了,也有关于如何使用STM32CubeMX来配置UART的操作了,而在该篇博客,主要会演示一下如何实现UART的详细介绍
2、UART发送
简介
嵌入式中开发,UART通信通信协议是我们常用的协议之一,全称通用异步收发传输器(通用异步收发器)。
3、准备工作
在
UART详解中已经有详细的说明,这里就不说明了。
注:
建议每次编写好一个相关功能且测试功能成功使用后,保存并压缩成一份演示例程,方便日后有需要的时候可以直接使用。
例如:
二、CubeMx配置及函数说明
说明:
这篇用到的配置跟UART详解里的配置都相同,可以按照UART详解。来配置好时钟,UART即可
所以在进行下一步之前,先确保已经按照UART详解的配置步骤配置好了,然后再进行一次的操作。
1、CubeMx配置
按照上一篇
UART详解来配置
2、函数说明
1)CubeMX生成的UART初始化(在usart.c中)
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
USART init
说明:
该函数能够通过huart串口发送Size位pData数据。
参数说明:
- huart :选择用来发送的UART串口
- pData :指向将要发送的数据的指针
- Size :发送数据的大小
- Timeout:超时时间
/**
* @brief Sends an amount of data in blocking mode.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer
* @param Size Amount of data to be sent
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint16_t *tmp;
uint32_t tickstart = 0U;
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Init tickstart for timeout managment */
tickstart = HAL_GetTick();
huart->TxXferSize = Size;
huart->TxXferCount = Size;
while (huart->TxXferCount > 0U)
{
huart->TxXferCount--;
if (huart->Init.WordLength == UART_WORDLENGTH_9B)
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
tmp = (uint16_t *) pData;
huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
if (huart->Init.Parity == UART_PARITY_NONE)
{
pData += 2U;
}
else
{
pData += 1U;
}
}
else
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
}
}
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
/* At end of Tx process, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
HAL_UART_Transmit
三、代码部分:实现UART发送
1、直接发送
1)在主主函数中定义一个数组
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; //数组内十六进制代表“ABCDE”
/* USER CODE END 1 */
2)在主函数中的while循环中调用HAL库UART发送函数
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* UART发送 */
HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
整个主要函数如下:
int main(void)
{
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45}; //数组内十六进制代表“ABCDE”
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* UART发送 */
HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
3)编译、下载烧写
4)实现效果(在PC端串口助手中显示发送成功)
2、字符串发送
说明:
前面的发送方式,不仅要传入句柄参数,还有数组、长度、超时时间参数。
为了简便发送,我们可以专门写一个字符串发送函数,可以直接传入一个数组即可发送,可以更简便地实现字符串发送。
优点是,发送数据更简便,能够一次性发送很长的数据数组。
但缺点就是不能控制发送的长度,会将整个数据数组发出。
1)在Uart.c中添加vUser_UART_SendString函数
/* USER CODE BEGIN 1 */
void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData)
{
/* -1- 判断数据是否发送完毕 */
while(*uData) //若为空即发送完毕,若不为空则还有数据
{
/* -2- 发送1Byte */
HAL_UART_Transmit(uartHandle, uData, 1, 0xffff);
/* -3- 移至下1Byte */
uData++;
}
}
/* USER CODE END 1 */
2)在Uart.h中声明一下vUser_UART_SendString函数(声明后就可以在别的地方调用该函数)
/* USER CODE BEGIN Prototypes */
extern void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData);
/* USER CODE END Prototypes */
3)在main主函数中定义一个数组
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[] = "rn Hallo World! 你好,世界!";
/* USER CODE END 1 */
4)在main主函数的while循环中调用字符串发送函数
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* 字符串发送 */
vUser_UART_SendString(&huart1, uTx_Data);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
整个main函数如下:
int main(void)
{
/* USER CODE BEGIN 1 */
unsigned char uTx_Data[] = "rn Hallo World! 你好,世界!";
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* UART发送 */
vUser_UART_SendString(&huart1, uTx_Data);
/* 延迟1s */
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
5)编译、下载烧写
6)实现效果(在PC端串口助手显示发送成功)
3、printf发送
说明:
。这种发送方式就是相当于编写Ç语言的时候,在小黑框中打印自己想要打印的东西,也。我们可以在串口助手上实现一样的功能
由于篇幅长度有限,可能需要后续有空再补上这个发送方式,这里先不讲解了。
四、总结
1 、总结这篇
主要博客是上一篇
UART详解为基础,来实现使用UART来实现发送功能,快速讲解了两种发送方式,而在等有机会补上第三篇种
打印f发送方式的。如果大家还通过UART 通信协议的,可以看一下上一篇
UART 详解。若还有此篇博客看不懂,可在下方留言评论,我会尽快回复。
举报