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

发布者:SparkCrafter最新更新时间:2008-09-05 来源: 单片机与嵌入式应用关键字:Qtopia  温度采集  车载信息  单总线  函数  init  采集系统  endif  argc  数字温度传感器 手机看文章 扫描二维码
随时随地手机看文章

  摘要本文将一线制温度传感器网络引入车载信息采集系统,介绍了嵌入式Linux下一线制温度传感器网络的内核驱动模块实现过程;设计了基于QTE/Qtopia温度测量图形界面应用程序,实现了温度网络的即时测量、数据保存、高温报警等功能,并成功应用于车载信息采集系统。

  关键词 车载信息采集 嵌入式Linux Qtopia 一线网络 温度网络采集 DS18B20

  引言

  本文在嵌入式Linux平台上实现了车载信息采集系统的一部分——汽车常规温度的数据采集,如采集车内温度、暖风或空调温度、车外温度、水箱温度等。DS18B20是一种可组网单总线数字温度传感器,为信息采集提供了经济有效的可行方案。嵌入式Linux以其源码开放、容易定制和扩展、多硬件平台支持和内置网络功能等优良性能,逐渐成为车载设备广泛使用的系统平台。本文涉及的系统使用三星公司的S3C2410AL20处理器,操作系统采用2.6.8.1内核Linux,GUI采用Trolltech公司的Qtopia;功能上主要实现:各路温度的采集显示、音频报警、温度数据的存储、相关功能设置等。当需要语音提示或报警时,应用程序调用语音模块;当需要存储或显示历史数据时,应用程序调用SD存储模块。

  1 Linux系统开发概述

  驱动程序的开发是嵌入式Linux开发的主要任务之一。设备驱动为上层应用程序提供控制硬件的设备接口,同时直接与Linux内核打交道。图1描述了Linux系统开发框架。

  

  

  图1 Linux系统开发框架

  应用程序开发是嵌入式Linux开发的另一个主要任务。Qt/Embedded 是著名Qt 库开发商Trolltech 公司开发的面向嵌入式系统的Qt 版本。Qtopia是在Qt/ Embedded 库的基础上,专门针对PDA、SmartPhone这类运行嵌入式Linux 的移动设备和手持设备所开发的开放源码的一套应用程序包和开发库。它包括全套的个人信息管理PIM ( Personal Information Management) ,如地址本、日程安排、MPEG播放、图像显示、浏览器等。

  2 车载信息系统及硬件平台概述

  车载信息采集系统开发主要包括用户界面开发,内核开发,音频模块设计,串口模块设计,CAN总线模块设计,车辆状态(又包含开关量、模拟量、数字量等)检测模块设计等。

  本设计着重实现一线制温度网络的数据采集。一线制温度网络的温度信号特点是:数值不高,多在0~100 ℃范围内;温度信号变化较慢;系统对采集到的温度信号的实时性要求不高;精度要求不高。

  一线网络的优点在于能测量大量的物理量,所有的通信都通过一线协议,而与被测的具体量无关。一线网络是能够方便地搭建起由一线传感器芯片组成的一系列测量环境参数的网络。

  DS18B20是一种可组网的单总线数字温度传感器,具有以下功能特点:

  ① 适应宽的电压范围(3.0~5.5 V),在寄生电源方式下可由数据线供电。

  ② 独特的单线接口方式,DS18B20在与微处理器连接时仅需要1条口线即可实现微处理器与DS18B20的双向通信。

  ③ 温度范围为-55~+125 ℃,在-10~+85 ℃时精度为±0.5 ℃。

  ④ 可编程的分辨率为9~12位,对应的可分辨温度分别为0.5 ℃、0.25 ℃、0.125 ℃和0.062 5 ℃,可实现较高的精度测温。

  单总线使得硬件开销极小,但需要相对复杂的软件进行补偿。由于DS18B20采用单总线串行数据传送,保证严格的读写时序成为测温关键,因此没有采用I/O驱动,而是单独编写一线制温度网络驱动。

  本设计采用寄生电源连接方式,12位分辨率。寄生电源的优点为:远程温度检测无需本地电源;缺少正常电源条件下也可以读ROM。为确保DS18B20在其有效变换期内得到足够的电源电流,在I/O线上通过MOSFET提供强的上拉(如图2所示)。当使用寄生电源方式时,VDD引脚必须连接到地。

  系统核心控制器S3C2410X是三星公司基于ARM920T核的芯片。S3C2410X集成了1个LCD控制器(支持STN和TFT带有触摸屏的液晶显示屏)、SDRAM、触摸屏、USB、SPI、SD和MMC等控制器,4个具有PWM功能的计时器和1个内部时钟,8通道的10位ADC,117位通用I/O口和24位外部中断源,8通道10位AD控制器,处理器工作频率最高达到203 MHz。系统显示采用SHARP 3.5 in的TFT_LCD液晶显示屏。系统框图如图2所示。

  

  

  图2 信息采集系统及部分电路连接原理

  3 驱动实现

  本节将实现一线制温度传感器网络的驱动模块。驱动从总体上看分为两部分:驱动与内核接口层、硬件设备接口层。

  3.1 驱动与内核接口层

  驱动与内核接口层主要完成驱动模块在Linux内核的注册加载、卸载清除工作。这部分工作分别由初始化和退出函数完成。

  ① 初始化函数完成驱动模块加载:

  static int __init DS18B20_init(void){

  ……

  register_chrdev(DS18B20_MAJOR,DEVICE_NAME, &DS18B20_fops);//完成设备注册

  #ifdefCONFIG_DEVFS_FS//创建设备文件系统

  devfs_mk_cdev(MKDEV(DS18B20_MAJOR,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);

  #endif

  ……

  }

  ② 退出函数完成驱动模块卸载:

  static void __exit DS18B20_exit(void) {

  #ifdef CONFIG_DEVFS_FS

  devfs_remove(DEVICE_NAME);//移除设备文件

  #endif

  unregister_chrdev(DS18B20_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) {

  ReleaseFlag=0//内核停止读取温度标志

  DS18B20_fasync(1,filp,0);//关闭异步通知

  module_put(THIS_MODULE);//设备计数器减1

  return 0;

  }

  写接口函数用来通知驱动。例如通知驱动读取通道2的数据,在应用程序中执行写接口函数write(fileno,&SLOT2,1),驱动设置当前读通道号为2。

  至此完成驱动接口函数。此驱动属于字符设备驱动,将源程序放在driver/char 目录下。同时需要修改该目录下的Kconfig配置文件并添加 Config 18B20_S3C2410选项,修改driver/char/Makefile,添加obj$(CONFIG_18B20_S3C2410) +=S3C2410_18B20.O。最后重新配置内核,将驱动以模块形式添加到内核,这样就可以编译驱动了。

  4 Qtopia应用程序设计

  (1) 创建工程

  首先利用QT Designer设计器创建一个窗体应用程序ThermometerFigure.ui。窗体程序创建好后根据需要添加窗体控件、槽函数、信号等。图3为ThermometerFigure类的实现框图。

  (2) ThermometerFigure类实现

  利用uic工具产生相应的*.cpp和*.h文件(窗体类的实现文件和头文件)。编辑*.cpp和*.h文件实现各成员函数、信号槽的连接。具体实现如图3所示。

  (3) 创建main及初始化

  首先创建main.cpp文件,并在main.cpp 中创建QApplication 对象。QApplication 类负责图像用户界面应用程序的控制流和主设置,对所有来自系统和其他源文件的事件进行处理和调度;还包括应用程序的初始化和结束。

  int main( int argc, char **argv ) {

  QApplication app(argc,argv);

  ThemometerFigure wyc;//创建对象

  app.setMainWidget( &wyc );//选为主窗体

  wyc.show(); return app.exec();

  }

  (4) 编辑*.pro文件并生成Makefile

  利用progen工具创建Thermometer.pro,具体实现如下:

  TEMPLATE=app

  CONFIG=qt warn_on release

  HEADERS=ThermometerFigure.h

  SOURCES=ThermometerFigure.cpp \\ main.cpp

  INTERFACES=

  执行qmake命令生成Makefile文件,执行之前要设置相关的环境变量,编译器路径等。

  qmakeo Makefile Thermometer.pro

  (5) 编译链接工程

  执行make命令,将生成目标二进制文件Thermometer,此文件即可在设备上运行。

  

  

  图3 ThermometerFigure类的实现框图

  

  

  图4 ThermometerFigure类实现界面

  (6) 将可执行文件发布到Linux系统

  将可执行文件添加到Qtopia的根文件系统中,将生成的新的根文件系统烧写到设备的Flash根文件系统区,这样就可以在桌面运行程序了。图4为 ThermometerFigure类实现界面。

  结语

  本文介绍了车载信息系统开发的部分实现方法。通过实例讲述了Linux的开发过程,包括驱动开发和应用程序开发流程。创新点在于将一线制传感器网络引入车载信息采集系统,大大简化了线路结构,有很高的实用价值。

  参考文献

  [1] 郑灵翔,等.嵌入式系统设计与应用开发[M].北京:北京航空航天大学出版社,2006.

  [2] 南金瑞,等.嵌入式车载信息系统开发与应用[M].北京:电子工业出版社,2006.

  [3] 朱青,等.一线网络及其在机车定置试验台温度采集系统中的应用[J].电气应用,2006,25(9).

  刘滨(教授),主要研究方向为嵌入式系统、网络化智能仪器仪表;

  王永才、张冰(硕士研究生),

  赵艳华(讲师),研究方向为嵌入式系统。

 

关键字:Qtopia  温度采集  车载信息  单总线  函数  init  采集系统  endif  argc  数字温度传感器 引用地址:基于Linux/Qtopia的车载温度网络采集

上一篇:全球首款模块化多点液晶触摸屏亮相(图)
下一篇:奥地利微电子推新型增量式、线性磁编码器

推荐阅读最新更新时间:2024-03-30 21:26

基于单片机的信号采集系统的设计
  信号采集设备广泛使用于机器健康诊断系统中用来记录、监视和诊断。机器情况数据经常由非便携式或者带导线的设备收集。对于一些重要的应用,比如危险或者遥远的地点,尤其是在航空上,提供可以方便地携带或者读取的设备是必要的。另外,机器健康诊断尤其是机床振动信号诊断经常处理低频信号,这值得关注。   本文研究一种微控制器为基础的信号采集系统,以满足信号采集的低成本和灵活模式。开发系统的主要硬件包括一台微型计算机、一个以PIC18F1320为基础的微控制器电路板以及串行通讯链接设备。EEPROM 24LC32A被用来进行存储器扩展。微型计算机运行控制程序。一旦用户在微型计算机界面上决定采样输入,信息便通过RS-232端口送往微控制器。微型计
[单片机]
基于单片机的信号<font color='red'>采集系统</font>的设计
STM32CubeIDE 中 HAL库的串口中断接收函数 HAL_UART_Receive_IT
一、代码自动生成以后的项目及代码结构: main.c中,调用了串口初始化 串口初始化函数赋值了串口的参数 相当于底层的初始化,配置引脚、并开启中断。 至此串口1配置完毕 二、库文件stm32f1xx_hal_uart.c内的秘密 2.1 初始化 1.usart.c中,MX_USART1_UART_Init 调用了库的HAL_UART_Init,将结构体传递进该函数中 2.HAL_UART_Init干了些什么事? if (huart- gState == HAL_UART_STATE_RESET) { huart- Lock = HAL_UNLOCKED; HAL_UART_MspInit(huar
[单片机]
STM32CubeIDE 中 HAL库的串口中断接收<font color='red'>函数</font> HAL_UART_Receive_IT
avr单片机 串口实现printf(使用变参函数
#include #include #include typedef unsigned char uint8; static void usart_init(void) { UCSRA = 0x02; UCSRB = 0x18; UCSRC = 0x06; UBRRH = 0x00; UBRRL = 103; } static void put_char(uint8 data) { if (data == '/r') put_char(0x09); while ( !(UCSRA & (1 UDRE
[单片机]
MSP-EXP430F5529LP开发板004-PWM库函数
测试了TIMER_A的PWM几种模式 pwmMultipleUp 2.06kHz,75%占空比 #include wdt_a.h #include gpio.h #include timer_a.h #define TIMER_PERIOD 511 #define DUTY_CYCLE1 384 #define DUTY_CYCLE2 128 int main( void ) { volatile unsigned int i; WDT_A_hold(WDT_A_BASE); //P2.0 and P2.1 output //P2.0 and P2.1 options select GPIO_set
[单片机]
车载信息娱乐系统品质提升之路
1. 概述 伴随汽车工业的蓬勃发展,车载信息娱乐系统正成为汽车智能化的一个重要环节。在为广大消费者提供更高级的舒适性、娱乐性和信息性的同时,车载信息娱乐系统作为整车高附加值的电子产品在汽车里所占的比重越来越大,且集成的功能由单纯的音响设备、CD设备、收音机设备逐渐扩展为影像娱乐、汽车导航、无线通讯等于一体的多媒体信息交互设备。 图1 信息娱乐系统功能概述 从图中可以看出,一个车载信息娱乐系统拥有音频播放、视频图像播放、广播、导航、蓝牙、语音识别、手机通信等功能,同时车载信息娱乐系统作为整车电气及网络的一个结点,担负着显示和反馈整车状态与信息的作用。 2. 测试需求 如上所述,车载信息娱乐设备在整车中所扮演
[汽车电子]
<font color='red'>车载</font><font color='red'>信息</font>娱乐系统品质提升之路
单片机中Sprint函数
利用sprintf()函数转化为字符串发出去 最近在做项目 ,用到了好几次sprint,这个函数功能甚是强大啊。是转换成字符串的利器。下面是我在网上找到的,感觉比较好的总结。感谢各位网友,大家一起进步! sprintf函数的用法 1、该函数包含在stdio.h的头文件中。 2、sprintf和平时我们常用的printf函数的功能很相似。sprintf函数打印到字符串中,而printf函数打印输出到屏幕上。sprintf函数在我们完成其他数据类型转换成字符串类型的操作中应用广泛。 3、sprintf函数的格式: int sprintf( char *buffer, const char *format ); 除了前两个参数固定
[单片机]
STM32F103 系统各部分时钟设置
STM32F103 系统各部分时钟设置 /******************************************************************************* * 函数名 : RCC_Configuration * 函数描述 : 设置系统各部分时钟 * 输入参数 : 无 * 输出结果 : 无 * 返回值 : 无 *******************************************************************************/ void RCC_Configuration(void) { /* 定义枚举类型变量
[单片机]
DSP编程技巧之21---在main函数运行之前,你需要知道的
  在一个 C/C++ 程序能正常运行之前,相关的 C/C++ 运行时(run-time)环境首先要正确建立。在CCS软件编程的情况下, C/C++ 的实时运行库RTS的源程序库rts.src中包含了名为boot.c或者boot.asm的启动程序(在一些TI的例子里,则使用了CodeStartBranch.asm来完成启动工作,它会自动调用库文件中的boot.asm),用于在系统启动后调用c_int00函数,并通过其中的操作来完成运行时环境的建立。通常情况下,c_int00函数位于rts2800.lib库函数中的boot.obj(即TI官方编译boot.c或者boot.asm生成的目标文件)下,这也就是为什么我们在C2
[嵌入式]
DSP编程技巧之21---在main<font color='red'>函数</font>运行之前,你需要知道的
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
最新工业控制文章
换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved