Linux应用开发-6-GPIO系统控制蜂鸣器
General Purpose I/O(通用输入输出端口),MCU/CPU 可控制的引脚,基本的是高低电平输入检测和输出。
GPIO 设备目录
GPIO 驱动子系统导出到用户空间的目录是“/sys/class/gpio”
#export: 导出 GPIO(只写的控制文件)。向它写入 GPIO 编号可以请求内核将该 GPIO 的控制权“导出”到用户空间。
#unexport: 取消导出 GPIO(只写的控制文件)。向它写入 GPIO 编号可以请求内核收回该 GPIO 的控制权,用户空间将无法再操作它。
ls -l /sys/class/gpio #查看当前 GPIO 控制接口的状态
#==================================================================================
#请求内核允许用户空间控制 GPIO 编号为 45 的引脚
echo 45 > /sys/class/gpio/export
#流程如下:
#检查系统中是否存在编号为 45 的 GPIO
#有效且可用,内核就会在 `/sys/class/gpio/` 目录下创建一个新的子目录,通常命名为 gpio45
#在这个新创建的 gpio45 目录中,内核会自动生成一系列属性文件
#总节:要求系统“把第 45 号 GPIO 的控制开关和状态指示灯暴露给用户”
#==================================================================================
#将 gpio45 从用户空间中取消导出
echo 45 > /sys/class/gpio/unexport
GPIO 设备属性

注:/的作用=>列出这个目录里面的内容,而不是这个目录本身的信息
属性文件:
- direction 文件:表示 GPIO 引脚的方向
- in将 GPIO 引脚配置为输入模式。
- out将 GPIO 引脚配置为输出模式,内核默认会将引脚的初始输出电平设置为低电平(0)。
- low(1.将 GPIO 引脚配置为输出模式 2.立即将引脚的输出电平设置为低电平(0))。
- high(1.将 GPIO 引脚配置为输出模式 2.立即将引脚的输出电平设置为高电平(1))。
- value 文件:表示 GPIO 的电平,1 表示高电平,0 表示低电平,当GPIO 被配置为输出模式,那
么修改该文件的内容可以改变引脚的电平。 - edge 文件:用于配置 GPIO 的中断触发方式,当 GPIO 被配置为中断时,可以通过系统的poll 函数监听。、
- none:没有使用中断模式。
- rising:表示引脚为中断输入模式,上升沿触发。
- 表示引脚为中断输入模式,下降沿触发。
- 表示引脚为中断输入模式,边沿触发。
说明:GPIO 子系统的设备则可以在用户空间灵活配置作为输入、输出或中断模式。只要我们知道一个设备(例如蜂鸣器)的 GPIO 引脚编号,就可以就可以通过它导出的 direction、value 文件控制引脚输出高低电平,从而控制它。
引脚编号转换
使用 GPIO 子系统时,需要用户自主控制导出使用哪个引脚,观察引脚并进行计算。

蜂鸣器的控制引脚名为“PC13”,该引脚输出高电平时,三极管导通,蜂鸣器响,引脚输出低电平时,电路断开,蜂鸣器不响。
文件使用的编号 index 与 GPIO 引脚名的转换关系:index = Pnx = (n-‘A’)*16 + x ==>PC13=(“C”-“A”)*16+13=45
标题(Shell端)控制蜂鸣器
# 请求内核允许用户空间控制 GPIO 编号为 45 的引脚
echo 45 > /sys/class/gpio/export
#查看gpio45设备是否导入到用户目录,供用户调用
ls /sys/class/gpio/
# 控制 gpio45 方向为输出
echo out > /sys/class/gpio/gpio45/direction
# 控制 gpio45 输出高电平
echo 1 > /sys/class/gpio/gpio45/value
# 控制 gpio45 输出低电平
echo 0 > /sys/class/gpio/gpio45/value
(系统调用)控制蜂鸣器
头文件 includes/bsp_beep.h
#ifndef BSP_BEEP_H
#define BSP_BEEP_H
// 定义蜂鸣器对应的GPIO编号PC13=(2)*16+13
#define BEEP_GPIO_INDEX "45"
// 头文件让 main.c 知道 bsp_beep.c 中有哪些函数可用,以便main函数编译通过
int beep_init(void); //初始化蜂鸣器 (导出GPIO并设置为输出)
int beep_deinit(void); //释放蜂鸣器 (取消导出GPIO)
int beep_on(void); //打开蜂鸣器
int beep_off(void); //关闭蜂鸣器#endif // BSP_BEEP_H
注:C语言使用 #include 来共享全局定义(直接用),而C++则更进一步,使用 class::name 这样的方式将变量和函数组织在类或命名空间中。
(蜂鸣器驱动文件)bsp_beep.c
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "includes/bsp_beep.h"int beep_init(void)
{int fd;// 1. 导出GPIOfd = open("/sys/class/gpio/export", O_WRONLY); if(fd < 0)return 1;//echo BEEP_GPIO_INDEX > /sys/class/gpio/exportwrite(fd, BEEP_GPIO_INDEX, strlen(BEEP_GPIO_INDEX)); close(fd); // 2. 配置GPIO方向为 "out" (输出)fd = open("/sys/class/gpio/gpio" BEEP_GPIO_INDEX "/direction", O_WRONLY); if(fd < 0)return 2; //echo out > /sys/class/gpio/gpio45/directionwrite(fd, "out", strlen("out")); close(fd); return 0;
}int beep_deinit(void)
{int fd;fd = open("/sys/class/gpio/unexport", O_WRONLY);if(fd < 0)return 1; //echo 45 > /sys/class/gpio/unexportwrite(fd, BEEP_GPIO_INDEX, strlen(BEEP_GPIO_INDEX));close(fd);return 0;
}int beep_on(void)
{int fd;fd = open("/sys/class/gpio/gpio" BEEP_GPIO_INDEX "/value", O_WRONLY);if(fd < 0)return 1;//echo 1 > /sys/class/gpio/gpio45/valuewrite(fd, "1", 1);close(fd);return 0;
}int beep_off(void)
{int fd;fd = open("/sys/class/gpio/gpio" BEEP_GPIO_INDEX "/value", O_WRONLY);if(fd < 0)return 1;//echo 0 > /sys/class/gpio/gpio45/valuewrite(fd, "0", 1);close(fd);return 0;
}
main 函数,它调用 bsp_beep.c 中封装好的函数
#include <stdio.h>
#include <unistd.h>
#include "includes/bsp_beep.h"int main(int argc, char *argv[])
{//保护,最高获取10个字符。但是只接受第一个字符char buf[10];printf("This is the beep demo\n"); // 初始化蜂鸣器res = beep_init();if(res){ printf("beep init error,code = %d",res); return 0;}// 进入主循环while(1){ printf("Please input the value : 0--off 1--on q--exit\n");scanf("%10s", buf);// 根据用户输入执行不同操作switch (buf[0]){ case '0': beep_off(); break; case '1': beep_on();break;case 'q': beep_deinit(); printf("Exit\n");return 0; default:break; }}
}
利用编译器在虚拟机进行编译,-Idrivers如果代码里有 #include “…”,请你也到 drivers 这个子文件夹里去找一找
arm-none-linux-gnueabihf-gcc -o beep main.c bsp_beep.c
通过文件系统进行挂载就可以在硬件进行编译了
sudo mount -t nfs -o nolock 192.168.137.3:/home/wang/arm_projects /mnt/host_projects
