《嵌入式系统》设计方案.docx
《《嵌入式系统》设计方案.docx》由会员分享,可在线阅读,更多相关《《嵌入式系统》设计方案.docx(22页珍藏版)》请在冰豆网上搜索。
《嵌入式系统》设计方案
移动打印终端终嵌入式系统设计方案
阅读目录
一项目概述
1.1系统设计的必要性与PC终端的比较
在信息社会中,打印终端应用非常广泛,比如超市的收银系统、图书管的借还书系统、移动营业厅的话费打印系统等场合,我们都可以看到打印终端的身影。
传统打印终端通常都是由PC加上一个微型打印机构成,这种架构的打印终端价格比较昂贵,体积庞大,移动笨拙,使用十分不方便。
随着嵌入式技术的发展,许多原来基于PC的应用都纷纷转向基于嵌入式技术来实现。
基于嵌入式技术的产品具有非常明显的优势,如价格便宜、功耗低、体积小及移动方便等。
具体到打印终端这个产品上来说,可以从下表看出基于PC的打印终端和基于嵌入式的打印终端在各个方面的差异性。
基于PC的打印终端
基于嵌入式的打印终端
价格
几千元不等
几百元左右
体积
很大
非常小
性能
强
较强
开发方便性
易
较易
移动方便性
难
易
1.2系统的主要功能
本项目实例中拟开发的嵌入式移动打印终端是解决从数据输入、数据处理和数据输出的一体化系统,它提供下列几个功能
●数据录入功能:
支持从扫描仪端录入数据;
●通过网络到数据库查询;
●数据打印功能
二系统总体架构
嵌入式移动终端是一套完整的嵌入式应用系统,包括和硬件和软件两部分,这一节先说一下硬件方面的设计。
2.1系统硬件组成的部件
●数据输入部件(手持扫描仪)—完成数据输入功能;
●数据处理部件(嵌入式开发板和远程服务器)—完成数据处理任务
●数据输出部件(微型打印机)—完成数据打印功能;
各个部件之间的关系如图
图1嵌入式移动打印终端架构
各功能部件作用
数据输入部件
通常一个系统可以有很多种输入数据的途径,常用的输入设备有键盘鼠标等.在嵌入式移动打印终端中,只采用了扫描仪来完成数据的输入工作,当然系统如果想要实用化,应该再加上键盘等其它输入部件,但在这里就只用为个来设计了.
数据处理部件
数据处理部件是一整个应用系统的核心,它的主要任务是得到扫描仪传来的数据信息,然后连接远程服务器,将数据传送到远程服务器端,完成查询任务后,从远程服务器端得到结果,然后将结果送给微型打印机打印.
所以,数据处理部件包括嵌入式开发板和远程服务器两个部分。
嵌入式开发板和远程服务器之间通过网络线相连。
数据输出部件
在超市收银系统中,收银员最后的一个动作总是打印顾客的单据。
同样,在嵌入式移动打印终端系统中,最后一个动作也是将查询到的结果通过一个微型打印机打印出来。
2.2对硬件的选择
2.2.1手持式扫描仪
该扫描仪主要完成的功能其实是条码扫描的任务。
条码扫描是用来扫描条形码的设备,利用光学原理,把条形码的内容解码后通过数据线或者无线的方式传输到电脑或者别的设备中。
根据实际情况,现在拟定了一个关于扫描仪的规格参数:
光学规格
■光学系统:
2048PixelCCD
■扫描速度:
每秒100次
■光源:
红色可见光LED
■读取条码宽度:
可读至90mm
■扫描距离:
0~20mm
接口类型
■支持键盘和RS-232C接口
■条码种类:
WPC(EAN-13,EAN-8,UPC-A,UPC-E)Code128Code39CodabarCode11,Code39,Code39extened,Interleaved2of5,Code32,EAN-128,ChinIATA,ChinIATA,MSI/PLESSY,STD2of4,Martix2of5,ItalianPhamacyCode,Industrial2of5,BC-412,中国邮政码
电气规格
■电压:
5VDC
■操作规格:
60~70mA
■待机电源:
20~30mA
其它
■操作法度:
0~440度
■传输线:
1.75M
■尺寸:
长166mm×宽90nm×高32nm
2.2.2嵌入式开发板
嵌入式开发板是本系统的核心部件,它担负着整个系统中心枢纽的重担,同时,它的选型也直接影响到上层操作系统和其它部件的选型。
所以,在选择这个部件时,要站在整个系统的高度来进行。
在设计嵌入式移动打印终端系统时,根据接口类型、所支持的操作系统、性价比这几个要素来选取开发的类型与参数,具体如下表所示:
硬件参数
软件参数
1、采用三星公司的S3C2410,主频可达203MHz
2、64MB的SDRAM,由两片K4S561632组成,工作在32位模拟式下
3、64MBNandFlash,采用的是K9F1208,可兼容16MB,32MB或128MB;2MB的NorFlash,采用的是SST39VF1601,工作在16位模式下
4、10Mbps以太网接口,采用的是CS8900Q3,带传输和连接指示灯
5、LCD和触摸屏接口
6、1个USNHost,S3C2410内置的,符合USB1.1;一个USBDevice,S3C2410内置的,符合USB1.1
7、支持音频输入和音频输出,音频模块由S3C2410的ⅡS音频总线接口和UDA1341音频编译解码器组成,模块还集成了一个MIC,用于音频输入
8、2路URART串行行口,波特率可高达115200bps,并具有RS-232电平转换电路
9、SD卡接口,兼容SDMemoryCardProtocol1.0
10、蜂鸣器,4个LED灯,4个按键
11、Embedded-ICE(20脚标准JTAG)接口和并口式JTAG接口,支持ADS、SDT软件的下载和调试,以及FLASHf烧写
■测试代码,启动引导源代码BIOS和下载烧写工具
■Linuxfor2410的内核源码包,以及内核交叉编译工具,可运行的根文件系统及根文件系统制作工具
■Qt-embedded-2.3和qtopia-free-源码,应用程序交叉编译器
■winCE4.2NET板级支持包BSPfor2410,以及已编译好的WINCE镜像文件
■ST2410底板和核心板电路原理图
■ST2410开发板使用手册
■实用工具
ST2410开发板相关参数
2.2.3微型打印机的选型
微型打印机腹胀荣达科技RD-M系列微型打印机,该款采用独特的面板式嵌入结构,便可将整个打印机固定在仪表面板上,操作简单、方便。
下面是它的一些参数指标
●打印方式:
针打,针式撞击点阵打印:
热敏,热敏加热热点阵打印
●打印速度:
针打,1.0行/秒,0.7行/秒,0.4行/秒:
热敏,35毫米/秒
●分辩率:
针打,8点/毫米,384点/行。
●打印宽度:
针打,16/24/40;热敏,32。
●打印字符:
全部448个字符及图块,包括96个ASCII字符,352个希腊文\德文\俄文\法文等字母,日文片假名,部分中文汉字,数字符号,打印字符,块图符;32个用户自定义字符。
国标一二级汉字库中全部汉字和西文字、图符共有817个。
●字符大小:
西文,5×7;块图符,6×8点阵;用户自定义字符,汉字,24×24,点阵,16×16
●控制板;采用模块化驱动控制电路,有效保护打印头的绝对安全;专门的复位控制电路、电源监测电路以及近乎完美的软硬件看门狗控制的电路,确保打印机不死机、不乱打。
●控制命令:
通用ESC/p打印命令。
●打印缓存:
32KB。
2.2.4.远程服务器
远程服务器用于存在放在型数据库,它通过网络接口接收嵌入式开发板发来的数据,然后进行查询、更新等处理操作,最后把结果再传给嵌入式开发板。
所以,远程服务器必须具备较强的数据存储能力和网络通信能力。
要本系统中我们可以用一台普通PC来完成这个功能。
三软/硬件设计
3.1设计的流程
嵌入式移动打印终端系统设计开发可以分为三5个模块:
■开发环境的建立
■硬件的设计;
■扫描仪驱动的设计;
■打印机驱动的设计
■服务器数据库的设计及通信模块的开发。
设计思想是:
从硬件到软件,从底层到上层的方法。
流程图如下
3.2硬件设计
由于本开发系统中的核心部件采用已有的开发板,硬件设计的任务就大为简单,其核心任务就转化为通过嵌入式开发板将各个部件连接在一起即可。
3.2.1嵌入式开发板和扫描仪的连接
这一步骤是要把电路设计的图给出的,但是由于现在的设计都是从理论上做而已,没有真实的开发板,所以画不出来电路图。
3.2.2嵌入式开发板和远程服务器的连接
这一步骤是要把电路设计的图给出的,但是由于现在的设计都是从理论上做而已,没有真实的开发板,所以画不出来电路图。
3.2.3嵌入式开发板和微型打印机的连接
这一步骤是要把电路设计的图给出的,但是由于现在的设计都是从理论上做而已,没有真实的开发板,所以画不出来电路图。
四各驱动程序的设计(软件设计)
4.1打印机驱动的设计
按照编写嵌入式驱动的方法,打印机驱动的编写可分为下列的几个环节:
■定义设备号和设备名
■实现设备驱动初始化函数和清除函数;
■设计所要实现的文件操作,定义file_operation结构,实现所需的底层接口调用函数;
■将驱动编译到内核或编译成模块,用insmod命令加载;
■生成设备节点文件。
4.1.1定义设备号和设备名
#defineDEVICE_NAME“weida_printer”
#defineWEIDA_MAJOR234
设备驱动初始化函数和清除函数
Module_init(weida_printf_init);
Module_exit(weida_print_exit);
MODULE_LICNSE(“GPL”);
其中,在初始化函数weida_printf_init中完成设备注册任务和微型打印机端口初始化任务,
具体函数如下:
staticint_weida_print_init(void)
{
intret;
ret=register_chrdev(WEIDA_MAJOR,DEVICE_ANME,&weida_print_fops);
if(tet<0)
{
printk(DEVICE_NAME"can'tregistermajornumber\n");
returnret;
}
weida_print_io_port_init();
weida_init();
printk("weida_printer_init!
/n");
return0;
}
ret=register_chrdev(WEIDA_MAJOR,DEVICE_ANME,&weida_print_fops);完成设备注册任务,其中WEIDA_MAJOR为设备号,DEVICE_NAME为设备名,weida_printer_fops为structfile_oerations结构休变量,其内部每一个成员都是函数指针,指向对应的微型打印机底层接口。
初始化GPIO端口
gpio_data_tab[]={GPIO_C8,GPIO_C10,GPIO_C11,GPIO_C12,GPIO_13,GPIO_14,GPIO_15};
#defineDATA_NUM(sizeof(gpio_data_tab/sizeof(gpio_data_tab[0])))
#defineWIDA_DATA_READYGPIO_D0
#defineWEIDA_ACKGPIO_D1
#defineWEIDA_BUSYGPIO_D2
#defineWEIDA_BUSYGPIO_D3
#defineWEIDA_BUSYGPIO_D4
Weida_printf_io_init()函数将调用一睦设置GPIO的函数将GPIO初始化:
staticvoidweida_printer_io_port_init(void)
{
inti;
unsignedgpio;
for(i=0;i{
gpio=gpio_data_tab[i];
set_gpio_ctrl(gpio|G[OP_PULLUIP_DIS|(GPIO_MODE_OUT));
write_gpio_bit(gpio,0);
}
set_gpio_ctrl(gpio|G[OP_PULLUIP_DIS|(GPIO_MODE_OUT));
set_gpio_ctrl(gpio|G[OP_PULLUIP_DIS|(GPIO_MODE_OUT));
set_gpio_ctrl(gpio|G[OP_PULLUIP_DIS|(GPIO_MODE_OUT));
set_gpio_ctrl(gpio|G[OP_PULLUIP_DIS|(GPIO_MODE_OUT));
set_gpio_ctrl(gpio|G[OP_PULLUIP_DIS|(GPIO_MODE_OUT));
printk("initport!
/n");
}
set_gpio_ctrl()函数用于设置GPIO口的相关属性,如set_gpio_ctrl(WEIDA_DATA_READYIGPIO_PULL_DISIGPIO_MODE_OUT)设置GPIO_D0口的一些属性,其中WEIDA_DATGA_READY为连接打印机的ready口的GPIO—D0,GPIO-PULL-DS设置不需要上拉电阻,GPIO—MODE-OUT设置口为输出口,同样可以定义其它几个GPIO口相应属性。
(3)初始化打印机
staticvoidweda_init(void)
{
INIT_WEIDA;
SET_LANDSCAPE;
SET_FONT_SPACE
(2);
SET_LINE_SPACE
(2);
DELETE_LINE;
}
这几个宏用来初始化打印机,它们的宏体中都用到TYPE_DATA(N)函数,该函数是嵌入式开发板向微型打印机发送ASCII数据n,其中具体实现代码如下:
staticvoidtype_data(unsignedchardata)
{
intdata_bit,j;
mdelay(150);
for(j=0;j<8;j++)
{
data_bit=((data&(1<>j)
printk("%d\",data_bit);
write_gpio_bit(gpio_data_tab[j],data_bit&0x01)
udelay
(2);
}
DATA_READY(0);
UDELAY
(2);
DATA_READY
(1);
}
每次发数据时都要延迟几毫秒,以防向打印机发送数据过快,打印机来不及处理而产生丢失数据现象,所以要设置。
下面具体分析如何编写这些惛层接口操作函数。
(1)weida_printer_open/weida_printer_close;打开/关闭打印机:
该函数完成打印操作,在该函数中,首先判断打印机是否在张,是否忙。
是否准备好,在打印机准备的情况下完成数据打印任务。
函数的具体实现代码如下:
staticintweida_printer_write(structfile,constchar*buffer,size_tcout,loff_t*ppos)
{
unsignedchar*kbuf;
intready;
ready=read_gpio_bit(WEIDA_BUSY);
if(ready)
return-EBUSY;
ready=read_gpio_bit(WEIDA_SELECT);
if(!
ready)
return-EAGAIN;
ready=read_gpio_bit(WEIDA_ERROR);
if(ready)
return-EINVAL;
kbuf=malloc(count+1,GPF_KERNEL);
memeset(kbuf,\0,count+1)
if(copy_from_user(kbuf,buffer,count))
{
printk("copyformuserwrong!
");
kfree(kbuf);
return-EFAULT;
}
while(*kbuf!
=\0)
{
tyupe_data(*kbuf);
while(read_gpio_bit(WEIDA_ACK));
prinntk("%c",*kbuf);
kbuf++;
}
kfreee(kbuf);
returncount;
}
打印时用函数copy_from_user(kbuf,buffer,count)将数据从用户态到核心态。
weida_printer_ioctl
通过该函数对打印机的字体、行距等属性进行设置,函数的具体实现代码如下:
staticintweida_printer_ioct(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)
{
intmum;
switch(cmd){
caseWEIDA_IOCSFONTSPACE;
copy_from_user(&num,&arg,sizeofnum);
SET_FONT_SPACE(num);
break;
caseWEIDA_IOCSLINESPACE;
COPY_from_user(&num,&arg,sizeofnum);
SET_LINE_SPACE(NUM);
break;
caseWEIDA_IOCSLINESPACE;
COPY_from_user(&num,&arg,sizeofnum);
break;
caseWEIDA_IOCSUPLINE;
copy_from_user(&num,&arg,sizeofnum);
SET_UPLINE(num);
break;
caseWEIDA_IOCSCHARACTER1;
select_character1;
break;
caseWEIDA+IOCSDOT_MATR1X;
COPY_FROM_USERT(NUM,&ARG,SIZEOFNUM);
caseWEIDA_IOCSLINESPACE;
COPY_from_user(&num,&arg,sizeofnum);
break;
caseWEIDA_IOCSUPLINE;
copy_from_user(&num,&arg,sizeofnum);
SET_UPLINE(num);
break;
caseWEIDA_IOCSCHARACTER1;
select_character1;
break;
caseWEIDA+IOCSDOT_MATR1X;
COPY_FROM_USERT(NUM,&ARG,SIZEOFNUM);
}
}
(2)weida_print_select
该函数用来选择打印机,函数的具体实现代码如下:
staticunsignedintweida_printer_select(structfile*file,structpoll_table_struct*)
{
intready;
ready=read_geipo_buf(WEIDA_BUSY);
if(!
ready)
returnl;
poll_wait(file,&weida_printer_wait,wait);
printk("select");
return;
}
4.编译扫描仪制备驱动
假设上述微型打印机驱动代码存放在weida_printer.c和weida_printer.h中并且放在weida_printer目录下。
在该目录下编写Makefile文件,内容如下:
CROSS=artm
Weida-printer.0.weida_printer.cweida_printer.h
$CROSSgcc-d_kerner_DMODULE-I/home/lichao/-rmk7/include\
-c–oweida_printerweida_printer.c
Clean
M–rfweida_printer
在/weida_printer目录下,执行下列命令编译:
make
在当前目录下就可以得到驱动模块文件weida_printer.o
5.加载设备
编译好驱动模块后,可以通过网络将weida_printer.o文件传输到嵌入式开发板,在嵌入式开发板超级终端环境下执行下列命令将打印机设备运动模块加载内核:
Inmsodweida_printer.o
生成设备节点:
Mknod/dev/weida_printerc2340
6.打印机驱动测试程序设计
通过上面的几个步骤,打印机驱动模块已经注册到内核,在/dev目录下可以打到weida_printer设备,那么编写的设备驱动模块是否正确,能否完成所要求的功能呢?
这些必须编写测试程序来进行测试.
下面是一个简单的测试程序代码,详细的功能测试代码可以在该程序的基础之上进行扩充.
intmain(void])
{
intweida_fd,ret;
char*data="Hell,Welcometouseweidaprinter";
weida_fd=open("/dev/weida_printer.O_WRONLY");
if(weida_fd<0)
{
perrof("opendevicebuttons");
exit
(1);
}
retwrite(weda_fd,data,strien(data);
if(ret!
=strlen(data))
{
perror("printworng/n");
}
ioctl(weida_fd,WIDA_IOCSLNESPACE,1);
sleep
(1);
ret=write(weida_fd,data,strlen(data));
if(ret!
=strlen(data))
{
perror("printfwrong\n");
}
clsoe(weida_fd);
return0;
}
扫描仪驱动设计
扫描仪直接接到嵌入式开发板串口上,对它的控制非常简单,只需要将串口1的波特率属性配置成和扫描仪一致,扫描仪扫描后直接可以从串口读出数据,读数据就为扫描仪扫到的条形码.
1.编写串口设置函数
Set_speed(intfd,intspeed)用于设置串口速率,其中fd为打开设备文件,speed为速率,具体的函数代码如下;
voidset_speed(intfd,intspeed)
{
int