感谢支持
我们一直在努力

Linux环境下的LED驱动[图文]

最近的时间了,本人都在从事软硬件间的程序设计,虽然我懂得不多,但是经过一段时间的摸索之后也找到了一些解决问题的方法。虽然从前的我,只会写软体程序,也从来没有想到我会接触到这个领域的东西,但是经过这几个月的努力终于有了一些小小的收获。
 
我所使用的实验平台是S3C2440A开发板,外观如下图: 


Linux环境下的LED驱动[图文]

 
这篇文章主要针对如何在Linux环境下驱动LED灯号做一个简单的说明,内容包含如何撰写一个Linux的module、如何使用module、如何测试module。在嵌入式系统中最常碰到的事情就是要控制周边的装置,例如灯号、蜂鸣器等等,这些装置可以通过GPIO来做控制,GPIO到底是什麽东西呢?你可以把GPIO当作是一堆可以控制周边装置的暂存器,每个暂存器都会有他对应的实体位置,对这些暂存器设定一些数值就可以控制周边的装置。我们先从最简单的LED控制开始研究,其他的装置都是大同小异,我也会在后面的文章中陆陆续续的说明这些装置如何来实作。我们假设已经可以正常的从S3C2440实验版上通过boot loader正常开机,并且载入Linux作业系统。如果我们能在Linux作业系统下控制LED灯号的亮或暗,就完成本文章的目的。
 
目前开发板上所使用的作业系统为Linux 2.4.18,所以该模组是针对2.4.18所撰写的,所以必须在编辑环境(我们所使用的开发环境是Dev-C++,请参考之前的文章)中include到2.4.18的kernel,设定的方法:「专桉(p)」->「专桉选项」,会弹出如下图的视窗,请设定「档桉/目录」->「引入标头档目录」,加入Linux 2.4.18中的include的目录。 


Linux环境下的LED驱动[图文]

 
接下来我们必须先了解一下灯号的接线,了解灯号到底使用到哪些GPIO,你可以去翻阅你手边所拥有的线路图,应该能找到一份有关Led的讯号接线方式,如下图所示:


Linux环境下的LED驱动[图文]


从图中你可以了解到控制第一个Led是由EINT4/GPF4来做控制的,有些线路图可能不会直些写出是哪个GPIO,你可能要去找找这个符号对应到2440A处理器的哪一个接脚以得知是由哪个GPIO控制。这张图显示第一个灯号是由GPF4所控制,当你知道是由GPF4所控制你可以从S3C2440A的规格书中得知对应的Address,如下图所示:


Linux环境下的LED驱动[图文]

当你已经得知这些基本的资料后可以开始撰写Linux的驱动程序。

如何撰写一个Linux的module

在这裡我们打算以module的方式将led driver放进Linux中,这种方式能让你日后容易维护,有需要修改时只要将该module修改好之后就可以使用,不必重新编译整个Linux Kernel。
一个module必须包含的三个东西:
 
1.  提供哪些控制的方法
struct file_operations QuickMarkLed_ctl_fops= { 方法: 函数名称, 方法: 函数名称…};
方法:如ioctl
函数名称:如QuickMarkLed_ctl_ioctl,该函数后面要自己实作,撰写其动作方法
 
2.  初始化函数:
int init_module(void)
{
    //想要初始化的资料,我们会在这裡注册一个装置
    //register_chrdev(装置编号, 装置名称, 提供哪些控制的方法);
    //装置编号:0~255  随便选一个号码,建议选择127以后的号码,
    //          不要与系统其他装置的号码冲到
    //装置名称:一个字串,自己随便取,让使用者知道这是什麽装置
    //提供哪些控制的方法:是一个结构指标,裡面纪录可以对该装置做哪些动作,如read, write, ioctl…
}
 
3.  模组关闭函数:
void cleanup_module(void)
{
    //反注册该装置
    //其它记忆体的使用归还
}

所以一个模组是由这三部份组成,只要掌握好这三部份就快要成功了。再来我们要做的事就是存取装置暂存器,我们存规格书中知道GPFCON的位置是0x56000050,GPFDATA的位置是0x56000054,GPFUP的位置是0x56000058,因此我们在程序码定义了这些位置,我们以base=0x56000000加上0x50就是GPFCON,宣告如下:


#define GPIO_CTL_BASE  0x56000000
#define bGPIO(p)  __REG(GPIO_CTL_BASE + (p))
#define rGPFCON                  bGPIO(0x50)
#define rGPFDAT                  bGPIO(0x54)
#define rGPFUP                     bGPIO(0x58)

 
针对这些位置最控制,该bit是0就会亮灯,如果是1就会暗灯,如此控制灯号闪烁。void QuickMarkLed_ctl_ioctl(struct inode*inode,struct file *flip,U32 ledNumber, U32 ledStatus)函数提供外界控制灯号的方法,ledNumber表示要控制哪个灯号,目前开发板上有四个led灯号,ledStatus表示要使该灯号亮或不亮,可参考后面范例以了解其控制的方法。


程序码下载:让使用者能够控制实验版上的LED灯号,编译完成之后会产生main.o的档案 
 
 
如何使用module
将main.o改名为QuickMarkLed.o download到实验版上
在Linux下执行:
insmod QuickMarkLed.o
mknod /dev/QuickMarkLed c 221 0 
 
 
如何测试module
测试程序如下:


#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/kd.h>
#include <signal.h>
#include <errno.h>
 
int main(int argc, char *argv[])
{
    int testdev;
   
    //led test…
    testdev = open(“/dev/QuickMarkLed”,O_RDWR);   
    ioctl(testdev, 2, 1); //ioctl(device, led number, open/close)  open=1
    ioctl(testdev, argv[1][0]-‘0’, argv[2][0]-‘0’); //ioctl(device, led number, open/close)  open=1
    close(testdev);   
       
    return 0;
}

 
编译完该程序,如果成功出始化会先将第二个灯号设成亮,之后通过使用者输入了两个参数设定Led的明暗,假设编译完成产生执行档的档名叫leds
leds 1 1  ->表示第一个led亮
leds 1 0 -> 表示第一个led暗
leds 2 1 -> 表示第二个led亮…..以此类推

赞(0) 打赏
转载请注明出处:服务器评测 » Linux环境下的LED驱动[图文]
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