树莓派基础之外设开发编程

news/2024/10/17 18:20:07/

外设开发篇

  • 一、树莓派外设开发接口
  • 二、树莓派wiringPi库
  • 三、树莓派控制继电器
  • 四、继电器组硬件控制开发
  • 五、超声波模块介绍
  • 六、串口通信协议概述
  • 七、树莓派和语音模块的综合应用

一、树莓派外设开发接口

树莓派的接口

对主控芯片来说有:
IO口(输入输出口):input output
Input:人体,烟雾,火焰,震动
Output:继电器,蜂鸣器

PWM(增强性IO口):电机调速,灯光调明亮度
其他串口:
uart,IIC,SPI,IIS
其他特定硬件接口:
flash

还有像树莓派一样要跑操作系统的芯片:
Nanopi:linux
S3c2410 2440 6410
Tiny210 tiny4412
海思方案,瑞芯微方案,移远方案
带有操作系统的芯片一般都会讲到驱动

不带操作系统的芯片:
C51,STM32,Arduino,WemosD1:没用OS(linux)

二、树莓派wiringPi库

1)树莓派的wiringPi库:
wiringPi库就好比 linux的动态库.so,静态库.a
也好比C语言里面的include<stdio.h> 的标准库
wiringPi库里面的API就好比include<stdio.h>里面的printf

2)wiringPi库不是树莓派自带的,是特定平台,特定功能的接口库。也就是别人已经给你封装好了,直接调用库里面的API就行,记得编译的时候要带 -lwiringPi

3)检查一下树莓派是否有下载这个wiringPi库:

gpio -v

在这里插入图片描述

4)硬件初始化,wiringPiSetup函数:

#include<wiringPi.h>
#include<stdio.h>
int main()
{int ret;ret = wiringPiSetup();if(ret == -1){printf("初始化失败!\n");return -1;}return 0;
}

在这里插入图片描述

5)树莓派wiringPi库参考博文

三、树莓派控制继电器

1)先查看下树莓派板上信息:

gpio readall

在这里插入图片描述
2)继电器的接口有三个,GND,IN,VCC
它的驱动电压是3.3v
所以正极(VCC) 接树莓派的3.3v
接地(GND) 接树莓派的0v
信号传输(IN)接 gpio口

接好后写代码:

#include<wiringPi.h>
#include<stdio.h>#define SWITCHER 7
int main()
{int cmd;if(wiringPiSetup() == -1){printf("初始化失败!\n");return -1;}pinMode(SWITCHER,OUTPUT);digitalWrite(SWITCHER,HIGH);while(1){printf("请输入0/1:0-断开开关,1-导通开关!\n");scanf("%d",&cmd);getchar();if(cmd == 1){digitalWrite(SWITCHER,LOW);}else if(cmd == 0){digitalWrite(SWITCHER,HIGH);}cmd = 10;}return 0;
}

运行结果可以:
在这里插入图片描述

四、继电器组硬件控制开发

1)树莓派和继电器组的接线:
在这里插入图片描述
VCC正极接 5V
GND接地接 0V
IN1-IN4(信号) 接 GPIO.29 - GPIO.26

2)写代码测试下:

#include<wiringPi.h>
#include<stdio.h>
#include<string.h>#define  SWI1 29
#define  SWI2 28
#define  SWI3 27
#define  SWI4 26int main()
{char cmd[12] = {'\0'};if(wiringPiSetup() == -1){printf("初始化失败!\n");return -1;}pinMode(SWI1,OUTPUT);pinMode(SWI2,OUTPUT);pinMode(SWI3,OUTPUT);pinMode(SWI4,OUTPUT);digitalWrite(SWI1,HIGH);digitalWrite(SWI2,HIGH);digitalWrite(SWI3,HIGH);digitalWrite(SWI4,HIGH);while(1){printf("请输入1-4 on/off 或者 all on/all off。off-断开开关,on-导通开关!\n");memset(&cmd,0,sizeof(cmd));gets(cmd);if(strcmp(cmd,"1 on") == 0){digitalWrite(SWI1,LOW);}else if(strcmp(cmd,"1 off") == 0){digitalWrite(SWI1,HIGH);}if(strcmp(cmd,"2 on") == 0){digitalWrite(SWI2,LOW);}else if(strcmp(cmd,"2 off") == 0){digitalWrite(SWI2,HIGH);}if(strcmp(cmd,"3 on") == 0){digitalWrite(SWI3,LOW);}else if(strcmp(cmd,"3 off") == 0){digitalWrite(SWI3,HIGH);}if(strcmp(cmd,"4 on") == 0){digitalWrite(SWI4,LOW);}else if(strcmp(cmd,"4 off") == 0){digitalWrite(SWI4,HIGH);}if(strcmp(cmd,"all on") == 0){digitalWrite(SWI1,LOW);digitalWrite(SWI2,LOW);digitalWrite(SWI3,LOW);digitalWrite(SWI4,LOW);       }else if(strcmp(cmd,"all off") == 0){digitalWrite(SWI1,HIGH);digitalWrite(SWI2,HIGH);digitalWrite(SWI3,HIGH);digitalWrite(SWI4,HIGH);}}return 0;
}                                

运行结果正常:
在这里插入图片描述

五、超声波模块介绍

在这里插入图片描述

超声波传感器模块上通常有两个超声波元器件,一个用于发射,一个用于接收。电路板上有4个引脚:VCC(正极),Trig(触发),Echo(回应),GND(接地),主要参数:

工作电压与电流:5V,15mA
感测距离:2-400cm
感测角度:不大于15°
被测物的面积不要小于50cm²,并且尽量平整
具备温度补偿电路

在超声波模块的触发脚位输入10微秒以上的高电位,即可发射超声波,发射超声波之后,与接收到传回的超声波之前,“脚位” 呈现高电位。因此,程序可从 “响应” 脚位的高电位脉冲持续时间,换算出被测物的距离。

在这里插入图片描述
参考博文

写代码前,想了解下需要用到的函数:

1)pinmode

void pinMode (int pin, int mode)

pin:配置的引脚
mode:指定引脚的IO模式
可取的值:INPUT、OUTPUT、PWM_OUTPUT,GPIO_CLOCK
作用:配置引脚的IO模式

注意:
只有wiringPi 引脚编号下的1脚(BCM下的18脚) 支持PWM输出

只有wiringPi编号下的7(BCM下的4号)支持GPIO_CLOCK输出

2)digitalWrite

void digitalWrite (int pin, int value)

pin:控制的引脚
value:引脚输出的电平值。

可取的值:HIGH,LOW分别代表高低电平
让对一个已近配置为输出模式的 引脚 输出指定的电平信号

3)digitalRead

int digitalRead (int pin)

pin:读取的引脚

返回:引脚上的电平,可以是LOW HIGH 之一
读取一个引脚的电平值 LOW HIGH ,返回
返回值也可以是1 / 0(当输入信号电压在0~1.16 V时该函数返回0,当输入信号在1.83~3.3 V时返回1。如果输入电压在1.16~1.83 V之间不确定会返回0还是1。)

4)delayMicroseconds

delayMicroseconds (unsigned int howLong)

将线程暂停指定的微秒数(1000微妙=1毫秒=0.001s),因为Linux是多线程的,所以实际暂停的秒数可能比设置的更多一些

5)gettimeofday

gettimeofday(struct timeval *, struct timezone *);

这个函数函数返回的是1970年0:00:00到现在经过的秒数,函数的正常传入时需要用到两个参数。功能是得到当前时间和时区,分别写到tv和tz中,如果tz为NULL则不向tz写入。

6)struct timeval结构体

#include <sys/time.h>struct timeval{time_t tv_sec;  //Seconds. suseconds_t tv_usec;  //Microseconds. };

这个结构体也是linux内核中的,直接调用就好了,接的包含头文件。tv_sec为Epoch到创建struct timeval时的秒数,tv_usec为微秒数,即秒后面的零头。

7)代码:

