树莓派字符驱动

STM32开发--- F429IG+3.5寸显示屏( ILI9486) +汉字驱动 更新中........2020.04.05 一、STM32显示系列主题链接: 【STM32】0.96寸屏SSD1306中文显示 【STM32】1.8寸屏ILI9486中文显示 【STM32】3.5寸屏ILI9486中文显示 【STM32】4.3寸屏ILI9486中文显示 【STM32】10.2寸屏 SDRAM中文显示 【STM32】用W25Q128制作字库 实验平台 板子... 阅读详情

先看测试代码,目的打开树莓派/dev/pin4模块,向其中写入一个整型数。

测试程序 pin4test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
int main()
{
        int data=0;
        int fd;
        fd=open("/dev/pin4",O_RDWR);
        if(fd<0){
                printf("opne pin4 defeat!\n");
        }
        else{
                printf("opne success!\n");
        }
        printf("please input a int num:\n");
        scanf("%d",&data);
        printf("data=%d\n",data);
        write(fd,&data,sizeof(data));
        return 0;
}

编译测试程序: gcc   pin4test.c -o pin4test 

直接运行测试程序./pin4test一定是不会成功的,因为/dev下根本就没有pin4这个模块,因此我们接下来的工作就是让dev下产生pin4这个模块。

首先我们需要根据驱动框架编写好自己的驱动代码,代码如下。

这个驱动是作用数将树莓派的第四个引脚配置成输出模式,并根据上层传递过来的整型数来控制输出高低电平。传入1输出高电平,传入0输出低电平。

驱动框架pin4driver.c 

#include <linux/fs.h> // 声明了文件操作相关的函数,比如文件打开,读写,关闭等
#include <linux/module.h> // 声明模块初始化和退出相关的函数
#include <linux/init.h> // 声明了初始化相关的宏,比如__init和__exit
#include <linux/device.h> // 设备相关的结构体和函数
#include <linux/uaccess.h> // 用户空间和内核空间数据交换相关的函数
#include <linux/types.h> // 定义了设备号等数据类型
#include <asm/io.h> // IO内存映射相关的函数
// 定义了一个结构体指针变量pin4_class,用于表示设备所属的类别
static struct class *pin4_class;  
// 定义了一个设备结构体指针变量pin4_class_dev,用于表示设备本身
static struct device *pin4_class_dev;
// 定义了一个设备号变量devno
static dev_t devno;                //设备号
// 定义了主设备号major
static int major =231;  		   //主设备号
// 定义了次设备号minor
static int minor =0;			   //次设备号
// 定义了一个字符指针变量module_name,用于存储模块名“pin4”
static char *module_name="pin4";   //模块名

volatile unsigned int *GPFSET0=NULL;//根据手册 GPFSET0寄存器 用来选择引脚
volatile unsigned int *GPSET0 =NULL;//根据手册 GPFSET0寄存器 用来置高电平
volatile unsigned int *GPCLR0 =NULL;//根据手册 GPFSET0寄存器 用来清0

// 参数inode代表打开的文件,file代表打开文件对应的file结构体
static int pin4_open(struct inode *inode,struct file *file)
{
    printk("pin4_open\n");  //内核的打印函数和printf类似

    //根据手册把GPFSET0第12~14位配置成001可以将树莓派第四个引脚配置成输出模式(output)
    *GPFSET0 &= ~(0x6<<12); //将二进制数0110左移十二位取反,然后与等于,将寄存器第13、14位置0
    *GPFSET0 |=(0x1<<12);//根让寄存器的第12位置1

    return 0; 
}

// 参数file代表写入的文件,buf是写入的数据缓冲区,count是写入的字节数,ppos是写入的文件位置指针
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{
    int userCmd;
	printk("pin4_write\n");
	copy_from_user(&userCmd,buf,count);//内核编程中常用的函数,它的主要作用是从用户空间复制数据到内核空间
	if(userCmd==1){
		printk("set 1\n");
		*GPSET0 |=0x01<<4;	//将树莓派第四个引脚置为高电平
	}
	else if(userCmd==0){
		printk("set 0\n");
		*GPCLR0 |=0x01<<4;    //将树莓派第四个引脚置为低电平
	}
	else{
		printk("undo\n");
	}

    return 0; 
}

