基于STM32之UART串口通信协议(二)发送

一、前言

1、简介

  在上一篇UART详解中,已经有了关于UART的详细介绍了,也有关于如何使用STM32CubeMX来配置UART的操作了,而在该篇博客,主要会讲解一下如何实现UART串口的发送功能。

2、UART简介

  嵌入式开发中,UART串口通信协议是我们常用的通信协议之一,全称叫做通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)。

3、准备工作

  在UART详解中已经有了详细的说明,在这里就不说明了。

注:

  建议每次编写好一个相关功能且测试功能成功使用后,保存并压缩成一份Demo例程,方便日后有需要的时候可以直接使用。

  例如:

二、CubeMx配置及函数说明

说明:

  这篇用到的配置跟UART详解里的配置都相同,可以按照UART详解来配置好时钟、UART即可。

  所以在进行下一步之前,先确保已经按照UART详解的配置步骤配置好了,然后再进行后面的操作。

1、CubeMx配置

  按照上一篇UART详解来配置

2、函数说明

1)CubeMX生成的UART初始化(在usart.c中)

 1 UART_HandleTypeDef huart1;
 2
 3 /* USART1 init function */
 4
 5 void MX_USART1_UART_Init(void)
 6 {
 7
 8   huart1.Instance = USART1;
 9   huart1.Init.BaudRate = 115200;
10   huart1.Init.WordLength = UART_WORDLENGTH_8B;
11   huart1.Init.StopBits = UART_STOPBITS_1;
12   huart1.Init.Parity = UART_PARITY_NONE;
13   huart1.Init.Mode = UART_MODE_TX_RX;
14   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
15   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
16   if (HAL_UART_Init(&huart1) != HAL_OK)
17   {
18     Error_Handler();
19   }
20
21 }
22
23 void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
24 {
25
26   GPIO_InitTypeDef GPIO_InitStruct = {0};
27   if(uartHandle->Instance==USART1)
28   {
29   /* USER CODE BEGIN USART1_MspInit 0 */
30
31   /* USER CODE END USART1_MspInit 0 */
32     /* USART1 clock enable */
33     __HAL_RCC_USART1_CLK_ENABLE();
34
35     __HAL_RCC_GPIOA_CLK_ENABLE();
36     /**USART1 GPIO Configuration
37     PA9     ------> USART1_TX
38     PA10     ------> USART1_RX
39     */
40     GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
41     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
42     GPIO_InitStruct.Pull = GPIO_PULLUP;
43     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
44     GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
45     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
46
47   /* USER CODE BEGIN USART1_MspInit 1 */
48
49   /* USER CODE END USART1_MspInit 1 */
50   }
51 }
52
53 void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
54 {
55
56   if(uartHandle->Instance==USART1)
57   {
58   /* USER CODE BEGIN USART1_MspDeInit 0 */
59
60   /* USER CODE END USART1_MspDeInit 0 */
61     /* Peripheral clock disable */
62     __HAL_RCC_USART1_CLK_DISABLE();
63
64     /**USART1 GPIO Configuration
65     PA9     ------> USART1_TX
66     PA10     ------> USART1_RX
67     */
68     HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
69
70   /* USER CODE BEGIN USART1_MspDeInit 1 */
71
72   /* USER CODE END USART1_MspDeInit 1 */
73   }
74 } 

USART init

2)HAL库函数HAL_UART_Transmit(在stm32f4xx_hal_uart.c中)

说明:

  该函数能够通过huart串口发送Size位pData数据。

参数说明:

  • huart    :选择用来发送的UART串口
  • pData   :指向将要发送的数据的指针
  • Size      :发送数据的大小
  • Timeout:超时时间

 1 /**
 2   * @brief  Sends an amount of data in blocking mode.
 3   * @param  huart  Pointer to a UART_HandleTypeDef structure that contains
 4   *                the configuration information for the specified UART module.
 5   * @param  pData Pointer to data buffer
 6   * @param  Size Amount of data to be sent
 7   * @param  Timeout Timeout duration
 8   * @retval HAL status
 9   */
