树莓派linux驱动学习之LED控制
前面我们编写了hello world的程序,接下来继续研究GPIO功能,通过GPIO来控制LED的亮灭,这在单片机中应该算是十分简单的一个程序了,但是在Linux系统中控制GPIO没有那么简单,难点就在于GPIO地址的获取,也是我一直在纠结的问题。
一、GPIO地址
二、硬件平台
三、编写驱动代码
#include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/irq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <asm/unistd.h> #include <asm/io.h> #include <asm/uaccess.h> #include <linux/ioport.h> #include "bcm2835.h" // Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17) #define PIN RPI_GPIO_P1_11 int open_state = 0; //文件打开状态 static int leds_open(struct inode *inode, struct file *filp) { if(open_state == 0) { open_state = 1; printk("Open file suc!\n"); return 0; } else { printk("The file has opened!\n"); return -1; } } static int leds_ioctl(struct file*filp, unsigned int cmd, unsigned long arg) { switch(cmd) { case 0: bcm2835_gpio_clr(PIN); printk("LED OFF!\n"); break; case 1: bcm2835_gpio_set(PIN); printk("LED ON!\n"); break; default: return-EINVAL; } return 0; } static int leds_release(struct inode *inode, struct file *filp) { if(open_state == 1) { open_state = 0; printk("close file suc!\n"); return 0; } else { printk("The file has closed!\n"); return -1; } } static const struct file_operations leds_fops = { .owner = THIS_MODULE, .open = leds_open, .unlocked_ioctl = leds_ioctl, .release = leds_release, }; static struct miscdevice misc = { .minor =MISC_DYNAMIC_MINOR, .name ="my_leds", .fops =&leds_fops, }; static int __init leds_init(void) { int ret; //注册混杂设备 ret =misc_register(&misc); //配置功能选择寄存器为输出 bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); //设置输出电平为高电平,LED亮 bcm2835_gpio_set(PIN); printk("ledsinit.\n"); return ret; } static void leds_exit(void) { //LED灭 bcm2835_gpio_clr(PIN); misc_deregister(&misc); printk("leds_exit\n"); } module_init(leds_init); module_exit(leds_exit); MODULE_AUTHOR("Hu Chunxu"); MODULE_LICENSE("GPL");
硬件相关操作:
#include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/irq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <asm/unistd.h> #include <asm/io.h> #include <asm/uaccess.h> #include <linux/ioport.h> #include "bcm2835.h" int bcm2835_gpio_fsel(uint8_t pin, uint8_t mode) { //初始化GPIOB功能选择寄存器的物理地址 volatile uint32_t * bcm2835_gpio = (volatile uint32_t *)ioremap(BCM2835_GPIO_BASE, 16); volatile uint32_t * bcm2835_gpio_fsel = bcm2835_gpio + BCM2835_GPFSEL0/4 + (pin/10); uint8_t shift = (pin % 10) * 3; uint32_t value = mode << shift; *bcm2835_gpio_fsel = *bcm2835_gpio_fsel | value; printk("fsel address: 0x%lx : %x\n", bcm2835_gpio_fsel, *bcm2835_gpio_fsel); return 0; } int bcm2835_gpio_set(uint8_t pin) { //GPIO输出功能物理地址 volatile uint32_t * bcm2835_gpio = (volatile uint32_t *)ioremap(BCM2835_GPIO_BASE, 16); volatile uint32_t * bcm2835_gpio_set = bcm2835_gpio + BCM2835_GPSET0/4 + pin/32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; *bcm2835_gpio_set = *bcm2835_gpio_set | value; printk("set address: 0x%lx : %x\n", bcm2835_gpio_set, *bcm2835_gpio_set); return 0; } int bcm2835_gpio_clr(uint8_t pin) { //GPIO清除功能物理地址 volatile uint32_t * bcm2835_gpio = (volatile uint32_t *)ioremap(BCM2835_GPIO_BASE, 16); volatile uint32_t * bcm2835_gpio_clr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; *bcm2835_gpio_clr = *bcm2835_gpio_clr | value; printk("clr address: 0x%lx : %x\n", bcm2835_gpio_clr, *bcm2835_gpio_clr); return 0; }
应用测试程序:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> int main(int argc, char **argv) { int on; int fd; if (argc != 2 || sscanf(argv[1],"%d", &on) != 1 ||on < 0 || on > 1 ) { fprintf(stderr, "Usage:%s 0|1\n",argv[0]); exit(1); } fd = open("/dev/my_leds", 0); if (fd < 0) { perror("open device leds"); exit(1); } /*通过ioctl来控制灯的亮、灭*/ if(on){ printf("turn on leds!\n"); ioctl(fd, 1); } else { printf("turn off leds!\n"); ioctl(fd, 0); } close(fd); return 0; }
分别编译,插入模块,然后运行测试程序,可以控制LED的亮灭了。
----------------------------------------------------------------
欢迎大家转载我的文章。
转载请注明:转自古-月
欢迎继续关注我的博客
树莓派linux驱动学习之LED控制的更多相关文章
- 树莓派linux驱动学习之hello world
最近想学习一下linux驱动,看了一些书和教学视频,大概了解了一下,不过要想深入,肯定需要实践.手上有几块linux的板子,最终选择了树莓派作为我的实验平台,资料比较丰富,接口也比较简单. 程序员的入 ...
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
- linux驱动学习(二) Makefile高级【转】
转自:http://blog.csdn.net/ghostyu/article/details/6866863 版权声明:本文为博主原创文章,未经博主允许不得转载. 在我前一篇写的[ linux驱动学 ...
- 超简单易用的 “在 pcduino 开发板上写 Linux 驱动控制板载 LED 的闪烁”
版权声明:本文为博主原创文章,未经博主同意不得转载.转载联系 QQ 30952589,加好友请注明来意. https://blog.csdn.net/sleks/article/details/251 ...
- Linux驱动开发之LED驱动
首先讲下字符设备控制技术 : 大部分驱动程序除了需要提供读写设备的能力外,还需要具备控制设备的能力.比如: 改变波特率. 在用户空间,使用ioctl系统调用来控制设备,原型如下:int ioctl(i ...
- Linux驱动学习之常用的模块操作命令
1.常用的模块操作命令 (1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表 (2)insmod(install module,安装模块),功能是向当前 ...
- Linux驱动学习之什么是驱动?
一.什么是驱动? 1: 驱动一词的字面意思 2: 物理上的驱动 3: 硬件中的驱动 4: linux内核驱动.软件层面上的驱动广义上是指:这一段代码操作了硬件去动,所以这一段代码就叫硬件的驱动程序. ...
- Linux驱动学习步骤(转载)
1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ls ...
- linux驱动学习之Input输入子系统
以前,看过国嵌关于input子系统的视频课程,说实话,我看完后脑子里很乱,给我的印象好像是input子系统驱动是一个全新的驱动架构,疑惑相当多.前几天在网上,看到有很多人介绍韦东山老师的linux驱动 ...
随机推荐
- Zookeeper的功能以及工作原理 (转自:http://www.cnblogs.com/felixzh/p/5869212.html)
1.ZooKeeper是什么?ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的 ...
- 深入Java虚拟机(2)——Java的平台无关性
一.平台无关性的好处 Java技术在网络环境下非常有用,其中一个关键理由是,用Java创建的可执行二进制程序,能够不加改变地运行于多个平台. 这样的平台无关性随之带来许多的好处.这将极大地减轻系统管理 ...
- 使用GDB调试STL容器
GDB中print方法并不能直接打印STL容器中保存的变量,想知道STL容器保存的变量,使用如下办法: 1. 创建文件~/.gdbinit: # # STL GDB evaluators/views/ ...
- Dynamics CRM2016 Update or Create parentcustomerid in Contact using web api
联系人实体中有个特殊的字段parentcustomerid 在通过web api创建或更新记录时,如果在给这个字段赋值时当做查找字段对待的话,那你就会遇到问题了,报错信息如下 正确的赋值方式如下
- linux中 probe函数的何时调用的?
点击打开链接 linux中 probe函数何时调用的 所以的驱动教程上都说:只有设备和驱动的名字匹配,BUS就会调用驱动的probe函数,但是有时我们要看看probe函数里面到底做了什么,还有传递给p ...
- Unity3D核心技术详解
在这里将多年游戏研发经验的积累写成一本书奉献给读者,目前已经开始预售,网址: http://www.broadview.com.cn/article/70 该书主要是将游戏中经常使用的技术给大家做了一 ...
- Struts 2 之拦截器
拦截器概述 Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP(Aspect Oriented Progr ...
- 【Android 系统开发】使用 Source InSight 阅读 Android 源码
1. 安装 Source Insight (1) Source Insight 相关资源 安装相关资源 : -- 下载地址 : http://www.sourceinsight.com/down35. ...
- 简单搭建iOS开发项目框架
今天我们来谈谈如何搭建框架,框架需要做一些什么. 第一步:找到我们的目标我们的目标是让其他开发人员拿到手后即可写页面,不再需要考虑其他的问题. 第二步:我们需要做哪些东西各位跟着我一步一步来进行. 假 ...
- 基于OpenCV 的美颜相机推送直播流
程序流程: 1.图像采集 先从opencv(2.4.10版本)采集回来摄像头的图像,是一帧一帧的 每一帧图像是一个矩阵,opencv中的mat 数据结构. 2.人脸的美化 人脸美化,我们用的皮肤检测, ...