#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>#define Trig    7  
#define Echo    0  void CSBInit(void)
{pinMode(Echo, INPUT);  //设置端口为输入pinMode(Trig, OUTPUT);  //设置端口为输出
}float disMeasure(void)
{struct timeval tv1;  //timeval是time.h中的预定义结构体 其中包含两个一个是秒,一个是微秒/*struct timeval{time_t tv_sec;  //Seconds. suseconds_t tv_usec;  //Microseconds. };*/struct timeval tv2;long start, stop;float dis;digitalWrite(Trig, LOW);delayMicroseconds(2);digitalWrite(Trig, HIGH);delayMicroseconds(10);      //发出超声波脉冲  digitalWrite(Trig, LOW);while(!(digitalRead(Echo) == 1));gettimeofday(&tv1, NULL);           //获取当前时间 开始接收到返回信号的时候 while(!(digitalRead(Echo) == 0));gettimeofday(&tv2, NULL);           //获取当前时间  最后接收到返回信号的时候start = tv1.tv_sec * 1000000 + tv1.tv_usec;   //微秒级的时间  stop  = tv2.tv_sec * 1000000 + tv2.tv_usec;dis = (float)(stop - start) / 1000000 * 34000 / 2;  //计算时间差求出距离  return dis;
}
int main(void)
{float dis;if(wiringPiSetup() == -1){ //如果初始化失败,就输出错误信息 程序初始化时务必进行printf("setup wiringPi failed !");return 1;}CSBInit();while(1){dis = disMeasure();printf("distance = %0.2f cm\n",dis);delay(1000);}return 0;
}

运行结果:
在这里插入图片描述
根据返回的秒数计算出微秒数
start = tv1.tv_sec * 1000000 + tv1.tv_usec;

stop = tv2.tv_sec * 1000000 + tv2.tv_usec;

我们知道 timeval结构体中含有两个变量,tv_sec表示的是秒数,1秒=1000000微妙,第二个参数tv_usec表示的就是微秒数,所以通过这两个式子我们就求出了开始和结束时的微秒数,然后做差即可得到超声波传递所使用的时间

根据时间计算距离
(stop - start) / 1000000 * 34000 / 2

因为stop和start原本表示的微妙,所以做差之后处1000000换算回是多少秒。因为声音在物质中的传播受到物质材质的影响,这里我们暂且不考虑介质的种类,默认为声音是在空气中传播,所以取声音的速度为340m/s=34000cm/s,因为超声波测距的误差较小的范围200-300cm,所以我们这里计算速度时用cm表示。

六、串口通信协议概述

1.串口通信
a)串口通信适用于多机通信

b)串口通信是通信方式属于全双工的(两个人互相骂)

c)串口通信关心的是数据格式波特率
数据格式:数据位,停止位,奇偶效验位

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

a)修改cmdline.text文件

sudo vi /boot/cmdline.txt

b)进入后修改删除红色括号的内容:
在这里插入图片描述

2.串口通信编程:
因为Linux一切皆文件,所以串口也是以文件的方式存放在树莓派中,所以我们调用串口通信的函数要包含头文件include<wiringSerial.h>

串口通信的函数有很多,我们实现简单的串口通信编程,要用到以下函数:

1)

int serialOpen (char *device, int baud)

device:串口的地址,在Linux中就是设备所在的目录。
默认一般是"/dev/ttyAMA0",我的是这样的。

baud:波特率
返回:正常返回文件描述符,否则返回-1失败。

功能:打开并初始串口

2)

void serialClose (int fd)

fd:文件描述符
功能:关闭fd关联的串口

3)

int   serialDataAvail (int fd)

fd:文件描述符
返回:串口缓存中已经接收的,可读取的字节数,-1代表错误

功能:获取串口缓存中可用的字节数。

4)

void  serialPuts (int fd, char *s)

fd:文件描述符
s:发送的字符串,字符串要以’\0’结尾

功能:发送一个字符串到串口

5)

int serialGetchar (int fd)

fd:文件描述符
返回:读取到的字符

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

6)

void  serialPutchar (int fd, unsigned char c)

fd:文件描述符
c:要发送的数据

功能:发送一个字节的数据到串口

7)

size_t read(int fd,void * buf ,size_t count);

fd:文件描述符
buf:接受的数据缓存的数组
count:接收的字节数.
返回:实际读取的字符数。

这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>
当要接收的数据量过大时,wiringPi建议使用这个函数。

8)

size_t write (int fd,const void * buf,size_t count)

fd:文件描述符
buf:需要发送的数据缓存数组
count:发送buf中的前count个字节数据
返回:实际写入的字符数,错误返回-1

这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>
当要发送到的数据量过大时,wiringPi建议使用这个函数。

9)简单测试下:

#include<wiringPi.h>
#include<wiringSerial.h>int main()
{int fd;wiringPiSetup();fd = serialOpen("/dev/ttyAMA0",9600);while(1){serialPutchar(fd,'c');serialPuts(fd,"i am handsome\r\n");delayMicroseconds(1000000);}serialClose(fd);return 0;
}

运行结果:
在这里插入图片描述

10)

#include<wiringPi.h>
#include<wiringSerial.h>int main()
{int fd;int cmd;wiringPiSetup();fd = serialOpen("/dev/ttyAMA0",9600);while(1){while(serialDataAvail(fd) != -1){cmd = serialGetchar(fd);if(cmd == '2'){serialPuts(fd,"i am handsome2\r\n");}if(cmd == '3'){serialPuts(fd,"i am handsome3\r\n");}if(cmd == '4'){serialPuts(fd,"i am handsome4\r\n");}}}serialClose(fd);return 0;
}

运行结果:
在这里插入图片描述

