




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提 供方便。如有错误之处,谢请指正。一、开发环境主 机:VMWare-Fedora 9二、硬件原理分析S3C2440内部ADC结构图我们从上面的结构图和数据手册可以知道,该ADC模块总共有8个通道可以进行模拟信号的输入,分别是AIN0、AIN1、AIN2、AIN3、 YM、YP、XM、XP。那么ADC是怎么实现模拟信号到数字信号的转换呢?首先模拟信号从任一通道输入,然后设定寄存器中预分频器的值来确定AD转换器 频率,最后ADC将模拟信号转换为数字信号保存到ADC数
2、据寄存器0中(ADCDAT0),然后ADCDAT0中的数据可以通过中断或查询的方式来访问。 对于ADC的各寄存器的操作和注意事项请参阅数据手册。上图是mini2440上的ADC应用实例,开发板通过一个10K的电位器(可变电阻)来产生电压模拟信号,然后通过第一个通道(即:AIN0)将 模拟信号输入ADC。三、实现步骤ADC设备在Linux中可以看做是简单的字符设备,也可以当做是一混杂设备(misc设备),这里我们就看做是misc设备来实现ADC的驱动。 注意:这里我们获取AD转换后的数据将采用中断的方式,即当AD转换完成后产生AD中断,在中断服务程序中来读取ADCDAT0的第0-9位的值(即AD
3、 转换后的值)。1、建立驱动程序文件my2440_adc.c,实现驱动的初始化和退出,代码如下:1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 13 /*定义了一个用来保存经过虚拟映射后的内存地址*/ 14 static void _iomem *adc_base; 15 16 /*保存从平台时钟队列中获取ADC的时钟*/ 17 static struct clk *adc_clk; 18 1
4、9 /*申明并初始化一个信号量ADC_LOCK,对ADC资源进行互斥访问*/ 20 DECLARE_MUTEX(ADC_LOCK); 21 22 static int _init adc_init(void) 23 24 int ret; 25 26 /*从平台时钟队列中获取ADC的时钟,这里为什么要取得这个时钟,因为ADC的转换频率跟时钟有关。 27 系统的一些时钟定义在arch/arm/plat-s3c24xx /s3c2410-clock.c中*/ 28 adc_clk = clk_get(NULL, adc); 29 if (!adc_clk) 30 31 /*错误处理*/ 32 pr
5、intk(KERN_ERR failed to find adc clock sourcen); 33 return -ENOENT; 34 35 36 /*时钟获取后要使能后才可以使用,clk_enable定义在arch/arm/plat-s3c/clock.c中*/ 37 clk_enable(adc_clk); 38 39 /*将ADC的IO端口占用的这段 IO空间映射到内存的虚拟地址,ioremap定义在io.h中。 40 注意:IO空间要映射后才能使用,以后对虚拟地址的操作就是对IO空间的操作, S3C2410_PA_ADC41 是ADC控制器的基地址,定义在mach-s3c2410
6、/include/mach/map.h中,0x20是虚拟地址长度大小*/ 42 adc_base = ioremap(S3C2410_PA_ADC, 0x20); 43 if (adc_base = NULL) 44 45 /*错误处理*/ 46 printk(KERN_ERR Failed to remap register blockn); 47 ret = -EINVAL; 48 goto err_noclk; 49 50 51 /*把看ADC注册成为misc设备,misc_register定义在miscdevice.h中adc_miscdev结构体定义 52 及内部接口函数在第步中讲,
7、MISC_DYNAMIC_MINOR是次设备号,定义在miscdevice.h中*/ 53 ret = misc_register(&adc_miscdev); 54 if (ret) 55 56 /*错误处理*/ 57 printk(KERN_ERR cannot register miscdev on minor=%d (%d)n,58 MISC_DYNAMIC_MINOR, ret); 59 goto err_nomap; 60 61 62 printk(DEVICE_NAME initialized!n); 63 64 return 0; 65 66 /以下是上面错误处理的跳转点 67
8、 err_noclk: 68 clk_disable(adc_clk); 69 clk_put(adc_clk); 70 71 err_nomap: 72 iounmap(adc_base); 73 74 return ret; 75 76 77 static void _exit adc_exit(void) 78 79 free_irq(IRQ_ADC, 1);/*释放中断*/ 80 iounmap(adc_base);/*释放虚拟地址映射空间*/ 81 82 if (adc_clk)/*屏蔽和销毁时钟*/ 83 84 clk_disable(adc_clk); 85 clk_put(ad
9、c_clk); 86 adc_clk = NULL; 87 88 89 misc_deregister(&adc_miscdev);/*注销misc设备*/ 90 91 92 /*导出信号量ADC_LOCK在触摸屏驱动中使用,因为触摸屏驱动和ADC驱动公用 93 相关的寄存器,为了不产生资源竞态,就用信号量来保证资源的互斥访问*/ 94 EXPORT_SYMBOL(ADC_LOCK); 95 96 module_init(adc_init); 97 module_exit(adc_exit); 98 99 MODULE_LICENSE(GPL); 100 MODULE_AUTHOR(Huang
10、 Gang); 101 MODULE_DESCRIPTION(My2440 ADC Driver); 2、adc_miscdev结构体定义及内部各接口函数的实现,代码如下:102 #include 103 104 /*设备名称*/ 105 #define DEVICE_NAME my2440_adc 106 107 /*定义并初始化一个等待队列adc_waitq,对ADC资源进行阻塞访问*/ 108 static DECLARE_WAIT_QUEUE_HEAD(adc_waitq); 109 110 /*用于标识AD转换后的数据是否可以读取,0表示不可读取*/ 111 static volat
11、ile int ev_adc = 0; 112 113 /*用于保存读取的AD转换后的值,该值在ADC中断中读取*/ 114 static int adc_data; 115 116 /*misc设备结构体实现*/ 117 static struct miscdevice adc_miscdev = 118 119 .minor = MISC_DYNAMIC_MINOR, /*次设备号,定义在 miscdevice.h中,为255*/ 120 .name = DEVICE_NAME, /* 设备名称*/ 121 .fops = &adc_fops, /*对ADC设备文件操作*/ 122 ; 1
12、23 124 /*字符设备的相关操作实现*/ 125 static struct file_operations adc_fops = 126 127 .owner = THIS_MODULE, 128 .open = adc_open, 129 .read = adc_read, 130 .release = adc_release, 131 ; 132 133 /*ADC设备驱动的打开接口函数*/ 134 static int adc_open(struct inode *inode, struct file *file) 135 136 int ret; 137 138 /*申请ADC中
13、断服务,这里使用的是共享中断:IRQF_SHARED,为什么要使用共享中断,因为在触摸屏驱动中 139 也使用了这个中断号。中断服务程序为:adc_irq在下面实现,IRQ_ADC是ADC的中断号,这里注意: 140 申请中断函数的最后一个参数一定不能为NULL,否则中断申请会失败,如果中断服务程序中用不到这个 141 参数,就随便给个值就好了,我这里就给个1*/ 142 ret = request_irq(IRQ_ADC, adc_irq, IRQF_SHARED, DEVICE_NAME, 1); 143 if (ret) 144 145 /*错误处理*/ 146 printk(KERN_
14、ERR IRQ%d error %dn, IRQ_ADC, ret); 147 return -EINVAL; 148 149 150 return 0; 151 152 153 /*ADC中断服务程序,该服务程序主要是从ADC数据寄存器中读取AD转换后的值*/ 154 static irqreturn_t adc_irq(int irq, void *dev_id) 155 156 /*保证了应用程序读取一次这里就读取 AD转换的值一次, 157 避免应用程序读取一次后发生多次中断多次读取AD转换值*/ 158 if(!ev_adc) 159 160 /*读取AD转换后的值保存到全局变量ad
15、c_data 中,S3C2410_ADCDAT0定义在regs-adc.h中, 161 这里为什么要与上一个0x3ff,很简单,因为AD转换后的数据是保存在ADCDAT0的第0-9位, 162 所以与上0x3ff(即:1111111111)后就得到第0-9位的数据,多余的位就都为0*/ 163 adc_data = readl(adc_base + S3C2410_ADCDAT0) & 0x3ff; 164 165 /*将可读标识为1,并唤醒等待队列*/ 166 ev_adc = 1; 167 wake_up_interruptible(&adc_waitq); 168 169 170 ret
16、urn IRQ_HANDLED; 171 172 173 /*ADC设备驱动的读接口函数*/ 174 static ssize_t adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) 175 176 /*试着获取信号量(即:加锁)*/ 177 if (down_trylock(&ADC_LOCK) 178 179 return -EBUSY; 180 181 182 if(!ev_adc)/*表示还没有AD转换后的数据,不可读取*/ 183 184 if(filp-f_flags & O_NONBLOCK)
17、 185 186 /*应用程序若采用非阻塞方式读取则返回错误*/ 187 return -EAGAIN; 188 189 else/*以阻塞方式进行读取*/ 190 191 /*设置ADC控制寄存器,开启AD转换*/ 192 start_adc(); 193 194 /*使等待队列进入睡眠*/ 195 wait_event_interruptible(adc_waitq, ev_adc); 196 197 198 199 /*能到这里就表示已有AD转换后的数据,则标识清0,给下一次读做判断用*/ 200 ev_adc = 0; 201 202 /*将读取到的AD转换后的值发往到上层应用程序*/
18、 203 copy_to_user(buffer, (char *)&adc_data, sizeof(adc_data); 204 205 /*释放获取的信号量(即:解锁)*/ 206 up(&ADC_LOCK); 207 208 return sizeof(adc_data); 209 210 211 /*设置ADC控制寄存器,开启AD转换*/ 212 static void start_adc(void) 213 214 unsigned int tmp; 215 216 tmp = (1 14) | (255 6) | (0 3);/* 0 1 00000011 000 0 0 0 *
19、/ 217 writel(tmp, adc_base + S3C2410_ADCCON); /*AD预分频器使能、模拟输入通道设为AIN0*/ 218 219 tmp = readl(adc_base + S3C2410_ADCCON); 220 tmp = tmp | (1 0); /* 0 1 00000011 000 0 0 1 */ 221 writel(tmp, adc_base + S3C2410_ADCCON); /*AD转换开始*/ 222 223 224 /*ADC设备驱动的关闭接口函数*/ 225 static int adc_release(struct inode *inode, struct file *filp) 226 227 return 0; 228 注意:在上面实现的每步中,为了让代码逻辑更加有条理和容易理解,就没有考虑代码的顺序,比如函数要先定义后调用。如果要编译此代码,请严格按照C 语言的规范来调整代码的顺序。3、编写用户应用程序测试my2440_adc驱动。建立应用程序adc_test.c,代码如下:229 #include
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 无人机项目申请报告
- 2025年纺织服装业智能化生产智能化生产设备市场潜力分析报告
- 数据操纵语句实验报告
- 2025年新能源商用车辆在校园交通中的应用场景分析报告
- 2025年文化产业金融支持政策与融资渠道对接策略研究:以图书出版电商平台为例
- 工业互联网平台生物识别技术在智能工厂设备维护与预测性维护中的应用报告
- 2025年超高压电缆输电系统项目可行性研究报告
- 电气运行复习试题有答案
- 《消防员灭火救援业务理论要点(试行)》上海市消防救援总队练习试题及答案
- 2024工程竞赛试题-多选复习测试卷含答案
- 揭榜挂帅 项目协议书
- 2024年广东省广州市市中考英语试卷真题(含答案)
- 注射泵操作使用课件
- DL∕T 5362-2018 水工沥青混凝土试验规程
- CB-Z-806-2016船舶动力定位模型试验规程
- 《马克思主义政治经济学》教案
- 因精神健康问题休学证明范本
- 化工设计智慧树知到期末考试答案章节答案2024年浙江大学
- 国开机考答案-工程数学(本)(闭卷)
- 初中语文++病句专题++课件+八年级统编版语文下册
- 宠物用药市场细分与竞争分析
评论
0/150
提交评论