条形码扫描器毕业设计 - 图文

更新时间:2024-05-17 05:08:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

条形码扫描器设计

摘 要

在这个科学技术日星月异的信息时代,条码技术自动识别技术被广泛应用于各行各业,他给人们的生活带来了许多的便捷,同时也大大提高了我们的工作效率。因而,无论是理论上还是实际应用一维条码识别系统研究都具有相当深远的意义。

本文从条形码图像的采集和条形码的识别两方面入手。条形码图像的采集系统是根据光电检测开关GDS对黑白颜色的识别输出不同的电平值,再利用单片机AT89C51对GDS开关输入的不同电平的值进行译码,此处采用交叉25码的编码方式进行相应的译码。最终通过max232通信串口电路将数据传送到PC 端显示。

关键词:AT89C51;单片机;GDS;交叉25码;

I

Design of Bar-code Scanner

Abstract

Nowadays we are living in an Information Age with gradual improvements of science and technology every day. Bar code technology and automatic identification technology are widely applied in many fields of our lives which has brought us a lot of convenience and made our work more efficient. Therefore, the study of bar code identification system has profound significance both theoretically and practically.

This paper is focused on image acquisition and bar code identification. Bar code image acquisition system includes several major data processing steps. Firstly, photoelectric switch GDS outputs a level value corresponding to the black and white color arrangement in the bar code. Then, Single Chip Microcomputer AT89C51 decodes the level value form the GDS switch. Cross-25-code coding scheme is used for decoding the corresponded level value here. Lastly, data is send to PC for displaying through the max232 communication serial interface circuit.

Key Words: AT89C51; MCU; GDS; Cross-25-code

II

目 录

1 绪论 ................................................... 1 1.1 本课题研究背景 ....................................... 1 1.2 国内外研究现状 ....................................... 1 1.3 课题设计目标及任务 ................................... 2 2 条形码的编码原理 ....................................... 3 2.1 条形码的编码方法 ..................................... 3 2.1.1 宽度调节编码法 ..................................... 3 2.1.2 模块组配编码法 ..................................... 4 2.2 常见条形码的编码 ..................................... 4 2.2.1 交叉25码 .......................................... 4 2.2.2 EAN13码 ........................................... 5 2.2.3 Code128码 ......................................... 6 2.3 脉宽测量方法 ......................................... 7 3条形码扫描器硬件设计 .................................. 10 3.1 硬件原理图设计 ...................................... 10 3.1.1 晶振电路设计 ...................................... 11 3.1.2 复位电路设计 ...................................... 11 3.1.3 指示灯电路设计 .................................... 12 3.1.4 信号采集电路设计 .................................. 13 3.1.5 串口通信电路设计 .................................. 14

3.1.6 电源电路设计 ...................................... 15 3.2 硬件实物图设计 ...................................... 16 3.2.1 PCB图设计 ........................................ 16 3.2.2 硬件实物设计 ...................................... 17 4 条形码扫描器软件设计 .................................. 19 4.1 编译预处理 .......................................... 19 4.2 程序设计流程图 ...................................... 19 5 总结 .................................. 错误!未定义书签。 5.1 存在的问题 ......................... 错误!未定义书签。 5.2 可改正和提高的地方 ................. 错误!未定义书签。 致谢 .................................... 错误!未定义书签。 参考文献 ................................ 错误!未定义书签。 附录 .................................................... 26

1 绪 论

1.1 本课题研究背景

数千年来,科学技术的发展促进着社会经济的发展,其中自动识别技术在人类工作生活中充当着不可或缺的重要地位。自动识别技术是指利用特定的电子设备,自动获取产品相关信息,同时将产品的相关信息输送给后台的计算机系统进行处理的一种技术。例如指纹识别技术,电子车牌号识别技术,条形码识别技术等等。

条形码技术就是众多自动识别技术中的一种,它以成本低廉,识别速度快,准确度高,可靠性强等一系列优势广泛应用于物流信息管理系统,超市结账管理系统,图书馆管理系统,工业生产流程管理系统等等。可以说目前的条形码识别技术涉及到我们日常生活的大部分领域。它给我们的生活带来了太多的便捷同时也为我们的生产提高了效率。所以研究这样的一种技术的重要性就不言而喻了。

1.2 国内外研究现状

20世纪70年代,我国在条形码领域的研究相对西方发达国家一直处于落后阶段,那时我们国家对于条形码技术仅仅处于一种简单了解的程度,并不能对条形码技术进行成熟的应用。到了20世纪80年代,随着我们国家的一些贸易出口单位以及相关科研部门对条形码识别技术的日益重视,我国的条形码技术研究事业开始进入高速发展时代。

目前条形码技术正在与其他技术相互渗透,典型的有条形码技术与便携嵌入式设备为代表的移动计算技术。这些技术的结合很大程度上提高了我们的工作效率,所以条形码自动识别技术有着相当广阔的发展前景。

就国际角度来看,自20世纪20年代提出条形码的概念以来,条形码技术已经发展长达近一个世纪的时间。所以早已对条形码技术能够进行成熟的应用。与此同时,条形码技术也在不断的升级发展,目前已经由简单的一维

1

条码发展到二维条码。应用领域也从商业拓展到了现在的物流,仓储等领域。

1.3 课题设计目标及任务

本设计是以单片机AT89C51为核心芯片,GDS光电检测开关为条形码扫描头,使用C语言在Keil uVision4软件平台编程实现。需要实现的目标是:

(1)利用GDS光电检测开关扫描条形码之后,系统能够对扫描的条形码进行相应的译码功能;

