树莓派开发——“串口通信协议” 解决针对串口通信的面试利器

串口通信协议

串口通信协议 ——多机通信

串口通信属于全双工

软件和硬件我们都是模块化的思想

串口通信协议
在这里插入图片描述

全双工和半双工的区别:

全双工:好比 男和女的在互骂,两个声音都听的到。
半双工:好比 男和女的在吵架 ,男的先骂,女的再骂,一个一个骂(一个能讲话时候,另一个闭嘴)。

两个人吵架,语言要互通,语速要正常
串口里呢就是:数据格式(语言要互通) 波特率(语速)

数据格式:

  1. 数据位
  2. 奇偶校验
  3. 停止位

接下来我们来用串口 实现树莓派和 win 的通信

关于串口库

串口通信,使用时需要包含头文件:#include <wiringSerial.h>

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:发送的字符串,字符串要以'\0'结尾

void  serialPrintf (int fd, char *message,)
功能:
	像使用C语言中的printf一样发送数据到串口
参数:
	fd:文件描述符
	message:格式化的字符串 

int   serialDataAvail (int fd)
功能:
	获取串口缓存中可用的字节数。
参数:
	fd:文件描述符
返回:
	串口缓存中已经接收的,可读取的字节数,-1代表错误

int serialGetchar (int fd)
功能:
	从串口读取一个字节数据返回。
	如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1
	所以,在读取前,做好通过serialDataAvail判断下。
参数:
	fd:文件描述符
返回:
	读取到的字符

void serialFlush (int fd)
功能:
	刷新,清空串口缓冲中的所有可用的数据。
参数:
	fd:文件描述符

*size_t write (int fd,const void * buf,size_t count)
功能:
	这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>
	当要发送到的数据量过大时,wiringPi建议使用这个函数。

*size_t read(int fd,void * buf ,size_t count); 
功能:
	这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>
	当要接收的数据量过大时,wiringPi建议使用这个函数。
参数:
	fd:文件描述符
	buf:接受的数据缓存的数组
	count:接收的字节数.
返回:
	实际读取的字符数。

初次使用树莓派串口编程,需要配置。

/* 修改 cmdline.txt文件 */
cd /boot/
sudo vim cmdline.txt
删除【】之间的部分
dwc_otg.lpm_enable=0 【console=ttyAMA0,115200】 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

/*修改 inittab文件 */
cd /etc/
sudo vim inittab
注释掉最后一行内容:,在前面加上 # 号
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
sudo reboot 重启

串口通信编程

串口通信代码

#include<stdio.h>
#include<wirtingPi.h>
#include<wiringSerial.h>

int main()
{
    int fd;
    
    if((wiringPiSetup())<0)  //初始化树莓派引脚
    {
         return 1;
    }

    if((fd=serialOpen("/dev/ttyAMA0",115200))<0)  //打开并初始串口 
        ///dev/ttyAMA0 串口的地址,在Linux中就是设备所在的目录。
    {
         return 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<stdio.h>
#include<wirtingPi.h>
#include<wiringSerial.h>

int main()
{
    int fd;
    int cmd;
    
    if((wiringPiSetup())<0)  //初始化树莓派引脚
    {
         return 1;
    }

    if((fd=serialOpen("/dev/ttyAMA0",115200))<0)  //打开并初始串口 
        ///dev/ttyAMA0 串口的地址,在Linux中就是设备所在的目录。
    {
         return 1;
    }
    while(1){
       while(serialDataAvail (fd) != -1){ //获取串口缓存中可用的字节数。串口缓存中已经接收的,可读取的字节数,-1代表错误
             cmd = serialGetchar (fd);  //从串口读取一个字节数据返回。如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1,所以,在读取前,做好通过serialDataAvail判断下。
             printf("get data:cmd=%d\n",cmd);
       }
       
    }
    serialClose (fd);
    return 0;
}

接下来我们简单使用一下语音模块

使用树莓派和语音模块实现语音识别功能

树莓派和语音模块接线图
在这里插入图片描述

树莓派串口接收语音模块信息代码

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<wiringPi.h>
#include<wiringSerial.h>

int main()
{
  int fd;
  char cmd[128]={'\0'}; 
  int n_read;

  if(wiringPiSetup()<0){
       return 1;
  }
  
  if((fd = serialOpen("/dev/ttyAMA0",9600))<0){
       return 1;
  }
  while(1){
       n_read=read(fd,cmd ,sizeof(cmd));
       if(strlen(cmd)== 0){   //收到的字符长度=0 ,就打印超时,并且等待。
          printf("chaoshi\n");
          continue;
       }
       printf("getData: %d byte ,context:%s\n",n_read,cmd);
       memset(cmd,'\0',sizeof(cmd)/sizeof(char));
  }
  return 0;
}

语音模块部分代码
在这里插入图片描述
对语音模块说话:极cc 它会反馈读到6个字节,内容不显示
在这里插入图片描述
对语音模块说话:极cc 打开灯 /关闭灯
在这里插入图片描述

结果把12字节拆分成了两次,我们本想它读128个字节,结果显示只要超过8个字节,就拆分。

我们来改变一下代码

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<wiringPi.h>
#include<wiringSerial.h>

int main()
{
  int fd;
  char cmd[128]={'\0'}; 
  int n_read;

  if(wiringPiSetup()<0){
       return 1;
  }
  
  if((fd = serialOpen("/dev/ttyAMA0",9600))<0){
       return 1;
  }
  while(1){
       n_read=read(fd,cmd ,sizeof(cmd));
       if(strlen(cmd)== 0){   //收到的字符长度=0 ,就打印超时,并且等待。
          printf("chaoshi\n");
          continue;
       }
       if(strstr(cmd,"open" != NULL)){
              printf("open light\n");
       }
       
       if(strstr(cmd,"close" != NULL)){
              printf("close light\n");
       }
       
       memset(cmd,'\0',sizeof(cmd)/sizeof(char));
  }
  return 0;
}

对语音模块说话:极cc 打开灯 /关闭灯
在这里插入图片描述这样就实现了全部字符串显示

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值