基于ARM9和Linux的嵌入式打印终端系统.docx
- 文档编号:23893173
- 上传时间:2023-05-22
- 格式:DOCX
- 页数:23
- 大小:118.66KB
基于ARM9和Linux的嵌入式打印终端系统.docx
《基于ARM9和Linux的嵌入式打印终端系统.docx》由会员分享,可在线阅读,更多相关《基于ARM9和Linux的嵌入式打印终端系统.docx(23页珍藏版)》请在冰豆网上搜索。
基于ARM9和Linux的嵌入式打印终端系统
河南理工大学
计算机科学与技术学院
课程设计报告
2012—2013学年第一学期
课程名称:
嵌入式系统课程设计
设计题目:
基于ARM9和Linux的
嵌入式打印终端系统
学生姓名:
学号:
专业班级:
指导教师:
2012年12月23日
1嵌入式打印终端系统的设计原理……………………………………………2
2嵌入式打印终端系统的硬件设计……………………………………………3
2.1硬件开发平台S3C2410结构…………………………………………3
2.2嵌入式开发板…………………………………………………………3
2.3打印机与开发板接口电路的设计………………………………………3
3嵌入式打印终端系统的软件设计……………………………………………5
3.1软件选型…………………………………………………………………5
3.2打印机驱动的编写……………………………………………………5
3.3扫描仪串口的设置……………………………………………………7
3.4主应用程序的设计……………………………………………………11
参考文献………………………………………………………………………12
附录……………………………………………………………………………12
基于ARM9和Linux的嵌入式打印终端系统
引言随着开放源代码运动的飞速发展,Linux操作系统越来越受到人们的重视。
其良好的可裁减性与可移植性,卓越的效率和稳定性,以及支持多种处理器体系架构的特点,使得Linux越来越广泛的应用于嵌入式领域。
同时,ARM9处理器高主频的处理速度、大容量的闪存芯片和MMU控制单元的支持,使得运行嵌入式Linux变得稳定而高效。
本文设计与实现的打印终端系统,正是基于这两个软硬件平台搭建起来的。
1嵌入式打印终端系统的设计原理
图1嵌入式移动打印终端架构
嵌入式打印终端原理连接图如图1所示。
主要由开发板、主机、打印机和扫描仪四部分组成。
主机是一台PC机。
开发板采用的是三星公司S3C2410开发板,ARM9的核,跑的是2.4内核版本的嵌入式Linux操作系统。
扫描仪为超市等用的手持扫描仪。
再加一台微型打印机接在开发板的GPIO口上。
工作流程为:
开发板将扫描仪的数据从串口读出,然后通过网口将数据发送给主机进行检索处理。
开发板等待直至接收到主机处理完毕的数据后转发给打印机,将信息打印出来。
2嵌入式打印终端系统的硬件设计
2.1硬件开发平台S3C2410结构
三星公司的S3C2410开发板用的是32位RISC架构基于ARM920T核,其增强的MMU单元、AMBA总线,可以支持WinCE、Linux等实时操作系统。
片上资源丰富接口众多,包含LCD控制器、USBHost、CS9800A网络芯片、SD卡、3个UART通用异步串行口等设备接口。
2.2嵌入式开发板
嵌入式开发板是本系统的核心部件,它担负着整个系统中心枢纽的重担,同时,它的选型也直接影响到上层操作系统和其它部件的选型。
所以,在选择这个部件时,要站在整个系统的高度来进行。
选择嵌入式开发板要考虑的因素非常多,但必须首先考虑下面几个核心要素:
接口类型:
在本系统中,嵌入式开发板连接着扫描仪、远程服务器和微型打印机。
所以,开发板上必须具备和这些部件连接的接口,如和扫描仪连接时需要的RS-232C串口,和远程服务器连接时的网络接口,和微型打印机连接时的打印接口。
所支持的操作系统:
嵌入式开发和单片机开发核心的区别之一就是嵌入式开发往往基于一个操作系统之上来进行。
嵌入式操作系统种类繁多,各具特色,因此,必须要选择一个较通用和易用的操作系统平台。
在本开发实例中,我们选择嵌入式Linux作为后面的平台开发。
性价比:
如果作为产品来开发,必须要考虑产品在价格上的竞争要素。
嵌入式开发板可以自己设计,也可以直接购买市场上已有的成熟开发板,当然这种开发板一定是能够满足使用的最小系统,即裁减掉任何用不到的多余软/硬件。
如果选择购买其他公司已有的开发板,首先要看该开发板是否稳定,其次要看该开发板是否能够提供所需的软件,比如各个部件的驱动;再次要看开发板的售后支持。
2.3打印机与开发板接口电路的设计
我们使用的微型打印机使用的是并行接口。
由于开发板上没有提供并口,所以必须自己设计一个板卡接口电路,以连接打印机的并口和我们的嵌入式开发板。
查看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口接口板设计图
3嵌入式打印终端系统的软件设计
软件平台采用的是基于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_printer
3.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_fd<0){
perror(“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串口设置
设置串口速率函数:
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;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(status! =0){ perror(“tcsetattrfd! ”); return; } tcflush(fd,TCIOFLUSH); } } } set_partity(intfd,intdatabits,intstopbits,intpartity)用于设置串口的通信参数,其中databits设置数据位位数,stopbit设置停止位位数,partity设置奇偶校验位。 具体的函数代码如下: intset_partity(intfd,intdatabits,intstopbits,intpartity) { structtermiiosoptions; if(tcgetattr(fd,&options))! =0{ perror(“SetupSerial1”); returnFALSE; } options.c_cflag&=~CSIZE; switch(databits) { case7: options.c_cflag! =CS7; break; case8: options.c_cflag|=CS8; break; default: fprintf(stderr,”Unsupporteddatasize\n”); returnFALSE; } switch(partity) { case‘n’: case’N’: options.c_cflag=~PARENB; options.c_cflag=~INPCK; break; case‘o’: case’O’: options.c_cflag|=(PARODD|PARENB); options.c_cflag|=INPCK; break; case‘e’: case’E’: options.c_cflag|=PARENB; options.c_cflag&=~PARODD; options.c_cflag|=INPCK; break; case‘s’: case’S’: options.c_cflag&=~PARENB; options.c_cflag&=~CSTOP; break; default: fprintf(stderr,”Unsupportedpartity\n”); returnFALSE; } switch(stopbits) { case1: options.c-cfag&=~CSTOPB; break; case2: options.c-cfag|=CSTOPB; break; default: fprintf(stderr,”Unsupportedstopbits\n”); returnFALSE; } 3.3.2编写读取扫描仪数据函数 首先打开设备文件,该系统中使用的串口为串口2,因此打开函数为: open(“/dev/ttyS1”,O_RDWR|O_NONBLOCK|O_NDELAY);其中,O_RDWR表示可读可写,O_NONBLOCK表示非堵塞模式,O_NDELAY表示没有延迟,立即发出去。 3.3.3客户端和服务器的socket编写 嵌入式打印终端采用C/S的模式,把PC机作为服务器,开发板作为客户端,通过以太网连接。 客户端建立一个socket连接去寻找PC机上的服务程序。 PC机上同时也运行一个socket用来listen请求和绑定。 采用的是TCP的连接方式。 3.4主应用程序的设计 开发板上的应用程序Main函数注册两个线程p1和p2,两个全局数组c1和c2。 线程p1将从串口读到的数据放入c1中,然后sentsocket直接从c1中取走数据发送给服务器。 线程p2负责将receivedsocket数据放入c2数组中,然后直接从c2取走数据交给打印机去打印。 这里对线程使用了两个信号量,并初始化为: sem_init(&sem1,0,1);sem_init(&sem2,0,0); 两个线程的核心代码如下: voidthread1(void){ 打开串口;设置串口;建立连接; while (1){ sem_wait(&sem1); 从串口读书据; 用clinetsocket发送出去; sem_post(&sem2);} } voidthread2(void){ 打开打印机设备; while (1){ sem_wait(&sem2); 接收数据;扔给打印机; sem_post(&sem1);} } 如此可以使两个线程得以同步运行,并可以执行多次扫描和打印任务。 总结 本文创新点及其经济效益: 本系统具有移动性强,功耗低等特点,而且与以往传统的用PC机实现的打印终端相比,还具有低成本优势。 能广泛地应用于超市收银系统,银行自动存取款机,等各种工业领域。 把802.11g的无线网卡移植到开发板上,就可以成功实现和主机的无线通信,使得该系统更加便携。 参考文献 [1]ARM嵌入式系统原理及应用开发.谭会生.西安电子科技大学出版社,2012. [2]CORBETJ,RUBINIA.LINUX设备驱动程序(第三版)[M].中国电力出社,2006.46-74TP316.81 [3]孙琼.嵌入式LINUX应用程序开发详解[M].人民邮电出版社,2006.184-191TP316.89 [4]田家林,陈利学,寇向辉.LINUX嵌入式操作系统在ARM上的移植[J].微计算机信息,2007,4-2: P60-62. 附录: (部分程序) #defineDEVICE_NAME“weida_printer” #defineWEIDA_MAJOR234 module_init(weida_printer_init); module_exit(weida_printer_exit); MODULE_LICENSE(“GPL”); staticintmodule_init(weida_printer_init) { intret; ret=register_chrlev(WEIDA_MAJOR,DEVICE_NAME,&weida_printer_fops); if(ret<0){ printf(DEVICE_NAME”can’tregistermajornumber\n”); returnret; } weida_printer_io_port_init(); weida_init(); printf(“weida_printer_init! \n“); returnret; } gpio_data_tb[]={GPIO_C8,GPIO_C9,GPIO_C10,GPIO_C11,GPIO_C12,GPIO_13,GPIO_C14,GPIO_C15}; #defineDATA_NUM((sizeofgpio_data_tab)/sizeof(gpio_data_tab[0])) #defineWEIDA_DATA_READYGPIO_D0 #defineWEIDA_ACKGPIO_D1 #defineWEIDA_BUSYGPIO_D2 #defineWEIDA_SELECTGPIO_D3 #defineWEIDA_ERRORGPIO_D4 staticvoidweida_printer_to_init(void) { intI; unsignedgpio; for(i=0;i gpio=gpio_data_tab[i]; set_gpio_ctrl(gpio|GPIO_PULLUP_DIS|GPIO_MODE_OUT); write_gpio_bit(gpio,0); } set_gpio_ctrl(WEIDA_DATA_READY|GPIO_PULLUP_DIS|GPIO_MODE_OUT); set_gpio_ctrl(WEIDA_ACk|GPIO_PULLUP_DIS|GPIO_MODE_IN); set_gpio_ctrl(WEIDA_BUSY|GPIO_PULLUP_DIS|GPIO_MODE_IN); set_gpio_ctrl(WEIDA_SELECT|GPIO_PULLUP_EN|GPIO_MODE_IN); set_gpio_ctrl(WEIDA_ERROR|GPIO_PULLUP_EN|GPIO_MODE_IN); printf(“initport! \n”); } staticintweida_printer_write(structfile*file,constchar8buffer,size_tcount,loff_t*ppos) { unsignedchar*kbuf; intready;//判断打印机是否忙 ready=read_gpio_bit(WEIDA_BUSY); if(ready) return–EBUSY;//判断打印机是否在线 readyread_gpio_bit(WEIDA_SELECT); if(! ready) return–EAGAIN; ready=read_gpio-bit(WEIDA_ERROR); if(! ready) return–EINVAL; kbuf=kmalloc(count+1,GFP_KERNEL); memset(kbuf,”\0”,count+1); if(copy_from_user(kbuf,buffer,count)){ printf(“copyformuserwrong! ”); kfree(kbuf);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 ARM9 Linux 嵌入式 打印 终端 系统
![提示](https://static.bdocx.com/images/bang_tan.gif)