012——LED模块驱动开发(基于I.MX6uLL)

这篇具有很好参考价值的文章主要介绍了012——LED模块驱动开发(基于I.MX6uLL)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、 硬件原理图

二、 驱动程序

三、 应用程序

四、 Makefile

五、操作


一、 硬件原理图

        又是非常经典的点灯环节 ,每次学新语言第一步都是hello world,拿到新板子或者学习新的操作系统,第一步就是点灯。

        LED 的驱动方式,常见的有四种。
① 使用引脚输出 3.3V 点亮 LED,输出 0V 熄灭 LED。
② 使用引脚拉低到 0V 点亮 LED,输出 3.3V 熄灭 LED。
有的芯片为了省电等原因,其引脚驱动能力不足,这时可以使用三极管驱动。
③ 使用引脚输出 1.2V 点亮 LED,输出 0V 熄灭 LED。
④ 使用引脚输出 0V 点亮 LED,输出 1.2V 熄灭 LED。
由此,主芯片引脚输出高电平/低电平,即可改变 LED 状态,而无需关注 GPIO
引脚输出的是 3.3V 还是 1.2V。所以简称输出 1 或 0:
⚫ 逻辑 1-->高电平
⚫ 逻辑 0-->低电平
        SOC级别的芯片通常电压都比较低,像我们之前用的exynos4412他是1.8V的,我们的i.MX6ULL则是可以做到更低的逻辑1,1.2V。现在最新的技术好像是0.8V的。电压降低的好处就是我们的功耗大幅减小。MCU为什么不降低呢,因为它是控制器需要高电压的驱动环境,所以一般都是3.3V和5V的。

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

这是板子上的LED的原理图

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

6ull的GPIO是这样描述的

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

看上面的原理图我找到了

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

        第五组GPIO的第三个也就是4*32+4-1 = 131

        每组GPIO有32个,我们0开始所以就是128+3 ,131就是我们的GPIO号

        知道这个就差不多可以写驱动程序了,这就是由操作系统和无操作系统的区别,裸机开发的话我们还要找到其它的寄存器,上面说到的那八个都要找到,但是因为GPIO是通用外设,操作系统已经处理过了,所以我们用的话就会很轻松,甚至可以直接给dev下的GPIO设备写值来控制。

然后我们就可以写代码了

二、 驱动程序

#include "asm-generic/errno-base.h"
#include "asm-generic/gpio.h"
#include "asm/uaccess.h"
#include <linux/module.h>
#include <linux/poll.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>

struct gpio_desc{
	int gpio;
	int irq;
    char *name;
    int key;
	struct timer_list key_timer;
} ;

static struct gpio_desc gpios[2] = {
    {131, 0, "led0", },
    //{132, 0, "led1", },
};

/* 主设备号                                                                 */
static int major = 0;
static struct class *gpio_class;


/* 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t gpio_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	char tmp_buf[2];
	int err;
    int count = sizeof(gpios)/sizeof(gpios[0]);

	if (size != 2)
		return -EINVAL;

	err = copy_from_user(tmp_buf, buf, 1);

	if (tmp_buf[0] >= count)
		return -EINVAL;

	tmp_buf[1] = gpio_get_value(gpios[tmp_buf[0]].gpio);

	err = copy_to_user(buf, tmp_buf, 2);
	
	return 2;
}

static ssize_t gpio_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
    unsigned char ker_buf[2];
    int err;

    if (size != 2)
        return -EINVAL;

    err = copy_from_user(ker_buf, buf, size);
    
    if (ker_buf[0] >= sizeof(gpios)/sizeof(gpios[0]))
        return -EINVAL;

    gpio_set_value(gpios[ker_buf[0]].gpio, ker_buf[1]);
    return 2;    
}



/* 定义自己的file_operations结构体                                              */
static struct file_operations gpio_key_drv = {
	.owner	 = THIS_MODULE,
	.read    = gpio_drv_read,
	.write   = gpio_drv_write,
};


/* 在入口函数 */
static int __init gpio_drv_init(void)
{
    int err;
    int i;
    int count = sizeof(gpios)/sizeof(gpios[0]);
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	for (i = 0; i < count; i++)
	{		
		/* set pin as output */
		err = gpio_request(gpios[i].gpio, gpios[i].name);
		if (err < 0) {
			printk("can not request gpio %s %d\n", gpios[i].name, gpios[i].gpio);
			return -ENODEV;
		}
		
		gpio_direction_output(gpios[i].gpio, 1);
	}

	/* 注册file_operations 	*/
	major = register_chrdev(0, "100ask_led", &gpio_key_drv);  /* /dev/gpio_desc */

	gpio_class = class_create(THIS_MODULE, "100ask_led_class");
	if (IS_ERR(gpio_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "100ask_led_class");
		return PTR_ERR(gpio_class);
	}

	device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "100ask_led"); /* /dev/100ask_gpio */
	
	return err;
}

/* 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数
 */
