03-树莓派基本外设控制

前言

树莓派作为一款受欢迎的微型计算机主板,凭借其丰富的外设接口、强大的处理能力和开源的生态系统,成为了学习嵌入式系统开发、物联网(IoT)应用的理想平台。本文通过介绍控制部分设备学习树莓派

树莓派外设开发

树莓派的外设开发涉及到通过其GPIO(通用输入输出)引脚与外部设备进行交互。这些设备包括但不限于LED灯、传感器、电机驱动器等。为了有效地进行外设开发,首先需要熟悉树莓派的硬件规格,包括其GPIO引脚的功能分配、电流限制等。

树莓派的接口

GPIO通用输入输出

  • Input
    • 输入设备如: 人体传感器、烟雾、火焰等
  • output
    • 输出设备如:继电器、蜂鸣器等

其他接口

  • PWM:可调节占空比的方波
  • 串口uart:
  • IIC
  • SPI
  • IIS
  • 其他特定硬件接口(flash等)

wiringPi库

wiringPi库是常用的IO控制库,使用C语言进行开发的,提供了丰富的接口:GPIO控制、中断、多线程等等。

安装wiringPi

  1. 判断是否已经安装wiringPi库
    • 使用命令gpio -v如果出现版本则已安装
    • 使用gpio readall 如果出现引脚标识则已安装
  2. 安装wiringPi
    • 在安装前需要确保你的树莓派连接到了网络,并且已经安装了git工具包,可以使用命令:sudo apt-get install git-core安装git工具
    • 使用git clone https://github.com/WiringPi/WiringPi获取到github中最新源代码
    • 进入wiringPi目录cd wiringPi
    • 执行./build编译安装wiringPi库
  3. 使用gpio readall查看效果
    在这里插入图片描述

wiringPi的常用函数

初始化函数

使用wiringPi时,你必须在执行任何操作前初始化树莓派,否则程序不能正常工作。
可以调用下表函数之一进行初始化,它们都会返回一个int , 返回 -1 表示初始化失败。

函数状态描述
int wiringPiSetup (void)返回:执行状态,-1表示失败当使用这个函数初始化树莓派引脚时,程序使用的是wiringPi 引脚编号表。引脚的编号为 0~16需要root权限
int wiringPiSetupGpio (void)返回执行状态,-1表示失败当使用这个函数初始化树莓派引脚时,程序中使用的是BCM GPIO 引脚编号表。需要root权限
wiringPiSetupPhys(void)不常用,不做介绍\
wiringPiSetupSys (void) ;不常用,不做介绍\
通用GPIO控制函数
函数状态描述
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输出
void digitalWrite (int pin, int value)pin:控制的引脚 value:引脚输出的电平值。 可取的值:HIGH,LOW分别代表高低电平让对一个已近配置为输出模式的 引脚 输出指定的电平信号
int digitalRead (int pin)pin:读取的引脚 返回:引脚上的电平,可以是LOW HIGH 之一读取一个引脚的电平值 LOW HIGH ,返回
void analogWrite(int pin, int value)pin:引脚 value:输出的模拟量模拟量输出 树莓派的引脚本身是不支持AD转换的,也就是不能使用模拟量的API, 需要增加另外的模块
int analogRead (int pin)pin:引脚 返回:引脚上读取的模拟量模拟量输入 树莓派的引脚本身是不支持AD转换的,也就是不能使用模拟量的API 需要增加另外的模块
void pwmWrite (int pin, int value)pin:引脚 value:写入到PWM寄存器的值,范围在0~1024之间输出一个值到PWM寄存器,控制PWM输出。 pin只能是wiringPi 引脚编号下的1脚(BCM下的18脚)
void pullUpDnControl (int pin, int pud)pin:引脚 pud:拉电阻模式 可取的值:PUD_OFF 不启用任何拉电阻。关闭拉电阻。 PUD_DOWN 启用下拉电阻,引脚电平拉到GND PUD_UP 启用上拉电阻,引脚电平拉到3.3v对一个设置IO模式为 INPUT 的输入引脚设置拉电阻模式。与Arduino不同的是,树莓派支持的拉电阻模式更丰富。树莓派内部的拉电阻达50K欧姆

wiringPi的基本使用

在使用wiringPi进行开发时,需要包含头文件 #include<wiringPi.h>。凡是写wiringPi的程序,都包含这个头文件。
随后通过命令gcc xxx.c -lwiringPi进行程序的编译

控制继电器

继电器介绍

继电器是一种电子控制器件,它具有控制系统(又称输入回路)和被控制系统(又称输出回路),通常应用于自动控制电路中,它实际上是用较小的电流去控制较大电流的一种“自动开关”。

操作继电器

硬件接线

三个引脚就可以控制继电器,VCC、GND和一个IO口就可以了。

GND
VCC
GPIO.7
继电器
树莓派

代码编写

代码分为初始化,判断,控制

Created with Raphaël 2.3.0 开始 初始化WiringPi 初始化成功? 输入命令 判断命令? 执行命令 结束 yes no yes

代码如下:

#include <wiringPi.h>
#include <stdio.h>

#define SWITCHER 7

