imx283 linux驱动595与166模拟时序串行IO扩展

这篇博客介绍了如何使用Linux GPIO驱动实现对低速输入输出接口的扩展,并通过定时器进行滤波和状态检测。代码展示了如何设置GPIO方向、读写操作以及中断处理,用于数据的输入输出。此外,还定义了一个输入检查函数,用于跟踪变化并过滤噪声。
摘要由CSDN通过智能技术生成

输入滤波,适合扩展低速的输入输出接口

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>

#define EXTIO_OUT_MAX   24
#define EXTIO_IN_MAX    24

typedef struct _input_t{
	uint8_t		buf[EXTIO_IN_MAX/8];
	uint8_t		save[EXTIO_IN_MAX/8];
	uint8_t		timer[EXTIO_IN_MAX];
}input_t;

typedef struct _output_t{
	uint8_t		byte[EXTIO_OUT_MAX/8];
}output_t;


typedef struct _extio_t{
	input_t		input;
	output_t	output;
}extio_t;

#define DEVICE_NAME "extio"

typedef struct  
{
    int data_out_pin;
    int data_in_pin;
    int clk_pin;
    int le_pin;
    int pe_pin;
}extio_handler;

extio_handler extio_define={
    2*32+5,2*32+7,2*32+13,2*32+15,2*32+17
};

static struct timer_list extio_timer;
extio_t	extio_buf;

#define data_in()      	gpio_get_value(extio_define.data_in_pin)

#define data_out_high()	gpio_direction_output(extio_define.data_in_pin,1)
#define data_out_low()	gpio_direction_output(extio_define.data_in_pin,0)

#define data_clk_high()	gpio_direction_output(extio_define.clk_pin,1)
#define data_clk_low()	gpio_direction_output(extio_define.clk_pin,0)

#define data_le_high()	gpio_direction_output(extio_define.le_pin,1)
#define data_le_low()	gpio_direction_output(extio_define.le_pin,0)

#define data_pe_high()	gpio_direction_output(extio_define.pe_pin,1)
#define data_pe_low()	gpio_direction_output(extio_define.pe_pin,0)

static void extio_write_bye(uint8_t byte)
{
	uint8_t i;
	for( i=0; i<8; i++ ){
		
		if( byte&(0x80) )
			data_out_high();
		else
			data_out_low();
		
		data_clk_high();
		data_clk_low();
		byte<<=1;
	}
}

static void extio_output(void)
{
	uint8_t i;
	for( i=0; i<EXTIO_OUT_MAX/8; i++ ){
		extio_write_bye(extio_buf.output.byte[i]);
	}
	data_pe_high();
	data_pe_low();
}

static void extio_read_byte(uint8_t *byte)
{
	uint8_t i;
	*byte = 0;
	for( i=0; i<8; i++ ){
			
		data_clk_high();
			
		(*byte)<<=1;
		if( data_in() )
			(*byte) |= 0x01;
			
		data_clk_low();
	}
}

static void extio_input(void)
{
	uint8_t *in_ptr =&extio_buf.input.buf[EXTIO_IN_MAX/8-1];
	uint8_t i;
	data_pe_low();
	data_pe_high();
	for( i=0; i<EXTIO_IN_MAX/8; i++ ){
		if( i==0 )
			extio_read_byte(in_ptr);
		else
			extio_read_byte(in_ptr);
		in_ptr--;
	}
}

static void extio_input_check( void )
{
	uint8_t i,io,k,num;

	for(  num=0; num<EXTIO_IN_MAX/8; num++ )
	{
		if( extio_buf.input.buf[num]!=extio_buf.input.save[num] )
		{
			io = extio_buf.input.buf[num]^extio_buf.input.save[num];
			for( i=0; i<8; i++ )
			{
				if( io&0x01 )
				{
					if( extio_buf.input.timer[num*8+i]<30 )
					{
						extio_buf.input.timer[num*8+i]++;	//每一个IO口对应一个计时器
					}
					else
					{
						extio_buf.input.timer[num*8+i] = 0;
						k = extio_buf.input.buf[num];
						k >>= i;
						if( k&0x01 )
						{
							extio_buf.input.save[num] |= (1<<i);
						}
						else
						{
							extio_buf.input.save[num] &= (~(1<<i));
						}
					}
				}
				else
				{
					extio_buf.input.timer[num*8+i] = 0;
				}
				io >>= 1;
			}
		}
	}
}

static ssize_t extio_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    int ret = 0;
    copy_from_user((char*)extio_buf.output.byte, buf, count);
    extio_output();
    return ret;
}

static ssize_t extio_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    int ret = 0;    
    copy_to_user(buf, (char*)extio_buf.input.save, EXTIO_IN_MAX/8);
    return ret;
}

static int extio_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
{
	return 0;
}

static struct file_operations extio_fops={
    .owner = THIS_MODULE,
    .write = extio_write,
    .read = extio_read,
    .ioctl = extio_ioctl,
};

static struct miscdevice extio_miscdev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &extio_fops,
};

static void extio_timer_function(unsigned long data)
{
	extio_input();
	extio_input_check();
    mod_timer(&extio_timer,jiffies+ HZ*100/1000  );
}

static int extio_init(void)
{
    //GPIO
    gpio_request(extio_define.data_in_pin, "data_in");
    gpio_direction_input(extio_define.data_in_pin);
    gpio_request(extio_define.data_out_pin, "data_out");
    gpio_direction_output(extio_define.data_out_pin,0); 
    gpio_request(extio_define.clk_pin, "clk");
    gpio_direction_output(extio_define.clk_pin,0);
    gpio_request(extio_define.pe_pin, "pe");
    gpio_direction_output(extio_define.pe_pin,0);
	gpio_request(extio_define.pe_pin, "le");
    gpio_direction_output(extio_define.le_pin,0);
    
    int err = 0;
    err = misc_register(&extio_miscdev); 
    
    init_timer(&extio_timer);
    extio_timer.function=extio_timer_function;
    extio_timer.expires=jiffies +HZ*100/1000;
    add_timer(&extio_timer);

    printk("extio driver up \n");
    return 0;
}

static void extio_exit(void)
{
    del_timer(&extio_timer);
    misc_deregister(&extio_miscdev);
    printk("extio driver remove \n");
}

module_init(extio_init);
module_exit(extio_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("KENG DENG");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵向深耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值