TQ2440上LED灯闪烁效果的驱动程序实现

本篇文章的驱动程序实现的要点:一是实现了设备文件的自动创建,不用每次运行驱动都要使用mknod指令自动创建设备文件,本文通过udev(mdev)来实现设备文件的自动创建。二是对LED灯的控制不是通过直接设置相关GPIO的二进制位来实现,本文使用linux系统中提供的对S3C2410 GPIO的操作函数,直接实现对相关GPIO的控制。三是实现了LED灯的闪烁效果,本文虽然没有在驱动程序代码中直接实现LED灯的闪烁效果,但是通过上层应用程序调用驱动程序中的ioctl间接实现了LED灯的闪烁效果。

一,驱动程序源代码My_Led.c:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h> //定义s3c2410的GPIO,S3C2410_GPB5至S3C2410_GPB8 
#include <mach/hardware.h> //定义操作s3c2410的GPIO的函数  
#include <linux/device.h> //自动创建设备文件应该包含的头文件 

#define DEVICE_NAME  "My_led" //加载模块后执行cat/proc/devices中看到的设备名称
#define Led_MAJOR        103        //主设备号
#define LED_ON        1
#define LED_OFF      0

//Led的控制引脚
//注意S3C2410_GPB5就是GPIO的编号,类型定义为unsigned long
//编号的规则是把所有的io口从0开始进行统一编号,如S3c2410_GPA0=0 S3c2410_GPA1=1 S3C2410_GPB0=32 
static unsigned long led_table[] =
{
    S3C2410_GPB5,
    S3C2410_GPB6, 
    S3C2410_GPB7,
    S3C2410_GPB8,
};

static int My_led_open(struct inode *inode,struct file *file)
{
    printk("My_led  open\n");
    return 0;
}

static int My_led_ioctl(struct inode * inode, struct file * file,unsigned int cmd,unsigned long arg)
{
    if(arg > 4)
    {
       return -1;            
    }
    switch(cmd)
    {
       case LED_ON:
            s3c2410_gpio_setpin(led_table[arg], 0);//设置指定引脚为输出电平为0
            return 0;
       case LED_OFF:
            s3c2410_gpio_setpin(led_table[arg], 1);//设置指定引脚为输出电平为1
            return 0;
    default:
    return  -1;
   }
}

//定义文件操作 file_operations
static struct file_operations My_led_fops =
{
  .owner = THIS_MODULE,
  .open = My_led_open,
  .ioctl = My_led_ioctl,
};

static struct class *led_class;

static int __init My_led_init(void)
{
   int ret;
   printk("My_led start\n");

   //册字符设备驱动程序
   //参数为主设备号、设备名字、file_operations结构
   //这样主设备号就与file_operations联系起来
   ret = register_chrdev(Led_MAJOR, DEVICE_NAME, &My_led_fops);
   if(ret < 0)
   {
       printk("can‘t register major number\n");
       return ret;
   }

   //注册一个类,使mdev可以在"/dev/目录下建立设备节点"
   led_class = class_create(THIS_MODULE, DEVICE_NAME);
   if(IS_ERR(led_class))
   {
      printk("failed in My_led class.\n");
      return -1;
   }
   device_create(led_class, NULL, MKDEV(Led_MAJOR,0), NULL, DEVICE_NAME);
   printk(DEVICE_NAME "initialized\n");
   return 0;
}

static void __exit My_led_exit(void)
{
   unregister_chrdev(Led_MAJOR, DEVICE_NAME);
   device_destroy(led_class, MKDEV(Led_MAJOR,0));//注销设备节点
   class_destroy(led_class);//注销类
}

module_init(My_led_init);
module_exit(My_led_exit);

MODULE_LICENSE("GPL");

源码分析:

1.本驱动程序中设备文件的自动创建是通过在驱动初始化代码里调用class_create为该设备创建一个class,然后再为设备调用device_create创建对应的设备。class_create和device_create定义在内核源码include/linux下,可去此目录查看他们的定义。