(2)系统内部译码成功之后,通过数据线,系统将译码的结果传送到计算机屏幕上进行显示。

本设计利用软件Altium Designer进行初始的电路原理图设计,之后再利用Altium Designer根据原理图画出相应的PCB图,利用Keil uVision4进行程序部分的功能实现。最后按照电路图将相应的元器件焊接在PCB板上,然后进行调试,直至最终的功能实现为止。具体任务有:

(1) 条形码的硬件系统设计: ① 单片机晶振电路设计; ② 单片机复位电路设计; ③ 信号采集电路设计; ④ 串口通信电路设计; (2) 条形码软件系统设计: ① 条形码扫描器的系统软件设计; ② 中断采集数据的程序设计; ③ 译码程序的设计; ⑤ 串口通信的程序设计; (3) 系统调试。

2

2 条形码的编码原理

2.1 条形码的编码方法

条形码的编码是根据条形码不同的“条”和“空”的来表示二进制的0和1,再根据这些“条”和“空”的不同组合来表示成不同的数字或者字符。以此来表示不同的商品信息。条码的码制有很多种,但大致上分类两大类,分别是宽度调节编码法和模块组配编码法,具体编码方法如下:

2.1.1宽度调节编码法

宽度调节编码法即条码符号中的条和空由宽、窄两种单元组成的条码编码方法。按照这种方式编码时,是以窄单元(条或空)表示逻辑值“0”,宽单元(条或空)表示逻辑值“l”。宽单元通常是窄单元的2~3倍。对于两个相邻的二进制数位,由条到空或由空到条,均存在着明显的印刷界限。39条码、库德巴条码及交插25条码均属宽度调节型条码。下面以交插25条码为例,简要介绍宽度调节型条码的编码方法。

交插25条码是一种条、空均表示信息的连续型、非定长、具有自校验功能的双向条码。它的每一个条码数据符由5个单元组成,其中两个是宽单元(表示二进制的“1”),三个窄单元(表示二进制的“0”)。图2.1是交插25码的一个示例。

图2.1 “3185”的交叉25码

3

2.1.2模块组配编码法

模块组配编码法即条码符号的字符由规定的若干个模块组成的条码编码方法。按照这种方式编码,条与空是由模块组合而成的。一个模块宽度的条模块表示二进制的“1”,而一个模块宽度的空模块表示二进制的“0”。

商品条码模块的标准宽度是0.33mm,它的一个字符由2个条和2个空构成,每一个条或空由1~4个标准宽度的模块组成,每一个条码字符的总模块数为7。凡是在字符间用间隔(位空)分开的条码,称为非连续性条码。凡是在条码字符间不存在间隔(位空)的条码,称为连续性条码。模块组配编码法条码字符的构成如图2.2所示。

图2.2 模块组配编码法条码字符的构成

2.2 常见条形码的编码

2.2.1 交叉25码

交叉25码是一种高密度的,可以嵌入任意数量数字的,长度可变化的数字条形码。该条形码是基于标准25码的规范改进而得来,它比标准25码有更高的密度与数据存储能力。交叉25码主要运用在物流行业与仓储业中。

标准25码只用黑色条码代表数字0-9,而交叉25码既使用黑色条码也使用白色条码来代表0-9的数字。例如,标准25码会用前五个黑色条码表示第一个数字,用紧接着的五个黑色条码表示第二个数字;而交叉25码是使用

4

前五条黑色条码表示第一个数字,而用介于前五个黑色条码中的白色条码表示第二个数字。这也是交叉25码名称的来源。

交叉25码是连续型、非定长、具有自动校验功能的双向条码,交叉25码的编码是以两个字符为一组(上下各一个)进行编码,其中一个字符以条编码,另一个字符以空编码,每个字符由5个单元组成(3个窄单元,2个宽单元),两个字符的条空相互交叉组合在一起。其中起始符为0000,终止符为100。编码方法以窄单元(条或空)表示逻辑值“0”,宽单元(条或空)表示逻辑值“1”。宽单元通常是窄单元的2~3倍。交叉25码图片如下:

图2.3 交叉25码

2.2.2 EAN13条码

一个EAN-13条码被划分成了4个区域:1)数制2)厂商码3)商品码4)校验位。通常,第一个数制位被打印在条码的左边,第二个数制位被作为条码下方左手边的那组六位数的第一个字符打印,厂商码是条码下方左手边的后5位数,产品码是条码下方右手边的前五位数,校验位是条码下方右手边的最后一位。

数制:数制是由2位组成的(有些时候是3位),用来区分国家或经济区域制定厂商码的编码权利。任何以0开始的数制都是一个UPC-A条码。下表给出了有效的数值码:

厂商码:厂商码是由数制码标示的编码管理局为每个厂商分配的一个唯一的编码。一个公司的所有产品将使用相同的厂商码。

5

产品码:产品码是厂商分配的唯一编码。和厂商码不同,产品码不需要UCC分配,厂商可以为他们的每个产品自由的分配产品码而不需要考虑任何其他的组织。既然UCC已经确保了厂商码的唯一性,厂商只需要确保他们自己的产品码不重复就是了。

校验位:校验位是一个附加的位,用来验证一个条码是否被正确的扫描。扫描可能产生不正确的数据,这可能是由于不一致的扫描速度、不完善的打印或一系列其他的问题造成的,因此,有必要验证条码的其余数据已经被正确的诠释。校验位是从条码中其余的数字位中计算得到的。通常,如果校验位和基于已经扫描得到的数据计算出来的校验位的值相同的话,就可以高度的信任条码已经被正确扫描。EAN-13码图片如下:

