日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux并口驱动编程开发

發布時間:2024/1/1 linux 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux并口驱动编程开发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考鏈接:

(1)https://www.cnblogs.com/chungshu/archive/2012/11/26/2789257.html

(2)https://blog.csdn.net/bg2bkk/article/details/8946424

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. 實現功能

用一個LED發光二極管、一個電阻以及一些導線和電腦主機的并口連接了一條回路,最后通過測試程序控制LED燈的開啟、關閉,驗證了并口驅動程序的正確性。



3. 驅動程序源碼

(1)parport_drv.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>?? ?/* printk() */
#include <linux/fs.h>?? ??? ?/* everything... */
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/ioport.h>
?
#include"parport_drv.h"? ?
/*****************************************************************************************/?? ?
#define Drv_major 240? ?
#define Drv_name? "parport_drv"? ?
#define Drv_read_addr 0x379? ?
#define Drv_write_addr 0x378? ?
/*****************************************************************************************/?? ?
MODULE_LICENSE ("GPL");
?
/*****************************************************************************************/ ?
int parport_open(struct inode *inode, struct file *filp);
ssize_t parport_write(struct file *filp, const char *buf, size_t count, loff_t *f_ops);
ssize_t parport_read(struct file *filp, char *buf, size_t count, loff_t *f_ops) ;
long??? parport_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ;
int parport_release(struct inode *inode, struct file *filp) ;
?
/*****************************************************************************************/ ?
struct file_operations parport_fops = {? ?
??? .owner? =?? THIS_MODULE,? ?
??? .write? =?? parport_write,? ?
??? .read?? =?? parport_read,? ?
??? .open?? =?? parport_open,? ?
??? .unlocked_ioctl =?? parport_ioctl,? ?
??? .release=?? parport_release,? ?
}; ?
/*****************************************************************************************/ ?
int parport_open(struct inode *inode, struct file *filp)? ?
{? ?
??? printk(KERN_ALERT "open the parport_dev\n");? ?
??? return 0;? ?
}? ?
/*****************************************************************************************/?? ?
ssize_t parport_write(struct file *filp, const char *buf, size_t count, loff_t *f_ops)? ?
{? ?
??? unsigned char status;? ?
??? int loop;? ?
??? for(loop = 0; loop < count; loop++)? ?
??? {? ?
??????? get_user(status, (char *)buf);? ?
??????? outb(status, Drv_write_addr);? ?
??? }? ?
??? return count;? ?
}? ?
/*****************************************************************************************/?? ?
ssize_t parport_read(struct file *filp, char *buf, size_t count, loff_t *f_ops)? ?
{? ?
??? unsigned char status;? ?
??? int loop;? ?
??? for(loop = 0; loop < count; loop++)? ?
??? {? ?
??????? status = inb(Drv_read_addr);? ?
??????? put_user(status, (char *) &buf[loop]);? ?
??? }? ?
??? return count;? ?
}? ?
/*****************************************************************************************/?? ?
long??? parport_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)? ?
{? ?
??? int loop;? ?
??? struct dat data;? ?
??? switch(cmd)? ?
??? {? ?
??????? case PARPORT_WRITE:? ?
//????????? outb(status, Drv_write_addr);? ?
??????????? copy_from_user(&data, (struct dat *)arg, sizeof(data));?????????? ?
??????????? printk(KERN_ALERT "out put %d\n",data.loop);? ?
??????????? for(loop = 0; loop < data.loop; loop ++)? ?
??????????? {? ?
??????????????? printk(KERN_ALERT "the %dth loop, write %d\n",loop,data.buf[loop]);? ?
??????????????? outb(data.buf[loop], Drv_write_addr);? ?
??????????????? wmb();? ?
??????????? }? ?
??????????? break;? ?
? ?
??????? case PARPORT_CLOSE:? ?
??????????? outb(0x00, Drv_write_addr);? ?
??????????? wmb();? ?
??????????? break;? ?
??? }? ?
??? return 0;? ?
}? ?
/*****************************************************************************************/?? ?
int parport_release(struct inode *inode, struct file *filp)? ?
{? ?
??? printk(KERN_ALERT "close the module parport_dev\n");? ?
??? return 0;? ?
}? ?
?? ?
/*****************************************************************************************/? ?
int parport_init(void)? ?
{? ?
??? int result;? ?
? ?
??? result = register_chrdev(Drv_major, Drv_name, &parport_fops);? ?
??? if(result < 0)? ?
?? ?{
?? ??? ?printk("register charactre devices error!\n");
?? ??? ?return result; ?
?? ?}
???????? ?
??? printk(KERN_ALERT "hello the module parport_dev\n");? ?
? ?
??? return 0;? ?
}? ?
/*****************************************************************************************/?? ?
void parport_exit(void)? ?
{? ?
??? printk(KERN_ALERT "exit the module parport_drv\n");? ?
??? unregister_chrdev(Drv_major, Drv_name);? ?
????? ?
}? ?
/*****************************************************************************************/?? ?
module_init(parport_init);? ?
module_exit(parport_exit);

