IO口操控代码

我们在编写驱动程序的时候,IO空间的起始地址是0x3f000000,加上GPIO的偏移量0x2000000,所以GPIO的物理地址应该是从0x3f200000开始的,然后在这个基础上进行Linux系统的MMU内存虚拟化管理,映射到虚拟地址上。

底层驱动代码

#include <linux/fs.h>            //file_operations声明
#include <linux/module.h>    //module_init  module_exit声明
#include <linux/init.h>      //__init  __exit 宏定义声明
#include <linux/device.h>        //class  devise声明
#include <linux/uaccess.h>   //copy_from_user 的头文件
#include <linux/types.h>     //设备号  dev_t 类型声明
#include <asm/io.h>          //ioremap iounmap的头文件static struct class *pin4_class;
static struct device *pin4_class_dev;static dev_t devno;                //设备号
static int major =231;                     //主设备号
static int minor =0;                       //次设备号
static char *module_name="pin4";   //模块名volatile unsigned int* GPFSEL0 = NULL;
volatile unsigned int* GPSET0   = NULL;
volatile unsigned int* GPCLR0   = NULL;
//这三行是设置寄存器的地址,volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{printk("pin4_open\n");  //内核的打印函数和printf类似*GPFSEL0 &=~(0x6<<12);*GPFSEL0 |=(0x1<<12);//把bit14,bit13配置成0//配置pin4引脚为输出引脚,bit 12~14配置成100return 0;
}
//read函数
static int pin4_read(struct file *file,char __user *buf,size_t count,loff_t *ppos)
{printk("pin4_read\n");  //内核的打印函数和printf类似return 0;
}//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{int usercmd;printk("pin4_write\n");  //内核的打印函数和printf类似//获取上层write函数的值copy_from_user(&usercmd,buf,count);//根据值来操作io口,高电平或者低电平if (usercmd==1){printk("set 1\n");*GPSET0 |=(0x1 <<4);}else if(usercmd==0){printk("set 0\n");* GPCLR0 |=(0x1<<4); }else{printk("do nothing\n");}return 0;
}static struct file_operations pin4_fops = {.owner = THIS_MODULE,.open  = pin4_open,.write = pin4_write,.read  = pin4_read,
};
//static限定这个结构体的作用,仅仅只在这个文件。
int __init pin4_drv_init(void)   //真实的驱动入口
{int ret;printk("module success\n");devno = MKDEV(major,minor);  //创建设备号ret   = register_chrdev(major, module_name,&pin4_fops);  //注册驱动  告诉内核,把这个驱动加入到内核驱动的链表中pin4_class=class_create(THIS_MODULE,"myfirstdemo");//让代码在dev下自动>生成设备pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  //创建设备文件GPFSEL0=(volatile unsigned int *)ioremap(0x3f200000,4);GPSET0 =(volatile unsigned int *)ioremap(0x3f20001C,4);GPCLR0 =(volatile unsigned int *)ioremap(0x3f200028,4);//这三行是设置寄存器的地址,volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.ioremap函数将物理地址转换为虚拟地址,IO口寄存器映射成普通内存单元进行访问。ioremap函数第一个参数输物理地址,第二个参数是return 0;
}void __exit pin4_drv_exit(void)
{iounmap(GPFSEL0);iounmap(GPSET0);iounmap(GPCLR0);//卸载驱动时释放地址映射device_destroy(pin4_class,devno);class_destroy(pin4_class);unregister_chrdev(major, module_name);  //卸载驱动
}
module_init(pin4_drv_init);  //入口,内核加载驱动的时候,这个宏会被调用,去调用pin4_drv_init这个函数
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");

上层代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>void main()
{int fd,data;fd = open("/dev/pin4",O_RDWR);printf("plese input 1 or 0 //1:high 0:low\n ");scanf("%d",&data);if(fd<0){printf("open fail\n");perror("reson:");}else{printf("open successful\n");}fd=write(fd,&data,1);
}

上层代码通过交叉编译发送到树莓派,底层驱动代码经编译后也发送到树莓派运行。
以上代码实现了引脚四功能为输出,根据用户的输入来决定引脚4电平的高低。

注意
为了不影响其他的引脚,配置寄存器的时候要用位操作,寄存器有32位,若想配13、14位为0,可以将二进制的110左移12位然后按位取反,在与上原来的寄存器地址,这样就不影响其他位。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/272387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#一些实用的函数

1.DateTime 转为Unix的long的时间戳long orderTime order.AddTime.ToUnixTimeStamp("Milliseconds");long payTime order.StartTime.Value.ToUnixTimeStamp("Milliseconds");2、获取客户端IP/// <summary>/// 获取调用方的IP地址/// </summary&…

Vscode如何新建html文件

1、点击Open Folder&#xff1a; 2、选择目标文件夹&#xff0c;在本地新建一个拓展名为html的文件&#xff1a; 3、在第1行输入!&#xff08;英文状态下&#xff09;&#xff0c;按tab键&#xff0c;新建成功。界面如下图所示&#xff1a;

混合app

cordova run android 把应用发送到手机ionic serve 电脑浏览器调试命令创建&#xff1a;cordova create hello com.example.hello HelloWorldcd hellocordova platform add androidcordova build androidcordova emulate android查询cordova platform lscord…

vscode浏览器打开html

1.点击拓展 2.输入open in browser&#xff0c;选择第一个 3.点击安装

VMware虚拟机克隆CentOS后网卡修改方法

转自:http://www.linuxidc.com/Linux/2015-03/114975.htm 转载于:https://www.cnblogs.com/water-sky/p/5169107.html