10 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
11 {
12   uint16_t *tmp;
13   uint32_t tickstart = 0U;
14
15   /* Check that a Tx process is not already ongoing */
16   if (huart->gState == HAL_UART_STATE_READY)
17   {
18     if ((pData == NULL) || (Size == 0U))
19     {
20       return  HAL_ERROR;
21     }
22
23     /* Process Locked */
24     __HAL_LOCK(huart);
25
26     huart->ErrorCode = HAL_UART_ERROR_NONE;
27     huart->gState = HAL_UART_STATE_BUSY_TX;
28
29     /* Init tickstart for timeout managment */
30     tickstart = HAL_GetTick();
31
32     huart->TxXferSize = Size;
33     huart->TxXferCount = Size;
34     while (huart->TxXferCount > 0U)
35     {
36       huart->TxXferCount--;
37       if (huart->Init.WordLength == UART_WORDLENGTH_9B)
38       {
39         if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
40         {
41           return HAL_TIMEOUT;
42         }
43         tmp = (uint16_t *) pData;
44         huart->Instance->DR = (*tmp & (uint16_t)0x01FF);
45         if (huart->Init.Parity == UART_PARITY_NONE)
46         {
47           pData += 2U;
48         }
49         else
50         {
51           pData += 1U;
52         }
53       }
54       else
55       {
56         if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
57         {
58           return HAL_TIMEOUT;
59         }
60         huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
61       }
62     }
63
64     if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
65     {
66       return HAL_TIMEOUT;
67     }
68
69     /* At end of Tx process, restore huart->gState to Ready */
70     huart->gState = HAL_UART_STATE_READY;
71
72     /* Process Unlocked */
73     __HAL_UNLOCK(huart);
74
75     return HAL_OK;
76   }
77   else
78   {
79     return HAL_BUSY;
80   }
81 }

HAL_UART_Transmit

三、代码部分:实现UART发送

1、直接发送

1)在main主函数中定义一个数组

1   /* USER CODE BEGIN 1 */
2     unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45};    //数组内十六进制代表“ABCDE”
3   /* USER CODE END 1 */

2)在main主函数中的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 */

整个main函数如下:

 1 int main(void)
 2 {
 3   /* USER CODE BEGIN 1 */
 4     unsigned char uTx_Data[5] = {0x41, 0x42, 0x43, 0x44, 0x45};    //数组内十六进制代表“ABCDE”
 5   /* USER CODE END 1 */
 6
 7
 8   /* MCU Configuration--------------------------------------------------------*/
 9
10   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
11   HAL_Init();
12
13   /* USER CODE BEGIN Init */
14
15   /* USER CODE END Init */
16
17   /* Configure the system clock */
18   SystemClock_Config();
19
20   /* USER CODE BEGIN SysInit */
21
22   /* USER CODE END SysInit */
23
24   /* Initialize all configured peripherals */
25   MX_GPIO_Init();
26   MX_USART1_UART_Init();
27   /* USER CODE BEGIN 2 */
28
29   /* USER CODE END 2 */
30
31   /* Infinite loop */
32   /* USER CODE BEGIN WHILE */
33   while (1)
34   {
35         /* UART发送 */
36       HAL_UART_Transmit(&huart1, uTx_Data, sizeof(uTx_Data), 0xffff);
37         /* 延迟1s */
38         HAL_Delay(1000);
39     /* USER CODE END WHILE */
40
41     /* USER CODE BEGIN 3 */
42   }
43   /* USER CODE END 3 */
44 }

3)编译、下载烧写

4)实现效果(在PC端串口助手中显示发送成功)

2、字符串发送

说明:

  前面的发送方式,不仅要传入句柄参数,还有数组、长度、超时时间参数。

  为了简便发送,我们可以专门写一个字符串发送函数,可以直接传入一个数组即可发送,可以更简便地实现字符串发送。

  优点是,发送数据更简便,能够一次性发送很长的数据数组。

  但缺点就是不能控制发送的长度,会将整个数据数组发出。

1)在Uart.c中添加vUser_UART_SendString函数

 1 /* USER CODE BEGIN 1 */
 2 void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData)
 3 {
 4     /* -1- 判断数据是否发送完毕 */
 5     while(*uData)        //若为空即发送完毕,若不为空则还有数据
 6     {
 7         /* -2- 发送1Byte */
 8         HAL_UART_Transmit(uartHandle, uData, 1, 0xffff);
 9         /* -3- 移至下1Byte */
10         uData++;
11     }
12 }
13 /* USER CODE END 1 */

2)在Uart.h中声明一下vUser_UART_SendString函数(声明后就可以在别的地方调用该函数)

1 /* USER CODE BEGIN Prototypes */
2 extern void vUser_UART_SendString(UART_HandleTypeDef* uartHandle, unsigned char * uData);
3 /* USER CODE END Prototypes */

