700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 《LINUX设备驱动程序》学习之与硬件通信(并行接口)实例

《LINUX设备驱动程序》学习之与硬件通信(并行接口)实例

时间:2018-08-07 08:33:04

相关推荐

《LINUX设备驱动程序》学习之与硬件通信(并行接口)实例

在学习这一节内容时,我根据书本写了一个并口驱动程序,然后用一个LED发光二极管、一个电阻以及一些导线和电脑主机的并口连接了一条回路,最后通过测试程序控制LED灯的开启、关闭,验证了并口驱动程序的正确性。整个过程没出现什么意外状况,但是有网友指出,这个实验是非常危险的,所以如果你想尝试,得足够了解可能会出现的意外情况。

1. 并行接口(并口)简介

并行接口是常见的一种I/O接口,通常主机上是25针D型接口。其引脚如下:

为操作并行口,SPP(Standard Parallel Port标准并行接口)定义了寄存器,并映射到PC机的I/O空间。寄存器包括了以并口地址为基址的3块连续 的寄存器,并口地址常见为3BCH、378H和278H,其中都包括数据、状态和控制寄存器,分别对应数据、状态和控制信号线操作,通常称为数据端口、状 态端口和控制端口。打印机卡1的地址常为378H,其中数据口0378H、状态口0379H、控制口037AH;打印机卡2的地址常为278H,其中数据 口0278H、状态口0279H、控制口027AH。支持新的IEEE 1284标准的并口,使用8到16个寄存器,地址为378H or 278H,即插即用(Plug and Play)兼容的的并口适配器也可以重新加载。

并行接口输出的是TTL标准逻辑电平,其中,标准TTL为+5V,低压TTL 为+3.3V。一般情况下,小于0.8V是低电平,大于2V是高电平。

2. 驱动程序

2.1 驱动程序源码

/*ParaPortDEV.c*//*Created by Chung-shu on November 26th, */#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/fcntl.h>#include <asm/uaccess.h>#include <asm/io.h>#include <linux/ioport.h>#define DEV_NAME "ParaPortDEV"#define PARA_PORT_DATA_REGISTER_ADDR 0x0378#define PARA_PORT_STATUS_REGISTER_ADDR 0x0379MODULE_LICENSE ("GPL");int para_port_open(struct inode *inode, struct file *filp);int para_port_release(struct inode *inode, struct file *filp);ssize_t para_port_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);ssize_t para_port_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);int dev_major=240;int dev_minor=0;struct file_operations para_port_fops ={.owner = THIS_MODULE,.read = para_port_read,.write = para_port_write,.open = para_port_open,.release = para_port_release,};int para_port_init(void){int result;result = register_chrdev(dev_major, DEV_NAME, &para_port_fops);if (result < 0){printk("register character device error!\n");return result;}if(request_region(PARA_PORT_DATA_REGISTER_ADDR, 3, DEV_NAME)==NULL){printk("register IO port error!\n");exit(1);}return 0;}void para_port_exit(void){release_region(PARA_PORT_DATA_REGISTER_ADDR, 3);unregister_chrdev(dev_major, DEV_NAME);}int para_port_open(struct inode *inode, struct file *filp){return 0;}int para_port_release(struct inode *inode, struct file *filp){return 0;}ssize_t para_port_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){unsigned char status;int i;for (i = 0; i <count; i++){status = inb(PARA_PORT_STATUS_REGISTER_ADDR);rmb();put_user(status, (char *)(buf+i));}return count;}ssize_t para_port_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos){unsigned char data;int i;for (i = 0; i < count; i++){get_user(data, (char *)(buf+i));outb(data, PARA_PORT_DATA_REGISTER_ADDR);wmb();}return count;}module_init(para_port_init);module_exit(para_port_exit);

2. 2 Makefile源码

obj-m:=ParaPortDEV.o#KERNELDIR:=/lib/modules/2.6.38.8/buildKERNELDIR:=/usr/src/linux-headers-2.6.38-8-genericPWD:=$(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -f *.o

2.3 安装驱动程序步骤

~/linux_study/para_port$ make~/linux_study/para_port$ sudo insmod ParaPortDEV.ko~/linux_study/para_port$ sudo mknod /dev/ParaPortDEV c 240 0~/linux_study/para_port$ sudo chgrp staff /dev/ParaPortDEV~/linux_study/para_port$ sudo chmod 664 /dev/ParaPortDEV

3. 测试程序

/*test_para_port_dev.c*/#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#define DEV_NAME "/dev/ParaPortDEV"int main(void){int i, dev;char buff[10];dev=open(DEV_NAME, O_RDWR|O_NDELAY);if(dev==-1){printf("open error: %s.\n", strerror(errno));return -1;}printf("read from para port:\n");for(i=0; i<10; i++){if(read(dev, buff+i, 1)==-1){printf("%dth read error: %s.\n", i, strerror(errno));break;}sleep(1);printf("data = %0X\n", buff[i]);}printf("write to para port:\n");for(i=0; i<10; i++){/*turn the light on*/buff[i] = 0xFF;if(write(dev, buff+i, 1)==-1){printf("%dth write error: %s.\n", i, strerror(errno));break;}printf("light on\n");sleep(1);/*turn the light off*/buff[i] = 0x00;if(write(dev, buff+i, 1)==-1){printf("%dth write error: %s.\n", i, strerror(errno));break;}printf("light off\n");sleep(1);}close(dev);return 0;}

4. 连接电路

在并口上的 2 脚和 25 脚分别引出两根引线,2 脚接 LED 灯的长脚,25 脚接 LED 灯的短脚,再在电路上串联一个500欧左右的电阻,电路图如下:

5. 测试

~/linux_study/para_port$ sudo ./test_para_port_dev

在应用程序中,使用 read() 系统调用不断尝试读取并口设备状态寄存器。如果并口上没有外接设备,则会打印信息:

read from para port:data = 7Fdata = 7Fdata = 7Fdata = 7Fdata = 7Fdata = 7Fdata = 7Fdata = 7Fdata = 7Fdata = 7F

当通过引线将13脚和25脚短接,则13引脚有低电平输入,这时候输出:

read from para port:data = 6Fdata = 6Fdata = 6Fdata = 6Fdata = 6Fdata = 6Fdata = 6Fdata = 6Fdata = 6Fdata = 6F

然后,通过调用 write() 函数向并口设备数据寄存器写数据,使 LED 灯开灯、关灯10次,最后关闭设备文件并退出。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。