赞
踩
无人问津也好,技不如人也罢,都应静下心来,去做该做的事。
最近在学STM32,所以也开贴记录一下主要内容,省的过目即忘。视频教程为江科大(改名江协科技),网站jiangxiekeji.com
本期开始学习STM32的通信接口,在STM32中,集成了很多用于通信的外设模块,比如这个表里,USART、I2C、SPI、CAN和USB,C8T6芯片是全部都支持的。
本期先学习USART串口。因为有些功能是STM32内部是没有的,比如我们想要蓝牙无线遥控的功能、想要陀螺仪加速度计测量姿态的功能,需要外挂芯片。而外挂芯片的数据都在外面,STM32如何获取这些数据呢?这就需要我们在这两个设备之间,连接上一根或多根通信线。通过通信线路发送或者接收数据,完成数据交换,从而实现控制外挂模块和读取外挂模块数据的目的。
第一个USART串口,它的脚是TX和RX,有的地方也叫TXD和RXD,这两种名称是一个意思。
CAN通信,引脚是CAN_H和CAN_L,这两个是差分数据脚,用两个引脚表示一个差分数据。
USB通信,引l脚是DP(Data Positive)和DM(Data Minus),或者叫D+和D-,也是一对差分数据脚。
异步:没有SCL,所以需要双方约定一个采样频率,并目还需要加一些帧头帧尾等,进行采样位置的对齐。
串口和USB是点对点的通信。
可以接电脑屏幕,非常适合调试程序,打印信息。像I2C和SPI这些,一般都是芯片之间的通信,不会接在电脑上。
左边的是USB转串口模块,上面有个芯片,型号是CH340。这个芯片可以把串口协议转换为USB协议。中间这个图是一个陀螺仪传感器的模块,可以测量角速度、加速度这些姿态参数,左右各有四个引脚,一边是串口的引脚,另一边是I2C的引脚。右边这个图是蓝牙串口模块,下面4个脚是串口通信的引脚,中间的芯片可以和手机互联,实现手机遥控单片机的功能。
TX和RX是单端信号,它们的高低电平都是相对于GND的。所以,串口通信的TX、RX是必须要接的。像下图这种,直接从控制器里出来的信号,一般都是TTL电平,相同的电平才能互相通信
RS232电平一般在大型的机器上使用,由手环境可能比较恶劣,静电干扰比较大。所以这里电平的电压都比较大,而目允许波动的范围也很大。
RS485电平,这里电平参考是两线压差,所以RS485的电平是差分信号。差分信号抗干扰能力非常强,使用RS485电平标准,通信距离可以达到上干米。而上面这两种电平,最远只能达到几十米,
再远就传不了了。
像单片机这种低压小型设备,使用的都是TTL电平,我们之后的内容,他都是基于TTL电平来讲解的。如果你做设备需要其他的电平,那就再加电平转换芯片就行了。在软件层面,它们都属于串口,所以程序并不会有什么变化。
还可在数据饿的最后加一个奇偶检验位,这样数据位就由8位变为9位。
首先,串口的空闲状态是高电平,也就是没有数据传输的时候。然后需要传输的时候,必须要先发送一个起始位,这个起始位必须是低电平,即通信开始前必须有个下降沿。同理,在一个字节数据发送完成后,必须要有一个停止位,同时这个停止位也是为了下一个起始位做准备。
串口通信是低位先行,也就是说低位的数据先发送。
奇偶校验可以判断数据传输是不是出错了,如果数据出错了,可以选择丢弃或者要求重传。校验可以选择3种方式,无校验、奇校验和偶校验。需要校验时,数据分为四个部分,起始位、数据位、校验位、停止位。如果使用了奇校验,那么包括校验位在内的9位数据会出现奇数个1。比如如果你传输00001111,目前总共4个1,是偶数个,奇校验时,校验位就需要再补一个1。如果想要更高的检错率,可以了解一下CRC校验,STM32中也有这个外设。
最后,看几个串口的波形直观了解时序。
下图的波特率是9600,所以每一位的时间就是1/9600,大概是104us。 没发送数据的时候,是空闲状态高电平,数据开始先发送起始位,产生下降沿,代表数据帧开始。数据0x55转为二进制,低位先行,就是依次发送10101010。然后,这个参数是8位数据,1位停止,无校验,没有校验位,所以之后就是停止位,把引脚置回高电平,这样一个数据帧就完成了。
在STM32中,这个根据字节数据翻转高低电平,是由USART外设自动完成的,不用我们操心。当然,你也可以软件模拟产生这样的波形,那就是定时器定一个104us的时间,时间到之后,按照数据帧要求,调用GPIO_WriteBit置高低电平,产生一个和这一模一样的波形,这样也是可以完成串口通信的。TX引脚发送, 就是置高低电平,那在RX引脚接收,显然就是读取高低电平了,这也可以由USART外设自动来完成,不用我们操心。如果想软件模拟的话,那就是定时调用GPIO_ReadInputDataBit来读取每一位,最终拼成每一位,当然接收的时候,应该还需要一个外部中断,在起始位的下降沿触发,进入接收状态,并且对齐采样时钟,然后依次采样8次,这就是接收的逻辑。
总结一下就是,TX引脚输出定时翻转的高低电平,RX引脚定时读取引脚的高低电平。每个字节的数据加上起始位、停上位、可选的校验位,打包为数据帧,依次输出在TX写引脚,另一端RX引脚依次接收,这样就完成了字节数据的传递。在STM32中,这个根据字节数据翻转高低电平,是由USART外设自动完成的,如果想用软件模拟也可以,参考上面串口时序。
我们可以写一个串口的模块,通过串口通信,把一些数据发送到电脑上的串口助手来显示。
程序里先串口初始化,然后我们会写一些功能函数,比如串口发送一个字节,字节数据是0x41;串口发送一个数组,把这个MyArray数组一起发送出去;还有串口发送字符串、发送数字这些函数。
最后给出3种实现printf函数的方法,printf函数它是一个非常强大的格式化打印字符串函数,在这里,我们也可以把printf函数移植到串口这里来,用于向电脑的串口助手打印消息。
- /*下述3种方法可实现printf的效果*/
-
- /*方法1:直接重定向printf,但printf函数只有一个,此方法不能在多处使用*/
- printf("\r\nNum2=%d", 222); //串口发送printf打印的格式化字符串
- //需要重定向fputc函数,并在工程选项里勾选Use MicroLIB
-
- /*方法2:使用sprintf打印到字符数组,再用串口发送字符数组,此方法打印到字符数组,之后想怎么处理都可以,可在多处使用*/
- char String[100]; //定义字符数组
- sprintf(String, "\r\nNum3=%d", 333);//使用sprintf,把格式化字符串打印到字符数组
- Serial_SendString(String); //串口发送字符数组(字符串)
-
- /*方法3:将sprintf函数封装起来,实现专用的printf,此方法就是把方法2封装起来,更加简洁实用,可在多处使用*/
- Serial_Printf("\r\nNum4=%d", 444); //串口打印字符串,使用自己封装的函数实现printf的效果
- Serial_Printf("\r\n");
这里我们通过这个USB转串口模块,把STM32的串口引脚,接到电脑上来。之后电脑端可以打开串口助手的软件,选择一下串口号,其他参数也根据STM32程序的配置来,最后打开串口,按一下STM32的复位键。我们的程序在每次上电之后会通过串口发送一批数据,当切换模式为文本模式时,再按一下复位键,这时,软件就会对刚才的数据进行文本映射,找到每个数据对应的字符,以字符串的形式显示出来。这样,电脑上就能显示Num1=111、Num2=222等等这些文本了。
这里程序的主体部分是,先判断是否收到数据,如果收到数据,则读取数据,并将数据回传电脑,并且也在OLED上显示一下。实际上在串口中,只能发送二进制数,也就是十六进制的最直接的数据,如果想发送字符,那我们就需要一个数据到字符的映射表,最简单最常用的映射表,就是ASCII码表。在ASCII码表里,0x41这个数,就映射为字符A。所以发送0x41,如果以HEX模式显示,就是数据本身;如果以文本模式显示,它就会先去找一下映射表,最终发现,0x41对应的是字符A,所以就是显示A了。这就是HEX模式和文本模式的区别。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。