// 定义了一个文件操作结构体变量pin4_fops,用于存储文件操作函数
static struct file_operations pin4_fops = {
    .owner = THIS_MODULE, // 表示文件操作的所有者是当前模块
    .open  = pin4_open,  // 表示文件打开时调用的函数是pin4_open
    .write = pin4_write,  // 表示文件写入时调用的函数是pin4_write
};

// pin4_drv_init函数的函数声明,这个函数是模块的初始化函数
int __init pin4_drv_init(void) 
{
    int ret; 
    devno = MKDEV(major,minor);  // 使用MKDEV宏生成设备号,这个宏在types.h中定义,主设备号和次设备号相加得到设备号devno
    ret   = register_chrdev(major, module_name,&pin4_fops);  // 使用register_chrdev函数注册字符设备驱动,告诉内核这个驱动加入到内核驱动的链表中

    pin4_class=class_create(THIS_MODULE,"myfirstdemo"); // 使用class_create函数创建设备类别,类别名是"myfirstdemo"
    pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  // 使用device_create函数创建设备文件,参数包括类别、父设备、设备号、名称等

    GPFSET0=(volatile unsigned int *)ioremap(0x3f200000,4);//将物理地址映射成虚拟地址,内核和上层空间都是访问虚拟地址的
    GPSET0 =(volatile unsigned int *)ioremap(0x3f20001c,4);
    GPCLR0 =(volatile unsigned int *)ioremap(0x3f200028,4);

    return 0; 
}

// pin4_drv_exit函数的函数声明,这个函数是模块的退出函数
void __exit pin4_drv_exit(void) 
{

    iounmap(GPFSET0);//将之前通过ioremap函数映射的IO地址空间解除映射
	iounmap(GPSET0);
	iounmap(GPCLR0);
    
    device_destroy(pin4_class,devno); // 使用device_destroy函数销毁创建设备文件
    class_destroy(pin4_class); // 使用class_destroy函数销毁创建的设备类别
    unregister_chrdev(major, module_name);  //卸载驱动
}
module_init(pin4_drv_init);  //入口宏
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");

将这个代码在虚拟机上拷贝到linux内核的/drivers/char字符驱动目录下,为了使该驱动文件能够被编译到,这里需要修改Makefile,Makefile文件的意义在于自动化构建项目,也就是为了更简便地执行程序,Makefile文件描述了整个工程所有文件的编译顺序、编译规则,它存在于项目的根目录下,并且可以在项目的任何子目录中存在,但通常在项目的根目录下创建或维护。

使用以下命令编辑Makefile,模仿其他的文件加入下面的语句,文件的后缀名改为.0,前面的-m表示以模块的方式加载到内核。

vi Makefile

然后回到内核目录下:编译内核模块。

还记的编译内核的代码吗,如下所示。这里只需要编译modules即可,因此使用如下第一个命令即可。

使用这个:

ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules 
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs

"ARCH": "定义目标体系结构,这里是arm,表示你正在为基于ARM的处理器构建内核。",
"CROSS_COMPILE": "定义交叉编译器的前缀,这里是指用于ARM架构的GNU编译器的前缀,包括编译器、链接器和其它工具。它的形式通常是 'arm-linux-gnueabihf-'.",
"KERNEL": "定义内核的版本或者名称,这里是kernel7。",
"make -j4": "使用make命令并且并行编译的数量为4,这可以大大提高编译速度。'-j'参数代表并行编译,后面的数字4代表同时编译4个文件。",
"zImage": "这是编译的内核镜像文件的名称,'zImage'是压缩内核镜像的简称。",
"modules": "这部分是编译所有的内核模块。",
"dtbs": "这个部分是编译设备树源文件(.dts)并生成设备树二进制文件(.dtb)和设备树自解压文件(.dtbs)。设备树描述了硬件的配置信息。"

