树莓派3B+ 驱动开发之GPIO

2023-05-16


1、查看树莓派GPIO地址映射基地址

方法一:

cat /proc/iomem

结果  3f200000-3f2000b3 : /soc/gpio@7e200000。3f200000为基地址,

方法二:

root@raspberrypi:/home/pi/Desktop# cd /proc/device-tree/soc/
root@raspberrypi:/proc/device-tree/soc# hexdump  -C ranges
00000000  7e 00 00 00 3f 00 00 00  01 00 00 00 40 00 00 00  |~...?.......@...|
00000010  40 00 00 00 00 00 10 00                           |@.......|
00000018

2、使用 mmap或者ioremap函数映射地址


3、根据手册BCM2835-ARM-Peripherals.pdf操作GPIO pin 4的地址

参考GPIO

  • Physical pin 7
  • BCM pin 4
  • Wiring Pi pin 7

 BCM2835-ARM-Peripherals.pdf手册中的偏移地址就是 BCM pin 4

 

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/uaccess.h>


#define BCM2835_GPIO_BASE   0x3f200000
#define LED_ON  1
#define LED_OFF 0

#define GPFSEL0 (0x0/4)
#define GPFSEL1 (0x4/4)
#define GPFSEL2 (0x8/4)
#define GPFSEL3 (0xc/4)
#define GPFSEL4 (0x10/4)
#define GPFSEL5 (0x14/4)
#define GPSET0 (0x1c/4)
#define GPSET1 (0x20/4)
#define GPCLR0 (0x28/4)
#define GPCLR1 (0x2c/4)


int major = 111;
int minor = 0;
static dev_t devno;
static struct class *cls;
static struct device *test_device;

unsigned int * global_gpio = NULL;

 static int led_open (struct inode *inode, struct file *filep)
{//open
	int sel0_value = 0;
	//实现对pin 4引脚 设为输出操作
	sel0_value = *(global_gpio+GPFSEL0);	
	sel0_value |= (1<<12);
	sel0_value &= ~(1<<13);
	sel0_value &= ~(1<<14);
	*(global_gpio+GPFSEL0) = sel0_value;

	printk(KERN_INFO"led_open dir set sel0_value = 0x%x\n", sel0_value);
	return 0;
}

 static ssize_t led_read(struct file *filep, char __user *buf, size_t len, loff_t *pos)
 {

	printk(KERN_INFO"led_read \n");
	 return 0;
 }

 static ssize_t led_write(struct file *filep, const char __user *buf, size_t len, loff_t *pos)
 {	//实现对pin 4引脚 高电平 低电平操作
	int set0_value = 0;
	char led_value = 0;
	unsigned long count = 1; 
	
	if(copy_from_user((void *)&led_value, buf, count))
	{
		return -1;
	}
        
	printk(KERN_ERR"led_write led_num =%d \n",led_value);


	if (led_value > 0)
	{
		
		set0_value = *(global_gpio+GPSET0);
		set0_value |= (1<<4);
		 *(global_gpio+GPSET0) = set0_value;
		printk(KERN_ERR"0 write led_value =0x%x \n",set0_value);
	}
	else 
	{
		set0_value = *(global_gpio+GPCLR0);
		set0_value |= (1<<4);
		 *(global_gpio+GPCLR0) = set0_value;
		printk(KERN_ERR"1 write led_value =0x%x \n",set0_value);
	}

	 printk(KERN_INFO"led_write end \n");

	 return 0;
 }


static struct file_operations led_ops = {

	.owner    =  THIS_MODULE,
	.open = led_open,
	.read = led_read,
	.write = led_write,
};


static int __init led_init(void)
{
	int ret;
  

	printk (KERN_INFO"global_gpio = 0x%lx\n", (unsigned long)global_gpio);

	global_gpio = ioremap(BCM2835_GPIO_BASE, 0x80);
	

	printk (KERN_INFO"global_gpio = 0x%lx\n", (unsigned long)global_gpio);

	devno = MKDEV(major,minor);

	ret = register_chrdev(major,"ledzfj", &led_ops);
	cls = class_create(THIS_MODULE, "myclass");
	   	if(IS_ERR(cls))
		{
			unregister_chrdev(major,"ledzfj");
			return -1;
		}
		test_device = device_create(cls,NULL,devno,NULL,"ledzfj");//mknod /dev/hello
		if(IS_ERR(test_device))
		{
			class_destroy(cls);
			unregister_chrdev(major,"ledzfj");
			return -1;
		}

       printk (KERN_INFO"\tinitialized\n");
       return 1;
}