图2.4 EAN13条码

2.2.3 Code128条码

Code128码于1981年推出,是一种长度可变、连续性的字母数字条码。与其他一维条码比较起来,相对较为复杂,支持的字元也相对较多,又有不同的编码方式可供交互运用,因此其应用弹性也较大。Code128特性如下:

(1) 允许双向扫描;

(2) 可自行决定是否加上检验位;

(3)条码长度可调,但包括开始位和结束位在内,不可超过232个字元; (4)具有A、B、C三种不同的编码类型,可提供ASCII中128个字元的编码使用;

(5)同一个128码,可以由A、B、C三种不同编码规则互换,既可扩大

6

字元选择的范围,也可缩短编码的长度。

Code 128码图片如下:

图2.5 Code 128码

2.3 脉宽测量方法

脉宽测量中会遇到这样的问题,何时对定时器采集的数据进行提取?显然,利用外部中断信号是比较方便的。扫描器发出的脉冲信号可以直接作用于INT0,如图,从扫描器输出信号可知,扫描器在扫描空时产生下降沿信号,假设在脉冲下降沿产生中断后开始记录数据,此处数据采集的是一个元素条的宽度,元素空的宽度被丢掉。因此,必须采取适当的硬件电路对扫描器的输出信号进行调整,才能使定时器记录每一个元素的宽度。

7

条空条记录条宽

图2.6 测量元素宽度方法

把扫描器的输出信号取反,其原始信号与取反信号分别与INT0和INT1相连,并同时采用定时器0和定时器1.扫描器输入的信号经过74LS04后,可以把其取反,然后将两个信号输入至单片机进行处理。

设外部中断0、外部中断1均为下降沿触发,则当INT1第一个脉冲下降沿触发中断时,中断服务程序启动定时器0,记录条的脉宽,关闭定时器1,读出定时器1中的数据(前一个空的脉宽)。当INT0的第一个脉冲下降沿触发中断时,中断服务程序启动定时器1记录空的脉宽,关闭定时器0,读出定时器0中的数据,此数据便是条1的脉宽。以此类推,可以测出所有条空的脉宽。这种方法的优点是硬件电路简单,缺点是多占用了外部中断1和定时器1。

8

扫描器输入信号174LS04234714+5v11AT89C51INT012INT1图2.7 输入信号与单片机连接方法一

9

3 条形码扫描器硬件设计

3.1 硬件原理图设计

一个完整的条形码扫描器系统由AT89C51芯片、晶振电路、复位电路、LED指示灯电路、GDS信号输入电路、MAX232通信串口电路以及电源电路组成。这其中除了AT89C51是集成芯片之外,其余部分电路都需要自行设计。其总电路原理图如下图3.1所示:

图3.1 条形码扫描器总电路原理图

10

如上图所示,单片机的XTAL1和XTAL2引脚分别接晶振电路;EA和RST引脚接复位电路;P1口接三个LED指示灯,指示扫描器的工作状态;GDS光电检测开关的输出信号输入到74LS04的4引脚,再通过6,7引脚输送到单片机的P3.2,P3.3引脚进行数据的采集;单片机的P3.0,P3.1引脚输出信号到MAX232进行一个TTL电平的转化,最后通过DB9接口将数据传送到计算机进行显示读取。

3.1.1 晶振电路设计

晶振电路由一个12MHz的晶体振荡器和两个22PF的瓷片电容组成。其中竞争的两个引脚分别接在单片机的XTAL1和XTAL2引脚上面,并且每个晶振的一个引脚都接一个瓷片电容,电容的另一端都接地。晶振电路的作用是给单片机提供工作脉冲信号的。这里的12MHz就是指单片机的每秒工作频率。电路原理图如下:

图3.2 晶振电路图

3.1.2 复位电路设计

复位是单片机的初始化操作,初始化操作只需要给单片机的RST引脚加上大于24个时钟震荡周期(即2个机器周期)的高电平即可。当AT89C51

11

单片机进行复位时,PC初始化为0000H,使AT89C51从程序存储器的0000H单元开始执行程序。除了进入系统的正常初始之外,当程序运行出错(如程序跑飞)或操作错误使系统处于死锁状态时,也需要按复位按钮进行重启,以便单片机摆脱“跑飞”或者“死循环”的状态。具体电路图如下图3.3所示:

图3.3 复位电路图

3.1.3 指示灯电路设计

生活中的电器工作时都会有对应的工作转态指示灯来告知人们其处于的工作状态。这里设计的状态指示灯用的是三个LED灯,分别接在单片机的的P1.0,P1.4以及P1.7引脚上面,对应的工作状态分别是扫描工作的开始,扫描工作的进行中以及扫描工作的结束这三种工作状态。此处为了便于区分,本设计分别采用红色,绿色以及黄色三种不同的颜色来指示不同的工作状态,具体电路图如下3.4所示:

12

图3.4 状态指示灯电路图

3.1.4 信号采集电路设计

GDS光电检测开关是一种基于光电效应传感器。在受到可见光照射后即产生光电效应,将光信号转换成电信号输出。本设计采用的是型号为GDS-3011,它具有稳定性高、反应速度快、光斑直径小等优点,因此适用于本设计。GDS-3011总共就一根数据传输线和一对电源线,总共三根线,额定工作电压为12V。具体电路原理图如下:

图3.5 信号采集电路

13

3.1.5 串口通信电路设计

单片机内部在对GDS光电检测开关扫描结束之后,需要进一步的将不同黑白的宽窄条纹进行译码。译码结束时,需要将译码的结果传送到PC端以便于我们能够在屏幕上直观的看到扫描出来的结果。所以单片机与PC机之间需要建立起数据通信。此处就得设计单片机与PC机之间进行串口通信。