编译通过以后会在linux-rpi-4.14.y/drivers/char路径下生成pin4driver.ko文件。

然后将这个文件传到树莓派的工作目录下/home/pi。

接着加载驱动,命令如下:

 sudo insmod pin4driver.ko

命令执行完成后可以执行lsmod命令,它用于列出已加载的内核模块     这里可以看到pin4driver已经被加载进去了。

同时树莓派/dev目录下会多一个  pin4  的文件

名字的来源为字符驱动框架程序中的如下语句

static char *module_name="pin4";   //模块名

使用命令 ls pin4 -l可以查看文件的详细信息,231为主设备号,0为从设备号。生成的主次设备号由在驱动代码的变量major minor决定的。

既然已经在/dev目录下生成了pin4模块,那么这里就可以执行测试程序pin4test了。

 这里看到运行 ./pin4test运行结果是打开失败,是因为加载驱动的时候使用的是超级用户权限,导致普通用户没有pin4的权限,所以这里需要使用超级用户权限改变/dev/pin4的权限,命令如下

sudo chmod 666/dev/pin4

然后在执行./pin4test就会正常运行。

使用dmesg命令可以打印内核的状态,内核成功执行了驱动中的 pin4_open函数,成功打印了pin4_open。


 

Linux驱动开发(六)---树莓派配合硬件进行字符驱动开发 通过DTS配合驱动,实现了灵活控制GPIO 阅读详情

相关推荐

基于树莓派Raspberry: 字符设备内核驱动程序框架编写

之前写了一篇移植2.4寸TFT驱动到树莓派的文章,那篇博文中的驱动代码是国外大牛写的,看了一下,还是有很多地方没理解,是得好好再学习一下内核驱动的编写,这里就从字符设备驱动开始,采用最简单的LED驱动来建立内核驱动移植的驱动框架.

MyBlog of Embbnux 8895

ESP32驱动LCD液晶屏选型、262K什么意思?SPI写LCD的GRAM时序、MCU液晶屏驱动IC的寄存器功能

最近转战ESP32,ESP32-D0WDQ6 型号的GPIO只有那么20个左右,且还有几个GPIO只能做输入,非常捉襟见肘。所以如果要驱动LCD液晶屏,绝大多数都会选择SPI接口的MCU屏。 为了编写一个通用的ESP32-SPI-LCD驱动,前前后后买了一小桌液晶屏,用了十几款驱动IC,说下整个过程的选型、体验、注意事项: 驱动IC的重要参数 像素点数(如240x320) 色彩深度(18Bit-262K,24Bit-16.7M) 时序、接口这类的参数都不会差太多,各厂商的寄存器定义基本都保持一致,使得后

Mark_md的博客 1万+

基于树莓派:MAX7219的字符驱动程序编写

本实验使用MAX7219驱动8x8点阵。上位机使用Ubuntu 14.04,下位机使用Raspberry pi。

shuqiHe的博客 4600

STM32F103软件模拟SPI接口驱动ILI9486液晶屏

STM32F103软件模拟SPI接口驱动ILI9486液晶屏ILI9486的工作模式ILI9486的SPI总线方式简介ILI9486的3线SPI总线底层驱动配置步骤 ILI9486的工作模式 ILI9486是ILITEC推出的一款LCD驱动器,支持262144种色彩,支持的显示分辨率为320480,内部GRAM显存为345600Bytres(320480*18bit)。ILI9486支持8种总线方...

zhanglianli的博客 1万+

树莓派linux led字符设备驱动(传统)

  Linux 下的任何外设驱动,最终都是要配置相应的硬件寄存器。所以 LED 灯驱动最终也是对树莓派的 IO 口进行配置,但是在 Linux 下编写驱动要符合 Linux的驱动框架。 一、树莓派GPIO

