Linux内核驱动开发-005ADC

embedded/2024/9/24 23:39:17/

1驱动程序

/*************************************************************************> File Name: adc_wait.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年04月23日 星期二 17时20分42秒************************************************************************/#if 1
/*=========================The adc_wait driver=========================*//*==========头文件包含==========*/
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/wait.h>
#include <linux/sched.h>#define ADCCON  (0x58000000)
#define ADCDAT0 (0x5800000C)
#define CLKCON	(0x4C00000C)/*==========全局变量声明==========*/
static u32 *regADCCON;
static u32 *regADCDAT0;
static u32 *regCLKCON;int adc_result=0;
static wait_queue_head_t wq;
static int condition;/*==========函数声明==========*/
/*adc配置函数声明*/
static void adc_init(void);
/*adc驱动函数声明*/
static irqreturn_t adc_interrupt(int irq,void *p);static void ioremap_r(void);
static int __init adc_driver_init(void);static int adc_driver_open(struct inode *node,struct file *fp);
static ssize_t adc_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset);
static ssize_t adc_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset);
static int adc_driver_close(struct inode *node, struct file *fp);static void iounmap_r(void);
static void __exit adc_driver_exit(void);/*******************************************************************************
* 函 数 名	: adc_interrupt
* 函数功能	: 处理中断任务
* 输    入  : 
*           irq : 中断号
*           *p  :中断处理函数传参,一般传【NULL】
* 输    出  :
*   irqreturn_t :表示中断由该设备处理,是一个枚举类型
*******************************************************************************/
static irqreturn_t adc_interrupt(int irq,void *p)
{adc_result=*regADCDAT0 & 0x3FF;condition=1;//唤醒等待队列的条件wake_up(&wq);//唤醒等待队列return IRQ_HANDLED;
}
/*******************************************************************************
* 函 数 名	: adc_driver_open
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int adc_driver_open(struct inode *node,struct file *fp)
{return 0;
}
/*******************************************************************************
* 函 数 名	: adc_driver_read
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static ssize_t adc_driver_read(struct file *fp, char __user *user_buffer, size_t len, loff_t *offset)
{	adc_result = *regADCDAT0 & 0x3FF;
//	*regADCCON &= ~(1 << 1);condition = 0;wait_event_interruptible(wq, condition);copy_to_user(user_buffer, &adc_result, sizeof(adc_result));return sizeof(adc_result);
}
/*******************************************************************************
* 函 数 名	: adc_driver_write
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static ssize_t adc_driver_write(struct file *fp, const char __user *user_buffer, size_t len, loff_t *offset)
{return 0;
}
/*******************************************************************************
* 函 数 名	: adc_driver_close
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int adc_driver_close(struct inode *node, struct file *fp)
{return 0;
}/*字符设备文件操作结构体*/
static struct file_operations fops =
{.owner = THIS_MODULE,.open = adc_driver_open,.read = adc_driver_read,.write = adc_driver_write,.release = adc_driver_close
};/*杂项设备结构体*/
static struct miscdevice adc_dev = 
{.minor = MISC_DYNAMIC_MINOR,.name = "adc_r",.fops = &fops,
};/*******************************************************************************
* 函 数 名	: ioremap_r
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static void ioremap_r(void)
{regADCCON = ioremap(ADCCON, 4);regADCDAT0 = ioremap(ADCDAT0, 4);regCLKCON = ioremap(CLKCON, 4);
}
/*******************************************************************************
* 函 数 名	: adc_driver_init
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static int __init adc_driver_init(void)
{int ret;/* 1 注册杂项设备*/ret = misc_register(&adc_dev);if(ret <  0){printk("misc_register is failed\n");goto misc_register_err;}/* 2 注册中断-【中断号】-【中断处理函数指针】-【中断产生的条件和系统处理中断时的行为(这里处理中断时不响应其他中断)】-【给中断名命名】-【中断服务函数传参-NULL】*/ret = request_irq(IRQ_ADC, adc_interrupt, IRQF_DISABLED | IRQF_TRIGGER_NONE, "adc", NULL);if(ret < 0){printk("request_irq is failed\n");goto request_irq_err;}/* 3 初始化等待队列*/init_waitqueue_head(&wq);/* 4 寄存器映射*/ioremap_r();/* 5 开启adc时钟*/*regCLKCON |= (1 << 15);/* 6 adc配置初始化*/adc_init();return 0;request_irq_err:misc_deregister(&adc_dev);
misc_register_err:return -1;
}
/*******************************************************************************
* 函 数 名	: iounmap_r
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static void iounmap_r(void)
{iounmap(regADCCON);iounmap(regADCDAT0);iounmap(regCLKCON);
}
/*******************************************************************************
* 函 数 名	: adc_driver_exit
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static void __exit adc_driver_exit(void)
{iounmap_r();//寄存器反映射disable_irq(IRQ_ADC);//禁止中断free_irq(IRQ_ADC, NULL);//注销中断misc_deregister(&adc_dev);//注销杂项设备
}/*==========adc配置函数==========*/
/*******************************************************************************
* 函 数 名	: adc_init
* 函数功能	: 
* 输    入  : 							
* 输    出  :
*******************************************************************************/
static void adc_init(void)
{u32 t=0;t=*regADCCON;t&=~((0X01<<14)|(0XFF<<6)|(0X01<<1));t|=(0X01<<14);t|=(0X31<<6);t&=~(0X07<<3);//选择通道0t&=~(0X01<<2);正常工作模式
//	t&=~(0X01<<1);t|=(0X01<<1);//读启动方式*regADCCON=t;
}#if 0
/*******************************************************************************
* 函 数 名	: adc_convert
* 函数功能	:
* 输    入  :
* 输    出  :
*******************************************************************************/
static u32 adc_convert(void)
{*regADCCON|=(0X01<<0);while((*regADCCON&(0X01<<15))==0);return ADCDAT0&0X3FF;
}
#endifmodule_init(adc_driver_init);
module_exit(adc_driver_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("XXX");
/*=========================The adc_wait driver=========================*/
#endif

2应用程序

/*************************************************************************> File Name: main.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年04月23日 星期二 17时20分42秒************************************************************************/#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>int main(void)
{#if 1
/*====================adc-r====================*/    int fd=0;int n=0;fd=open("dev/adc_r",O_RDWR);if(fd<0){printf("opening is failed\n");return -1;}while(1){read(fd,&n,4);printf("%d\n",n);
//        sleep(1);}return 0;
/*========================================*/    
#endif
}

3关于adc驱动

(1)这里adc驱动是采用字符设备驱动中的杂项驱动方式,所以主要应用的技术有:字符设备驱动,杂项驱动,内核中断,等待队列,adc硬件驱动配置。
(2)驱动流程:搭建字符设备驱动框架:定义字符设备结构体变量->编写字符设备结构体成员函数->编写adc驱动初始化函数(驱动加载函数)->编写adc驱动卸载函数建立杂项驱动:定义杂项设备结构体变量->注册杂项设备->注销杂项设备建立内核中断:注册中断->编写中断服务函数建立等待队列:定义等待队列头和等待条件->初始化等待队列->队列等待(读时等待)->唤醒队列(中断发生时唤醒)建立adc裸机配置:开启adc时钟发生寄存器->adc配置(硬件初始化)
(3)注意事项:由于adc是一种需要上电手动开启时钟开关,所以在进行adc硬件初始化操作之前需要先配置adc的时钟开关(CLKCON)

http://www.ppmy.cn/embedded/21353.html

相关文章

MySQL常用语句

1、创建数据库&#xff1a; CREATE DATABASE database_name; 2、选择数据库&#xff1a; USE database_name; 3、创建表&#xff1a; CREATE TABLE table_name ( column1 data_type, column2 data_type,...); 4、插入数据&#xff1a; INSERT INTO table_name (co…

彻底理清防抖和节流(前端性能优化)

目录 引言&#xff1a; 1.定义 防抖(Debounce) 节流(Throttle) 2.实现方式/原理 防抖&#xff1a; 节流&#xff1a; 3.应用场景 防抖(Debounce)&#xff1a; 节流(Throttle)&#xff1a; 4.两者总结 相同点&#xff1a; 不同点&#xff1a; 补充&#xff1a; 上…

RK3588构建ubuntu22.04根文件系统

前言 RK系列的平台提供了buildroot和debian的系统&#xff0c;使用脚本可以直接构建出来&#xff0c;但是没有提供ubuntu的系统&#xff0c;很多厂商只提供一个rootfs.img的固件包&#xff0c;没有将方法开源出来。本文实现了从ubuntu官网开始构建一个ubuntu22.04根文件系统。…

深圳杯东三省联赛数学建模挑战赛2024D题

音板的振动模态分析与参数识别 音乐来自乐器&#xff0c;乐器产生于制造&#xff0c;而制造需要数理逻辑。 在20世纪末&#xff0c;我国就已经形成了较为完整的乐器工业生产体系&#xff0c;基本可以加工世界上所有大类乐器&#xff0c;门类齐全&#xff0c;品种众多。其中&am…

Hotcoin Academy 市场洞察-2024年4月15日-21日

加密货币市场表现 BTC ETF在本周出现净流出&#xff0c;大盘有较大跌幅&#xff0c;BTC一度跌破60000美金&#xff0c;ETH一度跌破2800美金&#xff0c;整体以横盘为主&#xff0c;行情在周末有略微回升趋势。BTC市占率创21年4月来新高&#xff0c;目前市值1.28万亿&#xff0c…

成为程序员后你都明白了什么?

方向一&#xff1a;技术成长 作为程序员的技术成长和突破&#xff0c;我将其划分为几个阶段。 1、基础知识阶段。我投入大量时间学习编程语言的基础知识&#xff0c;如数据类型、循环、函数等&#xff0c;并通过具体的编程任务将所学知识转化为实战经验。 2、进阶技术阶段。…

idea 的使用和安装 以及简介

Java开发工具 大家刚才写代码的时候都是用记事本写的&#xff0c;但是有没有觉得记事本写代码不太方便啊&#xff01;记事本写代码单词写错了没有提示&#xff0c;格式也不好调整&#xff0c;写代码之后还需要我们到命令行使用javac命令手动编译&#xff0c;然后运行。 有没有一…

SQL中top的使用

1.介绍&#xff1a;查询最热门&#xff0c;最高的分的前几条数据 2.top的使用 &#xff08;1&#xff09;返回确定数目的记录个数 语法格式&#xff1a; SELECT TOP n <列名表> FROM <表名> [查询条件] 其中&#xff0c;n为要返回结果集中的记录条数 &#xf…