static void __exit gpio_drv_exit(void)
{
    int i;
    int count = sizeof(gpios)/sizeof(gpios[0]);
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	device_destroy(gpio_class, MKDEV(major, 0));
	class_destroy(gpio_class);
	unregister_chrdev(major, "100ask_led");

	for (i = 0; i < count; i++)
	{
		gpio_free(gpios[i].gpio);		
	}
}


/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */

module_init(gpio_drv_init);
module_exit(gpio_drv_exit);

MODULE_LICENSE("GPL");


三、 应用程序


#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>

static int fd;


//int led_on(int which);
//int led_off(int which);
//int led_status(int which);

/*
 * ./led_test <0|1|2|..>  on 
 * ./led_test <0|1|2|..>  off
 * ./led_test <0|1|2|..>
 */
int main(int argc, char **argv)
{
	int ret;
	char buf[2];

	int i;
	
	/* 1. 判断参数 */
	if (argc < 2) 
	{
		printf("Usage: %s <0|1|2|...> [on | off]\n", argv[0]);
		return -1;
	}


	/* 2. 打开文件 */
	fd = open("/dev/100ask_led", O_RDWR);
	if (fd == -1)
	{
		printf("can not open file /dev/100ask_led\n");
		return -1;
	}

	if (argc == 3)
	{
		/* write */
		buf[0] = strtol(argv[1], NULL, 0);

		if (strcmp(argv[2], "on") == 0)
			buf[1] = 0;
		else
			buf[1] = 1;
		
		ret = write(fd, buf, 2);
	}
	else
	{
		buf[0] = strtol(argv[1], NULL, 0);
		ret = read(fd, buf, 2);
		if (ret == 2)
		{
			printf("led %d status is %s\n", buf[0], buf[1] == 0 ? "on" : "off");
		}
	}
	
	close(fd);
	
	return 0;
}


四、 Makefile

韦东山老师的makefile写的有点太潦草了,我们来优化一下

CC := $(CROSS_COMPILE)gcc
FILE_NAME = led_test
DRIVER_NAME = led_drv
# 定义NFS根文件系统目录  
FS_FILE = ~/nfs_rootfs

KERN_DIR =  /home/book/program/100ask_imx6ull_mini-sdk/Linux-4.9.88 # 板子所用内核源码的目录

# all:
# 	make -C $(KERN_DIR) M=`pwd` modules 
# 	$(CROSS_COMPILE)gcc -o led_test led_test.c
# 默认目标  
all:  
	@echo "Starting build process..."  
	@echo "Building kernel modules..."  
	make -C $(KERN_DIR) M=$(PWD) modules  
	@echo "Building $(FILE_NAME) test program..."  
	$(CC) -o $(FILE_NAME) $(FILE_NAME).c  

# 安装目标  
install:  
	@echo "Installing $(DRIVER_NAME).ko to $(FS_FILE)..."  
	cp ./$(DRIVER_NAME).ko $(FS_FILE)  
	@echo "$(DRIVER_NAME).ko installed."  
	@echo "Installing $(FILE_NAME) to $(FS_FILE)..."  
	cp ./$(FILE_NAME) $(FS_FILE)  
	@echo "$(FILE_NAME) installed."  

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order  led_test

# 参考内核源码drivers/char/ipmi/Makefile
# 要想把a.c, b.c编译成ab.ko, 可以这样指定:
# ab-y := a.o b.o
# obj-m += ab.o

obj-m += led_drv.o
# 声明伪目标  
.PHONY: all clean install

五、操作

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

每次都要重新配置网络很难受所以我这面写了个脚本上机自动配置ip并且挂载nfs 

#!/bin/bash  
  
# 定义变量  
NFS_SERVER="192.168.5.10"  
NFS_SHARE="/home/book/nfs_rootfs"  
IPADDR="192.168.5.110"
MOUNT_POINT="/mnt"
INTERFACE="eth0"  
# 设置本机IP
sleep 1
ifconfig $INTERFACE $IPADDR
sleep 1

# 测试与NFS服务器的连通性  
ping -c 1 $NFS_SERVER > /dev/null 2>&1  
if [ $? -eq 0 ]; then  
    echo "NFS服务器 $NFS_SERVER 连通性正常"  
else  
    echo "无法与NFS服务器 $NFS_SERVER 建立连接"  
    exit 1  
fi  
  
# 检查挂载点是否存在,如果不存在则创建  
if [ ! -d "$MOUNT_POINT" ]; then  
    mkdir -p "$MOUNT_POINT"  
fi  
  
# 尝试挂载NFS共享  
mount -t nfs -o nolock,vers=3 $NFS_SERVER:$NFS_SHARE $MOUNT_POINT  
if [ $? -eq 0 ]; then  
    echo "NFS共享已成功挂载到 $MOUNT_POINT"  
else  
    echo "无法挂载NFS共享到 $MOUNT_POINT"  
    exit 1  
fi

最后我们上传一下

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile

012——LED模块驱动开发(基于I.MX6uLL),# 基于鸿蒙的芯片评估板自检系统,linux,嵌入式,驱动开发,脚本开发,shell,c,Makefile文章来源地址https://www.toymoban.com/news/detail-849398.html

