历史上的今天
返回首页

历史上的今天

今天是:2025年04月23日(星期三)

正在发生

2020年04月23日 | STM32CubeMX系列教程5:串行通信(USART)

2020-04-23 来源:eefocus

本章以串口为例讲解,HAL 库轮询,中断,DMA 三种编程模型。


1.前情回顾

在串行通信中,一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束。在进行传输之前,双方一定要使用同一个波特率设置。波特率就是每秒钟传输的数据位数。


常用的两种基本串行通信方式包括同步通信和异步通信。我们通常使用的是异步通信.异步通信规定传输的数据格式由起始位(start bit)、数据位(data bit)、奇偶校验位(parity bit)和停止位(stop bit)组成。


2.重定义printf函数。

打开STM32CubeMX新建工程,选择STMF746IGT6芯片,选择外部高速晶振(HSE)。USART1选择为异步通信方式。PA10设置RX接收,PA9设置为TX发送。

配置时钟系统时钟为216MHz,STMF746可以单独配置USART时钟,默认为108Mhz。


串口配置设置波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1.其他参数默认。

生成报告以及代码,编译程序。在usart.c文件中可看到串口1的初始化函数MX_USART1_UART_Init(void),以及管脚配置函数HAL_UART_MspInit()。


C语言中的标准库中所用的标准输出函数,默认的输出设备是显示器,要实现串口或LCD的输出,必须重新定义标准库函数里与输出函数相关的函数。例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下:只要自己添加一个int fputc(int ch, FILE *f)函数,能够输出字符就可以了。


在usart.c文件后面添加如下代码,代码中添加了#ifdef宏定义进行条件编译,如果使用GUNC编译,则PUTCHAR_PROTOTYPE 定义为int __io_putchar(int ch)函数,否则定义为int fputc(int ch, FILE *f)函数。


01

/* USER CODE BEGIN 1 */

02

#ifdef __GNUC__

03

  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf

04

     set to 'Yes') calls __io_putchar() */

05

  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

06

#else

07

  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

08

#endif /* __GNUC__ */

09

/**

10

  * @brief  Retargets the C library printf function to the USART.

11

  * @param  None

12

  * @retval None

13

  */

14

PUTCHAR_PROTOTYPE

15

{

16

  /* Place your implementation of fputc here */

17

  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */

18

  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

19

  

20

  return ch;

21

}

22

/* USER CODE END 1 */


其中HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);这个语句表示通过串口1发个一个字符。ch为字符的存储地址,0xFFFF为超时时间。在stm32f7xx_hal_uart.c文件中可以找到HAL_UART_Transmit函数。



在main.c文件中添加应用函数。


01

/* USER CODE BEGIN 2 */

02

  printf("nr UART Printf Example: retarget the C library printf function to the UARTnr");

03

/* USER CODE END 2 */

04

 

05

/* Infinite loop */

06

/* USER CODE BEGIN WHILE */

07

while (1)

08

{

09

/* USER CODE END WHILE */

10

 

11

/* USER CODE BEGIN 3 */

12

      printf("nr welcome to www.waveshere.com !!!nr");

13

      HAL_Delay(1000);

14

}

15

/* USER CODE END 3 */


编译程序并下载到开发板。用USB线连接开发板到电脑,在电脑上打开串口调试助手。选择对应的串口号,设置波特率为115200。按下复位按键会接收到如图信息。



打开stm32f7xx_hal_uart.h头文件,在文件后最后面可以看到有如下操作串口的函数。


串口的发送接收函数:

HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制。

HAL_UART_Receive();串口轮询模式发送,使用超时管理机制。

HAL_UART_Transmit_IT();串口中断模式发送,

HAL_UART_Receive_IT();串口中断模式发送

HAL_UART_Transmit_DMA();串口DMA模式发送

HAL_UART_Receive_DMA();串口DMA模式发送


串口相关的中断函数:

HAL_UART_TxHalfCpltCallback():一半数据(half transfer)发送完成后,通过中断处理函数调用。

HAL_UART_TxCpltCallback():发送完成后,通过中断处理函数调用。

HAL_UART_RxHalfCpltCallback():一半数据(half transfer)接收完成后,通过中断处理函数调用。