int main()
{
        int cmd = 0;
        // 初始化
        if(-1 == wiringPiSetup())
        {
                printf("初始化失败\n");
                return -1;
        }
        pinMode(SWITCHER,OUTPUT);

        while(1)
        {
                printf("请输入命令值(0,:关闭1,:打开)->\n");
                scanf("%d",&cmd);
                getchar();
                if(cmd == 0)
                {
                        digitalWrite(SWITCHER,HIGH);
                }else if(cmd == 1)
                {
                        digitalWrite(SWITCHER,LOW);
                }
                else
                {
                        printf("输入有误\n");
                }

        }

        return 0;
}

代码运行结果,当我们编译运行这个代码时,我们可以通过输入1或者0,控制GPIO.7口的电平进而控制继电器的开关
在这里插入图片描述
引脚状态如下:在这里插入图片描述
实现了一个寄存器的控制后,当我们拿到一个寄存器组的时候,也是一样的使用了。

超声波测距实验

HC-SR04超声波模块

在这里插入图片描述
超声波测距模块是根据超声波遇障碍反射的原理进行测距的,能够发送超声波、接收超声波并通过处理,输出一段和发送与接收间隔时间相同的高电平信号,是常用的测距模块之一。HC-SR04是最常用的超声波测距模块之一,HC-SR04超声波模块可提供2cm~400cm的非接触式距离感测功能,测距精度可达3mm,工作电压为5V;内部模块包括超声波发射器、接收器与控制电路。

超声波测距原理

让它发送波:给Trig端口至少10us的高电平

开始发送波:Echo信号由低电平跳转到高电平

接收返回波:Echo信号由高电平跳转回低电平

计算时间:Echo引脚维持高电平的时间!
开始发送波,启动定时器,接收到返回波,停止计时器

计算距离:测试距离=(高电平时间*声速(340m/s))/2

时序图

在这里插入图片描述

代码实现

时间函数gettimeofday()

在c语言中,可以使用函数gettimeofday(),获取到精确的时间。他的精度可以到微妙,是c语言的标准库

函数原型
#include <sys/time.h>
int gettimeofday(struct timeval *restrict tv,
                 struct timezone *_Nullable restrict tz);
int settimeofday(const struct timeval *tv,
                 const struct timezone *_Nullable tz);

在man手册中的解释如下:

The tv argument is a struct timeval (as specified in <sys/time.h>):

           struct timeval {
               time_t      tv_sec;     /* seconds */
               suseconds_t tv_usec;    /* microseconds */
           };

       and gives the number of seconds and microseconds since the Epoch (see time(2)).

       The tz argument is a struct timezone:

           struct timezone {
               int tz_minuteswest;     /* minutes west of Greenwich */
               int tz_dsttime;         /* type of DST correction */
           };

gettimeofday()会把目前的时间用tv 结构体返回,当地时区的信息则放到tz所指的结构中

在gettimeofday()函数中tv或者tz都可以为空。如果为空则就不返回其对应的结构体。
函数执行成功后返回0,失败后返回-1,错误代码存于errno中。

使用方法
  • 使用gettimeofday计算代码执行时长:
#include <sys/time.h>
 
struct timeval start,end;  
//timezone 参数若不使用则传入NULL即可.
gettimeofday(&start, NULL );  
//…executing…  
gettimeofday(&end, NULL );  
double timeuse = ( end.tv_sec - start.tv_sec ) + (end.tv_usec - start.tv_usec)/1000000.0;  
printf("time=%f\n",timeuse);  
  • 获取当前时间
#include <sys/time.h>
#include <time.h>
 
struct timeval now_time;
struct tm *p;
gettimeofday(&now_time, NULL);
p = gmtime(&now_time.tv_sec);        //借助强转,实际上now_time.tv_sec就是unix时间戳
printf("%d-%02d-%02d %02dh:%02dm:%02ds:%ldus\n", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec, now_time.tv_usec);

测距代码的实现

硬件接线
VCC
END
echo--GPIO.1
trig--GPIO.0
SR04
树莓派
启动流程图
Created with Raphaël 2.3.0 开始 初始化 初始化成功? 初始化SR04 测量距离 结束 yes no
源代码

hcse04.c

#include "hcsr04.h"
#include <stdio.h>
#include <wiringPi.h>
#include <sys/time.h>

#define TRIG 0
#define ECHO 1

void ultraInit(void)
{
        pinMode(TRIG,OUTPUT);
        pinMode(ECHO,INPUT);
}


float disMeasure(void)
{
        struct timeval tv1,tv2;
        float dis = 0.0;
        int differTimeus = 0;

        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);

        differTimeus = tv2.tv_sec * 1000000 + tv2.tv_usec - tv1.tv_sec * 1000000 - tv1.tv_usec;
        dis = (float)differTimeus * 0.034 / 2;
        return dis;
}

hcsr04.h


#define TRIG 0
#define ECHO 1

void ultraInit(void);
float disMeasure(void);

main.c

#include "hcsr04.h"
#include <stdio.h>
#include <wiringPi.h>
#include <time.h>

int main()
{
        float dis;
        if(wiringPiSetup() == -1)
        {
                printf("setup WiringPi  faild\n");
                return -1;
        }
        ultraInit();
        while(1)
        {
                dis = disMeasure();
                printf("距离:%.2f cm\n",dis);
                delay(500);
        }
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坏柠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值