树莓派开发(3)——树莓派外设开发

树莓派外设开发

转载:https://www.cnblogs.com/lulipro/p/5992172.html
作者:lulipro

一、树莓派wiringPi库详解

wiringPi是一个很棒的树莓派IO控制库,使用C语言开发,提供了丰富的接口:GPIO控制,中断,多线程,等等。

  1. wiringPi库安装
    因为树莓派镜像中自带wiringPi库,不用手动安装。如果没有手动安装。
    1.1 wiringPi的github (https://git.drogon.net/?p=wiringPi;a=summary) 下载安装包。点击页面的第一个链接的右边的snapshot,下载安装压缩包。
    1.2 然后进入安装包所在的目录执行以下命令:
    >tar xfz wiringPi-98bcb20.tar.gz   //98bcb20为版本标号,可能不同
    >cd wiringPi-98bcb20
    >./build
    
    1.3 验证wiringPi的是否安装成功,输入gpio -v,会在终端中输出相关wiringPi的信息。否则安装失败。
  2. 编译和运行
    2.1 假如你写了一个LEDtest.c 的项目,则如下。
    编译:gcc -o LEDtest LEDtest.c -lwiringPi //使用C语言编程
    运行:sudo ./LEDtest
  3. 查看引脚编号表格
    gpio readall

二、wiringPi库API大全

  1. 在使用wiringPi库时,你需要包含头文件 #include<wiringPi.h>。凡是写wiringPi的程序,都包含这个头文件。

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

    int wiringPiSetup (void)	
    //返回:执行状态,-1表示失败	
    //当使用这个函数初始化树莓派引脚时,程序使用的是wiringPi 引脚编号表。引脚的//编号为 0~16
    //需要root权限
    
    int wiringPiSetupGpio (void)	
    //返回执行状态,-1表示失败	
    //当使用这个函数初始化树莓派引脚时,程序中使用的是BCM GPIO 引脚编号表。
    //需要root权限
    
    wiringPiSetupPhys(void)	//不常用,不做介绍	 
    wiringPiSetupSys (void)	//不常用,不做介绍	 
    
  3. 通用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欧姆
    */
    
  4. 时间控制函数

    unsigned int millis (void)	
    /*这个函数返回 一个 从你的程序执行 wiringPiSetup  初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 毫秒数。
    返回类型是unsigned int,最大可记录 大约49天的毫秒时长。*/
    unsigned int micros (void)	
    /*这个函数返回 一个 从你的程序执行 wiringPiSetup  初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 微秒数。
    返回类型是unsigned int,最大可记录 大约71分钟的时长。*/
    void delay (unsigned int howLong)	
    /*将当前执行流暂停 指定的毫秒数。因为Linux本身是多线程的,所以实际暂停时间可能会长一些。参数是unsigned int 类型,最大延时时间可达49天*/
    void delayMicroseconds (unsigned int howLong)	
    /*将执行流暂停 指定的微秒数(1000微秒 = 1毫秒 = 0.001秒)。
    因为Linux本身是多线程的,所以实际暂停时间可能会长一些。参数是unsigned int 类型,最大延时时间可达71分钟*/
    
  5. 中断
    wiringPi提供了一个中断处理注册函数,它只是一个注册函数,并不处理中断。他无需root权限。

    int wiringPiISR (int pin, int edgeType,  void (*function)(void))	
    /*
    返回值:返回负数则代表注册失败
    pin:接受中断信号的引脚
    edgeType:触发的方式。
     INT_EDGE_FALLING:下降沿触发
     INT_EDGE_RISING:上升沿触发
     INT_EDGE_BOTH :上下降都会触发
     INT_EDGE_SETUP:编程时用不到。       
    function:中断处理函数的指针,它是一个无返回值,无参数的函数。
    注册的函数会在中断发生时执行
    和51单片机不同的是:这个注册的中断处理函数会和main函数并发执行(同时执行,谁也不耽误谁)
    当本次中断函数还未执行完毕,这个时候树莓派又触发了一个中断,那么这个后来的中断不会被丢弃,它仍然可以被执行。但是wiringPi最多可以跟踪并记录后来的仅仅1个中断,如果不止1个,则他们会被忽略,得不到执行。
    */
    
  6. 串口通信
    使用时需要包含头文件:#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,)	
    /*fd:文件描述符
    message:格式化的字符串
    像使用C语言中的printf一样发送数据到串口*/
    int   serialDataAvail (int fd)	
    /*fd:文件描述符
    返回:串口缓存中已经接收的,可读取的字节数,-1代表错误
     获取串口缓存中可用的字节数。*/
    int serialGetchar (int fd)	
    /*fd:文件描述符
    返回:读取到的字符
    从串口读取一个字节数据返回。
    如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1
    所以,在读取前,做好通过serialDataAvail判断下。*/
    void serialFlush (int fd)	
    /*fd:文件描述符
    刷新,清空串口缓冲中的所有可用的数据。*/
    *size_t write (int fd,const void * buf,size_t count)	
    /*fd:文件描述符
    buf:需要发送的数据缓存数组
    count:发送buf中的前count个字节数据
    返回:实际写入的字符数,错误返回-1
    这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>
    当要发送到的数据量过大时,wiringPi建议使用这个函数。*/
    *size_t read(int fd,void * buf ,size_t count);	
    /*fd:文件描述符
    buf:接受的数据缓存的数组
    count:接收的字节数.
    返回:实际读取的字符数。	
    这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>
    当要接收的数据量过大时,wiringPi建议使用这个函数。*/
    

三、程序源码

  1. IO口控制Beep蜂鸣器

    #include <wiringPi.h>
    #include <stdio.h>
    
    #define BEEP_PIN 7
    
    int main()
    {
    	int cmd=0;
    	wiringPiSetup();
    	pinMode(BEEP_PIN, OUTPUT);
    
    	digitalWrite(BEEP_PIN, HIGH);
    
    	while(1) {
    		printf("请输入控制开关,0-关,1-开\n");
    		scanf("%d",&cmd);
    		getchar();
    		printf("cmd = %d\n",cmd);
    		if(cmd == 1) {
    			digitalWrite(BEEP_PIN, LOW);
    		}
    		else if(cmd == 0){
    			digitalWrite(BEEP_PIN, HIGH);
    		}
    	}
    	return 0;
    }
    
  2. 超声波测距

    #include <stdio.h>
    #include <wiringPi.h>
    #include <unistd.h>
    #include <sys/time.h>
    #include <stdlib.h>
    
    #define ECHO 28  //0PIN
    #define TRIG 29	//1PIN
    
    double getDistance(void)
    {
    	double dis;
    	long time;
    	struct timeval start;
    	struct timeval stop;
    
    	digitalWrite (TRIG, LOW) ;	
    	usleep(20);
    	digitalWrite (TRIG, HIGH) ;
    	usleep(10);
    	digitalWrite (TRIG, LOW) ;
    
    	while(!digitalRead(ECHO));
    	gettimeofday(&start,NULL);
    	while(digitalRead(ECHO));
        gettimeofday(&stop,NULL);
    
    	time = 1000000*(stop.tv_sec - start.tv_sec) + (stop.tv_usec - start.tv_usec);
    	dis = (time/1000000.0)*340.0*100.0/2.0;
    
    	return dis;
    
    }
    
    int main (void)
    {
    	double dis;
    	wiringPiSetup () ;
    
    	pinMode (TRIG, OUTPUT) ;
    	pinMode (ECHO, INPUT) ;
    
    	while (1)
    	{
    		dis = getDistance();
    		printf("dis = %lf\n", dis);
    		sleep(1);
    	}
    
    	return 0;
    }
    
  3. 串口通信
    初次启动树莓派串口编程需要配置
    输入指令: sudo vi /boot/cmdline.txt
    树莓派的串口文件是/dev/ttyAMA0
    在这里插入图片描述

    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    #include <wiringPi.h>
    #include <wiringSerial.h>
    #include <pthread.h>
    #include <malloc.h>
    int fd;
    
    void *SendHandler()
    {
    	char *str;
    	str = (char *)malloc(128*sizeof(char));
    	
    	while(1) {
    		memset(str, '\0', 128*sizeof(char));
    		scanf("%s",str);
    	
    		while(*str) {
    			serialPutchar (fd, *str) ;
    			str++;
    		}
    	}
    }
    
    void *RevHandler()
    {
    	while(1) {
    		while (serialDataAvail (fd))
      	  {
         	 printf ("%c", serialGetchar (fd)) ;
        	}
    	}
    }
    
    int main ()
    {
    	pthread_t send_t;
    	pthread_t rev_t;
    
      if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0)
      {
        fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
        return 1 ;
      }
    
      if (wiringPiSetup () == -1)
      {
        fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
        return 1 ;
      }
    
    	pthread_create(&send_t, NULL, SendHandler, NULL);
    	pthread_create(&rev_t, NULL, RevHandler, NULL);
    
        while (1)
    	{
    	 //	usleep(1000);	
    	}
    
      return 0 ;
    }
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值