河南理工大学计算机科学与技术学院课程设计报告2012—2013学年第一学期课程名称:嵌入式系统课程设计设计题目:基于ARM9和Linux的嵌入式打印终端系统学生姓名:学号:专业班级:指导教师:2012年12月23日1目录1嵌入式打印终端系统的设计原理……………………………………………22嵌入式打印终端系统的硬件设计……………………………………………32.1硬件开发平台S3C2410结构…………………………………………32.2嵌入式开发板…………………………………………………………32.3打印机与开发板接口电路的设计………………………………………33嵌入式打印终端系统的软件设计……………………………………………53.1软件选型…………………………………………………………………53.2打印机驱动的编写……………………………………………………53.3扫描仪串口的设置……………………………………………………73.4主应用程序的设计……………………………………………………11参考文献………………………………………………………………………12附录……………………………………………………………………………122基于ARM9和Linux的嵌入式打印终端系统引言随着开放源代码运动的飞速发展,Linux操作系统越来越受到人们的重视。其良好的可裁减性与可移植性,卓越的效率和稳定性,以及支持多种处理器体系架构的特点,使得Linux越来越广泛的应用于嵌入式领域。同时,ARM9处理器高主频的处理速度、大容量的闪存芯片和MMU控制单元的支持,使得运行嵌入式Linux变得稳定而高效。本文设计与实现的打印终端系统,正是基于这两个软硬件平台搭建起来的。1嵌入式打印终端系统的设计原理远程服务器嵌入式开发板打印机扫描机图1嵌入式移动打印终端架构嵌入式打印终端原理连接图如图1所示。主要由开发板、主机、打印机和扫描仪四部分组成。主机是一台PC机。开发板采用的是三星公司S3C2410开发板,ARM9的核,跑的是2.4内核版本的嵌入式Linux操作系统。扫描仪为超市等用的手持扫描仪。再加一台微型打印机接在开发板的GPIO口上。工作流程为:开发板将扫描仪的数据从串口读出,然后通过网口将数据发送给主机进行检索处理。开发板等待直至接收到主机处理完毕的数据后转发给打印机,将信息打印出来。32嵌入式打印终端系统的硬件设计2.1硬件开发平台S3C2410结构三星公司的S3C2410开发板用的是32位RISC架构基于ARM920T核,其增强的MMU单元、AMBA总线,可以支持WinCE、Linux等实时操作系统。片上资源丰富接口众多,包含LCD控制器、USBHost、CS9800A网络芯片、SD卡、3个UART通用异步串行口等设备接口。2.2嵌入式开发板嵌入式开发板是本系统的核心部件,它担负着整个系统中心枢纽的重担,同时,它的选型也直接影响到上层操作系统和其它部件的选型。所以,在选择这个部件时,要站在整个系统的高度来进行。选择嵌入式开发板要考虑的因素非常多,但必须首先考虑下面几个核心要素:接口类型:在本系统中,嵌入式开发板连接着扫描仪、远程服务器和微型打印机。所以,开发板上必须具备和这些部件连接的接口,如和扫描仪连接时需要的RS-232C串口,和远程服务器连接时的网络接口,和微型打印机连接时的打印接口。所支持的操作系统:嵌入式开发和单片机开发核心的区别之一就是嵌入式开发往往基于一个操作系统之上来进行。嵌入式操作系统种类繁多,各具特色,因此,必须要选择一个较通用和易用的操作系统平台。在本开发实例中,我们选择嵌入式Linux作为后面的平台开发。性价比:如果作为产品来开发,必须要考虑产品在价格上的竞争要素。嵌入式开发板可以自己设计,也可以直接购买市场上已有的成熟开发板,当然这种开发板一定是能够满足使用的最小系统,即裁减掉任何用不到的多余软/硬件。如果选择购买其他公司已有的开发板,首先要看该开发板是否稳定,其次要看该开发板是否能够提供所需的软件,比如各个部件的驱动;再次要看开发板的售后支持。2.3打印机与开发板接口电路的设计我们使用的微型打印机使用的是并行接口。由于开发板上没有提供并口,所4以必须自己设计一个板卡接口电路,以连接打印机的并口和我们的嵌入式开发板。查看S3C2410的电路原理图,由于此系统不需要用到LCD屏,可以将板子上用于LCD连接的GPIO口进行改造,根据ARM9core的LCD电路引脚和板上的LCD插槽定义,如图2,找到了14根空闲的GPIO口:gpio_c8~gpio_d15,gpi0_d0~gpio_d4。用这14根通用输入输出口连接微型打印机的并口。图2核心core的LCD引脚和板上LCD引脚原理图同时查看打印机的电路手册和管脚定义,选用其STB选通线、ACK回答脉冲线、BUSY线、DATA0-DATA7数据线来与开发板的GPIO口相连,并初始化高低电平值。为了避免接线过紧互相干扰,制作一个接口板定义各引脚连接如图3所示。至此,硬件的电路设计及连接基本完成。图3打印机并口与开发板GPIO口接口板设计图53嵌入式打印终端系统的软件设计软件平台采用的是基于2.4内核的嵌入式Linux系统。采用的交叉编译器工具包为CROSS2.95.3.tgz(包含arm-linux-gcc等)。3.1软件选型嵌入式系统是一个软/硬件相结合的系统,硬件好比人的身体,而运行在其上的软件则好比人的灵魂。没有软件的驾驭,硬件只是一些废铜烂铁,因此,相比较硬件选型而言,软件的选择也异常重要。在整个软件选型中,要特别重视两个方面的因素:运行其上的嵌入式操作系统:嵌入式操作系统是整个软件的核心和基础,的功能的强大与否直接影响后面整个系统的设计,因此必须加以重视。目前嵌入式操作系统有几百种之多,它们各具特色,各有相应的用武之地。通常来说,各个嵌入式开发板提供商,在其嵌入式开发板上会提供已经移植好的的几个嵌入式操作系统,这些操作系统通常为嵌入式Linux、WinCE、VxWorks和uCosII。uCosII是一个非常好的教学操作系统,但由于其功能较少,在商用领域使用比较少。而VxWorks由于较昂贵的使用费用,在中小型公司中使用也较少。WinCE主要用于PDA等领域,嵌入式Linux由于其源码开放,共享资源丰富,整个系统功能异常强大,因此在嵌入式领域应用得也最为广泛。软件驱动支持:由于不同的嵌入式开发板上提供的接口也各不相同,因此Linux内核源码包不可能提供所有外设接口的底层驱动。通常情况下,这些底层驱动或者由嵌入式开发板提供商做好后提供给用户使用,或者由用户自己开发出来。而底层驱动的开发是整个系统设计中比较耗时的工作,所以用户在选择开发板时,尽量选择已提供自己所需要的底层驱动的开发板,这样可以缩短项目的开发周期,减少项目投资,提高整个产品的竞争力。3.2打印机驱动的编写Linux的设备分为块设备,字符设备和网络设备,该系统使用到的微型打印机属于字符设备,下面将具体说明如何设计打印机驱动。3.2.1定义设备名#defineDEVICE_NAMEweida_printer63.2.2模块函数设计在该系统中,采用模块化加载驱动程序的方法,因此必须实现模块的初始化函数和卸载函数。采用devfs方式注册打印机。初始化函数weida_init通过devfs_register函数向系统注册设备。函数原型devfs_register(NULL,DEVICE_NAME,DEVFS_FL_DEFAULT,0,0,S_IFCHR|S_IRUSR|S_IWUSR,&weida_printer_fops,NULL);其中,DEVICE_NAME为主设备名,weida_printer_fops为定义的一个数据结构,用来实现的文件操作,包括open、close、write等。3.2.3初始化打印端口初始化打印机第一个要做的事情就是要对GPIO口进行初始化,初始化函数如下:staticvoidweida_init(void){devfs_register();/*注册设备驱动*/set_gpio_ctrl(WEIDA_STB|GPIO_PULLUP_DIS|GPIO_MODE_OUT);/*设置STB口*/write_gpio_bit(WEIDA_STB,1);weida_printer_io_port_init();/*设置其它IO口,以及赋初值*/}其中,WEIDA_STB为连接打印机选通口初始化为高电平,GPIO_PULL_DIS是设置是否需要上拉电阻,GPIO_MODE_OUT设置GPIO口为输出口。最后使用module_init(weida_printer_init);采用模块方式加载驱动。3.2.4打印机驱动测试程序设计通过上面几个步骤,打印机驱动模块已经注册到内核,在/dev目录下可以找到weida_printer设备。编写如下简单程序测试代码。intmain(void){intweida_fd,ret;char*data=“Hello,welcomtouseweidaprinter!“;weida_fd=open(“/dev/weida_printer”,O_WRONLY);//打开/dev/weida_printer设备if(weida_fd0){7perror(“opendevicebuttons”);exit(1);}ret=write(weida_fd,data,strlen(data));//向打印机输出数据,打印“Hello……”字符串if(ret!=strlen(data))perror(“printwrong\n”);ioctl(weida_fd,WEIDA_IOCSLINESPACE,1);sleep(1);ret=write(weida_fd,data,strlen(data));if(ret!=strlen(data))perror(“printwrong\n”);close(weida_fd);return0;}3.2.5接口函数设计ioctl()函数主要完成打印机字体、行距等参数的设置,在设计过程中必须解决用户数据和内核数据之间如何传递。从用户态读取数据,然后在内核态运行,可以使用copy_from_user函数来完成传递数据。weida_printer_write()先对打印机是否在线,是否忙,是否准备好做进一步的判断,然后再进行打印。在打印的时候要注意每发一个字符要延迟150毫秒,因为如果打印数据发得过快打印机的来不急处理,所以要设置延时。open/close函数打开/关闭文件,因为在LINUX下设备都是当作文件来操作的,所以需要open和close这两个接口函数。3.3扫描仪串口的设置嵌入式移动打印终端中使用到的扫描仪是串口扫描仪,这种扫描仪相对于USB接口的扫描仪来说,控制较简单,在扫描仪扫描后,可以直接从串口读取数据。3.3.1串口设置8设置串口速率函数:set_speed(intfd,intspeed),其中fd为打开的设备文件,speed为速率。设置串口参数:set_parity(intfd,intdatabits,intstopbits,intparity),databits为有多少个数据位,stopbit为设置多少个停止位,parity为奇偶校验位设置。设置串口波特率为9600,数据位为8位,一位停止位,没有校验位。voidset_speed(intfd,intspeed){intj;intstatus;structtermiosOpt;tcgetattr(fd,&Opt);for(i=0;isizeof(speed_arr)/sizeof(int);i++){if(speed==name_arr[i]){tcflush(fd,TCIOFLUSH);cfsetispeed(&Opt,speed_arr[i]);cfsetospeed(&Opt,speed_arr[i]);status=tcsetattr(fd,TCSANOW,&Opt);if(stat