微波EDA网,见证研发工程师的成长! 2025骞�04鏈�02鏃� 鏄熸湡涓�
首页 > 应用设计 > 汽车电子 > 基于Linux/Qtopia的车载温度网络采集

基于Linux/Qtopia的车载温度网络采集

时间:05-10 来源:互联网 点击:

B20_MAJOR,DEVICE_NAME); //完成设备注销

……

}


3.2 硬件设备接口层

硬件设备接口层用来描述驱动程序与设备的交互。这些工作通过虚拟文件系统与设备驱动程序的接口实现。这个接口由file_operation结构定义,其结构如下:

static struct file_operations DS18B20_fops ={

.owner=THIS_MODULE, //指向拥有该结构的模块,内核使用该结构维护模块使用计数

.open=DS18B20_open, //打开设备函数

.read=DS18B20_read, //读接口函数

.write=DS18B20_write,//写接口函数

.fasync=DS18B20_fasync, //异步通知函数

.poll=DS18B20_poll,//poll函数

.release=DS18B20_release, //释放设备函数

};

3.2.1 打开设备函数

打开设备函数主要完成设备的初始化。

DS18B20_open(struct inode *inode,struct file *filp) {

Initial_Timer( );//初始化定时器,使内核模块按一定周期读温度

Initial_Device_DS18B20();//初始化硬件

readtemperature();//开始读取……

}

void readtemperature(void) {

……Temperature=DS18B20read();//读取2个8位数据,此函数完成的硬件操作时序,由当前读通道号变量指定当前通道

DS_SLOT_NO();//将本次读通道号放入缓冲区

DS18B20Event();//数据放入缓冲区,唤醒等待队列并启动异步通知

if(ReleaseFlag)

CycleTimer_Delay_Soft(hdelay);//如果没有读停止信号,通过内核定时器延时,进行下一次读,在中断服务程序中再次启动读

……

}

在使用内核定时器之前需定义一个定时器结构体 static struct timer_list CycleTimer。下面是定时器的具体操作:

static void Initial_Timer(void) {

init_timer(&CycleTimer); );//初始化定时器结构

CycleTimer.function=DS18B20_timer; //挂接定时中断服务程序

}

3.2.2 读接口函数

用户程序执行读操作的时候可能没有可以读取的数据,此时需要让read操作等待直到有数据可以读取。在此采用等待队列使进程在无数据读取时进入等待,数据到达时唤醒。等待队列设置成一个循环缓冲区,每放入一个新数据作为缓冲区的头,存放时间最久还未被取走的数据为缓冲区的尾。

DS18B20_read( ) {

DECLARE_WAITQUEUE(wait,current);//声明等待队列……

Next_try:

if(DS18B20dev.head != DS18B20dev.tail) {//等待队列不为空,即有数据

DS18B20_ret=Read_Buffer_DS18B20(); //取走缓冲区的尾

copy_to_user( ); //读取的数据送到用户空间

}

else { ……//等待队列为空,即没有数据

add_wait_queue(&queue,&wait);

current>state=TASK_INTERRUPTIBLE;//添加等待队列,声明状态为任务可中断

while((DS18B20dev.head==DS18B20dev.tail)&&!signal_pending(current) {//进入等待

schedule();

current>state=TASK_INTERRUPTIBLE;

}//如果缓冲区为空,Linux内核调度,等待通知

current>state = TASK_RUNNING;//得到有数据的通知,声明任务状态为运行

remove_wait_queue(&queue,&wait);//删除等待队列

goto Next_try;//返回到读取数据

}

}


3.2.3 fasync异步通知函数

异步通知函数向进程发送SIGIO信号,通知访问设备的进程,表示设备已经准备好I/O读写了,避免主动查询,提高程序效率。使用异步通知需增加一个struct fasync_struct的结构指针,然后实现fasync接口函数。

static struct fasync_struct *fasync;//定义一个结构体

static int DS18B20_fasync(int fd,struct file *filp,int on) {//实现接口函数

retval = fasync_helper(fd,filp,on,&fasync);

if ( retval<0) return retval;return 0;

}

最后在需要向用户空间通知的地方调用内核的kill_fasync函数。在打开设备函数中提到的DS18B20Event()功能是:将数据放入循环缓冲区,唤醒等待队列并启动异步通知,其后两项功能是这样实现的:

wake_up_interruptible(&queue);//唤醒等待队列

if (fasync) {

kill_fasync(&fasync,SIGIO,POLL_IN);//发送异步通知信号

}

3.2.4 poll系统调用操作接口函数

当程序需要进行对多个文件读写时,如果某个文件没有准备好,则系统就会处于读写阻塞的状态,影响其他文件的读写。为了避免读写阻塞,使用poll函数。如果设备无阻塞地读,就返回POLLIN;通常的数据已经准备好,可以读了,就返回POLLRDNORM。

static unsigned int DS18B20_poll(struct file *flip, poll_table *wait) {

poll_wait(flip,&queue,wait);

if(DS18B20dev.head != DS18B20dev.tail) {

return POLLIN|POLLRDNORM;

}

return 0;

}

3.2.5 release释放设备函数

static intDS18B20_release(struct inode *inode,struct file *filp) {

Releas

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top