然而本设计的使用的51单片机串口使用的是TTL电平,而想要和PC之间进行通信,但PC机的串口使用的是RS-232电平,所以此处需要设计一个电平转化的的通信串口电路。这里的电平转化的功能完全可以使用RS232芯片来实现。由于单片机需要+5V的工作电压,而MAX232也只需+5V的单电源电压,所以在很大程度上方便的电源电路这块的设计。MAX232可以将+5V的电源电压转化为+10V的电压,因此可以实现单片机与PC机之间的电平转化。其内部结构图如图所示:

图3.6 MAX232内部结构图

MAX-232作为通信工业设备与现代PC机的常用串行接口,其标准接口应用一共有9针,具体接口引管脚定义如下:

14

1引脚DCD:应用于调制解调器让计算机处在在线状态。 2引脚RXD:主要工作是接收外面传送进来的通信数据。 3引脚TXD:应用于将数据发送到其他的外部接收设备。

4引脚DTR:应用于指示数据终端准备就绪,表示此时可以开始传送数据。 5引脚GND:接电源地线。

6引脚DSR:此引脚处于工作状态时,表示Modem可以进行数据通信了。 7引脚RTS:该引脚由计算机自行控制,表示请求发送数据。

8引脚CTS:由调制解调器控制,通知PC将要传输的数据送至Modem。 9引脚RI:有呼叫进来时Modem通知PC,PC自己决定是否接听呼叫。 本设计单片机与计算机之间的串口通信只需要连接9个引脚中的3个引脚即可实现功能。三个引脚分别是RXD,TXD,GND。其连接电路图如下所示:

图3.7 MAX232与DB9的连接图

3.1.6 电源电路设计

本设计一共采用两种供电电压,分别是GDS光电检测开关需要的直流+12V电源电压和单片机需要的直流+5V电源电压。为了简化电路的设计,本设计采用了三端稳压器78L05来实现两种电压的供给。需要获得+12V和+5V的直流电,那么只需将+12V的直流电接入78L05的1引脚,将78L05的2引脚接地线,这样78L05的3引脚就能输出稳定的+5V直流电了,再将3引脚输出的+5V直流电接给单片机使用即可实现整个系统的供电需要。采用三端

15

稳压器78L05就可以省去电路需要单独外接两个电源的复杂情况,为后期的焊接以及调试带来很大的便利,具体电路原理图如下图3.7所示:

图3.8 电源电路原理图

3.2 硬件实物图设计

3.2.1 PCB图设计

设计好原理图之后,需要按原理图的设计焊接好实际的硬件电路板,这样才能实现最终的条形码扫描器的功能。这里,为了提高电路板的可靠性,本设计是根据设计好的电路原理图,画出实际电子元件的PCB板,然后根据PCB板焊接好整体硬件,最后进行硬件测试。此处设计PCB板需要格外注意实际元件的规格,型号等,根据实际的尺寸去设计。利用Altium Designer设计PCB板 ,PCB图如下:

16

图3.9 PCB图

3.2.2 硬件实物设计

PCB图画好之后,就可以加工PCB 板了,这一步需要工厂的代加工,只需将自己画好的PCB图送给厂家,厂家就可以将板子腐蚀好。拿到腐蚀好的PCB板子,这就可以开始最终的焊接了。参照电路原理图和PCB图,将电路所需的元器件按画好的安装位置,一个个的将其进行焊接到固定的位置上。焊接时需要特别注意,不能有虚焊等现象,不然到时候板子看上去焊接没有问题,但实际电路就是无法正常工作,但却又很难挖掘其中出现的问题,焊接就要保证一次性成功。本设计分别需要+12V和+5V电源进行供电,但本设计采用了三端稳压器件78L05,所以只需要在78L05的1引脚接上+12V的直流电源电压,它的3引脚就能输出稳定的+5V的直流电源电压,这样就

17

很大程度上方便了电源电路的接入,具体硬件焊接电路板如下图所示:

图3.10 硬件电路板正面图

18

图3.11 硬件电路板反面图

19

4 条形码译码器软件设计

4.1 编译预处理

由于条形码是由一些列黑白宽窄不同的条纹组成,而GDS光电检测开关的扫描原理是先将这些不同宽窄的黑白条纹进行扫描,GDS内部则在扫描的过程中将这些条纹转化成一系列脉冲数字信号。再将这些脉冲数字信号输送到单片机内部,单片机再根据特定的编码规则(本设计使用的是交叉25码)来进行译码。想要准确的测量出条形码符号就必须准确的采集到条形码的宽窄符号。在单片机进行正式的译码之前,我们需要先对单片机内部进行编译预处理。

与汇编语言相比,高级语言更接近自然语言和数学公式,与计算机的硬件结构和指令无关。所以本文选择了大家更容易理解的C语言作为编程语言。此处我们首先需要对中断,特殊寄存器还有单片机的端口进行定义。因此需要编写一个用于定义的头文件,这样才方便uVision4的编译环境预处理。

4.2程序设计流程图

编译预处理之后,程序就开始需要进行条形码的扫描识别了。由于条形码的编码方式有很多种,本设计使用的编码方式是常用的交叉25码。所以此处程序一开始要做的任务是判别所扫描的是不是交叉25码,如果是,才会进行下一步的操作,如果不是交叉25码,由于程序的限制,此时将不能进行成功的解码。此处识别的默认的是采用交叉25码编码的方式编码的条形码。

20