static void __exit led_exit(void)

{
	iounmap(global_gpio);
	device_destroy(cls,devno);
	class_destroy(cls);
	unregister_chrdev(major,"ledzfj");
	printk(KERN_INFO"led_exit \n");
}

module_init(led_init);

module_exit(led_exit);

MODULE_LICENSE("GPL");


4、写makefile文件

 

ifneq ($(KERNELRELEASE),)
obj-m += test.o 
else
PWD := $(shell pwd)
KDIR := /home/zfj/github/linux
all:
	make  -C  $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 
clean:
	rm -rf *.o *.mod.c *.ko *.symvers *.order *.makers
endif

5、挂载驱动部分参考上一篇文章

6、调试代码

这个代码可以直接在树莓派上使用gcc 编译。

gcc -g 指令可以使用gdb进行调试。gdb的使用参考csdn gdb

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 void main(int argc, char **argv)
 {
	 int fd,i,lednum;

	 fd = open("/dev/ledzfj",O_RDWR);
	 if(fd<0)
	 {
		 printf("open fail \n");
		 return ;
	 }
	 printf("open success fd=%d \n", fd);

	if( argc > 1 )
	{
         lednum= atoi(argv[1]);
	 write(fd,&lednum,sizeof(int));
	 printf(" str =%s \n", argv[1]);

	}


	 close(fd);
 }

7、调试驱动

在bcm pin4写入 0或1

./led.o 0

./led.o 1

参考:

树莓派LED驱动编写

C库说明

c-gpio-library-for-raspberry-pi

raspberrypi/linux

/bcm2835-1.58C库

 RPi_Low-level_peripherals
BCM2835-ARM-Peripherals.pdf

