实验三嵌入式Linux驱动(1)
一、 【实验目的】
1) 熟悉嵌入式Linux驱动程序编写框架。
2) 了解七段数码管驱动程序的工作原理,熟练掌握该驱动程序在嵌入式开
发平台的移植和注册使用。
二、 【实验内容】
1) 学习Linux驱动源代码,分析代码中各个函数模块的功能作用。 2) 在宿主机上交叉编译七段数码管驱动程序,然后移植到目标机上。 3) 在目标机上注册驱动程序,验证驱动的功能。
三、 【实验步骤】
1. 了解七段数码管工作原理
七段数码管是显示数字的电子元件,因为借助七个发光二极管以不同组合来显示数字,所以称为七段数码管(如图1)。七段数码管分为共阴极和共阳极,共阳极的七段数码管的正极(或者阳极)为八个发光二极管的共有正极,其他接点为独立发光二极管的负极(或者阴极),使用者只需要把正极接电,不同的负极接地就可以控制七段数码管显示不同的数字。共阴极的七段数码管与共阳极的只是接电的接法相反而已。
图1
2. 开发板七段数码管电路介绍
开发板上有四个七段共阴数码管,2个一组,第一组七段数码管使用系统LED_CS2作为其位选使能信号,两个数码管的段选信号分别使用数据总线的D0~D7位和D8~D15位,如图2所示。
图2
第二组七段数码管使用系统LED_CS3作为其位选使能信号,两个数码管的段选信号分别使用数据总线的D0~D7位和D8~D15位,如图3所示。
图3
分析可知,对七段数码管的操作主要是对其位选和段选信号的控制。其 中位选信号决定显示哪个七段数码管,段选信号决定其显示的字型信息(共阴极七段数码管段选控制信息如表1),这也是驱动程序和硬件关联的主要部分。 字型 0 1 2 3 4 5 6 7 8 9 A B C D
D7 Dp 0 0 0 0 0 0 0 0 0 0 0 0 0 0 D6 G 1 0 1 1 1 1 1 0 1 1 1 1 0 1 D5 F 1 0 0 0 1 1 1 0 1 1 1 1 1 0 D4 E 1 0 1 0 0 0 1 0 1 0 1 1 1 1 D3 D 1 0 1 1 0 1 1 0 1 1 0 1 1 1 D2 C 1 1 0 1 1 1 1 1 1 1 1 1 0 1 D1 B 1 1 1 1 1 0 0 1 1 1 1 0 0 1 D0 A 1 0 1 1 0 1 1 1 1 1 1 0 1 0 编码 0X3F 0X06 0X5B 0X4F 0X66 0X6D 0X7D 0X07 0X7F 0X6F 0X77 0X7C 0X39 0X5E
E F 0 0 1 1 1 1 1 1 表1
1 0 0 0 0 0 1 1 0X79 0X71 3. 七段数码管驱动程序分析
1) 添加驱动程序所需的头文件和变量:SEG_CS1和SEG_CS2就是上面硬
件接口所提及的两组七段数码管的位选使能信号,LED[10]数组中保存的就是在共阴极数码管上面显示0~9的段选信号。Seg这个结构体用于保存4个数码管即时显示的数字的段选信号。
#include
#include #include
MODULE_LICENSE(\//用于声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时将收到内核被污染(kernel tainted)的警告 char LED_MODULE=0;
#define DEVICE_NAME \#define SEG_CS1 0x10300000 #define SEG_CS2 0x10400000
static char LED[10]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7F, 0x6F}; unsigned long *CS1_Address, *CS2_Address; structseg { char LED1_Val; char LED2_Val; char LED3_Val; char LED4_Val; char negative; };
2) 同时更新所有七段数码管驱动显示函数:CS1_address对应第一组七段数
码管的位选信号,该组第一个数码管的段选信号保存在short变量的低8位,该组第二个数码管的段选信号保存在short变量的高8位。CS2_address对应第二组七段数码管,其余操作和第一组的七段数码管一
致。
static void Updateled(struct seg *seg_7) { unsigned short buff=0x00; buff=seg_7->LED1_Val; buff=buff|( seg_7->LED2_Val <<8); writew(buff,CS1_Address); buff=0x00; buff=seg_7->LED3_Val; buff=buff|( seg_7->LED4_Val<<8); writew(buff,CS2_Address); return; }
3) 写具体某位七段数码光驱动管显示函数:position对应的是4个七段数码
管的相对位置,value就是需要更新的七段数码管要显示数字的段选信号值。
voidvalue_seting(struct seg *seg_7, char position, char value) { if (seg_7->negative==0) value=~value & ~(0x1<<7); else value=(0x1<<7)|value; if (position==1) seg_7->LED1_Val=value; else if(position==2) seg_7->LED2_Val=value; else if(position==3) seg_7->LED3_Val=value; else if(position==4) seg_7->LED4_Val=value; }
4) 实现七段数码管驱动写操作函数:把用户写入的数码管显示更新数据,
转换成为要显示数字对应的段选信号,并且保存在led_forall数组中,并且调用Value_setting更新显示数据,最后调用Updateled()更新实际的数码管显示信息。
staticssize_t seg7_write(struct file *file, const char *buffer, size_t count, loff_t *