NET Core入门笔记

一、NET Core概念.NET Core 是开放源代码通用开发平台&#xff0c;由 Microsoft 和 .NET 社区在 GitHub 上共同维护。 它跨平台&#xff08;支持 Windows、macOS 和 Linux&#xff09;&#xff0c;并且可用于生成设备、云和 IoT 应用程序。&#xff08;MSDN&#xff09;二、NET…

解决redis-cli连接时出现Could not connect to Redis at 127.0.0.1:6379: Connection refused

解决redis-cli连接时Could not connect to Redis at 127.0.0.1:6379: Connection refused 原因&#xff1a;服务端未启动 [rootlocalhost bin]# ./redis-server redis.conf [rootlocalhost bin]# redis-cli -bash: redis-cli: 未找到命令 [rootlocalhost bin]# ./redis-cli 1…

ASP.NET MVC的过滤器笔记

过滤器概念APS.NET MVC中&#xff08;以下简称“MVC”&#xff09;的每一个请求&#xff0c;都会分配给相应的控制器和对应的行为方法去处理&#xff0c;而在这些处理的前前后后如果想再加一些额外的逻辑处理。这时候就用到了过滤器。1、过滤器&#xff08;Filters&#xff09;…

51单片机点亮第一个LED教程

单片机芯片型号&#xff1a; STC89C52 建立工程文件 打开keil4软件界面如下&#xff1a; 新建工程文件&#xff08;自己选择文件路径&#xff0c;并给工程命名&#xff09;&#xff1a; 若出现下图点击OK&#xff1a; 然后选择Atmel点击OK&#xff08;根据自己的芯片型号选择…

linux环境下用docker安装rabbitmq

1、进入docker hub镜像 仓库地址&#xff1a;https://hub.docker.com/ 2、搜索rabbitMq&#xff0c;进入官方 的镜像可以&#xff0c;看到以下几种类型的镜像&#xff1b;我们选择带有“mangement”的版本&#xff08;包含web管理页面&#xff09;&#xff1b; 3、拉取镜像 …

EF使用CodeFirst创建数据库和表

EF支持三种实体模型&#xff1a;Code First&#xff0c;Model First和DB First&#xff0c;分别表示代码优先&#xff0c;模型优先和数据库优先。目前就个人来说使用CodeFirst最多&#xff0c;对此相对比较熟悉&#xff0c;先写下Code First的使用吧。那什么是Code First代码优…

从头学Qt Quick(3)-- 用QML写一个简单的颜色选择器

先看一下效果图&#xff1a; 实现功能&#xff1a;点击不同的色块可以改变文字的颜色。 实现步骤&#xff1a; 一、创建一个默认的Qt Quick工程: 二、添加文件Cell.qml 这一步主要是为了实现一个自定义的组件&#xff0c;这个组件就是我们看到的那个色块&#xff0c;很明显定义…

LED闪烁和流水灯,调试教程,在线仿真器的使用

常用的延时方法&#xff1a; 软件延时&#xff08;使用简单但是浪费CPU资源&#xff09;、定时器延时&#xff08;不浪费CPU资源&#xff09;&#xff0c;本次先使用软件延时。 LED全亮代码&#xff1a; #include<reg52.h> //引用51的头文件 void main() {P10; }整体代…

docker中命令docker images

docker images 用于查看本地已下载的镜像 REPOSITORY 镜像仓库 TAG 镜像标签 IMAGE ID 镜像ID CREATED 镜像创建时间 SIZE 镜像大小

用VS2017开发安卓应用

vs2017自安装以后就没怎么打开过&#xff0c;虽然12出的时候用10&#xff0c;15出的时候用13&#xff0c;17出的时候用15&#xff0c;但我依然坚持不用也装上再说的理念。1、vs2017开发IOS和Android安装所必不可少的&#xff0c;uwp和net core也顺便装了吧&#xff0c;作为一个…

算法题11 字符串的所有对称子串

题目 给定一个字符串&#xff0c;求其中所有的对称子串 分析 对称字符串无非两种情况&#xff0c;一是以1个字符为中心对称&#xff0c;如"abcba",一是完全对称&#xff0c;如"abccba"。对于字符串对称的判断&#xff0c;从内往外查找比较方便 代码  1 in…

C51蜂鸣器和数码管动静态显示

蜂鸣器代码 #include<reg52.h> #include<intrins.h>#define uint unsigned int #define uchar unsigned charsbit beepP2^3; uchar temp; void delay(void) //误差 -0.000000000023us {unsigned char a,b;for(b221;b>0;b--)for(a207;a>0;a--); } void mai…

MYSQL 定时自动执行任务

MYSQL5.1开始支持EVENT功能&#xff0c;类似Oracle和MSSQL的定时任务job功能。有了这个功能之后我们就可以让MySQL自动的执行存储过程来实现数据汇总等功能了&#xff0c;不用像以前哪样手动操作完成了。下面我们来测试下&#xff0c;在MYSQL中如何自动执行指定存储过程&#x…

docker删除本地已下载的镜像

1&#xff1a;首先用 docker images 查看一下本地已下载的镜像 2&#xff1a;使用 docker rmi --force IMAGED ID 删除镜像

51单片机独立键盘和矩阵键盘

独立键盘代码&#xff1a; #include<reg52.h> #include<intrins.h>#define uint unsigned int #define uchar unsigned charsbit beepP2^3; sbit DUAN P2^6;//数码管段选 sbit WEIP2^7; //数码管位选sbit key_s2 P3^0;//独立按键s2 sbit key_s3 P3^1;//独立按键s3…