曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6290|回复: 1
打印 上一主题 下一主题

并口读写测试实例

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-9-23 12:58:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
驱动程序 (2.6 kernel)
#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>

#define RDWR_DEV_NAME    "rdwrdev"
#define RDWR_DEV_MAJOR      240

#define RDWR_WRITE_ADDR      0x0378
#define RDWR_READ_ADDR      0x0379

int rdwr_open (struct inode *inode, struct file *filp)
{
    return 0;
}

ssize_t    rdwr_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 (RDWR_READ_ADDR);
        put_user (status, (char *) & buf [loop]);
    }
   
    return count;
}

ssize_t rdwr_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
    unsigned char status;
    int          loop;

    for (loop = 0; loop < count; loop++) {
        get_user (status, (char *)buf);
        outb (status, RDWR_WRITE_ADDR);
    }
    return count;
}

int rdwr_release (struct inode *inode, struct file *filp)
{
    return 0;
}

struct file_operations rdwr_fops =
{
    .owner = THIS_MODULE,
    .read = rdwr_read,
    .write = rdwr_write,
    .open = rdwr_open,
    .release = rdwr_release,
};

int rdwr_init (void)
{
    int result;
   
    result = register_chrdev (RDWR_DEV_MAJOR, RDWR_DEV_NAME, &rdwr_fops);
    if (result < 0) return result;
   
    return 0;
}

void rdwr_exit (void)
{
    unregister_chrdev (RDWR_DEV_MAJOR, RDWR_DEV_NAME);
}

module_init (rdwr_init);
module_exit (rdwr_exit);

MODULE_LICENSE ("Dual BSD/GPL");

Makefile 文件
obj-m := rdwrdev.o

KDIR := /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

default:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
    rm -rf *.ko
    rm -rf *.mod.*
    rm -rf .*.cmd
    rm -rf *.o

测试用应用程序
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

#define DEVICE_FILENAME    "/dev/rdwrdev"

int main()
{
    int dev;
    char buff [128];
    int loop;

    dev = open (DEVICE_FILENAME, O_RDWR | O_NDELAY);
    if (dev >= 0) {
       
        printf ("waiting ... input\n");

        while (1) {
            if (read (dev, buff, 1) == 1) {
                printf ("read data [%02X]\n", buff [0] & 0xFF);
                if (!(buff [0] & 0x10))
                    break;
            }
        }

        printf ("input ok ... \n");
        printf ("led falshing ... \n");
        for (loop = 0; loop < 5; loop++) {
            buff [0] = 0xFF;
            write (dev, buff, 1);
            sleep (1);
            buff [0] = 0x00;
            write (dev, buff, 1);
            sleep (1);
        }
        close (dev);
    } else {
        perror ("open device");
        exit (1);
    }

    return (0);
}

创建设备文件
mknod  /dev/rdwrdev  c 240  0

编译驱动模块
make

加载模块
insmod  rdwrdev.ko


说明
在并口上的 25 脚和 13 脚分别引出两根引线,25 脚接地,13 脚为输入脚;2 脚接 LED 灯的长脚,18 脚接 LED 灯的短脚。

在应用程序中,使用 read() 系统调用不断尝试读取设备 0x379 上的地址信息。如果第 13 脚和第 25 脚上的两根引线没有接触,那么会一直打印信息:
read data [7F]
表明第 13 脚上并没有检测到低电平输入。

在驱动程序中的 read() 函数里,使用 inb() 函数读取设备的 0x379 这个地址,一次读取一个字节,然后再通过 put_user() 函数把读到的这个字节发送回应用程序中。

当 13 和 25 引线接触时,13 引脚有低电平输入,这时应用程序中根据 buff[0] & 0x10 可得到这个状态的判断,然后应用程序跳出 while 的无限检测循环。这时候输出:
read data [6F]
input ok ...
led falshing ...
接着,在 for 的 5 次循环中,通过调用 write() 函数写设备,使 LED 灯循环的每隔 1 秒闪烁,最后退出并结束设备文件。

驱动程序中的 write() 通过 get_user() 函数得到用户传送下来的写指令(0x00 或 0xff) ,然后把指令存入 status 变量中,最后通过 outb() 函数把这个指令发往设备的 0x378 地址。

以上,就是设备驱动程序的读写过程。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-3 13:35 , Processed in 0.088218 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表