3)在main主函数中定义一个数组

1   /* USER CODE BEGIN 1 */
2     unsigned char uTx_Data[] = "\r\n Hallo World! 你好,世界!";
3   /* USER CODE END 1 */

4)在main主函数的while循环中调用字符串发送函数

 1   /* Infinite loop */
 2   /* USER CODE BEGIN WHILE */
 3   while (1)
 4   {
 5         /* 字符串发送 */
 6       vUser_UART_SendString(&huart1, uTx_Data);
 7         /* 延迟1s */
 8         HAL_Delay(1000);
 9     /* USER CODE END WHILE */
10
11     /* USER CODE BEGIN 3 */
12   }
13   /* USER CODE END 3 */

整个main函数如下:

 1 int main(void)
 2 {
 3   /* USER CODE BEGIN 1 */
 4     unsigned char uTx_Data[] = "\r\n Hallo World! 你好,世界!";
 5   /* USER CODE END 1 */
 6
 7
 8   /* MCU Configuration--------------------------------------------------------*/
 9
10   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
11   HAL_Init();
12
13   /* USER CODE BEGIN Init */
14
15   /* USER CODE END Init */
16
17   /* Configure the system clock */
18   SystemClock_Config();
19
20   /* USER CODE BEGIN SysInit */
21
22   /* USER CODE END SysInit */
23
24   /* Initialize all configured peripherals */
25   MX_GPIO_Init();
26   MX_USART1_UART_Init();
27   /* USER CODE BEGIN 2 */
28
29   /* USER CODE END 2 */
30
31   /* Infinite loop */
32   /* USER CODE BEGIN WHILE */
33   while (1)
34   {
35         /* UART发送 */
36       vUser_UART_SendString(&huart1, uTx_Data);
37         /* 延迟1s */
38         HAL_Delay(1000);
39     /* USER CODE END WHILE */
40
41     /* USER CODE BEGIN 3 */
42   }
43   /* USER CODE END 3 */
44 }

5)编译、下载烧写

6)实现效果(在PC端串口助手显示发送成功)

3、printf发送

说明:

  这种发送方式就是相当于编写c语言的时候,在小黑框中打印自己想要打印的东西,我们也可以在串口助手上实现一样的功能。

  由于篇幅长度有限,可能需要后续有空再补上这一发送方式,在这里先不讲解了。

四、结尾

1、总结

  这篇博客主要是以上一篇UART详解为基础,来实现使用UART来实现发送功能,在这里简单讲解了两种发送方式,而在后续如果有机会还会补上第三种printf发送方式的。

  如果大家还不清楚UART串口通信协议的,可以阅读一下上一篇UART详解。若还有对于此篇博客不懂之处,可在下方留言评论,我会尽快回复。

2、后续

  待补充……

~

~

~

~

感谢阅读~

欢迎大家关注我的博客,一起分享嵌入式知识~

原文地址:https://www.cnblogs.com/ChurF-Lin/p/10798193.html

时间: 2024-10-28 11:14:59

基于STM32之UART串口通信协议(二)发送的相关文章

基于stm32的遥控小船(二)NRF24L01无线模块

无线收发数据我用的模块是NF24L01……这个模块小巧而便宜……几个引脚如图……功能大概是这样的 CSN:片选,电平为低时芯片工作 CE:CSN为低时控制CE状态 SCK:SPI时钟 MOSI:Master output slave input MISO:Master input slave output IRQ:中断,低电平触发(发送完成,接收数据,达到最大重发次数时触发) 关于这个模块详细的可以参照<NRF24L01学习笔记>……写的很全面详尽…… 调无线对我来说是一个比较痛苦的过程……我

uart串口发送---那些年我们一起玩mini2440(arm9)裸机

Uart工作原理: 数据通信方式为:并行通信与串行通信两种: §并行通信:利用多条数据线将数据的各位同时传送. 它的特点是:传输速度快,是用于短距离通信: §串行通信:利用一条数据线将数据一位位地顺序传送. 特点是通信线路简单,利用简单的线缆就实现通信,低成本,是用于远距离通信.   异步通信: ª异步通信:以一个字符为传输单位,通过两个字符间的时间间隔是不固定的,然而同一字符中的两个相邻位之间的时间间隔是固定的. ª通信协议:是指通信双方约定的一些规则.在异步通讯时,对数据格式有如下约定:规定

STM32之模拟串口设计