HAL_UART_RxCpltCallback():接收完成后,通过中断处理函数调用。

HAL_UART_ErrorCallback():传输过程中出现错误时,通过中断处理函数调用。


可看到串口发送和就是有三种通信模式:

第一种是上面用到的轮询的模式。CPU不断查询IO设备,如设备有请求则加以处理。例如CPU不断查询串口是否传输完成,如传输超过则返回超时错误。轮询方式会占用CPU处理时间,效率较低。


第二种就是中断控制方式。当I/O操作完成时,输入输出设备控制器通过中断请求线向处理器发出中断信号,处理器收到中断信号之后,转到中断处理程序,对数据传送工作进行相应的处理。


第三种就是直接内存存取技术(DMA)方式。所谓直接传送,即在内存与IO设备间传送一个数据块的过程中,不需要CPU的任何中间干涉,只需要CPU在过程开始时向设备发出“传送块数据”的命令,然后通过中断来得知过程是否结束和下次操作是否准备就绪。


3.中断模式。

打开STM32CubeMX重新建工程,配置和前面一样。只是这个工程中,开启了串口中断。


生成报告以及代码,编译程序。在main函数前面添加两个数组变量。


1

/* Private variables ---------------------------------------------------------*/

2

  

3

/* USER CODE BEGIN PV */

4

/* Private variables ---------------------------------------------------------*/

5

uint8_t aTxStartMessage[] = "rn****UART-Hyperterminal communication based on IT ****rnEnter 10 characters using keyboard :rn";

6

  

7

/* Buffer used for reception */

8

uint8_t aRxBuffer[20];

9

/* USER CODE END PV */


在main函数中添加两个语句通过串口中断发送aTxStartMessage数组的数据和接收数据10个字符,保存在数组aRxBuffer中。


1

/* USER CODE BEGIN 2 */

2

    HAL_UART_Transmit_IT(&huart1, (uint8_t *)aTxStartMessage, sizeof(aTxStartMessage));

3

    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10);

4

/* USER CODE END 2 */


在main.c文件后面添加中断接收完成回调函数。中断回调函数中将接收到的数据又通过串口发送回去。


01

/* USER CODE BEGIN 4 */

02

/**

03

  * @brief Rx Transfer completed callbacks

04

  * @param huart: uart handle

05

  * @retval None

06

  */

07

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

08

{

09

  /* Prevent unused argument(s) compilation warning */

10

  UNUSED(huart);

11

   

12

  /* NOTE : This function should not be modified, when the callback is needed,

13

            the HAL_UART_RxCpltCallback can be implemented in the user file

14

   */

15

    HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF);

16

}

17

/* USER CODE END 4 */


编译程序并下载到开发板。用USB线连接开发板到电脑,在电脑上打开串口调试助手。选择对应的串口号,设置波特率为115200。按下复位按键会接收到aTxStartMessage数组的数据。通过串口助手发送10个字符,串口助手回显示发送的数据。注意:串口要发够10个字符串,才会触发中断。少于10个字符则不会触发中断,串口不会显示发送的数据。超过10个字符,串口只会发送10个字符回来显示。


推荐阅读

史海拾趣

DIALIGHT公司的发展小趣事

DIALIGHT公司的故事始于1938年的纽约布鲁克林,当时该公司专注于为飞机生产仪表板灯。随着技术的不断进步和市场的变化,公司在1971年,即LED推出仅一年后,推出了他们的第一个LED产品。这一举措标志着DIALIGHT正式从传统的飞机仪表板灯制造转向LED照明技术的研发和应用。从此,DIALIGHT彻底改变了LED的用途,将其广泛应用于世界各地的交通控制、指示灯、结构塔和工业场所,为全球提供了优质的照明解决方案。

Bergquist Company公司的发展小趣事

70年代,随着电子技术的飞速发展,导热材料行业迎来了前所未有的机遇。Bergquist Company敏锐地捕捉到了这一机遇,开始涉足导热材料领域。公司投入大量资金进行研发,成功开发出了一系列具有创新性的导热产品。这些产品不仅性能卓越,而且价格合理,深受市场欢迎。凭借这些优势,Bergquist Company逐渐在导热材料行业崭露头角,成为了行业的领军企业。

