A/D驱动程序

设备树中的节点编写:

<span style="font-size:18px;">fs4412-adc{
    compatible = "fs4412,adc";
    reg = <0x126C0000 0x20>;
    interrupt-parent = <&combiner>;
    interrupts = <10 3>;
};</span>

驱动编写:

driver.c

<span style="font-size:18px;">#include<linux/module.h>
#include<linux/device.h>
#include<linux/platform_device.h>
#include<linux/interrupt.h>
#include<linux/fs.h>
#include<linux/wait.h>
#include<linux/sched.h>
#include<asm/uaccess.h>
#include<asm/io.h>

static int major=250;

/*定义队列头*/
static wait_queue_head_t wq;

/*中断标志*/
static int have_data=0;

/*存储ADCDAT的数据*/
static int adc;

static struct resource *res1;
static struct resource *res2;

/*ADC的基地址*/
static void *adc_base;

/*ADC寄存器的相对地址*/
#define ADCCON 0x0000
#define ADCDLY 0x0008
#define ADCDAT 0x000C
#define CLRINTADC 0x0018
#define ADCMUX 0x001C

static irqreturn_t adc_handler(int irqno,void *dev)
{
	/*中断来了,有数据可以读*/
	have_data=1;
	printk("irq hanppend\n");

	/*清中断*/
	writel(0x12,adc_base+CLRINTADC);
	wake_up_interruptible(&wq);//唤醒休眠的进程
	return IRQ_HANDLED;
}

static int adc_open(struct inode *inode,struct file *file)
{
	return 0;
}

static ssize_t adc_read(struct file *file,char __user *buf,size_t len,loff_t *ops)
{
	/*开启控制器可读*/
	writel(0x3,adc_base+ADCMUX);
	writel(1<<0|1<<14|0x1<<16|0xFF<<6,adc_base+ADCCON);

	/*如果没有数据可读,休眠*/
	wait_event_interruptible(wq,have_data==1);

	/*read data*/
	adc=readl(adc_base+ADCDAT)&0xfff;

	if(copy_to_user(buf,&adc,sizeof(int)))
	{
		return -EFAULT;
	}
	have_data=0;
	return len;
}

static int adc_release(struct inode *inode,struct file *file)
{
	return 0;
}

static struct file_operations adc_ops=
{
	.open=adc_open,
	.release=adc_release,
	.read=adc_read,
}

static int adc_probe(struct platform_device *pdev)
{
	int ret;
	printk("match ok\n");

	res1=platform_get_resource(pdev,IORESOURCE_IRQ,0);
	res2=platform_get_resource(pdev,IORESOURCE_MEM,0);

	/*注册中断处理函数*/
	ret=request_irq(res1->start,adc_handler,IRQF_DISABLED,"adc1",NULL);//第一个参数是中断号,0--15的样子
	adc_base=ioremap(res2->start,res2->end-res2->start);

	register_chrdev(major,"adc",&adc_ops);

	/*初始化队头*/
	init_waitqueue_head(&wq);

	return 0;
}

static int adc_remove(struct platform_device *pdev)
{
	free_irq(res1->start,NULL);
	free_irq(res2->start,NULL);
	unregister_chrdev(major,"adc");
	return 0;
}

static struct of_device_id adc_id[]=
{
	/*与设备树中的device名字进程匹配*/
	{.compatible="fs4412,adc"},
}

static struct platform_driver adc_driver=
{
	.probe=adc_probe,
	.remove=adc_remove,
	.driver=
	{
		.name="bigbang",
		.of_match_table=adc_id,
	},
};

static int adc_init(void)
{
	printk("hello_init\n");
	return platform_driver_register(&adc_driver);
}
static void adc_exit(void)
{
	platform_driver_unregister(&adc_driver);
	printk("hello exit\n");
}

MODULE_LICENSE("GPL");
module_init(adc_init);
module_exit(adc_exit);</span>

test.c

<span style="font-size:18px;">#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

int main(void)
{
	int fd,len,adc;
	fd=open("/dev/adc",O_RDWR);
	if(fd<0)
	{
		printf("open fail\n");
		return 0;
	}

	while(1)
	{
		read(fd,&adc,4);
		printf("adc%0.2f V\n",(1.8*adc)/4096);
	}

	close(fd);

	return 0;
}</span>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面试中遇到的问题基本囊括其中 说出Servlet的生命周期,并说出Servlet和CGI的区别。Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其 service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其 destroy方法。与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。 12.EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 13.EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的? 14.说出数据连接池的工作机制是什么? 15同步和异步有和异同,在什么情况下分别使用他们?举例说明。 16应用服务器有那些? 17你所知道的集合类都有哪些?主要方法? 18给你一个:驱动程序A,数据源名称为B,用户名称为C,密码为D,数据库表为T,请用JDBC检索出表T的所有数据。 19.说出在JSP页面里是怎么分页的? 页面需要保存以下参数:总行数:根据sql语句得到总行数 每页显示行数:设定值当前页数:请求参数 页面根据当前页数和每页行数计算出当前页第一行行数,定位结果集到此行,对结果集取出每页显示行数的行即可。 数据库方面:1.存储过程和函数的区别存储过程是用户定义的一系列sql语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。
LCD0802A 是一种基于液晶显示技术的显示模块,常用于嵌入式系统、电子设备等领域。要想驱动 LCD0802A 模块,需要编写相应的驱动程序。 首先,我们需要连接 LCD0802A 模块和控制器(比如单片机)之间的引脚。一般来说,LCD0802A 模块有16个引脚,其中8个用于数据传输(D0-D7),3个用于控制信号(RS、R/W、E),还有5个引脚用于背光(VCC、VDD、VSS、A、K)。我们需要按照规定将这些引脚连接到控制器的对应引脚上。 接下来,编写驱动程序。首先,我们需要初始化 LCD0802A 模块。这包括设置模块的工作模式、显示模式、光标移动方向等等。具体的初始化步骤可以通过查阅 LCD0802A 模块的技术文档来了解。 然后,我们需要编写一些函数来操作 LCD0802A 模块。比如,可以编写函数来设置光标的位置、写入字符或字符串到显示屏上、清除显示屏内容等等。这些函数需要与控制器进行通信,通过控制信号和数据传输引脚来操作 LCD0802A 模块。 最后,我们可以在主程序中调用这些编写的函数,实现对 LCD0802A 模块的控制和显示。通过调用设置位置函数来定位光标,然后调用写入字符或字符串函数来显示内容。循环执行这些操作,就可以实现实时更新显示屏上的内容。 总之,要驱动 LCD0802A 模块,需要连接引脚并编写相应的初始化和操作函数。通过这些函数的调用,可以实现对显示模块的控制和显示内容的更新。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值