一.设计用途: 公司PCB制成板降成本,选择的MCU比项目需求少一个串口,为满足制成板成本和项目对串口需求,选择模拟一路串口. 二.硬件电路: 三.设计实现: 工具&软件:STM32F030R8    KEIL5    STM32CubeMX 1. 串口通信 串口是一种很常用的通信接口,按位(bit)发送和接收字节,串口通信是异步传输,端口能够在一根线上发送数据同时在另一根线上接收数据.串口通信最重要的参数是比特率.数据位.停止位和奇偶校验.对于两个进行通信的端口,这些参数必须匹配,在我们单片机

嵌入式Linux裸机开发(七)——UART串口通信

嵌入式Linux裸机开发(七)--UART串口通信 一.UART串口通信简介 通用异步收发器简称UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER, 它用来传输串行数据.发送数据时, CPU 将并行数据写入UART,UAR按照一定的格式在一根电线上串 行发出:接收数据时, UART检测另一根电线的信号,将串行收集在缓冲区中, CPU 即可读取 UART 获得这些数据. 在 S5PV210中, UART提供了 4 对独立的异步串口I/O端口,

基于Modbus的C#串口调试开发

说明:本文主要研究的是使用C# WinForm开发的串口调试软件(其中包含Modbus协议相关操作).Modbus相关协议可以查阅百度文库等,可参考: <http://wenku.baidu.com/link?url=J-QZeQVLfvfZh7_lh8Qf0MdwANZuVjEoTqox6zJYrSnKyfgES2RTb_bjC5ZTn8-xgsuUAyiELRYVA3-3FBkBGywWhQ9YGoavJOzwB0IxTyK >. (1)先测试串口设置,发送和接收数据. (2)发送modb

基于树莓派的Linux串口编程_实现自发自收

串口是计算机上一种非常通用设备通信的协议,常用PC机上包含的是RS232规格的串口,具有连接线少,通讯简单,得到广泛的使用. Linux对所有设备的访问是通过设备文件来进行的,串口也是这样,为了访问串口,只需打开其设备文件即可操作串口设备.在linux系统下面,每一个串口设备都有设备文件与其关联,设备文件位于系统的/dev目录下面.如linux下的/ttyS0,/ttyS1分别表示的是串口1和串口2. 树莓派UART端口的位置:见下图的GPIO14(TXD).GPIO 15(RXD) 本文是基于

单片机: 自定义串口通信协议的实现

使用51单片机完成一个简单的串口通信协议. 要求: 一个协议帧为8个字节,其中头部两个字节,分别是0xFF,0xFE; 第3个字节代表第一个数据,第4个字节代表第二个数据(均为正数); 第5个字节如果是0,代表两个数据的和,1的话代表两个数据的差; 第6个字节为0,代表使用十进制显示,为1代表十六进制显示; 最后两个字节代表协议尾部,值分别为0xFD,0xFC. 将传输的两个数据和他们的计算结果分别显示在数码管上. 注意,如果差为负数,要将负号显示出来. 思路:使用串口中断,先接收8个字节至数组

SJXXX串口扩展芯片 4串口芯片 UART串口芯片

SJXX串口扩展芯片1 概述SJ000是一款具备I2C总线/SPI总线/UART接口的四通道异步收发器件,通过模式选择使得该器件工作于以上任何一种主接口模式下.器件的四个通道UART可提供高达2Mbps的数据率,低功耗模式和睡眠电流.每个通道含有一个接收器和一个发送器,并带有64字节发送/接收FIFO,通道波特率.字长.校验格式可独立设置,也可以独立设置IrDA红外通信.RS-485自动收发控制.9位网络地址自动识别.软件/硬件自动流量控制.广播接收等.器件还带有可编程中断功能,实现与主机的信息

【转】搞定单片机多字节串口接收(串口多字节接收发送的高阶研究)

搞定单片机多字节串口接收(串口多字节接收发送的高阶研究) 原文地址:http://bbs.ednchina.com/BLOG_ARTICLE_3007162.HTM 工作了一年多,写了不少单片机串口程序.感觉串口多字节接收部分的逻辑相对于配置寄存器跟串口回复来说,是有点难度的——寄存器配置基本上都是死的,串口回复多字节跟回复一字节只是多了一个循环. 串口接收程序是基于串口中断的,单片机的串口每次接收到一字节数据产生一次中断,然后再读取某个寄存器就可以得到串口接收的数据了.然而在实际应用当中,基本