基于嵌入式linux电表采集终端显示模块设计论文内容摘要:

冲区,通过参数k可以设置。 ASCII mode(XLATE)模式:识别各种键盘码的组合,转换为TTY终端代码放入缓冲区,通过参数a可以设置。 UTF8 mode(Unicode)模式:Unicode模式基本上与XLATE相同,只不过可以通过数字小键盘间接输入Unicode代码,通过参数u可以设置。 4.电表终端显示模块的设计与实现自20世纪80年代以来,随着液晶屏幕成本的降低,各种嵌入式图形消费产品和工业设备逐步获得了广泛的应用,从面向专业人员的高端产品逐步转变成为面向普通消费者和普通技术人员的低端产品。 作为人机交互的纽带,图形用户界面(GUI)的重要性越来越凸现出来。 考虑到实际应用的专用性以及消费类产品对成本的敏感性,由桌面PC操作系统演变来的Windows CE /QT Embedded等嵌入式操作系统所提供的GU I所要求的资源普遍较高。 Mini GU I等GU I系统虽然专为嵌入式系统设计,但开发使用需要考虑较多琐碎的细节。 因此本文从实际应用出发,在上文完成的framebuffer驱动和小键盘驱动基础上,开发了一套适合电表采集终端显示信息的图形界面。 framebuffer小键盘framebuffer,小键盘设备驱动通用APIopenreadwriteclose图形界面 电表终端图形界面系统结构 framebuffer驱动实现帧缓冲设备对应的设备文件是/dev/fb*。 如果系统有多个显卡,Linux还支持多个帧缓冲设备,最多可达32个,即/dev/fb0~/dev/fb31。 而/dev/fb则为当前缺省的帧缓冲设备,通常指向/dev/fb0。 当然在嵌入式系统中支持一个显示设备就够了。 帧缓冲设备为标准字符设备,主设备号为29,次设备号则从0到31。 分别对应/dev/fb0~/dev/fb31。 帧缓冲设备采用“文件层驱动层”的接口方式。 在文件层为之定义了以下数据结构。 Static struct file_operations fb_fops={ower: THIS_MODULE,read: fb_read, /*读操作*/write: fb_write, /*写操作*/ioct1: fb_ioct1, /*I/O操作*/mmap: fb_mmap, /*映射操作*/open: fb_open, /*打开操作*/release: fb_release, /*关闭操作*/}其成员函数都在linux/driver/video/,其中的函数对具体的硬件进行操作,对寄存器进行设置,对显示缓冲进行映射。 主要结构体还有以下几个。 struct fb_fix_screeninfo:记录了帧缓冲设备和指定显示模式的不可修改信息。 它包含了屏幕缓冲区的物理地址和长度。 struct fb_var_screeninfo:记录了帧缓冲设备和指定显示模式的可修改信息。 它包括显示屏幕的分辨率、每个像素的比特数和一些时序变量。 其中变量xres定义了屏幕一行所占的像素数,yres定义了屏幕一列所占的像素数,bits_per_pixel定义了每个像素用多少个位来表示。 struct fb_info:Linux为帧缓冲设备定义的驱动层接口。 它不仅包含了底层函数,而且还有记录设备状态的数据。 每个帧缓冲设备都与一个fb_info结构相对应。 其中成员变量modename为设备名称,fontname为显示字体,fbops为指向底层操作的函数的指针。 LCD驱动开发的主要工作包括如下三个步骤:初始化函数首先初始化LCD控制器,通过写寄存器设置显示模式和颜色数,然后分配LCD显示缓冲区。 在Linux中可以用kmalloc()函数分配一段连续的空间。 缓冲区大小为:点阵行数点阵列数用于表示一个像素的比特数/8。 缓冲区通常分配在大容量的片外SDRAM中,起始地址保存在LCD控制寄存器中。 本文采用的LCD显示方式为240320,16位彩色,则需要分配的显示缓冲区为2403202=150kb。 最后是初始化一个fb_info结构,填充其中的成员变量,并调用register_framebuffer(amp。 fb_info),将fb_info登记入内核。 编写结构fb_info中函数指针fb_ops对应的成员函数,对于嵌入式系统的简单实现,只需要下列三个函数就可以了。 struct fb_ops{…… int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)。 int (*fb_get_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info)。 int (*fb_set_var)(struct fb_var_screeninfo *var, int con, struct fb_info *info)。 ……}struct fb_ops在include/linux/。 这些函数都是用来设置/获取fb_info结构中的成员变量的。 当应用程序对设备文件进行ioctl操作时候会调用它们。 对于fb_get_fix(),应用程序传入的是fb_fix_screeninfo结构,在函数中对其成员变量赋值,主要是smem_start(缓冲区起始地址)和smem_len(缓冲区长度),最终返回给应用程序。 而fb_set_var()函数的传入参数是fb_var_screeninfo,函数中需要对xres、yres和bits_per_pixel赋值。 实现显示设备的主要操作。 读/写(read/write)/dev/fb:相当于读/写屏幕缓冲区。 映射(map)操作:由于Linux工作在内核保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。 为此,Linux在文件操作 file_operations结构中提供了mmap函数,可将文件的内容映射到用户空间。 对于帧缓冲设备,则可通过映射操作,可将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。 I/O控制:对于帧缓冲设备,对设备文件的ioctl操作可读取/设置显示设备及屏幕的参数,如分辨率、显示颜色数和屏幕大小等。 ioctl的操作是由底层的驱动程序来完成的。 在应用程序中,操作/dev/fb的一般步骤如下:打开/dev/fb设备文件;用ioctrl操作取得当前显示屏幕的参数,如屏幕分辨率和每个像素的比特数,根据屏幕参数可计算屏幕缓冲区的大小;将屏幕缓冲区映射到用户空间;映射后即可直接读写屏幕缓冲区,进行绘图和图片显示了。 加载LCD驱动编写模块化驱动程序,有以下几个关键的函数。 s3c2410fb_init(void)//当模块被载入时执行 s3c2410fb_exit(void)//当模块被移出内核空间时被执行 s3c2410fb_ioctl(struct*inode, struct*file, unsigned int cmd, unsigned longarg) //其他功能 每当装配设备驱动程序时,系统自动调用初始化模块s3c2410fb_init(void)。 另一个必须提供的函数是s3c2410fb_exit(void),它在模块被卸载时调用,负责进行设备驱动程序的工作。 执行insmod ,执行rmmod s3c2410fb命令即可从内核中删除LCD驱动。 小键盘驱动实现 初始化s3c2410_keypad_init()函数是键盘代码执行的入口点。 s3c2410_keypad_init ()在对键盘的工作模式及其他参数进行配置后,调用HW_keypad_init()。 对于上层来说,s3c2410_keypad_init()是一个统一的接口,对于不同体系结构或同体系下的不同开发板,它们的HW_keypad_init()的实现代码是不同的,它就是进行键盘的硬件初始化功能。 然后将keyboard tasklet加入到tasklet链表中。 至此键盘驱动的初始化工作已经完成。 响应按键 如何处理键盘事件是键盘驱动中最为重要的一部分。 当有按键事件产生时,则用键盘中断处理函数,也就是IRQ_keypad_interrupt(),它会调用到HR_del_pre_scancode()并调用handle_scancode()函数。 handle_scancode()这个函数完成按键处理的过程,它的功能是与TY设备通讯,keymap表装入,按键处理。 handle_scancode()处理的结果就是把按键发给相应的处理函数,这些函数基本上都会调用put_queue()函数。 这个函数就是将处理函数的结果发送到TY或者console进行显示。 转化按键扫描码 在完成键盘的初始化之后,就需要完成对键盘扫描码的转化。 这里调用函数pckdb_translate,实现了scancode和keycode之间的转换。 通用按键处理在完成键盘扫描码转换之后就可以进行按键处理。 图形引擎的设计 全局变量的定义static unsigned char* _lGUI_pFrameBuffer。 static struct fb_fix_screeninfo _lGUI_fInfo。 static struct fb_var_screeninfo _lGUI_vInfo。 static int _lGUI_iFrameWidth。 static int _lGUI_iFrameHeight。 其中_lGUI_pFrameBuffer是用来将framebuffer映射到用户空间,_lGUI_fInfo,_lGUI_vInfo分别用来存储framebuffer的不可变信息和可变信息。 图形引擎初始化_lGUI_iFrameBuffer = open (/dev/fb0, O_RDWR)。 ioctl (_lGUI_iFrameBuffer, FBIOGET_VSCREENINFO, amp。 _lGUI_vInfo)。 _lGUI_iFrameHeight=。 _lGUI_iFrameWidth=。 _lGUI_pFrameBuffer =mmap (NULL, _lGUI_iBufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, _lGUI_iFrameBuffer, 0)。 打开fb0,并将framebuffer映射到用户空间字符数组,首地址存放在_lGUI_pFrameBuffer中。 使用mmap函数使用户空间的一段内存关联到设备内存(framebuffer)上。 无论何时,只要程序在分配的地址范围内进行读取或者写入,实际上就是对设备的访问,使用 mmap 可以既快速又简单地访问显示卡的内存。 对于象这样的性能要求比较严格的应用来说,直接访问能给我们提供很大不同。 基本图元设计1. 点的绘制void inline lGUI_SetPixel_Direct( int x, int y, COLORREF color){ unsigned char* pDest。 pDest = _lGUI_pFrameBuffer + _lGUI_iLineSize * y + (x * _lGUI_iBytesPerPixel)。 if(_lGUI_iBytesPerPixel == 3){ *pDest = B(color)。 *(pDest+1) = G(color)。 *(pDest+2) = R(color)。 } else *((PCOLORREF)pDest)=color。 }首先计算将要画点的地址。 点x、y表示点位于LCD显示屏上的第x行,第y列,由此计算映射到用户空间的字符数组的偏移量,加上字符数组首地址既是要画点的地址pDest。 然后根据定义的颜色结构,将pDest强制类型转换为定义的颜色类型指针,最后在pDest指向的地址里赋值。 这样避免了因颜色定义的不同而修改程序,提高了程序的移植性。 2. 直线的绘制直线由点构成,更精确的说,直线是由靠近这条线的像素构成。 这就引出一个问题,究近哪些点算是靠近一条直线;哪些点不算是靠近一条直线,这必须使用一种算法作为依据。 本文使用简单的直线方程算法。 我们使用公式y = kx + b来作为绘图的依据,那么就需要分3种情况:水平直线,斜率为0;垂直直线,斜率为无穷大(或者说k不存在);普通直线。 假设我们已经知道直线的起始坐标点(Xbegin,Ybegin)和终点(Xend,Yend),x,y,是当前的坐标点,如果我们通过增加x反算出y的方法的话,这个公式就可以很容易转换为伪代码。 LineMode 为直线的类型:水平,垂直,普通if Xbegin == Xend then LineMode = 水平elseif Ybegin = Yend??then LineMode = 垂直else k = (Yend Ybegin) / (Xend Xbegin)switch LineModecase 水平for x = Xbegin to Xend在x,Ybegin处画点case 垂直for y = Ybegin to Yend在Ebegin,y处画点default:for x = Xbegin to Xend{y = kx + b在x,y处画点}3. 其他图元的绘。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。