已判别为交叉25码正向扫描取起始字符后5个条元素和5个空元素的逻辑值按照编码规则判断其表示的数值存储数据取下5个条和5个空元素逻辑值N所有元素判别完否Y转向数据发送 图4.1 译码运作流程图

21

前四个元素逻辑值为0000后三个元素逻辑值为100置正向扫描标志位,转向交叉25码数据符判别前四个元素逻辑值为0000前四个元素逻辑值为0000置反向扫描标志位,转向交叉25码数据符判别转向其他码制的判别图4.2码制判别流程图

22

初始化wide[n],设允许中断INT0的中断,记录条宽,存入wide[n]INT1的中断,记录空宽,存入wide[n]n=N?NY逻辑化wide[n]的值N码制的判别,译码发送数据,并显示扫码成功指示

图4.3主程序流程图

23

5 总 结

5.1 存在的问题

本设计根据光电检测开关对不同的黑白条纹反射输出不同的电信号的原理,实现了将条形码转化为可读的信息。但本设计由于采用的是最原始的手动扫描的方式来读取条形码信息的,所以还存在一定的问题:

(1) 由于条纹的宽窄和光斑通过的时间和距离有关,所以在扫描时如果不是匀速,将会影响扫描结果,同时也必须保持扫描距离一样;

(2) 由于GDS-3011的扫描光斑直径达到1mm,所以本设计很难用于扫描十分细小的条形码;

(3) 本设计只针对交叉25码编码的条形码能够进行识别,其他编码的条码则无法识别;

5.2 可改正和提高的地方

本设计做的是最基础的条形码扫描器,由于现代对条形码的广泛应用,所以应该在最大程度上提升条码识别的效率。由于用GDS光电检测开关识别效率太低,所以可以设计用CCD摄像头来识别条码。同时,由于国际条码的编码方式很多,所以在设计条码识别器的时候可以设计出能够同时识别更多编码方式编码的条形码,这样才能提高条码识别的效率。

24

致 谢

在本论文即将撰写结束之际,我的心情其实是复杂的。在选定本课题以来,一直对自己动手能力这块不够自信。中间遇到过很多棘手的问题,一时不知如何解决,但最终都是黄小平老师为我耐心的一一解答了。他的学识让我由衷的钦佩,他在教授我们科学知识的同时总是能给我们一定的额外启发,同时黄老师对我们的工作生活也是表现的尤为关心。他是我们今后学习以及生活的榜样。也正是因为有黄老师的耐心,细心的指导我才能最终顺利的完成本设计以及论文的撰写。在此,我衷心的感谢黄小林老师。

在此,我也要感谢大学四年来对我进行过授课的老师们,是他们辛勤的工作我才能掌握这么多的科学文化知识,同时他们也都指引着我们人生观向正确的方向发展,这些都将是我今后人生的巨大财富。最后感谢我的大学同学们,大学四年的时间,是他们让我的学习生活充满了欢声笑语,他们让我的生活充满精彩,同时他们也对我本次的毕业设计提供了不少的帮助,感谢他们。

最后,感谢感谢各位对本文进行审阅的老师们。

25

参考文献

[1] 李全利. 单片机原理及接口技术[M].北京:高等教育出版社,2003 [2] 张毅刚. 单片机原理及应用C51编程[M]. 北京:高等教育出版社,2012 [3] 朱云芳. PROTEL99SE电路设计与制板[M]. 北京:机械工业出版社,2007 [4] 饶庆和. 89C51单片机实用技术 [M]. 北京:人民邮电出版社,2003 [5] 李金哲,朱俊喜. 条形码自动识别技术 [M] . 国防工业出版社,1991 [6] 仲崇权. 微机键盘接口的研究及其在仪器仪表中的应用 [J] . 电子技术应用,2001

[7] 张新国,尚建宇,高慧颖. 基于一维条形码技术的新生注册系统的设计与实现 [J] . 计算机,2005

[8] 郑新景,蒋洪. PS/ 2 键盘鼠标协议 [J] . 电脑世界,2001

[9] 钟富昭. 8051单片机典型模块设计与应用[M]. 人民邮电出版社, 2007 [10] 李启炎. Protel99SE应用教程[M]. 上海: 同济大学出版社, 2005 [11] 胡烨, 姚鹏翼, 江思敏. 电路设计与仿真教程[M]. 北京:机械工业出版社, 2006

[12] 肖洪兵. 跟我学用单片机[J]. 北京: 北京航空航天大学出版社, 2002 [13] 孔超,张玮. 51单片机应该这样学[J]. 中国铁道出版社,2013 [14] 赵景波,向先波. 多层电路板设计与制作[M]. 人民邮电出版社,2012 [15] 朱俊英. 条形码自动识别技术[M]. 科学技术出版社,1993

[16] 乌利希.蒂泽. 电子电路设计原理与应用[M]. 电子工业出版社,2013 [17] 孙丽霞,殷侠. 实用电子电路设计与调试[M]. 中国电力出版社,2011 [18] 黄智伟. 电子系统的电源电路设计[M]. 电子工业出版社,2014 [19] 程国钢,文 坤. 51单片机常用模块设计查询手册[M]. 清华大学出版社,2016

[20] 薛红. 条码技术及商业自动化系统-条码技术[M]. 北京:中国轻工业出版, 2010.

26

附 录

源程序:

代码1————头文件REGX51.H:

