实验连接示意图、实物图

所用器材列表
硬件
- Linux实验板卡一块
- 5V/1A电源一个
- microUSB线一根
- 面包板一块
- MAX7219驱动的8*8LED矩阵一个
- 面包线若干
- PC一台
- 以太网线一根
软件
- 编译软件
- Fritzing
外部设备连线图

实验步骤
1. 设计方案,画连线示意图
2. 在面包板上连线,完成外部电路
3. 编写C/C++程序,采用Arduido-ish库或虚拟文件系统访问GPIO,实现在矩阵上显示文字或图案
1) 使用ssh连接上Raspberry
2) 编写C/C++程序,通过虚拟文件系统控制GPIO
3) 编译并执行C/C++程序,执行结果如下

4. 编写字符设备驱动程序,直接访问GPIO控制寄存器,能将write() 送来的单个字符在矩阵上显示出来
1) 编写字符设备驱动的内核模块程序
2) 编译程序并将内核模块插入
3) 使用驱动程序在矩阵上显示数字










代码和解释
1. 利用虚拟文件系统访问GPIO,实现在矩阵上显示文字或图案
1
| #define DIN 4
#define CS 3
#define CLK 2
GPIO_Pin din, cs, clk;
int write_byte(unsigned char b){
unsigned char i, tmp;
for (i=0; i<8; i++){
tmp = (b & 0x80) > 0;
b <<= 1;
GPIO_Pin_Write(&din, tmp);
GPIO_Pin_Write(&clk, 1);
GPIO_Pin_Write(&clk, 0);
}
}
int write_word(unsigned char addr, unsigned char num){
GPIO_Pin_Write(&cs, 1);
GPIO_Pin_Write(&cs, 0);
GPIO_Pin_Write(&clk, 0);
write_byte(addr);
write_byte(num);
GPIO_Pin_Write(&cs, 1);
}
int Matrix_init(){
write_word(0x09, 0x00);
write_word(0x0a, 0x03);
write_word(0x0b, 0x07);
write_word(0x0c, 0x01);
}
int Matrix_render(unsigned char* tmp){
int i;
for (i=0; i<8; i++){
printf("%d %d\n", i, tmp[i]);
write_word(i+1, tmp[i]);
}
}
int Matrix_clear(){
unsigned char SCN[]={
0xFF, 0x01, 0x01, 0xFF, 0xFF, 0x01, 0x01, 0xFF
};
Matrix_render(SCN);
}
int main(){
GPIO_Pin_export(&din, DIN, GPIO_DIRECTION_OUT);
GPIO_Pin_export(&cs, CS, GPIO_DIRECTION_OUT);
GPIO_Pin_export(&clk, CLK, GPIO_DIRECTION_OUT);
Matrix_init();
Matrix_clear();
return 0;
}
|
2. 字符设备驱动程序
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/workqueue.h>
MODULE_LICENSE("GPL");
#define DIN 4
#define CS 3
#define CLK 2
void write_byte(unsigned char b){
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 char addr, 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(unsigned char* 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},
{0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c},
{0x1c, 0x22, 0x22, 0x04, 0x08, 0x10, 0x20, 0x3e},
{0x1c, 0x22, 0x02, 0x0c, 0x02, 0x02, 0x22, 0x1c},
{0x04, 0x0c, 0x14, 0x14, 0x24, 0x1e, 0x04, 0x04},
{0x3e, 0x20, 0x20, 0x3c, 0x02, 0x02, 0x22, 0x1c},
{0x1c, 0x22, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x1c},
{0x3e, 0x24, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08},
{0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c},
{0x1c, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x22, 0x1c},
};
unsigned char SCN[]={
0x99, 0x01, 0x01, 0x99, 0x99, 0x01, 0x01, 0x99
};
void Matrix_clear(void){
Matrix_render(SCN);
}
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(unsigned long);
void ptr_inc(int *ptr){
*ptr = (*ptr + 1) % BUFFERSIZE;
}
static void timer_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);
}
void Matrix_next_display(unsigned long data){
if (head != tail){
unsigned char *ptr = SCN;
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(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos){
int i;
if (head == tail && count > 0){
disp_start();
}
for (i=0; i<count; i++){
ptr_inc(&tail);
if (tail == head)
ptr_inc(&head);
disp[tail] = buffer[i];
}
return count;
}
static struct file_operations matrix_fops = {
.owner = THIS_MODULE,
.write = matrix_write,
.llseek = noop_llseek
};
static struct miscdevice matrix_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "matrix",
.fops = &matrix_fops
};
static int __init matrix_init(void){
if (!gpio_is_valid(DIN) || !gpio_is_valid(CLK) || !gpio_is_valid(CS)){
printk(KERN_INFO "GPIO_TEST: invalid GPIO\n");
return -ENODEV;
}
misc_register(&matrix_misc_device);
gpio_request(DIN, "sysfs");
gpio_direction_output(DIN, 0);
gpio_request(CS, "sysfs");
gpio_direction_output(CS, 1);
gpio_request(CLK, "sysfs");
gpio_direction_output(CLK, 0);
Matrix_init();
printk(KERN_INFO"matrix device has been registed.\n");
return 0;
}
static void __exit matrix_exit(void){
misc_deregister(&matrix_misc_device);
printk(KERN_INFO"matrix device has been unregisted.\n");
del_timer(&timer);
}
module_init(matrix_init);
module_exit(matrix_exit);