实验七——字符设备驱动程序
日期:2016-6-10
一、实验目的
1. 学习嵌入式Linux的GPIO的使用方式;
2. 学习嵌入式Linux的Arduino接口库;
3. 学习使用面包板搭简单的外部电路;
4. 学习Linux设备驱动程序的开发过程。
5. 学习在内核中访问外设寄存器,操纵外设的方法。
二、实验器材
硬件
Ÿ Linux实验板卡一块;
Ÿ 5V/1A电源一个;
Ÿ microUSB线一根;
Ÿ MAX7219驱动的8x8 LED矩阵一个
;
Ÿ 面包板一块
;
Ÿ PC(Windows/Linux)一台;
Ÿ USB-TTL串口线一根;
软件
Ÿ 交叉编译软件;
Ÿ Fritzing。
三、实验步骤
1. 设计方案,画连线示意图;
Vcc-1,Clk-2,Cs-3,Din-4,Gnd-5
2. 在面包板上连线,完成外部电路;
3. 编写C/C++程序,采用Arduino-ish库或虚拟文件系统访问GPIO,实现在矩阵上显示文字或图案;
使用WiringPi库访问GPIO,在矩阵上显示图案“ZJ”
#define DIN 4
#define CS 3
#define CLK 2
#include
#include
#include
#include
void write_byte(unsigned charb){
unsigned char i, tmp;
for (i=0; i<8; i++){
tmp = (b & 0x80) > 0;
b <<= 1;
if(tmp==1){
digitalWrite(DIN,HIGH);
}
else{
digitalWrite(DIN,LOW);
}
digitalWrite(CLK, HIGH);
digitalWrite(CLK, LOW);
}
}
void write_word(unsigned charaddr, unsigned char num){
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
digitalWrite(CLK, LOW);
write_byte(addr);
write_byte(num);
digitalWrite(CS, HIGH);
}
void Matrix_init(){
write_word(0x09, 0x00);
write_word(0x0a, 0x03);
write_word(0x0b, 0x07);
write_word(0x0c, 0x01);
}
void Matrix_render(unsignedchar* tmp){
int i;
for (i=0; i<8; i++){
printf("%d %d
", i, tmp[i]);
write_word(i+1, tmp[i]);
}
}
void Matrix_clear(){
unsigned char ZJ[]={
0xF8, 0x10, 0x2F, 0x41, 0xF9, 0x01, 0x09,0x06
};
Matrix_render(ZJ);
}
int main(){
wiringPiSetup();
pinMode(DIN,OUTPUT);
pinMode(CS,OUTPUT);
pinMode(CLK,OUTPUT);
Matrix_init();
Matrix_clear();
return 0;
}
4. 编写字符设备驱动程序,直接访问GPIO控制寄存器,能将write()送来的单个字符在矩阵上显示出来
内核模块编写:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DIN 4
#define CS 3
#define CLK 2
void write_byte(unsigned charb){
unsigned char i, tmp;
for (i=0; i<8; i++){
tmp = (b & 0x80) > 0;
b <<= 1;
gpio_set_value(DIN, tmp);
gpio_set_value(CLK, 1);
gpio_set_value(CLK, 0);
}
}
void write_word(unsigned charaddr, unsigned char num){
gpio_set_value(CLK, 0);
gpio_set_value(CS, 1);
gpio_set_value(CS, 0);
write_byte(addr);
write_byte(num);
gpio_set_value(CS, 1);
}
void Matrix_render(unsignedchar* tmp){
int i;
for (i=0; i<8; i++){
write_word(i+1, tmp[i]);
}
}
unsigned char digits[][8]={
{0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,0x1c}, // 0
{0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08,0x1c}, // 1
{0x1c, 0x22, 0x22, 0x04, 0x08, 0x10, 0x20, 0x3e},// 2
{0x1c, 0x22, 0x02, 0x0c, 0x02, 0x02, 0x22,0x1c}, // 3
{0x04, 0x0c, 0x14, 0x14, 0x24, 0x1e, 0x04,0x04}, // 4
{0x3e, 0x20, 0x20, 0x3c, 0x02, 0x02, 0x22,0x1c}, // 5
{0x1c, 0x22, 0x20, 0x3c, 0x22, 0x22, 0x22,0x1c}, // 6
{0x3e, 0x24, 0x04, 0x08, 0x08, 0x08, 0x08,0x08}, // 7
{0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22,0x1c}, // 8
{0x1c, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x22,0x1c}, // 9
};
unsigned char ZJ[]={
0xF8,0x10, 0x2F, 0x41, 0xF9, 0x01, 0x09, 0x06
};
void Matrix_clear(void){
Matrix_render(ZJ);
}
void Matrix_init(void){
write_word(0x09, 0x00);
write_word(0x0a, 0x03);
write_word(0x0b, 0x07);
write_word(0x0c, 0x01);
Matrix_clear();
}
#define BUFFERSIZE 128
#define DELAYTIME 1
unsigned char disp[BUFFERSIZE];
int head = 0, tail = 0;
static struct timer_list timer;
void Matrix_next_display(unsignedlong);
void ptr_inc(int *ptr){
*ptr = (*ptr + 1) % BUFFERSIZE;
}
static voidtimer_register(struct timer_list* ptimer){
init_timer(ptimer);
ptimer->data = DELAYTIME;
ptimer->expires = jiffies + (DELAYTIME *HZ);
ptimer->function = Matrix_next_display;
add_timer(ptimer);
}
void disp_start(void){
timer_register(&timer);
}
voidMatrix_next_display(unsigned long data){
if (head != tail){
unsigned char *ptr = LM;
unsigned char c = disp[head];
if ('0' <= c && c <='9'){
ptr = digits[c - '0'];
}
Matrix_render(ptr);
ptr_inc(&head);
disp_start();
}else{
Matrix_clear();
}
}
static int matrix_write(structfile *file, const char __user *buffer,
size_t count, loff_t *ppos){
int i;
if (head == tail && count > 0){
disp_start();
}
for (i=0; i
编译内核模块,载入,运行。该模块在加载到系统内部时,会申请在/dev目录下生成一个matrix文件。使用的时候直接向其输出想要在点阵上显示的字符即可。
pi@raspberrypi ~ $make
pi@raspberrypi ~ $ sudo insmod matrix.ko
pi@raspberrypi ~ $ cd /dev
pi@raspberrypi /dev $ sudochown pi:pi matrix
pi@raspberrypi /dev $ echo0123456789 > matrix
5. GPIO库的来源 -> 安装了Wiringpi库