/*位寄存器的定义*/ sfr p0 =0x80; sfr SP =0x81; sfr DPL =0x82; sfr DPH =0x83; sfr PCON=0x87; sfr TCON=0x88; sfr TMOD=0x89; sfr TL0 =0x8A; sfr TL1 =0x8B; sfr TH0 =0x8C; sfr TH1 =0x8D; sfr p1 =0x90; sfr SCON=0x98; sfr SBUF=0x99; sfr p2 =0xA0; sfr IE =0xA8; sfr p3 =0xB0; sfr IP =0xB8; sfr PSW =0xD0; sfr ACC =0xE0; sfr B =0xF0;

/*--------------- p0 的位寄存器----------------*/ sbit p0_0=0x80; sbit p0_1=0x81; sbit p0_2=0x82; sbit p0_3=0x83; sbit p0_4=0x84; sbit p0_5=0x85; sbit p0_6=0x86; sbit p0_7=0x87;

/*--------------- p1 的位寄存器----------------*/ sbit p1_0=0x90; sbit p1_1=0x91; sbit p1_2=0x92; sbit p1_3=0x93; sbit p1_4=0x94;

27

sbit p1_5=0x95; sbit p1_6=0x96; sbit p1_7=0x97;

/*--------------- p2 的位寄存器----------------*/ sbit p2_0=0xA0; sbit p2_1=0xA1; sbit p2_2=0xA2; sbit p2_3=0xA3; sbit p2_4=0xA4; sbit p2_5=0xA5; sbit p2_6=0xA6; sbit p2_7=0xA7;

/*--------------- p3 的位寄存器----------------*/ sbit p3_0=0xB0; sbit p3_1=0xB1; sbit p3_2=0xB2; sbit p3_3=0xB3; sbit p3_4=0xB4; sbit p3_5=0xB5; sbit p3_6=0xB6; sbit p3_7=0xB7; sbit RXD =0xB0; sbit TXD =0xB1; sbit INT0=0xB2; sbit INT1=0xB3; sbit T0 =0xB4; sbit T1 =0xB5; sbit WR =0xB6; sbit RD =0xB7;

/*---------------PCON 的位寄存器----------------*/ #define IDL_ 0x01 #define STOP_ 0x02 #define PD_ 0x02 #define GF0_ 0x04 #define GF1_ 0x08 #define SMOD_ 0x80

/*---------------TCON 的位寄存器----------------*/ sbit IT0 =0x88; sbit IE0 =0x89; sbit IT1 =0x8A; sbit IE1 =0x8B; sbit TR0 =0x8C; sbit TF0 =0x8D; sbit TR1 =0x8E;

28

sbit TF1 =0x8F;

/*--------------- TMOD 的位寄存器----------------*/ #define T0_M0_ 0x01 #define T0_M1_ 0x02 #define T0_CT_ 0x04 #define T0_GATE_ 0x08 #define T1_M0_ 0x10 #define T1_M1_ 0x20 #define T1_CT_ 0x40 #define T1_GATE_ 0x80 #define T1_MASK_ 0xF0 #define T0_MASK_ 0x0F

/*--------------- SCON 的位寄存器----------------*/ sbit RI =0x98; sbit TI =0x99; sbit RB8 =0x9A; sbit TB8 =0x9B; sbit REN =0x9C; sbit SM2 =0x9D; sbit SM1 =0x9E; sbit SM0 =0x9F;

/*---------------IE 的位寄存器----------------*/ sbit EX0 =0xA8; sbit ET0 =0xA9; sbit EX1 =0xAA; sbit ET1 =0xAB; sbit ES =0xAC; sbit ET2 =0xAD; sbit EA =0xAF;

/*--------------- IP 的位寄存器----------------*/ sbit PX0 =0xB8; sbit PT0 =0xB9; sbit PX1 =0xBA; sbit PT1 =0xBB; sbit PS =0xBC; sbit PT2 =0xBD;

/*---------------PSW 的位寄存器----------------*/ sbit P =0xD0; sbit FL =0xD1; sbit OV =0xD2; sbit RS0 =0xD3; sbit RS1 =0xD4; sbit F0 =0xD5; sbit AC =0xD6;

29

sbit CY =0xD7;

/*---------------中断向量Interrupt Address =(Number*8)+3 ----------------*/ #define IE0_VECTOR 0 /* 0X03 External Interrupt 0 */ #define TF0_VECTOR 1 /* 0X0B Timer 0 */

#define IE1_VECTOR 2 /* 0X13 External Interrupt 1 */ #define TF1_VECTOR 3 /* 0X1B Timer 1 */ #define SI0_VECTOR 4 /* 0X23 Serial port */ 代码2————系统主程序:

#include static int wide[19]; static char wi[19]; static int x=0,y=0;

static char a[2],b[2],c[2]; static char n=0;

static char TT0=0,TT1=0,ZZ0=0,ZZ1=0;

void delay (void) { unsigned char i,j; for (i=0;i<255;i++)

for(j=0;j<255;j++) ; }

/*void delay1 (void) { unsigned char i,j; for (i=0;i<100;i++) for(j=0;j<2;j++) ; }*/

static void xint0_isr(void) interrupt IE0_VECTOR {

ZZ0=1;ZZ1=0; }

static void xint1_isr(void) interrupt IE1_VECTOR {

ZZ1=1;ZZ0=0; }