Continental Industries公司的发展小趣事

经过多年的发展,Continental Industries已经成为电子行业中的佼佼者。公司不断追求创新和发展,积极拓展新的业务领域和市场空间。未来,随着电子行业的不断发展和变革,Continental Industries将继续保持敏锐的市场洞察力和强大的技术实力,努力成为行业的领导者。

这五个故事展示了Continental Industries在电子行业中的发展历程和取得的成就。虽然无法涵盖公司的全部发展细节,但通过这些故事,我们可以感受到公司在技术创新、市场拓展、合作共赢、应对挑战以及持续发展等方面的努力和成果。

ERGOBAHCO公司的发展小趣事

在快速发展的同时,ERGOBAHCO公司始终不忘履行社会责任和推动可持续发展。公司积极参与社会公益事业,捐款捐物支持贫困地区的教育、医疗等事业。同时,ERGOBAHCO公司还注重环保和节能减排工作,通过引进先进的环保技术和设备,实现了生产过程的绿色化、低碳化。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

亿晶源(ekinglux)公司的发展小趣事

亿晶源(EKINGLUX)公司成立于2005年,总部位于深圳。创始人凭借对LED半导体行业的深刻理解和敏锐的市场洞察力,决定在这一领域深耕。公司成立之初,面临资金、技术和市场的多重挑战,但团队凭借不懈的努力和坚定的信念,逐步在市场中站稳脚跟。

HIT(日立)公司的发展小趣事
在电路中设置过流、过压等保护电路,以防止电路在异常情况下损坏或引发安全事故。

问答坊 | AI 解惑

单身男女找缘份

看看你的缘份是谁,预定你后面的楼位,不要定从复了啊。 我先来定108号了。 不过要定位子先要发点东西 来啊。 …

查看全部问答>

单片机解密,芯片解密PCB抄板,烧录IC

深圳市南源电子科技有限公司 芯片解密/单片机解密/IC解密/PLD解密/CPLD解密: (慎重声明:仅限合法研究用途) 单片机(MCU)解密、IC解密 、PLD解密、CPLD解密、鉴定芯片型号;成功率高,周期短,费用合理. 大量供应PIC/EMC兼容IC,性能稳定, ...…

查看全部问答>

红外发光二极管的接收头主要用什么?

红外发光二极管的接收头主要用什么?外发光二极管又是用什么样的二极管? [ 本帖最后由 冷枫yj 于 2009-5-15 10:37 编辑 ]…

查看全部问答>

wince 5.0 如何加载touch驱动

各位大侠,我在wince5.0的PB中搞了好久加载touch驱动就是没有搞出来,各位帮帮忙了,告诉小女子怎么加载?…

查看全部问答>

想买一块嵌入式开发板,大家有什么好的建议?

请推荐一款嵌入式开发板子,可以移植uclinux,wince,arm 平台的,其他平台也ok了.基本的 usb device .LCD 触摸屏的最好 了,LAN interface.....大家有什么好介绍..…

查看全部问答>

请问QV2 D极为何会发黑,而且QV2零件还是好的

请教各位大侠以下问题:  以下图中QV2 N-MOS的D极在线路板上为何会有烧黑的痕迹,而且该MOS管用万用表量测还是好的, 这应该是个利用电感 升压的电路,输入是+12v ,输出为-52v左右,是共Voip电压使用的, 电感LV4=6.8uH +/-20% -4.5A ...…

查看全部问答>

发现SM32的STOP休眠模式很难适用实时低功耗应用!

STM32有三种休眠模式:SLEEP、STOP、STANDBY;休眠层次依次加深,功耗越来越低。SLEEP 模式最容易使用,任何中断或事件都可以唤醒CPU。但低功耗的表现不尽如意。STANDBY 模式下对于实时采集系统来说,几乎没法用。STOP 模式怎么 ...…

查看全部问答>

请教,怎样对STM32FARM中Flash的某一位擦除?

    想把数据分块存储在Flash中,想单独对Flsh中某一部分进行擦除和写入,而不是对整个业擦除。     看了Flash.c文件中的选择擦除函数,没看懂什么意思,这个函数没有指定擦除地址竟然能实现擦 ...…

查看全部问答>