正点原子imx6ull使用八位数码管,Linux驱动八位静态数码管

开发步骤介绍

觉得可以的话,还请大哥们点赞,后面有完整示例代码

step1

1.采用74hc595的数码管驱动只需要由GPIO口的高低电平控制即可,也就是0、1控制。通过一定的输出规律进行控制。芯片hc595,只有三根控制信号线。数码管有动态与静态之分,动态8位数码管一次只能显示一个数字,不能同时显示多个数字,需要不断高速刷新显示,且有闪烁缺点,驱动方式类似。我这里是74hc595的8位静态共阳极数码管。数码管控制原理不做赘述。

step2

2.本人的开发板是imx6ull mini板。首先明确采用哪个GPIO口,通过GPIO口进行控制。mini的底板标注的GPIO_4其实对应的是GPIO1_IO04,这点很坑。(踩坑)关于接线如何接,后文会提到。

step3

3.接下来进行驱动编写。首先出厂的板件选用EMMC启动,自带了正点原子的Linux系统,文件树,uboot。设置IP地址后,可以用xshell与winscp连接该系统,上传下载文件等。

step4

4.想要编译驱动,使用make -j32 命令,但是编译时需要调用linux内核内容,需要在makefile中设置内核绝对路径。
例如:

KERNELDIR := /home/vincent/vincent/linux
CURRENT_PATH := $(shell pwd)

obj-m := newchrled.o

build: kernel_modules

kernel_modules:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

step5

5.由于使用的是正点原子的出厂系统,所以在/lib/modules/目录下存在目录名称4.1.15-gc0de9f6,其中-gc0de9f6需要设置在linux内核中的makefile中。否则无法挂载驱动。(踩坑)同时,在内核编译时,需要选择ARM7,去掉ARM6,否则也是无法挂载驱动,报错。具体参考《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》中第三十七章 Linux 内核移植。
源码使用《03、正点原子Uboot和Linux出厂源码》内核源码的makefile中修改第4行,第252行253行。

EXTRAVERSION =-gc0de9f6

ARCH		?= arm
CROSS_COMPILE	?= arm-linux-gnueabihf-

内核编译正确好后,方可成功挂载驱动。最好重新烧写。驱动挂载不上再重新烧写内核到开发板。

step6 驱动编写

接下来配置GPIO_1,GPIO_2,GPIO_4,也就是GPIO1_IO01,GPIO1_IO02,GPIO1_IO04(均属于GPIO1这一组IO口)
在驱动中,linux驱动通过c语言中的ioremap函数将物理地址转换为虚拟地址,通过操作这些变量从而操作寄存器,示例:

 #define SW_MUX_GPIO1_IO01_BASE		(0X020E0060)
 static void __iomem *SW_MUX_GPIO1_IO01;
 SW_MUX_GPIO1_IO01 = ioremap(SW_MUX_GPIO1_IO01_BASE, 4);

首先在《IMX6ULL参考手册》查找用于GPIO时钟使能的CCM_CCGR1,其地址是0X020C406C。通过设置其寄存器中27-26位的值,对GPIO1这一组的io口进行时钟使能。
在这里插入图片描述
接下来,查找用于配置GPIO复用模式的IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO01,其物理地址在(0X020E0060),通过设置第0-4位,从而设置为通用的GPIO模式。连续查找并配置GPIO1_IO02、GPIO1_IO04。
在这里插入图片描述
配置完复用模式后,需要配置电器属性,通过IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO01寄存器,物理地址(0X020E02EC),进行相关配置。
在这里插入图片描述
接下来再进行IO的输入输出方向配置,需要全部配置为输出模式,通过寄存器GPIO1_GDIR配置,物理地址(0X0209C004)。
在这里插入图片描述
最后,通过寄存器GPIO1_DR控制GPIO1这一组IO口的输出高电平还是低电平。到此裸机开发的流程结束,至于Linux驱动开发中其他的格式写法在官方示例代码中有。其中值得注意的是module_init绑定了一个驱动挂载时运行的函数。file_operations函数,该函数定义了一些外部调用的函数,如需要c++程序调用的write函数就写在这里,通过write函数进行与c++的通信。其中open函数是c++程序代码打开驱动时运行的函数。示例如下

static struct file_operations newchrled_fops = {
   
	.owner = THIS_MODULE,
	.open = led_open,
	.read = led_read,
	.write = led_write,
	.release = 	led_release,
};

其中函数led_write示例内容如下

static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
   
	//printk("vincent kernel write start\r\n");
	int retvalue;
	unsigned char databuf[100];
	unsigned char ledstat;
  
	retvalue = copy_from_user(databuf, buf, cnt);
	if(retvalue < 0) {
   
 
		printk("kernel write failed!\r\n");
		return -EFAULT;
	}
 	printk("get data : %s",databuf);
 	return 0;
}

完整驱动74hc595八位静态数码管代码如下,改代码通过修改Linux示例程序中newchrled得来。注意其中rck的地方,是由低拉到高。某些数码管可能不一样。dio接gpio1-2,sclk接gpio1-1,rclk接gpio1-4

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
 
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
 
 
#define NEWCHRLED_CNT			1		  	/* 设备号个数 */
#define NEWCHRLED_NAME			"newchrled"	/* 名字 */
#define LEDOFF 					0			/* 关灯 */
#define LEDON 					1			/* 开灯 */
 
 
 
/* 寄存器物理地址 */
// GPIO1时钟
#define CCM_CCGR1_BASE				(0X020C406C)
// GPIO1 多路选择
#define SW_MUX_GPIO1_IO00_BASE		(0X020E005C)	
#define SW_MUX_GPIO1_IO01_BASE		(0X020E0060)
#define SW_MUX_GPIO1_IO02_BASE		(0X020E0064)
#define SW_MUX_GPIO1_IO03_BASE		(0X020E0068)
#define SW_MUX_GPIO1_IO04_BASE		(0X020E006C)
 
// GPIO模式配置
#define SW_PAD_GPIO1_IO00_BASE		(0X020E02E8)
#define SW_PAD_GPIO1_IO01_BASE		(0X020E02EC)
#define SW_PAD_GPIO1_IO02_BASE		(0X020E02F0)
#define SW_PAD_GPIO1_IO03_BASE		(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值