gdb

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树莓派3B+ 驱动开发之GPIO 的相关文章

  • NVIDIA Jetson NX 控制GPIO

    目录 前言运行引脚图片 前言 看到一些博客说需要pip安装Jetson GPIO 以及通过下面命令设置用户权限 sudo groupadd span class token operator span f span class token
  • APM32F103CBT6调试接口复用为GPIO配置问题

    APM32F103CBT6调试接口复用为GPIO配置问题 xff1a 可以通过调整复用配置 xff0c 改为GPIO口 xff0c xff08 注意 xff1a 改为上电默认为GPIO口后 xff0c 将无法再用调试功能 xff0c 慎重选
  • DSP中GPIO位域

    在TMS320F2812中 xff0c 对于程序中寄存器的名称是如何映射到物理地址的 xff0c 这里做一下详细的讲解 主要应用到三个文件 xff1a CMD h DSP28 GLobalVariableDefs c xff0c 其中CMD
  • STM32F103笔记(二)——GPIO原理

    GPIO的工作原理与两个实验实例 一 STM32F103 GPIO说明1 stm32 GPIO引脚的主要功能2 GPIO相关配置寄存器的简介3 STM32F103 GPIO的8种工作方式4种输入模式4种输出模式 二 点亮LED实例 xff0
  • 使用 FreeRTOS 时使用 GPIO 监控 CPU 负载的正确方法?

    总目录链接 61 61 gt gt AutoSAR入门和实战系列总目录 总目录链接 61 61 gt gt AutoSAR BSW高阶配置系列总目录 文章目录 我想切换一些 GPIO 以监控 CPU 活动和 FreeRTOS 上下文 更具体
  • 通信方式梳理:GPIO,I2C,SPI,UART,USART,USB的区别

    GPIO xff0c I2C xff0c SPI xff0c UART xff0c USART xff0c USB的区别 1 简单区别 xff1a 1 xff09 GPIO xff08 General Purpose Input Outpu
  • NVIDIA Jetson Xavier NX 控制GPIO

    NVIDIA Jetson Xavier NX 控制GPIO 文章目录 NVIDIA Jetson Xavier NX 控制GPIO前言一 简介二 代码实例1 gpio h2 gpio cpp 三 拓展 前言 在linux系统中以文件io的
  • void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)的一些理解

    GPIO TypeDef GPIOA BASE 表示将GPIOA BASE强制转换为指针类型的结构体 xff0c define GPIOA GPIO TypeDef GPIOA BASE 表示用 GPIO TypeDef GPIOA BAS
  • 0.8 - GPIO的输入输出模式

    GPIO xff1a General purpose input output 从参考手册可知 xff0c GPIO可以配置成上图中的多种模式 xff0c 但是要理解这些名字的含义还是要具体分析GPIO功能框图 xff1a 结合GPIO的输
  • Arduino通过继电器控制电机(5V小马达)ESP8266-12F同理(小白初学)

    用Arduino ESP8266 12F控制电机 一 实验环境 IDE Arduino 材料 Arduino UNO ESP82266 12F 4 5V电池盒子 继电器 6脚 5V电机一个 5V小马达 面包板 杜邦线若干 二 接法 参照37
  • 【STM32F4】二、I/O引脚的复用和映射

    目录 一 基本概念 1 什么是I O引脚 2 什么是I O引脚的复用 二 如何配置I O引脚复用 1 复用器 GPIOx AFRL GPIOx AFRH 和复用功能 AF 2 程序编写 2 1 打开I O时钟和复用功能对应外设时钟 2 2
  • [STM32系列]二、实现STM32 GPIO端口状态实现最大速度翻转

    STM32系列 二 实现STM32 GPIO最快速度翻转 文章目录 STM32系列 二 实现STM32 GPIO最快速度翻转 前言 一 实验准备 二 测试 1 C语言翻转测试 2 汇编翻转测试 总结 前言 在STM32F103系列应用过程中
  • 零基础玩转树莓派(四)—GPIO端口控制(LED灯)

    一 GPIO介绍 树莓派3B 和普通电脑不一样的地方在于它还带了40个可编程的GPIO General Purpose Input Output 可以用来驱动各种外设 如传感器 步进电机等 GPIO General Purpose I O
  • 学习笔记:STM32的ACD

    STM32f103系列有3个ADC ADC1 ADC2 ADC3 通道 ADC1和ADC2都有16个外部通道 2个内部通道 连接到温度传感器和内部参考电压 VREFINT 1 2V ADC3有8个外部通道 通道列表 通道顺序转换 使用多个通
  • X2000 Linux 驱动中配置GPIO的上下拉

    由于sdk不支持标准gpio api函数int gpio pull updown unsigned gpio unsigned value 需要用到soc gpio h中的int jzgpio set func int port enum
  • 如何在Python中运行后一段时间内禁用Raspberry Pi GPIO事件?

    每当我的 Raspberry Pi 的 GPIO 引脚出现下降沿时 我就会创建一个事件 但是 我想在每次运行后禁用此事件一段时间 例如 5 秒 我希望在该时间段之后再次启用该事件 我的第一个想法就是使用sleep 5 在实际的事件函数中 但
  • Raspberry pi 4 用 java 控制 GPIO

    我想用java控制我的树莓派4上的16 2液晶显示屏 问题是Pi4J 用java修改gpios的解决方案没有更新到pi4 还有其他解决方案吗 当我启动程序时出现此错误 pi raspberrypi desktop gpio sudo sta
  • gpiod - 在设备树中使用标签

    我想用libgpiod通过自定义板上的用户空间控制一些 GPIO 我有一个 i MX6UL 处理器 它有数百个引脚 我将只使用其中 8 个 作为 GPIO 我读到了关于libgpiod因为它正在取代旧的 sysfs API 我很高兴您可以为
  • Python使用sudo启动时找不到模块

    我有一个使用 Google Assistant 库的脚本 并且必须从那里导入一些模块 我发现这只适用于 Python 虚拟环境 这真的很奇怪 在同一个文件夹中 我有一个使用 GPIO 引脚并且必须使用 root 的脚本 它们相互交互 因此当
  • 对 FINTEK F81866A 芯片组上的 GPIO 引脚进行编程

    我有一个德承DE 1000 http www cincoze com goods info php id 10工业 PC 具有芬泰克 F81866A http www fintek com tw index php i o controll

随机推荐