七、树莓派和语音模块的综合应用

1)语音模块自身有源码,上次根据需求我们改了一些代码,实现的功能是当我们说开灯,语音模块识别后会往串口打印出相应的数据。
那么我们把语音模块连接树莓派,树莓派打开串口功能,当我们去给语音模块收到数据的时候,语音模块就会往树莓派的串口输入收到的数据,我们就可以通过树莓派串口打印出相应的数据。

2)树莓派和语音模块接线:
树莓派的TXD 接 语音模块的RXD
树莓派的RXD 接 语音模块的 TXD
树莓派的0V 接 语音模块的GND
树莓派的5v 接语音模块的5v

3)代码编程:

#include<stdio.h>
#include<wiringPi.h>
#include<wiringSerial.h>
#include<unistd.h>
#include<string.h>
int main()
{int fd;char cmd[128] = {'\0'};int nread;wiringPiSetup();fd = serialOpen("/dev/ttyAMA0",9600);if(fd == -1){printf("串口打开失败!\n");}while(1){nread =  read(fd,cmd,sizeof(cmd));if(strlen(cmd) == 0){printf("超时!\n");continue;}printf("读到%d个字节\n",nread);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;
}

http://www.ppmy.cn/news/662934.html

相关文章

新手入门树莓派必做的四件事

随着树莓派在国内的热度越来越高&#xff0c;现在已经有很多人开始接触树莓派了。对于新手&#xff0c;有四件必须完成的事&#xff1a; 为树莓派更换国内源。让Raspbian系统显示中文。安装中文输入法。调整树莓派的时区时间。 不过安装一个合适的系统才是这四件事的前提&…

Arduino和树莓派 对比

开始玩嵌入式&#xff0c;就无法绕开arduino和树莓派。 区别 树莓派和 Arduino 看起来很相似&#xff0c;都是带控制功能的小型电路板&#xff0c;但它们完全是属于两种不同的设备。 树莓派是基于微处理器的硬件平台&#xff0c;核心是 Broadcom ARM 架构 CPU&#xff0c;可…

树莓派能做什么呢?如何使用树莓派

我们知道树莓派是最常用的开发板&#xff0c;树莓派受欢迎的原因之一在于树莓派的功能非常全面&#xff0c;不论是做视频播放、音频播放等功能&#xff0c;树莓派都能派上用场。为增进大家对树莓派的认识&#xff0c;本文将带大家了解一下曾有人用树莓派做了什么。如果你对树莓…

新手玩硬件,买单片机还是树莓派?

对于电子爱好初学者来说&#xff0c;现在可供学习的电子技术太多了。没办法&#xff0c;电子技术的发展和其它行业一样&#xff0c;专业方向越来越多&#xff0c;也越来越精细。 以往像51这样的8位单片机打天下的时代早过去了&#xff0c;今天你耳朵里充斥的单片机已经是以32位…

树莓派能做什么?如何使用树莓派

我们知道树莓派是最常用的开发板&#xff0c;树莓派受欢迎的原因之一在于树莓派的功能非常全面&#xff0c;不论是做视频播放、音频播放等功能&#xff0c;树莓派都能派上用场。为增进大家对树莓派的认识&#xff0c;本文将带大家了解一下曾有人用树莓派做了什么。如果你对树莓…

新手选 Arduino 还是 树莓派?

参考来源 | 奇异思维 01 前言 Arduino 和 树莓派 都是电子、嵌入式工程师比较熟悉的两类开发板&#xff0c;也是很多新手都会考虑的开发板。 究竟该选择 Arduino 还是 树莓派&#xff1f; 02 背景 Arduino诞生于意大利。它的发明者马西莫班齐和联合创始人在一个酒吧想到了这个…

人穷志不短,穷学生也能玩转树莓派

人穷志不短&#xff0c;穷学生也能玩转树莓派 我致力于用人类能听懂的语言向大众科普人工智能前沿科技并帮助初学者快速上手开发实践应用。目前正在制作《说人话的人工智能视频教程》、《零基础入门树莓派趣味编程》等视频教程。 必备物品 必备物品是实现树莓派核心功能必不可…

【树莓派初始化】教你从0开始搭建树莓派的使用环境

文章目录 前言1.什么是树莓派&#xff1f;1.1什么用户适合购买树莓派学习编程&#xff1f; 2.如何初始化一个树莓派2.1 烧录系统2.2 测试开机2.3 设置树莓派显示输出的分辨率2.4 网络链接2.5 Putty链接树莓派2.6 VNC链接树莓派2.7 使用filezilla软件传输文件到树莓派 3.使用Xsh…