基于STM32使用CubeIDE实现串口通信

串口的配置与使用

CubeIDE配置

首先在左侧列表中找到USART,然后选择一个你喜欢的数字,作为串口使用 选择异步模式,下面Paramete Setting中,Baud Rate就是串口的波特率,这里我们不用动,不过一会连接需要它。设置完成后保存,Alt+K生成代码,串口配置完成

串口阻塞方式收发

发送数据

可以看到,这个函数一共有四个参数, 第一个参数是要使用的串口句柄地址,比如要使用U(S)ART1,参数就设置为U(S)ART1的句柄地址&huart1 第二个参数是要发送的数据缓冲区首地址 第三个参数是发送的数据长度,这里可以直接用sizeof()函数获取发送缓冲区的长度 第四个参数是超时时间,单位是ms,如果超过设置的时间,则函数返回HAL_TIMEOUT,如果设置为HAL_MAX_DELAY,处理器就会一直等到数据发送完成再执行下一条语句。 打开main.c来到如图位置,输入如下代码

HAL_UART_Transmit(&huart1,"Hello world",11,100);
Hal_Delay(999);

注意这里一定要在/* USER CODE END WHILE */ 之前输入代码,不然再生成一次就会被覆盖掉(血泪史.jpg) 接下来直接烧录(我想这个应该是不用教) 下载群里发的XCOM(正点原子推荐).rar,解压,为了以防万一,先运行dotNetFx40_Full_x86_x64.exe·当然,一会打不开回来再安装也不是不行。 打开XCOM V2.2.exe,我们可以看到如下界面 首先,我们需要把右侧的波特率改为刚刚上面你自己配置的波特率(如果没改就是115200) 然后连接USB/TTL到板子上,rx,tx分别接stm32板子上tx,rx 打开串口,理论上我们就可以看到左侧上方显示每秒都会发过来的Hello world了

接收数据

同HAL_UART_Transmit()函数一样,这个函数也有四个参数 第一个参数是要使用的串口句柄地址,比如要使用U(S)ART1,参数就设置为U(S)ART1的句柄地址&huart1 第二个参数是接受数据的缓冲区首地址 第三个参数是接受的数据长度,这里可以直接用sizeof()函数获取接受缓冲区的长度 第四个参数是超时时间,单位是ms,如果超过设置的时间,则函数返回HAL_TIMEOUT,如果设置为HAL_MAX_DELAY,处理器就会一直等到接受到设置好的数据数量再执行下一条语句。 在此处初始化接收缓冲区,一个char为8bit,故此处11个成员的数组可以容纳11个char

uint8_t Rxbuf[11];
    

然后在原先发送处输入如图代码,此处意为当完成接收后,把接收到的内容发送回接收者

  if(HAL_UART_Receive(&huart1,Rxbuf,sizeof(Rxbuf),1000) == HAL_OK)
  {
	  HAL_UART_Transmit(&huart1,Rxbuf,sizeof(Rxbuf),100);
  }

接下来我们重复发送时的操作 但现在我们需要在下面的输入框中输入不长于11个byte的文本,如Hello world,此时上方就会收到32发送回来的相同内容,到此,串口阻塞方式的收发教程就已经完成

UART中断方式收发

CubeIDE配置

回到原来的界面,在下方面板选择NVIC Setting,随后勾选Enabled,至此,中断便配置完毕了

中断方式收发代码

中断方式的收发函数只有三个参数 第一个参数时要使用的串口句柄地址 第二个参数是发送/接受缓冲区的首地址,用于存放要发送/接收的数据 第三个参数是发送/接受缓冲区长度

前三个参数和阻塞方式完全一致,为什么没有超时时间了呢? 因为中断(IT)方式配置完成寄存器之后不需要再占用CPU,会在接受完成后触发中断。

阻塞方式就好比你要拿快递,就一遍遍都前台询问快递到没到,在这期间你不能干别的, 中断方式是你告诉前台快递到了给你打电话,在这期间你是可以腾出身子来干别的事情。

由此可见,中断方式效率大于阻塞方式,极端情况下,中断方式的安全性也高于阻塞方式 接收中断回调函数 顾名思义,该函数是当中断方式串口接收触发中断(接收完成)所调用的函数

该函数的返回值为__weak,表示这个函数需要用户自己去编写,最终会执行用户所自行编写的回调函数(如果用户不编写,也会执行自带的回调函数,只不过自带的HAL_UART_RxCpltCallback()函数是空函数,所以等同于什么也没有做)

注意:用户自行编写的回调函数返回值不能为__weak。 与接收同理,也有发送的中断,但一般情况下不会去使用,故不多赘述

接下来,我会带着你们用中断实现之前使用阻塞方式完成的信息收发 首先像阻塞方式一样建立我们的缓冲区 然后在CubeIDE生成完成之后,开始循环之前,开启中断的接收

  HAL_UART_Receive_IT(&huart1,Rxbuf,sizeof(Rxbuf));
 

接下来重写中断的回调函数以实现方法

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
        if(UartHandle -> Instance == USART1)
        {
            //发送数据
            HAL_UART_Transmit(&huart1,Rxbuf,sizeof(Rxbuf),100);
            //重新开启串口的接收中断
            HAL_UART_receive_IT(&huart,Rxbuf,sizeof(Rxbuf));
        }
}

注意要注释掉阻塞方式的代码,以免影响测试 接下来像阻塞方式一样测试,就可以得到相同的结果

DMA方式串口收发

什么是DMA

知识拓展链接:百度-DMA

前文说过中断方式就好比你告诉前台,等快递到了给你打电话,让你亲自来取,假设你正在做着一些重要的事情,正好来了电话让你取快递,这样一来就会耽误事。 这怎么办呢?雇个保姆不就好了吗,DMA就好比这个保姆,你告诉她在哪里取快递,她就会等快递到了之后自己帮你把快递拿回家。

CubeIDE配置

回到原来的界面,在下方面板选择DMA Settings,然后点击Add,在DMA Request中分别选择RXTX,随后单击选中,在Mode中选择Circular,若选择Normal则只能接收一次的数据,其他的一般情况下不需要修改,配置完成后显示如下图

DMA方式收发代码

接收函数如上图所示,参数含义与中断方式的相同,可以点击此处回到中断方式处复习单击此处跳转 随后我们依旧去实现最开始我们用阻塞方式实现收发功能 依旧是设置缓冲区

uint8_t Rxbuf[11];

然后是与中断极为类似的业务代码,同样不要写在循环中

最后是与中断一模一样的回调代码,这里就不重复了,点击这里回到中断部分复习 至于最后烧录和测试,我在这里也就不过多赘述,仿照之前的操作即可

串口通讯原理

懒得写了,直接上一个我觉得讲的还可以的链接

Q.E.D.