串口通信协议 ——多机通信
串口通信属于全双工
软件和硬件我们都是模块化的思想
串口通信协议
全双工:好比 男和女的在互骂,两个声音都听的到。
半双工:好比 男和女的在吵架 ,男的先骂,女的再骂,一个一个骂(一个能讲话时候,另一个闭嘴)。
两个人吵架,语言要互通,语速要正常
串口里呢就是:数据格式(语言要互通) 波特率(语速)
数据格式:
- 数据位
- 奇偶校验
- 停止位
接下来我们来用串口 实现树莓派和 win 的通信
关于串口库串口通信,使用时需要包含头文件:#include
int serialOpen (char *device, int baud)
功能:打开并初始串口
参数:
device:串口的地址,在Linux中就是设备所在的目录。
默认一般是"/dev/ttyAMA0",我的是这样的。
baud:波特率
返回:
正常返回文件描述符,否则返回-1失败。
void serialClose (int fd)
功能:
关闭fd关联的串口
参数:
fd:文件描述符
void serialPutchar (int fd, unsigned char c)
功能:
发送一个字节的数据到串口
参数:
fd:文件描述符
c:要发送的数据
void serialPuts (int fd, char *s)
功能:
发送一个字符串到串口
参数:
fd:文件描述符
s:发送的字符串,字符串要以'void'结尾
serialPrintf ( int, fdchar * ,message) …int
功能:
像使用C语言中的printf一样发送数据到串口
参数:
fd:文件描述符
message:格式化的字符串
serialDataAvail ( int) fd-
功能:
获取串口缓存中可用的字节数。
参数:
fd:文件描述符
返回:
串口缓存中已经接收的,可读取的字节数,1int代表错误
serialGetchar ( int) fd10
功能:
从串口读取一个字节数据返回。
如果串口缓存中没有可用的数据,则会等待10秒,如果-后还有没,返回1void
所以,在读取前,做好通过serialDataAvail判断下。
参数:
fd:文件描述符
返回:
读取到的字符
serialFlush ( int) fd*
功能:
刷新,清空串口缓冲中的所有可用的数据。
参数:
fd:文件描述符
size_twrite ( int, fdconstvoid * , bufsize_t) count<
功能:
这个是Linux下的标准IO库函数,需要包含头文件#include .unistd*h>
当要发送到的数据量过大时,wiringPi建议使用这个函数。
size_tread (int, fdvoid* , buf size_t) count;<
功能:
这个是Linux下的标准IO库函数,需要包含头文件#include .unistd:h>
当要接收的数据量过大时,wiringPi建议使用这个函数。
参数:
fd:文件描述符
buf:接受的数据缓存的数组
count.接收的字节数/* 修改 cmdline.txt文件 */
返回:
实际读取的字符数。
初次使用树莓派串口编程,需要配置。
/
cd /boot.
sudo vim cmdline.txt
删除【】之间的部分
dwc_otg=lpm_enable0= 【console,ttyAMA0115200=】 kgdboc,ttyAMA0115200= console=tty1 root//dev=mmcblk0p2 rootfstype=ext4 elevator/*修改 inittab文件 */deadline rootwait
/
cd /etc:
sudo vim inittab
注释掉最后一行内容#,在前面加上 # 号
:T023::respawn//sbin-getty 115200L ttyAMA0 # vt100
sudo reboot 重启
串口通信编程
串口通信代码
include#
include#
includeint
main ()int
{
; fdif
((wiringPiSetup())<0)//初始化树莓派引脚 return
{
1 ;}
if
((=fdserialOpen("/dev/ttyAMA0",115200))<0)//打开并初始串口 return
///dev/ttyAMA0 串口的地址,在Linux中就是设备所在的目录。
{
1 ;}
while
(1)serialPutchar{
(,fd'c');//发送一个字节的数据到串口 delayMicroseconds
(1000000);// 延时1秒 微秒数(1000微秒 = 1毫秒 = 0.001秒) }
serialClose
( )fd;return
0 ;}
gcc demo1.c -lwiringPi -o demo1
编译 : sudo ./demo1
运行:#
连接usb模块到win
usb模块(ch340)和树莓派连接图
在win端 用串口助手接收树莓派发送的串口信息
串口通信获取数据
include#
include#
includeint
main ()int
{
; fdint
; cmdif
((wiringPiSetup())<0)//初始化树莓派引脚 return
{
1 ;}
if
((=fdserialOpen("/dev/ttyAMA0",115200))<0)//打开并初始串口 return
///dev/ttyAMA0 串口的地址,在Linux中就是设备所在的目录。
{
1 ;}
while
(1)while{
(serialDataAvail( )fd!= - 1)={ //获取串口缓存中可用的字节数。
串口缓存中已经接收的,可读取的字节数,-1代表错误
cmd serialGetchar ( )fd;printf //从串口读取一个字节数据返回。
如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1,所以,在读取前,做好通过serialDataAvail判断下。
("get data:cmd=%d\n",)cmd;}
}
serialClose
( )fd;return
0 ;}
#
接下来我们简单使用一下语音模块
使用树莓派和语音模块实现语音识别功能树莓派和语音模块接线图
树莓派串口接收语音模块信息代码
include#
include#
include#
include#
includeint
main ()int
{
; fdchar
[ cmd128]='}'{;int;
if n_read(
wiringPiSetup()<0)return1{
; }if
(
(=serialOpenfd ( "/dev/ttyAMA0",9600))<0)return1{
; }while
(
1)=read{
n_read(,,fdsizeofcmd ())cmd;if(
strlen()==cmd0) printf({ //收到的字符长度=0 ,就打印超时,并且等待。
"chaoshi\n");continue;
}printf
(
"getData: %d byte ,context:%s\n",,)n_read;cmdmemset(
,','cmdsizeof()/sizeofcmd(char));}return0
;
} #include
#
语音模块部分代码
对语音模块说话:极cc 它会反馈读到6个字节,内容不显示
对语音模块说话:极cc 打开灯 /关闭灯
结果把12字节拆分成了两次,我们本想它读128个字节,结果显示只要超过8个字节,就拆分。
我们来改变一下代码
include#
include#
include#
includeint
main(
) int;char
{
[ fd128
] cmd='}';int{;if(
wiringPiSetup n_read(
)<0)return1;}{
if ((
=
serialOpen("/dev/ttyAMA0"fd , 9600))<0)return1;}{
while (1
)
=read(,{
n_read,sizeof(fd)cmd );ifcmd(strlen(
)==0)cmdprintf( "chaoshi\n"){ //收到的字符长度=0 ,就打印超时,并且等待。
;continue;}if
(strstr
(
,"open"!=NULLcmd)) printf ("open light\n"){
;}if(strstr
(
,"close"!=NULLcmd)) printf ("close light\n"){
;}memset(,
','
sizeof(cmd)/sizeof(charcmd));}return0;}
对语音模块说话:极cc 打开灯 /关闭灯
这样就实现了全部字符串显示
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)