从零开始的嵌入式电子设计 软件(九)STM32的UART(串口)通信
https://www.zhihu.com/video/ UART是最简单的通信方式,不需要时钟同步,全双工这两个优点可以说很强了,而且使用起来也很简单,属于是IoT,嵌入式都很常用的了,目前来说,各种各样的模块都在用UART作为通信方式,比如陀螺仪,即使芯片可能是IIC,SPI接口的,但是还会加个芯片做成模块,一边解算了数据,一边使用UART做通信,降低了学习成本和系统的复杂度。 在通常的语境中,串口都指UART,即使串行口通信可以包含IIC,SPI等等很多协议,但是一般而言,提到串口指的都是UART,对此,STM32准备了大量的UART接口,当然,主要原因还是UART他不是一个总线,虽然可以魔改,也可以用485,232这种来构成总线,再搭配一个modbus,但毕竟复杂了。 F407zet6 有六个可以配成UART的外设,这挺多的了。USART可以配置为同步模式,但是一般也选择异步模式了。 基于F030得串口轮询发送接收教程 F030有2个可以配成UART的外设。USART可以配置为同步模式,但是一般也选择异步模式了
在CubeMX中选择串口1,将Mode设置为Asynchronous(异步)模式并将Baud Rate(波特率)修改为9600,然后就生成代码了。打开群文件中的友善串口调试助手zip,可以选择安装包安装,也可以直接使用免安装程序。
当我们用typec接到核心板上(注意,不是下载器,下载器和核心板上都有typec口)并将电源切换至使用USB供电,也就是途中左侧的USB power
打开原理图可以看见这个开关的作用是切换由+5V_IN还是USB_5V作为5V供电。
我们还需要安装一个CP2102的驱动https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads
下载CP210x windows Drivers
解压后选择CP210xVCPInstaller_x64启动,安装驱动。如果不安装这个CP210x的驱动,我们的电脑就不会识别核心板上的UART转USB器件,就无法实现通信。基础参数要保证一致,就是说,波特率要相等,数据位长度,有无校验,停止位,其中其他的都默认,只有波特率根据需要来选择就好。
当我们再次打开串口助手,并连接好核心板后,可以在端口出看见COMx(Silicon Labs)这个就是核心板了生成好cubeMX的代码后,打开keil,编写串口的程序。由于核心板上最直观的人机交互接口就是LED了,所以我们的基础教程都是用LED来实现的。我们使用串口来进行电脑和单片机的通信,使单片机可以听懂PC的命令进行对应的操作软件协议:这个软件协议是建立在硬件UART通信的基础上的,是人为规定了单片机和电脑间的“语言”我们让电脑发送{LED:X}这样字段,并让单片机根据X来判断是哪个LED会被点亮。比如让LED1亮,就用串口助手发送{LED:1}在单片机里声明两个数组的全局变量,UART_Transmit是装单片机发给电脑的字符串,UART_Receive用来接收电脑发给单片机的字符串,我们已知这个字符串有多长,所以可以提前设定好接收数组的长度 我们在while循环中添加如下代码,HAL_UART_Transmit(&huart1,UART_Transmit,sizeof(UART_Transmit),1000);是串口发送函数,我们在上面初始化了串口1,在这行代码里就表现为“huart1”,UART_Transmit就是我们要发送的字符串,值得注意的是,有C语言的同学应该知道,UART_Transmit这个作为数组名,实际上也是一个指针(地址),sizeof(UART_Transmit)就是要发送的这个字符串的长度,最后的1000是等待的时间,当超过1000这个时间还没有将字符串的内容发送出去就不发送了。 也就是说,当你使用HAL_UART_Transmit时,需要提供,从哪个串口发送,发送什么,要发送多少个字节出去,以及等待时间四个变量。 if(HAL_UART_Receive(&huart1,UART_Receive,sizeof(UART_Receive),1000)==HAL_OK)这行代码,首先说明一下HAL_UART_Receive,huart1,从哪个串口进行接收,接收完放在哪,要接收多少字符,最后呢,也有一个等待时间,要等多少,等1000后还没接到就不等了推出。如果接收到了字符串,这个函数就会返回“HAL_OK”,那咱们的这个if就通过了,就可以执行if里面的代码,如果没通过,就回去执行HAL_UART_Transmit,然后继续等待。最后,我们解释一下上面经常使用的HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET); #define LED0_Pin GPIO_PIN_0 #define LED0_GPIO_Port GPIOBLED0_GPIO_Port 就是GPIOB,LED0_Pin就是GPIO_PIN_0,GPIOB和LED0_Pin,就指代了PB0,前面是哪“套”GPIO,后面指代了这一套GPIO的具体哪个Pin。打开cubeMX可以看见PA多少多少PC多少多少。GPIO_PIN_SET就是高电平,GPIO_PIN_RESET是低电平。另外,可以看见单片机的右下角这里有两个LED,分别是RXD和TXD
就是这俩,所以,每次单片机串口向电脑发送时,绿灯都会闪,每次电脑给单片机发送时,黄灯都会闪。 基于F407的串口中断教程
常见的串口助手的界面 基础参数要保证一致,就是说,波特率要相等,数据位长度,有无校验,停止位,其中其他的都默认,只有波特率根据需要来选择就好。 对于选择哪个引脚作为UART使用的引脚,有一个简单的方法,在图一里,当UART1开启时,默认的PA9和PA10作为UART的引脚而启用,但是如果我们不想用这俩脚,并且还不知道其他引脚是什么,我们可以这样。 在UART1 disable的情况下把PA9选择为GPIO_OUTPUT,或者其他任何除了USART1_TX之外的功能
这样就可以给TX“挤”过去,这就给挤到PB6去了,同理,选择PA10也可以给RX挤到PB7那去。 UART也有自己的中断,顺便可以引出这个。可以在各个外设的自己的界面里也勾选NVIC
当开启USART global interrupt的时候,就可以使用串口中断了。一般我们会使用中断进行接收。 UART发送 UART发送是三种,和之前提到的一样,轮询,中断和DMA。我的确,没怎么用过除了轮询之外的方法进行发送。 这个函数其实比较简单,直接就给发出去了。要提供串口的指针,要发送的数据的数组(字节数组)和要发送的大小(多少个字节)以及阻塞的时间。
设置一个UART发送的缓冲区,每次发送时都先将发送的内容存在buffer里,然后发送,习惯(个人)上将UART1Buffer作为全局变量声明在PV里。private variable 搞了个thisyear是为了演示sprintf的用法,和printf相比,只是加了个“要把字符串打印到哪里”的数组指针。 可以添加\0作为空字符使得strlen的值不会受数组内残留素的影响。 这样的话,就只会发送 Hello World!了。 这样也可以。 UART接收 这个其实不是很好演示。 因为,即使,你用一个仅测试串口接收的程序,成功接收了,在实际中的大程序里也很难直接用起来。无论是轮询,中断还是DMA,都是在一定的场合下才最有效果,或者说才好使。他不像发送那样,是一个“主动”的过程,发送就很好想。 轮询 对于轮询而言,多数情况是你想去等一下有没有数据传过来,没有的话就不接了。比如说,某个模块如果出错了,上电就会报,那么你开启自检的时候,没接到这个消息就说明是正常的了呗,或者开机的时候等某些信息,没有的话就正常执行。 这就类似于电脑的BIOS中断,总是要按一下(通常都会连续按按按)按键才会进去,不按呢,就正常开机了。这个时候用轮询很有意义。 或者呢,就是你都知道他啥时候给你发了,中断还容易出一些不知为何的小问题,就轮询了。 中断 stm32的中断基本都有这种回调函数的,写起来和外部中断差不多。 以上的代码中,接收都是一个字节一个字节接收的,再放入FreeRTOS的队列里。也可以不这么来,也可以一次接很长一段,但是可能会错位,不如这样一个一个接,然后在队列转数组,在数组里找帧头帧尾。 如果不使用FreeRTOS的话,大可以这样 另外,Receive_IT会在接受完指定字节之后,才会引发中断。在上面这段里是接收到sizeof(UART2INPUT)个uint8,也就是char,才会中断。 记得要先开启中断 当执行这两段函数之后,UART1和UART2的接收中断就开始了。 为什么我说要找帧头帧尾,接收任何数据的时候都最好有帧头帧尾。这样可以有效应对错位的问题。很容易发生错位的实际上。 可以这样 帧头(5A A5) 数据 帧尾(A5 5A),一共12个字节,然后中断接收24个字节,for循环在24个字节中寻找帧头,找到之后,在去校验帧尾对不对(跳过8个数据位去校验帧尾),对的话,证明数据位不乱,就可以取出来了。如果更严密的话就加中间位。 就是终极校验,认为这帧是正确的从而读取某些位,比如上一段代码,首先校验帧头,然后读取“读写“位,然后读取功能位(让谁动作),最后读取数据位(怎么动作)。这个代码比较久远了,当时的数据量特别小,校验了个帧头意思一下就可以了,从未出错,后续的代码数据量越大越出幺蛾子,尤其是什么陀螺仪,数据飞快,终极错位,就不得不认真校验了。 总结 UART配置中,最重要的就是波特率了,其他的东西基本都那样,都是默认的配置了。发送方面轮询发送即可,接收看情况,自定义协议最好有帧头帧尾,甚至有奇偶校验。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/25900.html