/*****************************************************************************************/?

(2) parport_drv.h

#ifndef _PARPORT_DRV_H? ?
#define _PARPORT_DRV_H? ?
? ?
? ?
#define PARPORT_WRITE 1? ?
#define PARPORT_CLOSE 2? ?
? ?
? ?
struct dat{? ?
?? ?int loop;? ?
?? ?unsigned char *buf;? ?
};? ?
? ?
? ?

#endif

(3)模塊編譯Makefile


# To build modules outside of the kernel tree, we run "make"
# in the kernel source tree; the Makefile these then includes this
# Makefile once again.
# This conditional selects whether we are being included from the
# kernel Makefile or not.
ifeq ($(KERNELRELEASE),)

??? # Assume the source tree is where the running kernel was built
??? # You should set KERNELDIR in the environment if it's elsewhere
??? KERNELDIR ?= /lib/modules/$(shell uname -r)/build
??? # The current directory is passed to sub-makes as argument
??? PWD := $(shell pwd)

modules:
?? ?$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
?? ?$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
?? ?rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else
??? # called from kernel build system: just declare what our modules are
??? obj-m := parport_drv.o
endif

(4)模塊加載shell腳本 :?load_rdwrdev

#!/bin/sh
insmod parport_drv.ko
mknod /dev/parport_drv c 240 0
chgrp staff /dev/parport_drv

chmod 664 /dev/parport_drv

(5)模塊卸載shell腳本 :unload_rdwrdev

#!/bin/sh
rmmod parport_drv.ko
rm /dev/parport_drv

(6)測試代碼

par_test.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/errno.h>
?
#include "parport_drv.h"? ?
?
/*****************************************************************************************/ ?
#define DEVICE_NAME "/dev/parport_drv"? ?
?
/*****************************************************************************************/? ?
int main()? ?
{? ?
??? int fd;? ?
??? char buf[128];? ?
??? int loop;? ?
? ?
??? fd = open(DEVICE_NAME, O_RDWR | O_NDELAY);? ?
? ?
??? if(fd < 0)? ?
??? {? ?
??????? perror("open device");? ?
??????? exit(1);? ?
??? }? ?
??? else? ?
??? {? ?
??????? int i;? ?
??????? int arg=0x99;? ?
??????? unsigned char buf[255];? ?
??????? struct dat da;? ?
??????? da.loop = 4;? ?
??????? da.buf = (unsigned char *)malloc(5 * sizeof(unsigned char));? ?
??????? for(i = 0;i< da.loop; i++)? ?
??????????? da.buf[i] = i*2+1;? ?
??????? for(i=0;i<da.loop;i++)? ?
??????????? printf("test:%d\n", da.buf[i]);? ?
??????? ioctl(fd, PARPORT_WRITE,&da);? ?
??????? sleep(1);? ?
??????? ioctl(fd, PARPORT_CLOSE);? ?
??????? sleep(1);? ?
??????? close(fd);? ?
??? }? ?
? ?
??? return 0;? ?
} ?
?
/*****************************************************************************************/?

(5) 測試代碼 編譯命令: gcc -o par_test par_test.c

4. 實例運行方法

(1)建立6個文件并拷貝源碼:parport_drv.c,? parport_drv.h, Makefile, par_test.c, load_rdwrdev, unload_rdwrdev

(2)運行:Makefile 生成 parport_drv.o

(3)運行模塊加載shell腳本:sudo bash load_rdwrdev

(4)編譯測試代碼文件 : gcc -o par_test par_test.c

(5)運行: sudo ./par_test

(6) 運行模塊卸載shell腳本:sudo bash unload_rdwrdev

5. 實驗現象

并口D2引腳示波器信號波形





?

總結

以上是生活随笔為你收集整理的linux并口驱动编程开发的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。