2.本驱动程序通过内核中提供的对S3C2410 GPIO的操作函数S3C2410_gpio_setpin来控制指定引脚高低电平的输出。此函数定义在hardware.h的头文件中,需在驱动程序中添加#include<mach/hardware.h> 。

3.至于LED灯闪烁效果的实现等下将上层应用程序代码列出来后再进行分析。

二,Makefile文件:

obj-m:=My_led.o
CC=arm-linux-gcc
KERNELDIR=/usr/local/opt/EmbedSky/linux-2.6.30.4
PWD:=$(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

三,驱动对应的上层应用程序源代码My_Led_Test.c

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>      
#include <sys/types.h>    
#include <sys/stat.h>  
#include <fcntl.h>    
int main()  
{  
    int fd,i,cmd=0;      
    fd=open("/dev/My_led",0); 
    if (fd<0)  
    {  
        printf("open led_driver error");  
        exit(1);  
    }
    while(1)
    {
       switch(cmd)
       {
          case 0:
          printf("All off\n");
          for(i = 0;i < 4;i ++)
              ioctl(fd,0,i); 
          for(i=0;i<100;++i);
          
          case 1:
          printf("light first led\n");
          ioctl(fd,1,0); 
          for(i=0;i<100;++i);
          
          case 2:
          printf("light second led\n");
          ioctl(fd,0,0);
          ioctl(fd,1,1); 
          for(i=0;i<100;++i);
          
          case 3:
          printf("light third led\n");
          ioctl(fd,0,1);
          ioctl(fd,1,2); 
          for(i=0;i<100;++i);
          
          case 4:
          printf("light fourth led\n");
          ioctl(fd,0,2);
          ioctl(fd,1,3); 
          for(i=0;i<100;++i);
          
          case 5:
          printf("All light \n");
          for(i = 0;i < 4;i ++)
          ioctl(fd,1,i); 
          for(i=0;i<100;++i);
       }
    }   
    return 0;  
 }

源码分析:

case0,case1,case2,case3,case4,case5分别表示四盏灯全灭,第一盏灯亮,第二盏灯亮,第三盏灯亮,第四盏灯亮,四盏灯全亮,这四个case彼此之间都使用一个空循环for来实现延迟的效果,从而最终实现LED灯闪烁的效果。

时间: 2024-10-20 07:55:01

TQ2440上LED灯闪烁效果的驱动程序实现的相关文章

四、按键控制LED灯亮灭

材料: 1.SAGOO UNO 1块: 2.按键模块 1块: 3.杜邦线若干. 步骤: 1.按照下图连接按键模块和UNO: SAGOO UNO引脚                                      按键模块引脚 3V3  <------------------------------------>    V(电源) GND <------------------------------------>    G(电源) Pin2  <----------

Arduino 翻译系列 - LED 灯闪烁

原文地址 - https://www.arduino.cc/en/Tutorial/Blink 闪烁 这个例子展示了你能拿 Arduino / Genuino 板子来干的最简单的事:使开发板上的 LED 灯闪烁. 硬件需求 Arduino 开发板 LED (非必要) 220欧电阻(非必要) 电路 这例程使用了大部分 Arduino / Genuino 开发板上都有的 LED 指示灯.这 LED 灯是连接到数字引脚的,而它在不同型号的开发板上的引脚号都不一样.为了方便大家,我们已经每种开发板的描述

如何在家自制LED灯?很简单,我来告诉你!

首先LED分凸头.平头和凹头,当中的凹头是没无方向性. 做示宽灯这类晚间才运用的光源,用凹头就好,它没无方向性,可将整个反光碗照亮. 做转向灯等指示性的光源用,准绳上应该用凸头的,它是个聚光镜,投映的光点小.亮度高.投光方向性强,不易受外界光照的影响. 但是平凡LED的亮度远不及白炽灯,包括所谓超亮型的,跟同体积.同功耗的白炽灯相比,在少数条件下仍有差距. 指望靠十几只乃至几只LED获得一个灯泡的结果是不实在际的,比方做佳星的转向灯光源时,原灯具的反光板根本上没有作用了,完全要靠LED本身收回的

第七章主要讲的是控制发光二极管的驱动程序,用来控制开发板上的4个led灯

首先讲了led驱动的实现原理,linux驱动并不是直接向硬件的内存中写数据,而是与本机的i/o内存进行交互,每一个连接linux的硬件在i/o内存中都会有映射首地址. 编写驱动程序,先创建led驱动的设备文件: 1.使用cdev_init函数初始化cdev 描述设备文件需要一个cdev的结构体,cdev的大多是成员变量并不需要我们去初始化,只要调用cdev_init函数就可以初始化大部分cdev的成员变量 2.指定设备号 Linux 的设备的文件号分为 主设备号和此设备号,设备号有两种指定方法:

TQ2440按键点亮LED灯的裸机程序

一,说到做ARM的裸机程序,很多人马上就会联想到一个名为ADS的开发工具,但是我们在linux下同样也可以做ARM的裸机程序,下面来说说其具体实施过程: 步骤一:编辑代码,这个没什么好说的. 步骤二:编译代码,编译代码分为三个方面的内容:1.链接脚本 2.用命令行确定链接时的文件顺序 3.用命令行编译.这三部分的内容可以全部写成一个Makefile文件,编译的时候执行make命令就可以了. 步骤三:把编译后的".bin"文件烧写进开发板,重新上电观察效果. 二,TQ2440按键点亮LE

第一个FPGA工程----点亮开发板上的3个LED灯

第一个FPGA工程----点亮开发板上的3个LED灯 1.新建FPGA工程 开启Quartus2的画面 File--New Project Wizard..指定工程的路径与工程名 指定所使用的FPGA设备型号 2.添加设计文件 本设计采用Verilog HDL硬件描述语言建模 3.建模 本设计有三个输出量,没有输入量,这三个输出量对应FPGA芯片的三个管脚,同时被置高电平,用来驱动LED灯. 4.编译工程 Processing--Start compilation 并生成编译报告 5.引脚分配

在 S5PV210 的 开发板上 点亮 一个 LED 灯

参考学习教程:周立功嵌入式Linux开发教程-(上册) 材料:首先 准备一个 安装好 Linux 的 开发板 使用  xshell 工具 连接 开发板  ,winscp 工具 连接 开发板  ,  准备 一个 Ubuntu  32位 ,装上 交叉编译链.. 使用下面 代码 和 Makefile 文件 进行编译  ,生成的  执行 文件  利用 winscp 软件复制到 Linux开发板上 ,利用 xshell 运行 这个可执行文件. 下面    代码的  功能  是   新建 一个 TCP 客户

Beaglebone Black - 控制 BBB 板上的 LED 灯

BBB 的板上有五个 LED 灯,一个电源,四个其他指示灯,usr0 至 usr3 .这次学习是控制 usr0 至 3 让它们亮着,熄灭,闪.算是个 Hello World 实验.非常简单. 需要的材料: BBB 一台 购买BBB 自带的数据线一条 手提电脑或台式电脑,有 USB 插头的 首先用数据线把 BBB 和电脑连接,自动开机了之后,可以开始了. 这次三个做法都试试: Bonescript Python C++ Bonescript 操作 Bonescript 做法是用 Cloud9,假设

基于TINY4412的Andorid开发-------简单的LED灯控制【转】

本文转载自:http://www.cnblogs.com/pengdonglin137/p/3857724.html 基于TINY4412的Andorid开发-------简单的LED灯控制 阅读目录(Content) 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源代码情景分析> <嵌入式Linux系统开发完全手册_基于4412_上册> 作者:彭东林 邮箱:[em