void luoji(void){ unsigned char m; wi[2]=0;

for(m=2;m<19;m++) {

if(wide[m+1]>2*wide[m])

30

wi[m+1]=1;

else if(2*wide[m+1]

else wi[m+1]=wi[m]; } }

void yuedu(void) {

{

if((wi[4]==0)&&(wi[6]==0)&&(wi[8]==1)&&(wi[10]==1)&&(wi[12]==0))a[0]=0; else if((wi[4]==1)&&(wi[6]==0)&&(wi[8]==0)&&(wi[10]==0)&&(wi[12]==1))a[0]=1; else if((wi[4]==0)&&(wi[6]==1)&&(wi[8]==0)&&(wi[10]==0)&&(wi[12]==1))a[0]=2; else if((wi[4]==1)&&(wi[6]==1)&&(wi[8]==0)&&(wi[10]==0)&&(wi[12]==0))a[0]=3; else if((wi[4]==0)&&(wi[6]==0)&&(wi[8]==1)&&(wi[10]==0)&&(wi[12]==1))a[0]=4; else if((wi[4]==1)&&(wi[6]==0)&&(wi[8]==1)&&(wi[10]==0)&&(wi[12]==0))a[0]=5; else if((wi[4]==0)&&(wi[6]==1)&&(wi[8]==1)&&(wi[10]==0)&&(wi[12]==0))a[0]=6; else if((wi[4]==0)&&(wi[6]==0)&&(wi[8]==0)&&(wi[10]==1)&&(wi[12]==1))a[0]=7; else if((wi[4]==1)&&(wi[6]==0)&&(wi[8]==0)&&(wi[10]==1)&&(wi[12]==0))a[0]=8; else if((wi[4]==0)&&(wi[6]==1)&&(wi[8]==0)&&(wi[10]==1)&&(wi[12]==0))a[0]=9; } {

if((wi[5]==0)&&(wi[7]==0)&&(wi[9]==1)&&(wi[11]==1)&&(wi[13]==0)) a[1]=0; else if((wi[5]==1)&&(wi[7]==0)&&(wi[9]==0)&&(wi[11]==0)&&(wi[13]==1)) a[1]=1; else if((wi[5]==0)&&(wi[7]==1)&&(wi[9]==0)&&(wi[11]==0)&&(wi[13]==1)) a[1]=2; else if((wi[5]==1)&&(wi[7]==1)&&(wi[9]==0)&&(wi[11]==0)&&(wi[13]==0)) a[1]=3; else if((wi[5]==0)&&(wi[7]==0)&&(wi[9]==1)&&(wi[11]==0)&&(wi[13]==1)) a[1]=4; else if((wi[5]==1)&&(wi[7]==0)&&(wi[9]==1)&&(wi[11]==0)&&(wi[13]==0)) a[1]=5; else if((wi[5]==0)&&(wi[7]==1)&&(wi[9]==1)&&(wi[11]==0)&&(wi[13]==0)) a[1]=6; else if((wi[5]==0)&&(wi[7]==0)&&(wi[9]==0)&&(wi[11]==1)&&(wi[13]==1)) a[1]=7; else if((wi[5]==1)&&(wi[7]==0)&&(wi[9]==0)&&(wi[11]==1)&&(wi[13]==0)) a[1]=8; else if((wi[5]==0)&&(wi[7]==1)&&(wi[9]==0)&&(wi[11]==1)&&(wi[13]==0)) a[1]=9; } {

if((wi[6]==0)&&(wi[8]==0)&&(wi[10]==1)&&(wi[12]==1)&&(wi[14]==0))b[0]=0; else if((wi[6]==1)&&(wi[8]==0)&&(wi[10]==0)&&(wi[12]==0)&&(wi[14]==1))b[0]=1; else if((wi[6]==0)&&(wi[8]==1)&&(wi[10]==0)&&(wi[12]==0)&&(wi[14]==1))b[0]=2; else if((wi[6]==1)&&(wi[8]==1)&&(wi[10]==0)&&(wi[12]==0)&&(wi[14]==0))b[0]=3; else if((wi[6]==0)&&(wi[8]==0)&&(wi[10]==1)&&(wi[12]==0)&&(wi[14]==1))b[0]=4; else if((wi[6]==1)&&(wi[8]==0)&&(wi[10]==1)&&(wi[12]==0)&&(wi[14]==0))b[0]=5; else if((wi[6]==0)&&(wi[8]==1)&&(wi[10]==1)&&(wi[12]==0)&&(wi[14]==0))b[0]=6; else if((wi[6]==0)&&(wi[8]==0)&&(wi[10]==0)&&(wi[12]==1)&&(wi[14]==1))b[0]=7; else if((wi[6]==1)&&(wi[8]==0)&&(wi[10]==0)&&(wi[12]==1)&&(wi[14]==0))b[0]=8; else if((wi[6]==0)&&(wi[8]==1)&&(wi[10]==0)&&(wi[12]==1)&&(wi[14]==0))b[0]=9; }

31

{

if((wi[7]==0)&&(wi[9]==0)&&(wi[11]==1)&&(wi[13]==1)&&(wi[15]==0)) b[1]=0; else if((wi[7]==1)&&(wi[9]==0)&&(wi[11]==0)&&(wi[13]==0)&&(wi[15]==1)) b[1]=1; else if((wi[7]==0)&&(wi[9]==1)&&(wi[11]==0)&&(wi[13]==0)&&(wi[15]==1)) b[1]=2; else if((wi[7]==1)&&(wi[9]==1)&&(wi[11]==0)&&(wi[13]==0)&&(wi[15]==0)) b[1]=3; else if((wi[7]==0)&&(wi[9]==0)&&(wi[11]==1)&&(wi[13]==0)&&(wi[15]==1)) b[1]=4; else if((wi[7]==1)&&(wi[9]==0)&&(wi[11]==1)&&(wi[13]==0)&&(wi[15]==0)) b[1]=5; else if((wi[7]==0)&&(wi[9]==1)&&(wi[11]==1)&&(wi[13]==0)&&(wi[15]==0)) b[1]=6; else if((wi[7]==0)&&(wi[9]==0)&&(wi[11]==0)&&(wi[13]==1)&&(wi[15]==1)) b[1]=7; else if((wi[7]==1)&&(wi[9]==0)&&(wi[11]==0)&&(wi[13]==1)&&(wi[15]==0)) b[1]=8; else if((wi[7]==0)&&(wi[9]==1)&&(wi[11]==0)&&(wi[13]==1)&&(wi[15]==0)) b[1]=9; } {

if((wi[8]==0)&&(wi[10]==0)&&(wi[12]==1)&&(wi[14]==1)&&(wi[16]==0)) c[0]=0; else if((wi[8]==1)&&(wi[10]==0)&&(wi[12]==0)&&(wi[14]==0)&&(wi[16]==1))c[0]=1; else if((wi[8]==0)&&(wi[10]==1)&&(wi[12]==0)&&(wi[14]==0)&&(wi[16]==1))c[0]=2; else if((wi[8]==1)&&(wi[10]==1)&&(wi[12]==0)&&(wi[14]==0)&&(wi[16]==0))c[0]=3; else if((wi[8]==0)&&(wi[10]==0)&&(wi[12]==1)&&(wi[14]==0)&&(wi[16]==1))c[0]=4; else if((wi[8]==1)&&(wi[10]==0)&&(wi[12]==1)&&(wi[14]==0)&&(wi[16]==0))c[0]=5; else if((wi[8]==0)&&(wi[10]==1)&&(wi[12]==1)&&(wi[14]==0)&&(wi[16]==0))c[0]=6; else if((wi[8]==0)&&(wi[10]==0)&&(wi[12]==0)&&(wi[14]==1)&&(wi[16]==1))c[0]=7; else if((wi[8]==1)&&(wi[10]==0)&&(wi[12]==0)&&(wi[14]==1)&&(wi[16]==0))c[0]=8; else if((wi[8]==0)&&(wi[10]==1)&&(wi[12]==0)&&(wi[14]==1)&&(wi[16]==0))c[0]=9; } {

if((wi[9]==0)&&(wi[11]==0)&&(wi[13]==1)&&(wi[15]==1)&&(wi[17]==0)) c[1]=0; else if((wi[9]==1)&&(wi[11]==0)&&(wi[13]==0)&&(wi[15]==0)&&(wi[17]==1)) c[1]=1; else if((wi[9]==0)&&(wi[11]==1)&&(wi[13]==0)&&(wi[15]==0)&&(wi[17]==1)) c[1]=2; else if((wi[9]==1)&&(wi[11]==1)&&(wi[13]==0)&&(wi[15]==0)&&(wi[17]==0)) c[1]=3; else if((wi[9]==0)&&(wi[11]==0)&&(wi[13]==1)&&(wi[15]==0)&&(wi[17]==1)) c[1]=4; else if((wi[9]==1)&&(wi[11]==0)&&(wi[13]==1)&&(wi[15]==0)&&(wi[17]==0)) c[1]=5; else if((wi[9]==0)&&(wi[11]==1)&&(wi[13]==1)&&(wi[15]==0)&&(wi[17]==0)) c[1]=6; else if((wi[9]==0)&&(wi[11]==0)&&(wi[13]==0)&&(wi[15]==1)&&(wi[17]==1)) c[1]=7; else if((wi[9]==1)&&(wi[11]==0)&&(wi[13]==0)&&(wi[15]==1)&&(wi[17]==0)) c[1]=8; else if((wi[9]==0)&&(wi[11]==1)&&(wi[13]==0)&&(wi[15]==1)&&(wi[17]==0)) c[1]=9; } }

void send() {

unsigned char i; SCON=0x50; TMOD=0x20; PCON=0x80; TH1=0xF3;

32

TL1=0xF3; TR1=1;

for(i=0;i<2;i++) {

ACC=a[i]; SBUF=ACC; delay(); }

for(i=0;i<2;i++) {

ACC=b[i]; SBUF=ACC; delay(); }

for(i=0;i<2;i++) {

ACC=c[i]; SBUF=ACC; delay(); }

n=0; }

void main(){

EA=0; EX0=1; EX1=1; PX0=0; PX1=0; ET0=0;ET1=0; IT0=1;IT1=1;

EA=1;

while(1){

if(ZZ0==1&&TT0==0){ p1_0=0; p1_7=1; wide[n]=x; x=0; n++;

if(n==18)TT0=1; loop0:

y++;

if(ZZ0==1&&TT0==0)goto loop0;

if(ZZ1==1&&TT1==0){

33

} p1_0=1; p1_7=0; wide[n]=y; y=0; n++;

if(n==18)TT1=1; loop1: x++;

if(ZZ1==1&&TT1==0) goto loop1;

if(n==18){ EA=0; p1_0=1; p1_7=1; p1_4=0; luoji(); yuedu(); send(); }

}

34

} }

元件清单:

名称 单片机 光电检测开关 电阻 可调电阻 电阻 极性电容 电解电容 瓷片电容 发光二极管 按钮开关 晶振 DB9母头 三端稳压器

规格型号 AT89C51 GDS-3011 3KΩ 20KΩ 300Ω 10UF 470UF 22UF LED SW-PB 12MHz DB9 78L05 工位 U1 CON3 R1 R2 R3,R4,R5 C1,,C4,C5,C7,C9 C3,C6 C2,C3 D1,D2,D3 S1 Y1 RS232 U4 数量 1 1 1 1 3 5 2 2 3 1 1 1 1

本文来源:https://www.bwwdw.com/article/kpl7.html

Top