UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用来主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,多用于上位机与下位机的通信。
在UART通信中,两个UART直接相互通信。 发送UART将控制设备(如CPU)的并行数据转换为串行形式,以串行方式将其发送到接收UART。只需要两条线即可在两个UART之间传输数据,数据从发送UART的Tx引脚流到接收UART的Rx引脚:
波特率:每秒传输二进制位数。
例:1分钟传输数据57600BYTE,帧格式10位,求波特率?
二进位:57600*10=576000/60 = 9600bit/s
UART属于异步通讯,这意味着没有时钟信号,取而代之的是在数据包中添加起始和停止位。这些位定义了数据包的开始和结束,通过识别起始位和结束位可以解析出数据。
帧格式:1位起始位+(5-8)位数据+1位奇偶校验位+(1~2)位停止位 =10位
奇校验:数据位上的1的个数+校验位上1的个数和位奇数。
数据包的传输示意图:
上图来自此文。
①串口是什么?
串口就是一种通信方式(TX和RX)
②串口通信的特点
异步 全双工 串行
③串口通信数据帧
起始位 数据位(8) 【奇偶校验】 停止位
有关串口的详细介绍参考此文。
今天主要借助陶晶驰串口屏配合树莓派4B实现一个通信效果。
串口屏内置一块STM32,构建了相对独立的系统,有配套的软件能够进行图形化编程,极大地降低了界面设计的时间和难度,而且还有各种控件以便于灵活实现更多功能,可以通过串口完成对各类控件的操作,有很强的实用性。
有关陶晶驰串口屏的具体使用可以参考官网的资料。
将串口屏的TX、RX与树莓派的UART硬件接口连接,注意交叉。(没有屏幕的同学也可以使用USB转TTL连接树莓派,然后安装陶晶驰的开发环境,在线仿真也可。)
树莓派 | 串口屏 |
---|---|
5V | VCC |
板载编码8脚(TX) | RX |
板载编码10脚(RX) | TX |
GND | GND |
树莓派一共有两个串口如下图所示:(来自B站树小悉)
这里还需要注意,树莓派的串口分为了主串口和辅助串口;
(硬件串口标识符为ttyAMA0;主串口标识符为serial0;辅助串口的标识符为serial1)。本此介绍使用的是硬件串口和主串口,利用引脚通信。
跟之前类似,打开Serial Port,关闭Serail Console,点击OK,会提示重启。
点击Yes等待重启。
重启完毕后,打开命令终端,输入ls /dev -al 回车。(若重启失败,先把串口屏拔下来,重启完毕后再接上去)
下拉找到串口,此时发现,主串口(serial0)指向了mini串口,辅助串口(serial1)指向了硬件串口(ttyAM0);这与我们所需要将主串口指向硬件串口,所以需要进一步修改配置。
利用nano编辑器打开并修改config.txt,具体步骤如下:
(1)在终端输入:sudo nano /boot/config.txt 回车,弹出下图画面,利用滚轮来到文件末尾。
(2)添加如下代码:
dtoverlay=pi3-miniuart-bt
force_turbo=1
按Ctrl+S保存,Ctrl+X返回。
然后再次重启树莓派,输入sudo reboot 等待重启完成
再次打开终端,输入ls /dev -al 回车此时上滑找到串口发现已经修改为主串口指向硬件串口了。
为了验证树莓派串口有没有真的工作,需要安装一个minicom的串口助手来验证一下。
安装步骤:打开终端输入:sudo apt-get install minicom回车等待下载和安装,安装过程中有提示,直接输入Y回车。
安装完成后需要先将USB转TTL连接到树莓派,然后打开电脑的串口调试助手,连接到CH340(波特率9600八位数据一位停止)。
同时打开树莓派的串口助手:
在终端输入命令: minicom -D /dev/ttyAMA0 -b 9600回车即可进入。
在电脑端输入abcd点击发送,可以发现在树莓派上有了显示,表示串口开启OK。此时我们需要退出minicom ,退出步骤:首先Ctrl+A,然后按Z;最后按X,选是即可退出。
验证了串口功能后,我们开始利用串口编程,在编程之前,根据前面的经验,我还是需要先了解一下WiringPi的串口库给我们提供了哪些可以调用的函数。
之前一直没提这个库是怎么查询的,在这里说明一下:
安装后wiringpi的库后我们可以载可以在/usr/linclude找到wiringPi相关的头文件如下图所示:
wiringPi.h 基本IO驱动和常用配置定义;
wiringPiI2C.h I2C驱动的头文件;
wiringPiSPI.h SPI驱动的头文件;
wiringSerial.h Serial驱动的头文件;
双击wiringSerial.h Serial.h,我们可以看见有以下几个函数:
具体解释转载与此文。
extern int serialOpen (const char *device, const int baud) ;//打开串口,输入设备描述符和串口波特率,返回串口的设备ID
extern void serialClose (const int fd) ;//关闭串口,
extern void serialFlush (const int fd) ;//清空缓存区
extern void serialPutchar (const int fd, const unsigned char c) ;//输出一个字符
extern void serialPuts (const int fd, const char *s) ;//输出字符串
extern void serialPrintf (const int fd, const char *message, …) ;//格式化输出
extern int serialDataAvail (const int fd) ;//返回设备缓存区接收到的数据个数
extern int serialGetchar (const int fd) ;//从设备ID读取一个字符
此处转载的此文。
打开Geany输入以下代码:
// An highlighted block
#include<wiringPi.h>
#include<wiringSerial.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
void delay_ms(int ms);
int main()
{
int filedevid;
int recbytenum;
int i;
char buf[1024];
memset(buf,0,1024);
wiringPiSetup();
if((filedevid=serialOpen("/dev/ttyAMA0",115200))<0)//打开串口
{
printf("/dev/ttyAMA0 Open Faild\r\n");
return -1;
}
else
{
printf("/dev/ttyAMA0 Open with 115200, success\r\n");
while(1)
{
recbytenum = serialDataAvail(filedevid);//记录接受到的数据个数
if(recbytenum > 1)//如果接收到
{
i=0;
while(recbytenum--)
{
buf[i++] = serialGetchar(filedevid);//读出缓存区的数据
}
printf("Rpi uart recv: %s\r\n",buf);输出在终端
serialPrintf(filedevid,"Rpi uart send: %s\r\n",buf);//通过串口打印到上位机啊。
memset(buf,0,1024);
}
}
}
}
上述代码效果如下:
C语言代码如下:
//树莓派通过串口屏输出两个通道正弦波形。
#include<wiringPi.h>
#include<wiringSerial.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#define uchar unsigned char
#define uint unsigned int
int filedevid;
int second,minute,hour,day,month,week,year,zwc,fwc,wdc,bal,txt,wendu;
char endbuf[]={0xff,0xff,0xff};
char buf[64];
//唤醒屏幕准备通信
void UART_Send_start(void)
{
delay(10);
serialPuts (filedevid,(char *)endbuf);//发送结束标志0xff,0xff,0xff包尾
delay(10);
}
int main()
{
uint ch0,ch1;
signed int i,j;
second=50;minute=48;hour=12;day=15;month=7;week=2;year=16;bal=0;txt=0;wendu=0;
wiringPiSetup();
if((filedevid=serialOpen("/dev/ttyAMA0",9600))<0)//打开串口
{
printf("/dev/ttyAMA0 Open Faild\r\n");
return -1;
}
else
{
printf("/dev/ttyAMA0 Open with 9600, success\r\n");
UART_Send_start();//初始化串口屏
serialPuts (filedevid,"page 0");//切换到初始页面
serialPuts (filedevid,(char *)endbuf);//发送结束标志0xff,0xff,0xff包尾
delay(1000);//等待屏幕启动
while(1)
{
j= 32;
for(i=0;i<sizeof(zhengxianbo);i++) //正弦波显示
{
ch0 = zhengxianbo[i]/3+40;
ch1 = zhengxianbo[j++]/3+40;
if(j>=sizeof(zhengxianbo))
j = 0;
sprintf(buf,"add 1,0,%d",ch0);//将波形数据打包
serialPuts(filedevid,(char *)buf);
serialPuts (filedevid,(char *)endbuf);//发送结束标志0xff,0xff,0xff包尾
sprintf(buf,"add 1,1,%d",ch1);//将波形数据打包
serialPuts(filedevid,(char *)buf);
serialPuts (filedevid,(char *)endbuf);//发送结束标志0xff,0xff,0xff包尾
}
}
}
}
//此处展示的代码不全,有需要的点赞收藏私信笔者免费获取。
效果如下:
有关树莓派串口的记录就到这里,到此笔者关于树莓派的基础部分笔记也就结束了,后面会根据情况更新进阶版的,前面有关内容如果存在不妥之处欢迎批评指正,此系列到此基本画上了句号。如果觉得对你有帮助记得点赞收藏加关注。
树莓派4B学习笔记——系统烧录及初次开机
树莓派4B学习笔记——点亮你的LED
树莓派4B学习笔记——IO输入检测
树莓派4B学习笔记——IO通信篇(I2C)
树莓派4B学习笔记——IO通信篇(SPI)
树莓派4B学习笔记——IO通信篇(1-Wire)
树莓派4B学习笔记——IO通信篇(UART)