当前位置: 首页 > news >正文

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

http://www.dtcms.com/a/553004.html

相关文章:

  • LeetCode 刷题【140. 单词拆分 II】
  • 网站开发 犯法网站漏洞扫描工具
  • 漏洞修复学习之CVE-2023-38545漏洞复现与修复
  • 逻辑回归特征重要性排序实验报告:不同特征选择方法的排序一致性验证
  • 深入解析MySQL(6)——存储过程、游标与触发器
  • Linux操作系统学习之---线程池
  • 做网站 免费字体wordpress的slider
  • “十五五”规划前瞻:短剧小程序系统开发的技术浪潮与开发新机遇
  • Rust开发之使用 Trait 定义通用行为——实现形状面积计算系统
  • 解决小程序滚动穿透问题
  • 《风格锚点+动态适配:Unity跨设备渲染的核心逻辑》
  • Unity与iOS原生交互开发入门篇 - 调用iOS的Alert
  • 旧物二手回收小程序:引领绿色消费,开启时尚生活新方式
  • LeetCode 3289.数字小镇中的捣蛋鬼:哈希表O(n)空间 / 位运算O(1)空间
  • Cargo深度解析:Rust的构建系统与包管理器
  • 站长之家官网php做的网站如何运行
  • Bayes/BO-CNN-LSTM、CNN-LSTM、LSTM三模型多变量回归预测Matlab
  • # AI时代的人机交互写作:从方法论框架搭建到实践探索
  • 【fixchart】【来学习基于Mermaid语法生成“流程图”】
  • 解决小程序样式隔离styleIsolation
  • 改变世界的编程语言MoonBit:配置系统介绍(下)
  • mip网站推广普通话宣传周活动方案
  • EL(F)K日志分析系统
  • 算法题——图论
  • AutoCAD开发:主流语言与实用插件精选
  • 余姚响应式网站建设做个网站应该怎么做
  • Docker 日志管理实战:轻松掌控容器输出
  • 移动端h5适配方案
  • 【雅思备考】雅思写作笔记
  • 亚马逊产品备案网站建设要求域名不变修改网站怎么做