到了这里,关于012——LED模块驱动开发(基于I.MX6uLL)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux驱动开发 ST7789 LCD驱动移植(I.MX6ULL平台)

    前言 I.MX6ULL的板子未选配RGB的屏幕,无法在板子上进行GUI的开发调试,不过手头上有块控制器为ST7789V3的LCD屏幕(1.3inch),通过简易接线后可以很方便进行驱动的移植 如有异议,欢迎留言指正 ST7789 LCD控制器 ST7789是一款单芯片TFT-LCD控制器,支持并口与SPI通信方式 特性 控制器支

    2023年04月09日
    浏览(70)
  • i.MX6ULL驱动开发 | 27 - 使用WM8960 CODEC播放音频

    WM8960是欧胜公司(wolfson)的一款低功耗、高质量的立体声音频编解码芯片。 其内部集成D类喇叭功放,每个通道可以驱动一个1W喇叭(8Ω),内部集成3个立体声输入源,可以灵活配置,拥有一路完整的麦克风接口。 WM8960内部ADC和DAC都为24位,主要特性如下: DAC的SNR(信噪比)

    2024年02月02日
    浏览(33)
  • I.MX6ULL开发笔记(二)——硬件外设操作

    在文章http://t.csdnimg.cn/EGWt9中有介绍Linux下文件目录,那么在Linux系统下,RGB灯也是一个设备,所以我们需要到 /sys 目录下去操作这个设备。 之后,我们进入到 class 目录,这里挂载着开发板上的外设: 在这里就能看到熟悉的硬件接口了,那么我们进入到 leds 的目录下: 可以看

    2024年01月24日
    浏览(35)
  • 使用一根网线,让Ubuntu和正点原子I.MX6ULL开发板互相ping通

    准备一根网线即可 2.1 找根网线将I.MX6ULL和电脑连起来 2.2 让I.MX6ULL通电运行起来,我这里使用的是正点原子版本的内核、 2.3 进入电脑的网络连接后,按照如下步骤操作 2.4 将ip地址、子网掩码、默认网关设置如下,= 注意,子网掩码一定要是255.255.255.0 IP地址推荐使用192.168.5.

    2024年02月19日
    浏览(31)
  • I.MX6ull UART

     一 简介 UART 全称叫做串行接口,通常也叫做 COM 接口,串行接口指的是数据一个一个的顺序传输,通信线路简单。使用两条线即可实现双向通信,一条用于发送,一条用于接收。串口通 信距离远 ,但是速 度相对会低 ,串口是一种很常用的工业接口。I.MX6U 自带的 UART 外设

    2024年02月09日
    浏览(25)
  • I.MX6ull EPIT定时器

    一 简介 EPIT定时器是一种增强的周期中断定时器,完成周期性中断定时的功能。 具有以下特点  EPIT定时器是一个32位的定时器  时钟源可选的向下计数器  EPIT 共有 3 个时钟源可选择,ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq  当计数值和比较值相等的时候产生中断  12 位分频器 对

    2024年02月08日
    浏览(34)
  • I.MX6ull GPT高精度定时器

    一 简介 GPT的全称是General Purpose Timer,它是一个32位的向上的定时器, GPT 定时器也可以跟一个值进行比较,当计数器值和这个值相等的话就发生比较事件,产生比较中断。GPT 定时器有一个 12 位的分频器,可以对 GPT 定时器的时钟源进行分频。 分析方式 同EPTI  它具有以下特点

    2024年02月08日
    浏览(31)
  • i.MX6ULL移植NXP官方Linux内核imx_5.4.47_2.2.0

    系统:Ubuntu18.04 参考资料:百问网 IMX6ULL开发板(从零移植篇-预览版)-V0.1,正点原子驱动开发指南 开发板:100ask i.MX6ULL PRO 交叉编译工具链的获取就不写了 打开 .bashrc 文件。 vi ~/.bashrc 。在该文件最后面添加如下(根据自己的交叉编译工具链) (1)直接从官网下载,非常慢而

    2024年02月12日
    浏览(38)
  • 【Linux 裸机篇(五)】I.MX6ULL BSP工程管理下的 Makefile编写、链接脚本

    文件夹 描述 bsp 存放驱动文件 imx6ul 存放跟芯片有关的文件,比如 NXP 官方的 SDK库文件 obj 存放编译生成的.o 文件 project 存放 start.S 和 main.c 文件,也就是应用文件 行 描述 1~7 定义了一些变量,除了第 2 行以外其它的都是跟编译器有关的,如果使用其它编译器的话只需要修改第

    2023年04月20日
    浏览(34)
  • 基于I.MX6ULL的Linux C多线程物联网网关+STM32+Qt上位机+Linux C++多线程服务器(含web)的多种无线通信系统的智慧农场

    我国是农业大国,而非农业强国。近30年来农业高产量主要依靠农药化肥的大量投入,大部分化肥和水资源没有被有效利用而随地弃置,导致大量养分损失并造成环境污染。我国农业生产仍然以传统生产模式为主,传统耕种只能凭经验施肥灌溉,不仅浪费大量的人力物力,也

    2024年04月14日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包