123 1万+

ILI9486显示屏驱动

这是ILI9486显示屏的驱动,亲测可用,移植性好

树莓派底层字符驱动的实现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、二、使用步骤1.引入库2.读入数据总结 前言 继前面编译了树莓派内核之后,这次来实现树莓派底层字符驱动,刚接触树莓派的时候,我们都是调用wiringPi库中的API来实现一些特定的功能,但随着学习的深入,我们应该要去接触一下这些底层的东西,尝试自己编写代码来实现wiringPi库的功能。 一、 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引入库 代码如下(示例

weixin_48264057的博客 315

ILI9486 3.5TFT液晶屏Arduino驱动

ILI9486 3.5TFT液晶屏Arduino驱动,有Arduino各种使用例程

树莓派字符驱动的添加与测试

树莓派字符驱动的添加与测试编译模块添加加载模块测试删除模块代码 编译模块 **1.**将 .c 文件放入linux里的 linux-rpi-4.14.y/drivers/char **2.**cd …/…来编译模块ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules 生成字符驱动.ko (在drivers/char 下看得到) 添加加载模块 再将 .ko 传给树莓派 pi 执行 sudo insmod 字符驱动.ko

m0_55144543的博客 1707

STM32-ILI9486程序

利用STM32F105芯片,通过SPI通信,实现ILI9486驱动液晶屏,可以在液晶屏显示图片和文字,实时接收触摸屏的信息。

ILI9486L数据手册

ILI9486L数据手册,开发ILI9486L或者ILI9486的同学们尽快下载吧

树莓派 字符设备驱动开发

前期准备工作:要有交叉编译工具,有编译好的内核在/arch/arm/boot下生成内核镜像文件zImage 驱动程序框架 #include <linux/fs.h> //file_operations声明 #include <linux/module.h> //module_init module_exit声明 #include <linux/init.h> //__init __exit 宏定义声明 #include <linux/dev

weixin_45012976的博客 615

STM32F103驱动3.5寸ILI9486触摸屏幕HAL库版本,全部代码,可直接烧录

使用STM32cubemx配置,移植中景园ILI9486屏幕驱动代码,HAL库代码,方便二次开发

树莓派字符设备驱动代码(基于框架)的编译测试

一、树莓派字符设备驱动代码框架: 以下框架只添加了open write函数,可以根据需求在结构体中自行添加 #include <linux/fs.h> //file_operations声明 #include <linux/module.h> //module_init module_exit声明 #include <linux/init.h> //__init __exit 宏定义声明 #include <linux/device.h&gt

Heavysea的博客 256

海思Hi3516CV610--SPI NAND Flash移植实战:从手册到驱动的完整适配

本文详细介绍了海思Hi3516CV610芯片上SPI NAND Flash的移植实战,包括从手册解读到驱动适配的完整流程。以GD5F2GM7UEYIGR Flash为例,重点讲解了关键参数确认、模式选择、时序配置以及U-Boot和Linux内核驱动的具体实现步骤,帮助开发者快速完成Flash移植工作。

weixin_29158413的博客 447

ATAC-seq数据分析流程

Outline0. ATAC-seq原理0.1 染色体结构0.2 原理0.3 结果0.4 意义1. ATAC-seq数据分析流程1.1 上游分析(1)序列质控和比对(2)序列筛选1.2 下游分析1.3 进阶分析 0. ATAC-seq原理 0.1 染色体结构 0.2 原理 0.3 结果 0.4 意义 1. ATAC-seq数据分析流程 1.1 上游分析 (1)序列质控和比对 fastqc trim_golare bowtie2 mapping时要加上参数 --very-sensitive -X 2000

weixin_57830892的博客 1万+

树莓派最简单的字符设备驱动框架

实现的功能 通过这个驱动可以实现文件的打开,写等操作,例如,控制gpio, 这里先写基础的结构 整体框架 #include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> #include <mach/platform.h> #include <linu...

weixin_43152585的博客 586

从零构建SOEM主站:基于STM32的EtherCAT伺服控制实战指南

本文详细介绍了如何从零构建基于STM32的SOEM主站系统,实现EtherCAT伺服电机的高精度控制。通过硬件选型、SOEM协议栈移植、PDO/SDO配置优化等实战步骤,帮助开发者掌握工业自动化中的关键运动控制技术,特别适用于23位编码器伺服电机的应用场景。

weixin_29186249的博客 666

基于树莓派的Linux字符设备驱动框架

#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

love12fly@sina.com 136

到底什么是电源的斜波补偿,电源芯片CS引脚作用,一文讲清楚!

上文有提到电流环,其实电流环再细分也有很多模式,用的最多的是峰值电流模式峰值电流模式调节工作原理如下:(1)当输出负载增大时,输出电压降低,因此,Vc 增大,线性增加的电感电流只有升高到更大的值才能使 PWM 电流比较器翻转,开关管导通的时间增长,占空比增加,输入功率增加,因此输出电压增加,当输出电压增加到调节的范围内时,系统保持平衡。

jwgdhuwdhg的博客 1万+

117、HDR多帧融合算法:曝光序列、运动鬼影消除与合成权重的高效实现

HDR多帧融合算法实战经验总结 本文分享了HDR多帧融合算法在实际应用中的关键技术和优化经验。主要内容包括: 曝光序列设计:强调动态调整曝光时间比、帧间间隔和拍摄顺序的重要性,特别指出短-中-长的拍摄顺序优势。 运动鬼影消除:比较了三种运动检测方法,推荐梯度域检测方案,并强调在RAW域进行检测的必要性。 合成权重设计:提出基于高斯型权重函数的多因素考量方法,包括基础权重、运动权重和噪声权重的综合处理策略。 高效实现方案:提供NEON指令集加速的具体代码示例,包括梯度计算、权重查表和融合处理等关键步骤。 实用

zzfmlxs的博客 65

linux驱动(驱动编译、字符设备驱动框架、交叉编译树莓派驱动、树莓派驱动本地编译)

用户态: 是指用户编写程序、运行程序的层面,用户态在开发时需要C的基础和C库,C库讲到文件,进程,进程间通信,线程,网络,界面(GTk)。C库(是linux标准库一定有):就是Clibary,提供了程序支配内核干活的接口,调用的open,read,write,fork,pthread,socket由此处封装实现,由写的应用程序调用,C库中的各种API调用的是内核态,支配内核干活。 内核态: 用户要使用某个硬件设备时,需要内核态的设备驱动程序,进而驱动硬件干活,就比如之前文章里面所提到的wiringPi

FHN优快云 558

【Python爬虫教程】第3篇-解决使用reqeusts遇到的ProxyError异常

Python request代理错误提示“HTTPSConnectionPool, Cannot connect to proxy, no such file or directory”

分享技术,记录思考和感悟 1507

树莓派4bwlan驱动_树莓派的内核模块编程之字符设备驱动

引言在linux系统中,硬件设备是通过特殊的设备文件与内核进行通信,这些设备文件根据所传输的数据量与传输速度被分为字符设备(character device)与块设备(block device),并且都被放在/dev目录下。本文主要介绍字符设备的相关内容,并说明如何在树莓派上编写字符设备驱动。一、字符设备与块设备linux系统通过特殊的设备文件来控制硬件设备与linux内核之间的通信,这些设备文件...

weixin_39985820的博客 265

详解AUTOSAR:DaVinci Configurator配置CAN和UART数据协议解析器(RH850)(实战篇—1)

通过学习本篇博文项目,将会把所学的DaVinci Configurator知识系统串联起来。

不脱发的程序猿 2811

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

上一篇: 树莓派的刷机、串口登录、ssh登录
下一篇: Linux libcurl库的使用,通过libcurl库进行人脸识别
init_hello
博客等级 码龄6年 2粉丝 9原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值