2024年2月6日发(作者:樊典雅)
第8章 LTPA245热敏打印机驱动设计
热敏打印机是利用发热元件产生热量,使紧贴在其表面的热敏纸迅速变色,从而在纸上形成相应点阵字符或图形的一种打印机。相对于针式、笔式打印机,热敏打印机具有结构简单、体积小、重量轻、噪声小、功耗低、印字质量高、价格便宜、运行成本较低及使用可靠等一系列优点。已越来越广泛地应用于医疗仪器、银行柜员机及POS终端等各种便携式计算机系统和智能化设备中,被认为是最合适的便携式硬拷贝输出设备。本章以精工(SEIKO)SII生产的一款高速热敏打印机LTPA245为例,介绍一种通用热敏打印机的驱动设计。
8.1 热敏打印机的工作原理
8.1.1 热敏打印机结构原理
热敏式打印机的关键部件是打印头。它包含很多微型发热元件,这些发热元件一般采用集成电路工艺和光刻技术,通过物理化学方法在陶瓷基片上加工制成。为防止发热元件与热敏纸接触时产生的磨损,表面涂了一层类似玻璃的保护膜。目前的工艺水平已将发热元件的密度做到8点/mm (分辨率达200dpi)、16点/mm,甚至更高。在印字速度低于100cps时,热敏头寿命可达1亿字符,或记录纸滑行30km的可靠性。热敏打印机所用的打印纸不是普通纸,而是经特殊处理过的感热记录纸。这种记录纸是将两种混合成份材料涂复在纸上而成,基层纸上涂有一层几微米厚的白色感热生色层。在这个感热生色层上涂有无色染料和特殊生色剂。为使他们能有效地附在纸上,在它们周围的空隙里还填充有粘合剂。感热生色层一经加热,生色剂立即熔化,并熔进无色染料中,引起化学反应显出颜色,这一过程仅需几个毫秒即可完成。
由于感热记录纸是受热后材料熔融引起化学反应而呈现颜色,如温度过高,新的合成物质被分解,颜色又会消失。另外,这种物质在光的长时间作用下也会自动分解,所以感热记录纸不能长期保存。虽然热敏打印机对打印纸有特殊要求,但是这种记录纸价格并不贵,无需像针打那样经常要更换色带。因此,越来越多的智能化仪器仪表采用热敏打印机作为输出设备。
8.1.2 热敏打印机设计中需要注意的问题
为实现高品质的打印,在设计热敏打印机电路和控制时序时必须注意三个问题:
1. 常能量控制
常能量控制指的是打印头上每一个发热元件发出的热量要相同,且保持一个常量,否则打印出的字符颜色有深有浅,影响打印效果。发热元件每次发出的热量,除了与发热元件流过的电流的大小和持续时间有关外,还与其本身的余热(如果前次已经通电发热)有关。它的余热直接影响下一次发热元件传给打印纸的热量,从而影响打印效果。因此,热敏打印机电路除了要检测环境温度外,还要记录每一个发热元件前一次状态,甚至前几次的通电发热的状态,以决定本次究竟要给出多大热量(可以通过控制通电时间来确定)。打印速度越快,这个问题就越重要。
2. 大电流脉冲控制
由于打印时要同时激励的发热元件可能会很多,如一个分辨率为8点/mm,打印宽度为72mm的打印头,一点行上要排列8×72 = 576个发热元件。尽管每个发热元件只要几十毫安的电流,但若同时激励这些发热元件,总电流就很可观了,而且这种脉冲式的电流谐波分量极其丰富,会给其它电路带来很大的干扰,甚至使打印电路失控,烧毁打印头发热元件。
150
因此,发热元件通电驱动程序要仔细考虑,一般可将每点行分成几段,以几段为一组同时传送,使电流变化比较平稳。
3. 处理时间与CPU速度协调
由于打印速度较快,尽管每点行只需要几十个字节的数据,但必须在数毫秒内完成这些数据的接收、处理、输出到打印头、常能量控制等一系列要求,故对CPU的速度就有较高的要求。
8.2 LTPA245热敏打印机
LTPA245是精工公司生产的一款高速热敏打印机,采用全新的结构及打印技术,小巧轻便。分离式的压纸轴设计更便于上纸,加上低电压驱动,可实现两节锂电池供电。广泛应用于测量分析仪、POS机、通讯设备或数据终端及各种便携式设备上,已成为目前热敏打印机业界的最畅销机型,其外形结构如图8-1所示。
其性能特点为:
◆ 分离式压纸轴设计便于上纸
◆ 小巧轻便可应用于手持设备
◆ 优质耐用(打印头可连续打印超过50km)
◆ 准确快速(90mm/秒)
◆ 配有纸源感应器,自动检测上纸情况
◆ 结构合理,便于维护保养
LTPA245的技术参数如表8-1所示。
图8-1 LTPA245的外形
表8-1 LTPA245的技术参数
型号
打印头类型打印
分辨率(dots/line)
点密度(dots/mm)(WxH)
打印速度(mm/s)
LTPA245
热敏行式
384
8×16
53.4(驱动电压5V)
77(驱动电压7.2V)
90(驱动电压8.5V)
送纸间距
打印宽度/纸宽(mm)
打印头寿命
操作电压(V)
打印纸长(Km)
逻辑电路
打印头
尺寸(mm)(W×D×H)
重量(g)
0.0625mm
48/58
脉冲个数(pulses) 10
50
2.7~5.25
4.5~8.5
69.2×28.3×31.7
约41
8LTPA245通过一个1mm间距的27针FPC连接器(见图8-1)与驱动器进行连接,连接器各引脚的定义和功能如表8-2所示。
LTPA245采用同步串行通信接口,数据以串行移位的方式从驱动器移入打印机内部的数据锁存器,其工作时序如图8-2所示。其中,DAT为串行移位数据,CLK为移位时钟,/LATCH为数据锁存信号,DST为分段加热控制信号。打印数据以384 bit(12 words)为一行,在CLK作用下,数据从DAT端逐一移入打印机内数据寄存器中。每一个数据位对应1个加热元
151
表8-2 FPC连接器各针脚定义
引脚序号 引脚名称 信号方向 功能描述
1 PS 输出 纸检测器输出,高电平表示缺纸
2 VPS 输入 纸检测器发光器信号输入
3 GND — 纸检测器的地
4 Vp — 热敏打印头驱动电压
5 Vp — 热敏打印头驱动电压
6 DAT 输入 同步串行输入
7 DST6 输入 发热元件激活信号
8 DST5 输入 发热元件激活信号
9 DST4 输入 发热元件激活信号
10 GND — 电源地
11 GND — 电源地
12 GND — 电源地
13 GND — 电源地
14 TH 输出 热敏电阻
15 DST3 输入 发热元件激活信号
16 DST2 输入 发热元件激活信号
17 DST1 输入 发热元件激活信号
18 Vdd — 逻辑电源
19 CLK 输入 打印数据传输的同步时钟
20 /LATCH 输入 打印数据锁存。低电平时数据从输入寄存器送打印锁存器,上升沿锁存
21 DATO 输出 打印数据输出(串行输出)
22 Vp — 热敏打印头驱动电压
23 Vp — 热敏打印头驱动电压
24 /A 输入 步进电机控制信号
25 /B 输入 步进电机控制信号
26 A 输入 步进电机控制信号
27 B 输入 步进电机控制信号
图8-2 LTPA245的打印时序
152
件,当该位数据为0时,表示不加热,为1时表示加热。热敏纸被加热的位置变黑,不加热的位置不变色(白)。当384个bit全部移入打印机后,驱动器应输出1个/LATCH锁存信号(负脉冲),将数据送到打印寄存器。实际打印时,为防止电流过大,打印头温度过高,驱动器应控制DST0~DST5的输出信号,将一行数据分段(本系统分3段)打印。一行打印结束后,驱动器从A、/A、B、/B端送出脉冲,控制步进电机带动热敏纸前移一段距离,继续打印下一行。
LTPA245内部带有一个微型、大力矩的精密2相4线步进电机。电机有A、B两组线圈、4个控制端,分别定义为A、/A、B、/B。当驱动器按表8-3所示的脉冲序列从控制端给步进电机输入脉冲时,可控制电机匀速转动。
表8-3 步进电机驱动时序
控制端 停止
A
B
/A
/B
0
0
0
0
Step1
0
0
1
1
Step2
0
1
1
0
Step3
1
1
0
0
Step4
1
0
0
1
8.3 步进电机的驱动
LTPA245内部不带步进电机驱动芯片,需外接驱动电路。本章设计的驱动系统选用FAN8200D驱动热敏打印机内部的步进电机。FAN8200/FAN8200D是美国快捷半导体公司设计生产的低工作电压、低饱和压降单片式步进电机驱动器集成电路,可用于两相步进电机的驱动。它带有双路H桥,可分别驱动两个独立的PNP功率管。每一个桥都有各自独立的使能引脚,非常适合于需要独立控制的步进电机驱动系统。
FAN8200/FAN8200D的主要特点有:
◆ 具有3.3V和5V微处理器(MPU)接口;
◆ 内含可驱动双极步进电机的双向H桥路;
◆ 内含垂直PNP功率晶体管;
◆ 可适应宽达2.5V~7.0V的电源电压范围;
◆ 具有很低的饱和压降(可低达0.4V/0.4A);
◆ 每一路H桥均具有独立的使能引脚,并可单
独进行使能控制;
◆ 具有过流保护功能;
图8-3 FAN8200D的引脚
◆ 具有过热关断(TSD)功能。
FAN8200/FAN8200D的上述特性使其可广泛应用于通用低压步进电机驱动系统、磁盘驱动器、PC照相机和数码相机的步进电机驱动、安全移动控制器、热敏式打印机、运动控制器以及需要两通道直流电机驱动的控制系统,同时还可用于微处理器接口的通用功率驱动器的电机驱动系统。
1. FAN8200/FAN8200D的引脚功能
FAN8200采用14脚DIP-300封装,而FAN8200D则采用14脚SOP-225封装。他们的工作温度都是-20~+70℃,其引脚排列如图8-3所示,各引脚的功能见表8-4。
2. FAN8200/FAN8200D的工作原理
FAN8200/FAN8200D的内部由两路完全相同的控制电路组成。外部脉冲信号从IN1(或IN2)输入,经片内前级缓冲放大后送入片内控制器,此信号在CE1(或CE2)使能的情况下,
153
表8-4 FAN8200的引脚功能
引脚序号 引脚名称 信号方向 功能描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
VCC
CE1
OUT1
VS1
OUT2
IN1
SGND
PGND
IN2
OUT4
VS2
OUT3
CE2
PGND
—
输入
输出
输入
输出
输入
—
—
输入
输出
输入
输出
输入
—
逻辑电源电压输入
通道1器件触发使能,高电平有效
通道1步进脉冲输出
通道1电源输入
通道1步进脉冲输出
通道1步进脉冲输入
信号地
功率地
通道2步进脉冲输入
通道2步进脉冲输出
通道2电源输入
通道2步进脉冲输出
通道2器件触发使能,高电平有效
功率地
由控制部分进行处理并驱动晶体管,最后从OUT1(或OUT3)脚输出反相的脉冲信号,从OUT2(或OUT4)脚输出同相的脉冲信号,与步进电机的线圈形成回路后控制电机的运行。
器件触发使能端口(CE)的作用是分别对两个通道的输出进行控制,当CE端的输入控制信号为低电平时,无论有无输入控制信号,输出端OUT始终呈现高阻抗状态。因此,要使FAN8200/FAN8200D控制器的输出端在输入信号的控制下正常工作,器件的触发使能端必须为高电平。FAN8200/ FAN8200D中CE、IN和输出端OUT之间的逻辑控制关系如表8-5所示,表中的L表示低电平,H表示高电平,×表示无关,Z表示处于高阻态。
表8-5 FAN8200/FAN8200D的逻辑控制关系
CE1(或CE2)
L
H
H
IN1(或IN2) OUT1(或OUT3) OUT2(或OUT4)
×
L
H
Z
H
L
Z
L
H
FAN8200/FAN8200D内部的热关断和偏置电路可用来对整个电路提供过热和过流保护,当负载过大或其它故障导致电路电流增大,从而使器件温度升高到片内温度传感器的设定门限以上时,FAN8200/FAN8200D中的热关断和偏置电路将向片内控制器发出关断控制信号以关断整个电路。
8.4 单片机资源分配
本章设计的热敏打印机驱动系统选用STC89C58(PLCC封装)作为控制中心,负责接收上位机通过标准并行通信口传送过来的点阵或字符数据(对程序稍作改动也可接收串口数据),经单片机处理后,控制打印机加热板的加热及步进电机的走纸,从而在热敏纸上打印出上位机需要输出的字符或图形。
单片机I/O口资源的分配如表8-6所示。
154
表8-6 单片机I/O口的资源分配(PLCC封闭)
引脚序号 引脚名称
2
3
4
5
P1.0
P1.1
P1.2
P1.3
信号方向
输出
输出
输出
输出
功能描述
步进电机A相驱动脉冲输出(FAN8200的IN1)
步进电机B相驱动脉冲输出(FAN8200的IN2)
FAN8200D触发使能(CE1、CE2),高电平使能
74HC32或门1开启控制。当P1.3=0(反相后为1)时,关闭或门,锁存器74HC374输出为高阻态,禁止读并口数据;当P1.3=1时,开启或门,系统在P3.7(/RD)和并口/STB的控制下,读标准并口数据
热敏打印机数据锁存控制,上升沿锁存热敏打印机的打印数据
接收串口打印数据时,接标准串口的DSR。当接收缓冲器满时,此脚输出高电平,通知串口暂停发送
与并口通信的握手应答信号,负脉冲表示系统可以接收新的打印数据
接收缓冲器满。P1.7=1时,经74HC32或门2向并口发系统忙信号,表示接收缓冲器满;P1.7=0时,开启74HC32或门2,表示系统可以接收并口数据。
6
7
P1.4
P1.5
输出
输出
8
9
P1.6
P1.7
输出
输出
11 P3.0(RxD) 输出/输入 接收并口打印数据时,作为移位寄存器方式的数据输出,向热敏打印机输出打印数据;接收串口打印数据时,作为异步串行通信的数据接收端
输出 接收并口打印数据时,作为移位寄存器方式的同步时钟输出,控制热敏打印机的数据读取;接收串口打印数据时,作为异步串行通信的数据接收端
外中断0。标准并口发数据选通信号(/STB)时,由74HC74的/1Q产生中断请求,读取标准并口输出的数据,下降沿产生中断
按键输入。打印机自检控制,低电平有效
打印机缺纸检测。低电平有效,打印机缺纸
未用
读标准并口数据控制。当P3.7=0且P1.3=1(反相后为0)时,使能锁存器74HC374并对74HC74置0,读标准并口数据
热敏打印机发热元件加热信号
热敏打印机发热元件加热信号
热敏打印机发热元件加热信号
未用
并口数据输入
13 P3.1(TxD)
14 P3.2(/INT0) 输入
15
16
17、18
19
P3.3(/INT1) 输入
P3.4(T0)
P3.7(/RD)
输入
输出
P3.5、 P3.6 —
24
25
26
27~31
36~43
P2.0
P2.1
P2.2
P2.3~P2.7
P0
输出
输出
输出
—
输入
155
8.5 系统硬件设计
本书介绍的通用热敏打印机驱动系统由复位及时钟电路、并行通信模块、打印控制及串行通信模块等三大模块构成。可接收标准并行通信口发送过来的打印数据,经分析和处理后送LPTA245热敏打印机打印;对程序稍加修改后,也可以接收串行通信口发送过来的打印数据,处理后送热敏打印机打印。
1. 系统复位电路
本系统的复位有两种情况:一是系统上电复位;二是标准并口发出的复位信号对系统复位。系统复位及时钟电路如图8-4所示。
图8-4 系统复位电路
本系统的上电复位电路与一般单片机的上电复位电路一样,由于标准并口的RST输出端正常情况输出高电平,经反相器(74HC04)反相后输出低电平,打开或门,所以上电复位的过程与普通单片机系统的上电复位过程一样。
系统上电复位后,正常工作时,由于上电复位电路输出的是低电平,打开了74HC32的或门3。此时,如果并口输出一个负脉冲(如图8-4所示),则经过反相后,变为正脉冲,由于或门3已经打开,则在或门3的输出端将输出一个正脉冲,如果此脉冲的宽度大于两个机器周期,将对单片机进行复位。
2. 并行通信模块
并行通信模块由单片机、六反相器(U6,74HC04)、或门(U5,74HC32)、D触发器(U3,74HC74)、锁存器(U2,74HC374)及标准并口等组成。负责与标准并口通信、接收并口输出的打印数据、输出缺纸信号等,其电路组成如图8-5所示。
⑴ D触发器的复位与锁存器的使能
系统初始化时,置单片机P1.3为高电平,经74HC04的反相器2反相后,输出低电平。打开74HC32的或门1,允许在P3.7控制下,对D触发器74HC74进行复位、对锁存器74HC374使能操作。当P3.7=1(常规状态)时,D触发器正常工作(在CP脉冲的控制下将输入送到输出),禁止锁存器的使能,使锁存器输出高阻状态,数据不能传送到单片机P0口;当P3.7=0(单片机有读数操作)时,对D触发器复位(1Q=0,/1Q=1),同时对锁存器使能,使锁存器的数据能输出到单片机的P0口。
⑵ 触发器状态的翻转与锁存器的锁存
当并口没发送数据时,标准并口的数据选通输出端/STB输出高电平。经74HC04的反相器1反相后,输出低电平。此低电平分为两路:一路送D触发器U3(74HC74)的时钟输入端CP,禁止D触发器的状态改变;另一路送锁存器U2(74HC374)的锁存控制端CLK,禁止锁存器的数据锁存。
当并口发送一个数据后,从数据选通输出端/STB输出一个负脉冲,其下降沿经反相后
156
变为上升沿。此上升沿也分两路:一路接D触发器的时钟输入端CP,使触发器的状态翻转。由于触发器的输入端接电源(高电平),则触发器将输出“1”状态(1Q=1,/1Q=0);另一送锁存器的锁存控制端CLK,将并口发送过来的数据锁存在锁存器内。
触发器输出的“1”信号有两个作用:一是1Q=1,此高电平经74HC32的或门2向标准并口发系统忙信息,通知并口现在系统正在读取本次传送的数据,暂不发下一个数据;二是/1Q=0,其下降沿向单片机发中断请求(/INT0),请求单片机读取本次数据。单片机收到此中断请求后,将会在外中断0中断服务子程序中读取本次并口传送过来的数据。
图8-5 并行通信模块
⑶ 系统忙信号BUSY
系统忙信号由74HC32的或门2送出。此信号的产生分两种情况:一是当单片机内部的接收缓冲器满时,从P1.7输出一个高电平,经74HC32或运算后送给并口,通知并口系统忙;二是在单片机的接收缓冲器不满时(P1.7=0),如果系统正在读并口前一次发送的数据,则由触发器74HC74的1Q输出高电平,此信号经74HC32或运算后送给并口,通知并口系统忙,暂不发下一个数据。
⑷ 单片机读取并口数据的过程
单片机接收缓冲器未满(P1.7=0)且未读取并口数据的情况下(无系统忙信号),单片机允许并口发送相应的打印数据。并口发送及单片机接收数据的过程为:
并口先输出一个字节的并行数据,然后发数据选通端信号/STB。/STB经74HC04反相后分两路:一路送锁存器的CLK端将并口输出的数据锁存在锁存器以供单片机读取;另一路送触发器的CP端,使触发器输出“1”状态(1Q=1,/1Q=0)。
触发器的输出中,1Q=1经74HC32的或门2向并口送系统忙信号,通知并口暂不发送下一个数据;/1Q=0向单片机发中断请求,单片机接收并响应该中断请求后,在中断服务子程序里先执行一个读外部数据存储器的指令,使P3.7(/RD)输出一个负脉冲。此负脉的低电平经74HC32的或门2后输出低电平(系统初始化时,置P1.3=1,打开了74HC32的或门2),此低电平分两路:一路送锁存器74HC374的使能端(/OE),使能锁存器,将前面锁存的数据传送给单片机P0口,完成一次数据的读取。另一路送D触发器的复位端(/1RD),使触发器输出“0”状态,触发器“0”状态的1Q=0清除系统忙信号,通知并口可以发送下一下数据;/1Q=1使单片机外中断0输入高电平,准备产生下一次中断。
157
单片机读完一个数据后,P3.7(/RD)变为高电平,此高电平经74HC32的或门1后分两路:一路禁止锁存器74HC374使能,使锁存器输出高阻,与单片机P0口隔绝;另一路开放触发器74HC74,使触发器能正常翻转,为下一次读数据作准备。
3. 打印控制及串行通信模块
打印控制及串行通信模块由单片机、步进电机驱动芯片(FAN8200D)、热敏打印机接口、UART接口及打印机自检信号输入等电路组成。完成步进电机的驱动、打印数据及加热信号的输出、串行打印数据的接收及打印机自检的控制等工作。打印控制及串行通信电路如图8-6所示。
图8-6 打印控制及串行通信模块
⑴ 打印的控制过程
单片机通过自带有串口向热敏打印机发送待打印的数据,串口工作于方式0、移位寄存器方式。当单片机接收到标准并口发送过来的打印数据,经内部程序处理后,送输出缓冲器。在单片机输出缓冲器有数据,且打印机不缺纸的情况下,通过P3.0口(RXD)向热敏打印机接口的DAT端按位输出打印数据,同时由P3.1口(TXD)输出同步移位脉冲。
当一行打印数据(384个位)全部输出完后,由P2.0、P2.1、P2.2口输出加热信号(加热时间的长短由延时电容的充放电时间常数确定),然后运行一段延时程序(确保热敏纸变色)完成一行的打印。一行打印完后,从P1.0、P1.1、P1.2输出FAN8200D选通信号及步进电机走纸命令,使热敏打印纸移动一行,准备下一行的打印。
⑵ 打印机的自检
系统还设计有打印自检的功能。当需要检查打印机是否能正常工作时,可按下按键,给单片机P3.3口输入一个低电平。当系统检测到P3.3口有低电平输入时,执行自检程序,打印预先设定好的自检图形和字符。
⑶ 串行通信
本系统的硬件电路还设计有串行通信接口,在上位机没有标准并口的情况下,可以接收上位机串口发送过来的打印数据(程序需作适当修改)。使用串口接收上位机数据时,单片机工作于串行通信方式1、UART模式,通过P1.5口输出数据装置准备好(DSR)信号,通知上位机可以发送下一个数据。
158
8.6 系统软件
通用热敏打印机驱动系统的软件由主程序(MAIN.C)、外中断程序(EXT.C)、串行通信程序(SERIAL.C)、打印数据输出程序()、定时器中断程序(TIME.C)、打印数据处理程序(CONST.C)及自定义的库函数集组成。其中,打印数据通过单片机自带的串口输出,采用方式0(同步移位寄存器方式),程序用汇编语言编写;串行通信程序主要用于本系统接收上位机从串口发送过来的打印数据,完成串口的初化、接收串口数据等工作。由于系统程序较大,限于篇幅的原因,本书只给出系统主函数、打印数据输出程序、打印机初始化程序、外中断及定时器中断程序等。需要完整程序的读者,可到出版社官方网站下载,也可来函向作者索取。
1. 系统主函数
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:主程序处理
参数:
返回:无
描述:
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void main( void )
{
WDT();
PARA_HAND_BUSY();
DelayTime( 100 );
Ltp_Init(); // 打印机初始化
Ser_Init(); // 串口初始化
Time_Init(); // 定时器初始化
Ext_Init(); // 外中断初始化
VaryInit(); // 变量初始化
PARA_HAND_FREE();
EI();
printf("system power on!!!rn");
while( 1 )
{
WDT();
RxDecode(); // 处理接收的数据
Ltp_CheckPaper(); // 检查打印机是否缺纸
if(bRecordEnd && GetKey()) // 有按键,则打印机自检
{
Do_Self(); // 打印机自检
}
}
}
159
2. 打印数据输出程序(汇编语言程序,同步移位寄存器方式)
NAME LTP
_SendData SEGMENT CODE
PUBLIC _SendData
; /* void SendData( byte *ptr, byte len ) using 2 */
RSEG _SendData
_SendData:
USING 2
PUSH PSW
MOV PSW,#010H
;/* DPTR = ptr */
MOV DPH, R2
MOV DPL, R1
;R5 = len
AGAIN1:
;/* SBUF = *DPTR */
MOVX A, @DPTR
MOV SBUF, A
;/* *DTPR++ = 0 */
CLR A
MOVX @DPTR, A
INC DPTR
;/* while(!TI) ;*/
JNB TI, $
; /* TI = 0 */
CLR TI
; /* while(R3 < 0x30) */
DJNZ R5,AGAIN1
exit:
POP PSW
RET
;==========end of asm==================
END
3. 外中断服务程序
⑴ 外中断初始化
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:外部中断初始化处理
参数: 无
返回:无
描述:
* low interrupt prio
160
* edge triggle
* enable interrupt
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ext_Init( void )
{
byte tmp;
tmp = XBYTE[0x0fff]; // mask 74HC374 normal word status
tmp = XBYTE[0x0fff];
/* exteral interrupt 0 initial */
EXT_EDGE_INT_MODE( 0 );
EXT_CLR_INT_FLAG( 0 );
EXT_LOW_PRIO_INT( 0 );
EXT_INT_EN( 0 );
PARA_READ1_HIGH();
}
⑵ 外中断服务程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:外部中断程序
参数: 无
返回:无
描述:
* 仅仅从并口接收数据,由上层程序处理协议
* 下降沿触发中断
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ext0_Int( void ) interrupt 0 using 1
{
word addr;
#if 1
RxTimeCnt = 0; // rx time and flag reset
#endif
bRxTimeOut = FALSE;
PARA_HAND_BUSY(); // manual busy
RxBufNum++; // rx data num acc
BYTE(addr)[0] = P2; // reserve P2 value
BYTE(addr)[1] = 0xFF;
RxBuf[RxIn++] = XBYTE[addr];
if(RxIn >= RX_BUF_LEN) // adjust in pointer to begin
{
RxIn = 0;
}
if((RX_BUF_LEN - RxBufNum) < RX_FULL_LIMIT) // check buf free or full
{
161
PARA_HAND_BUSY(); // buffer is full
bComBusy = TRUE; // set busy flag
EXT_INT_DI( 0 ); // disable interrupt
DEBUG_LED_ON();
}
else
{
PARA_HAND_FREE(); // buffer is not full, clr manual busy
PARA_ASK_CLK(); // request new data
bComBusy = FALSE; // clr busy flag
}
}
4. 定时器中断服务程序
⑴ 定时器初始化程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:定时器初始化处理
参数:
返回:
描述:
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Time_Init( void )
{
/* time0 initial */
TIME_STOP( 0 ); // time stop
TIME_CLR_INT_FLAG( 0 ); // clr int flag
T0_WORK_MODE(T0_MODE_1, T0_TIME, T0_GATE_DI );
// mode_1, time mode,no gate
TIME_DELAY_TIME( 0, MOTOR_STEP_TIME_00 );
TIME_HIGH_PRIO_INT( 0 ); // high prio
TIME_INT_EN( 0 ); // int enable
TIME_RUN( 0 ); // run
/* time2 initial */
TIME_STOP( 2 ); // time2 stop
TIME_CLR_INT_FLAG( 2 ); // clr int flag
T2_WORK_MODE( T2_TIME, T2_RELOAD,T2_EXT_TRI_DI );
// time,reload, no external trig */
T2_RELOAD_DELAY( TIME2_INT_TIME );
TIME_INT_EN( 2 ); // int enable
TIME_LOW_PRIO_INT( 2 ); // low proi
TIME_RUN( 2 ); // run
}
162
⑵ 定时器0中断服务程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:定时器0中断处理程序
参数:
返回:
描述:
* 打印机走纸,打印,打印优先于走纸
* 打印TEXT, GRAPH, CURVE
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Time0_Int( void ) interrupt 1 using 2
{
byte data tmp;
word data time;
switch( MotorStatus )
{
case MOTOR_LINE_FEED_S: // line feed num step
FeedNumber = 0;
MotorStatus = MOTOR_STOP_S;
break;
case MOTOR_PRINT_S: // print buffer data
LTP_DST_HEAT_OFF(); // heat off all element
/* change motor phase */
PhaseIdx++;
PhaseIdx %= MOTOR_PHASE_NUM;
MOTOR_PHASE( MotorPhaseTbl[ PhaseIdx ]);
/* dec total print line */
TotalLine--;
/* print head pointer change */
if(BackPrnHead != PrnHead)
{
BackPrnHead = PrnHead;
if(PrnBufPtr == NULL)
{
/* get next line pointer and send num */
tmp = MOD( PrnRear, PRINT_BUF_NUM );
/* get next line buffer pointer */
PrnBufPtr = PrnBuf[tmp];
PreSendNum = PRINT_BUF_LEN / PrnRepeatCnt[PrnRear];
}
}
if(PrnBufPtr != NULL)
{
SendData( PrnBufPtr, PreSendNum );
PrnBufPtr += PreSendNum;
}
163
/* dec repeat print count */
if(--PrnRepeatCnt[PrnRear] == 0)
{
PrnRear = MOD( PrnRear, PRINT_BUF_NUM );
if(PrnHead == PrnRear)
MotorStatus = MOTOR_STOP_S;
else
{
LTP_STB_CLK(); // latch next line print data
/* get next line pointer */
tmp = MOD( PrnRear, PRINT_BUF_NUM );
if(tmp != PrnHead)
{
/* get next line buffer pointer */
PrnBufPtr = PrnBuf[tmp];
PreSendNum = PRINT_BUF_LEN / PrnRepeatCnt[PrnRear];
}
else
PrnBufPtr = NULL;
}
}
/* acc or dec speed, if SpeedIdx == LineFeedNum, no change speed */
if(SpeedIdx < TotalLine)
{
/* acc speed and const speed */
SpeedIdx = (SpeedIdx >= MotorMaxSpeed) ? MotorMaxSpeed : (SpeedIdx + 1);
}
else if(SpeedIdx > TotalLine)
SpeedIdx--;
LPT_DST_HEAT_ON(); // heat on all element
/* set interrupt time */
TIME_STOP( 0 );
BYTE(time)[0] = TH0;
BYTE(time)[1] = TL0;
time += MotorSpeedTbl[SpeedIdx];
TIME_SET_PARMS( 0, BYTE(time)[0], BYTE(time)[1] );
TIME_RUN( 0 );
break;
case MOTOR_PAUSE_S: // motor pause status
MOTOR_PAUSE_PHASE();
case MOTOR_STOP_S: // motor stop status
LTP_DST_HEAT_OFF();
if((PrnHead != PrnRear) && (!bPaperStatus))
164
{
/* stop phase or restart stop phase */
MOTOR_PHASE( MotorPhaseTbl[ PhaseIdx ] );
MotorStatus = MOTOR_PRINT_S;
SpeedIdx = 0;
/* send print data to ltp */
SendData( PrnBuf[PrnRear], PRINT_BUF_LEN );
/* latch data */
LTP_STB_CLK();
/* heat on all element */
LPT_DST_HEAT_ON();
/* get next line pointer and number */
tmp = MOD( PrnRear, PRINT_BUF_NUM );
if(tmp != PrnHead)
{
/* get next line buffer pointer */
PrnBufPtr = PrnBuf[tmp];
PreSendNum = PRINT_BUF_LEN / PrnRepeatCnt[PrnRear];
}
else
PrnBufPtr = NULL;
/* save current PrnHead value */
BackPrnHead = PrnHead;
}
else
{
/* enter MOTOR_PAUSE_S status */
MotorStatus = MOTOR_PAUSE_S;
SpeedIdx = 0;
}
/* set interrupt time */
TIME_STOP( 0 );
BYTE(time)[0] = TH0;
BYTE(time)[1] = TL0;
time += MotorSpeedTbl[SpeedIdx];
TIME_SET_PARMS( 0, BYTE(time)[0], BYTE(time)[1] );
TIME_RUN( 0 );
break;
default:
MotorStatus = MOTOR_STOP_S;
break;
}
}
165
⑶ 定时器2中断服务程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:定时器2中断处理程序
参数:
返回:
描述:
* 一般定时器使用
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Time2_Int( void ) interrupt 5 using 1
{
TIME_CLR_INT_FLAG( 2 ); // clr interrupt flag
GeneralCnt++; // inc count
if(RxTimeCnt < RX_DATA_TIME_OUT) // check rx time out
{
RxTimeCnt++;
if(RxTimeCnt >= RX_DATA_TIME_OUT)
{
/* rx already time out and paper present */
bRxTimeOut = TRUE;
}
}
}
5. 打印机初始化及缺纸检测程序
⑴ 打印机初始化程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:打印机初始化处理
参数:
返回:
描述:
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ltp_Init( void )
{
/* hardware init */
LTP_STB_HIGH();
LTP_DST_HEAT_OFF(); // close all dst segment
/* init start phase and pause phase*/
MOTOR_PHASE( MotorPhaseTbl[ 0 ]);
MOTOR_PAUSE_PHASE();
/* vary init */
MotorStatus = MOTOR_STOP_S;
SpeedIdx = 0;
PhaseIdx = 0;
166
}
MotorMaxSpeed = 3; // motor speed 25mm/s
⑵ 打印机缺纸检测程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:检测打印机的纸状态,缺纸/有纸
参数:
* TRUE: 缺纸
* FALSE: 有纸
返回:无
描述:
* 必须周期性的调用
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ltp_CheckPaper( void )
{
byte i;
/* check paper present */
if(GET_PAPER_STATUS() != bPaperStatus)
{
/* delay a little time */
for(i = 0; i < 100; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
if(GET_PAPER_STATUS() != bPaperStatus)
{
/* confirm change,level steady */
bPaperStatus = GET_PAPER_STATUS();
}
}
}
167
2024年2月6日发(作者:樊典雅)
第8章 LTPA245热敏打印机驱动设计
热敏打印机是利用发热元件产生热量,使紧贴在其表面的热敏纸迅速变色,从而在纸上形成相应点阵字符或图形的一种打印机。相对于针式、笔式打印机,热敏打印机具有结构简单、体积小、重量轻、噪声小、功耗低、印字质量高、价格便宜、运行成本较低及使用可靠等一系列优点。已越来越广泛地应用于医疗仪器、银行柜员机及POS终端等各种便携式计算机系统和智能化设备中,被认为是最合适的便携式硬拷贝输出设备。本章以精工(SEIKO)SII生产的一款高速热敏打印机LTPA245为例,介绍一种通用热敏打印机的驱动设计。
8.1 热敏打印机的工作原理
8.1.1 热敏打印机结构原理
热敏式打印机的关键部件是打印头。它包含很多微型发热元件,这些发热元件一般采用集成电路工艺和光刻技术,通过物理化学方法在陶瓷基片上加工制成。为防止发热元件与热敏纸接触时产生的磨损,表面涂了一层类似玻璃的保护膜。目前的工艺水平已将发热元件的密度做到8点/mm (分辨率达200dpi)、16点/mm,甚至更高。在印字速度低于100cps时,热敏头寿命可达1亿字符,或记录纸滑行30km的可靠性。热敏打印机所用的打印纸不是普通纸,而是经特殊处理过的感热记录纸。这种记录纸是将两种混合成份材料涂复在纸上而成,基层纸上涂有一层几微米厚的白色感热生色层。在这个感热生色层上涂有无色染料和特殊生色剂。为使他们能有效地附在纸上,在它们周围的空隙里还填充有粘合剂。感热生色层一经加热,生色剂立即熔化,并熔进无色染料中,引起化学反应显出颜色,这一过程仅需几个毫秒即可完成。
由于感热记录纸是受热后材料熔融引起化学反应而呈现颜色,如温度过高,新的合成物质被分解,颜色又会消失。另外,这种物质在光的长时间作用下也会自动分解,所以感热记录纸不能长期保存。虽然热敏打印机对打印纸有特殊要求,但是这种记录纸价格并不贵,无需像针打那样经常要更换色带。因此,越来越多的智能化仪器仪表采用热敏打印机作为输出设备。
8.1.2 热敏打印机设计中需要注意的问题
为实现高品质的打印,在设计热敏打印机电路和控制时序时必须注意三个问题:
1. 常能量控制
常能量控制指的是打印头上每一个发热元件发出的热量要相同,且保持一个常量,否则打印出的字符颜色有深有浅,影响打印效果。发热元件每次发出的热量,除了与发热元件流过的电流的大小和持续时间有关外,还与其本身的余热(如果前次已经通电发热)有关。它的余热直接影响下一次发热元件传给打印纸的热量,从而影响打印效果。因此,热敏打印机电路除了要检测环境温度外,还要记录每一个发热元件前一次状态,甚至前几次的通电发热的状态,以决定本次究竟要给出多大热量(可以通过控制通电时间来确定)。打印速度越快,这个问题就越重要。
2. 大电流脉冲控制
由于打印时要同时激励的发热元件可能会很多,如一个分辨率为8点/mm,打印宽度为72mm的打印头,一点行上要排列8×72 = 576个发热元件。尽管每个发热元件只要几十毫安的电流,但若同时激励这些发热元件,总电流就很可观了,而且这种脉冲式的电流谐波分量极其丰富,会给其它电路带来很大的干扰,甚至使打印电路失控,烧毁打印头发热元件。
150
因此,发热元件通电驱动程序要仔细考虑,一般可将每点行分成几段,以几段为一组同时传送,使电流变化比较平稳。
3. 处理时间与CPU速度协调
由于打印速度较快,尽管每点行只需要几十个字节的数据,但必须在数毫秒内完成这些数据的接收、处理、输出到打印头、常能量控制等一系列要求,故对CPU的速度就有较高的要求。
8.2 LTPA245热敏打印机
LTPA245是精工公司生产的一款高速热敏打印机,采用全新的结构及打印技术,小巧轻便。分离式的压纸轴设计更便于上纸,加上低电压驱动,可实现两节锂电池供电。广泛应用于测量分析仪、POS机、通讯设备或数据终端及各种便携式设备上,已成为目前热敏打印机业界的最畅销机型,其外形结构如图8-1所示。
其性能特点为:
◆ 分离式压纸轴设计便于上纸
◆ 小巧轻便可应用于手持设备
◆ 优质耐用(打印头可连续打印超过50km)
◆ 准确快速(90mm/秒)
◆ 配有纸源感应器,自动检测上纸情况
◆ 结构合理,便于维护保养
LTPA245的技术参数如表8-1所示。
图8-1 LTPA245的外形
表8-1 LTPA245的技术参数
型号
打印头类型打印
分辨率(dots/line)
点密度(dots/mm)(WxH)
打印速度(mm/s)
LTPA245
热敏行式
384
8×16
53.4(驱动电压5V)
77(驱动电压7.2V)
90(驱动电压8.5V)
送纸间距
打印宽度/纸宽(mm)
打印头寿命
操作电压(V)
打印纸长(Km)
逻辑电路
打印头
尺寸(mm)(W×D×H)
重量(g)
0.0625mm
48/58
脉冲个数(pulses) 10
50
2.7~5.25
4.5~8.5
69.2×28.3×31.7
约41
8LTPA245通过一个1mm间距的27针FPC连接器(见图8-1)与驱动器进行连接,连接器各引脚的定义和功能如表8-2所示。
LTPA245采用同步串行通信接口,数据以串行移位的方式从驱动器移入打印机内部的数据锁存器,其工作时序如图8-2所示。其中,DAT为串行移位数据,CLK为移位时钟,/LATCH为数据锁存信号,DST为分段加热控制信号。打印数据以384 bit(12 words)为一行,在CLK作用下,数据从DAT端逐一移入打印机内数据寄存器中。每一个数据位对应1个加热元
151
表8-2 FPC连接器各针脚定义
引脚序号 引脚名称 信号方向 功能描述
1 PS 输出 纸检测器输出,高电平表示缺纸
2 VPS 输入 纸检测器发光器信号输入
3 GND — 纸检测器的地
4 Vp — 热敏打印头驱动电压
5 Vp — 热敏打印头驱动电压
6 DAT 输入 同步串行输入
7 DST6 输入 发热元件激活信号
8 DST5 输入 发热元件激活信号
9 DST4 输入 发热元件激活信号
10 GND — 电源地
11 GND — 电源地
12 GND — 电源地
13 GND — 电源地
14 TH 输出 热敏电阻
15 DST3 输入 发热元件激活信号
16 DST2 输入 发热元件激活信号
17 DST1 输入 发热元件激活信号
18 Vdd — 逻辑电源
19 CLK 输入 打印数据传输的同步时钟
20 /LATCH 输入 打印数据锁存。低电平时数据从输入寄存器送打印锁存器,上升沿锁存
21 DATO 输出 打印数据输出(串行输出)
22 Vp — 热敏打印头驱动电压
23 Vp — 热敏打印头驱动电压
24 /A 输入 步进电机控制信号
25 /B 输入 步进电机控制信号
26 A 输入 步进电机控制信号
27 B 输入 步进电机控制信号
图8-2 LTPA245的打印时序
152
件,当该位数据为0时,表示不加热,为1时表示加热。热敏纸被加热的位置变黑,不加热的位置不变色(白)。当384个bit全部移入打印机后,驱动器应输出1个/LATCH锁存信号(负脉冲),将数据送到打印寄存器。实际打印时,为防止电流过大,打印头温度过高,驱动器应控制DST0~DST5的输出信号,将一行数据分段(本系统分3段)打印。一行打印结束后,驱动器从A、/A、B、/B端送出脉冲,控制步进电机带动热敏纸前移一段距离,继续打印下一行。
LTPA245内部带有一个微型、大力矩的精密2相4线步进电机。电机有A、B两组线圈、4个控制端,分别定义为A、/A、B、/B。当驱动器按表8-3所示的脉冲序列从控制端给步进电机输入脉冲时,可控制电机匀速转动。
表8-3 步进电机驱动时序
控制端 停止
A
B
/A
/B
0
0
0
0
Step1
0
0
1
1
Step2
0
1
1
0
Step3
1
1
0
0
Step4
1
0
0
1
8.3 步进电机的驱动
LTPA245内部不带步进电机驱动芯片,需外接驱动电路。本章设计的驱动系统选用FAN8200D驱动热敏打印机内部的步进电机。FAN8200/FAN8200D是美国快捷半导体公司设计生产的低工作电压、低饱和压降单片式步进电机驱动器集成电路,可用于两相步进电机的驱动。它带有双路H桥,可分别驱动两个独立的PNP功率管。每一个桥都有各自独立的使能引脚,非常适合于需要独立控制的步进电机驱动系统。
FAN8200/FAN8200D的主要特点有:
◆ 具有3.3V和5V微处理器(MPU)接口;
◆ 内含可驱动双极步进电机的双向H桥路;
◆ 内含垂直PNP功率晶体管;
◆ 可适应宽达2.5V~7.0V的电源电压范围;
◆ 具有很低的饱和压降(可低达0.4V/0.4A);
◆ 每一路H桥均具有独立的使能引脚,并可单
独进行使能控制;
◆ 具有过流保护功能;
图8-3 FAN8200D的引脚
◆ 具有过热关断(TSD)功能。
FAN8200/FAN8200D的上述特性使其可广泛应用于通用低压步进电机驱动系统、磁盘驱动器、PC照相机和数码相机的步进电机驱动、安全移动控制器、热敏式打印机、运动控制器以及需要两通道直流电机驱动的控制系统,同时还可用于微处理器接口的通用功率驱动器的电机驱动系统。
1. FAN8200/FAN8200D的引脚功能
FAN8200采用14脚DIP-300封装,而FAN8200D则采用14脚SOP-225封装。他们的工作温度都是-20~+70℃,其引脚排列如图8-3所示,各引脚的功能见表8-4。
2. FAN8200/FAN8200D的工作原理
FAN8200/FAN8200D的内部由两路完全相同的控制电路组成。外部脉冲信号从IN1(或IN2)输入,经片内前级缓冲放大后送入片内控制器,此信号在CE1(或CE2)使能的情况下,
153
表8-4 FAN8200的引脚功能
引脚序号 引脚名称 信号方向 功能描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
VCC
CE1
OUT1
VS1
OUT2
IN1
SGND
PGND
IN2
OUT4
VS2
OUT3
CE2
PGND
—
输入
输出
输入
输出
输入
—
—
输入
输出
输入
输出
输入
—
逻辑电源电压输入
通道1器件触发使能,高电平有效
通道1步进脉冲输出
通道1电源输入
通道1步进脉冲输出
通道1步进脉冲输入
信号地
功率地
通道2步进脉冲输入
通道2步进脉冲输出
通道2电源输入
通道2步进脉冲输出
通道2器件触发使能,高电平有效
功率地
由控制部分进行处理并驱动晶体管,最后从OUT1(或OUT3)脚输出反相的脉冲信号,从OUT2(或OUT4)脚输出同相的脉冲信号,与步进电机的线圈形成回路后控制电机的运行。
器件触发使能端口(CE)的作用是分别对两个通道的输出进行控制,当CE端的输入控制信号为低电平时,无论有无输入控制信号,输出端OUT始终呈现高阻抗状态。因此,要使FAN8200/FAN8200D控制器的输出端在输入信号的控制下正常工作,器件的触发使能端必须为高电平。FAN8200/ FAN8200D中CE、IN和输出端OUT之间的逻辑控制关系如表8-5所示,表中的L表示低电平,H表示高电平,×表示无关,Z表示处于高阻态。
表8-5 FAN8200/FAN8200D的逻辑控制关系
CE1(或CE2)
L
H
H
IN1(或IN2) OUT1(或OUT3) OUT2(或OUT4)
×
L
H
Z
H
L
Z
L
H
FAN8200/FAN8200D内部的热关断和偏置电路可用来对整个电路提供过热和过流保护,当负载过大或其它故障导致电路电流增大,从而使器件温度升高到片内温度传感器的设定门限以上时,FAN8200/FAN8200D中的热关断和偏置电路将向片内控制器发出关断控制信号以关断整个电路。
8.4 单片机资源分配
本章设计的热敏打印机驱动系统选用STC89C58(PLCC封装)作为控制中心,负责接收上位机通过标准并行通信口传送过来的点阵或字符数据(对程序稍作改动也可接收串口数据),经单片机处理后,控制打印机加热板的加热及步进电机的走纸,从而在热敏纸上打印出上位机需要输出的字符或图形。
单片机I/O口资源的分配如表8-6所示。
154
表8-6 单片机I/O口的资源分配(PLCC封闭)
引脚序号 引脚名称
2
3
4
5
P1.0
P1.1
P1.2
P1.3
信号方向
输出
输出
输出
输出
功能描述
步进电机A相驱动脉冲输出(FAN8200的IN1)
步进电机B相驱动脉冲输出(FAN8200的IN2)
FAN8200D触发使能(CE1、CE2),高电平使能
74HC32或门1开启控制。当P1.3=0(反相后为1)时,关闭或门,锁存器74HC374输出为高阻态,禁止读并口数据;当P1.3=1时,开启或门,系统在P3.7(/RD)和并口/STB的控制下,读标准并口数据
热敏打印机数据锁存控制,上升沿锁存热敏打印机的打印数据
接收串口打印数据时,接标准串口的DSR。当接收缓冲器满时,此脚输出高电平,通知串口暂停发送
与并口通信的握手应答信号,负脉冲表示系统可以接收新的打印数据
接收缓冲器满。P1.7=1时,经74HC32或门2向并口发系统忙信号,表示接收缓冲器满;P1.7=0时,开启74HC32或门2,表示系统可以接收并口数据。
6
7
P1.4
P1.5
输出
输出
8
9
P1.6
P1.7
输出
输出
11 P3.0(RxD) 输出/输入 接收并口打印数据时,作为移位寄存器方式的数据输出,向热敏打印机输出打印数据;接收串口打印数据时,作为异步串行通信的数据接收端
输出 接收并口打印数据时,作为移位寄存器方式的同步时钟输出,控制热敏打印机的数据读取;接收串口打印数据时,作为异步串行通信的数据接收端
外中断0。标准并口发数据选通信号(/STB)时,由74HC74的/1Q产生中断请求,读取标准并口输出的数据,下降沿产生中断
按键输入。打印机自检控制,低电平有效
打印机缺纸检测。低电平有效,打印机缺纸
未用
读标准并口数据控制。当P3.7=0且P1.3=1(反相后为0)时,使能锁存器74HC374并对74HC74置0,读标准并口数据
热敏打印机发热元件加热信号
热敏打印机发热元件加热信号
热敏打印机发热元件加热信号
未用
并口数据输入
13 P3.1(TxD)
14 P3.2(/INT0) 输入
15
16
17、18
19
P3.3(/INT1) 输入
P3.4(T0)
P3.7(/RD)
输入
输出
P3.5、 P3.6 —
24
25
26
27~31
36~43
P2.0
P2.1
P2.2
P2.3~P2.7
P0
输出
输出
输出
—
输入
155
8.5 系统硬件设计
本书介绍的通用热敏打印机驱动系统由复位及时钟电路、并行通信模块、打印控制及串行通信模块等三大模块构成。可接收标准并行通信口发送过来的打印数据,经分析和处理后送LPTA245热敏打印机打印;对程序稍加修改后,也可以接收串行通信口发送过来的打印数据,处理后送热敏打印机打印。
1. 系统复位电路
本系统的复位有两种情况:一是系统上电复位;二是标准并口发出的复位信号对系统复位。系统复位及时钟电路如图8-4所示。
图8-4 系统复位电路
本系统的上电复位电路与一般单片机的上电复位电路一样,由于标准并口的RST输出端正常情况输出高电平,经反相器(74HC04)反相后输出低电平,打开或门,所以上电复位的过程与普通单片机系统的上电复位过程一样。
系统上电复位后,正常工作时,由于上电复位电路输出的是低电平,打开了74HC32的或门3。此时,如果并口输出一个负脉冲(如图8-4所示),则经过反相后,变为正脉冲,由于或门3已经打开,则在或门3的输出端将输出一个正脉冲,如果此脉冲的宽度大于两个机器周期,将对单片机进行复位。
2. 并行通信模块
并行通信模块由单片机、六反相器(U6,74HC04)、或门(U5,74HC32)、D触发器(U3,74HC74)、锁存器(U2,74HC374)及标准并口等组成。负责与标准并口通信、接收并口输出的打印数据、输出缺纸信号等,其电路组成如图8-5所示。
⑴ D触发器的复位与锁存器的使能
系统初始化时,置单片机P1.3为高电平,经74HC04的反相器2反相后,输出低电平。打开74HC32的或门1,允许在P3.7控制下,对D触发器74HC74进行复位、对锁存器74HC374使能操作。当P3.7=1(常规状态)时,D触发器正常工作(在CP脉冲的控制下将输入送到输出),禁止锁存器的使能,使锁存器输出高阻状态,数据不能传送到单片机P0口;当P3.7=0(单片机有读数操作)时,对D触发器复位(1Q=0,/1Q=1),同时对锁存器使能,使锁存器的数据能输出到单片机的P0口。
⑵ 触发器状态的翻转与锁存器的锁存
当并口没发送数据时,标准并口的数据选通输出端/STB输出高电平。经74HC04的反相器1反相后,输出低电平。此低电平分为两路:一路送D触发器U3(74HC74)的时钟输入端CP,禁止D触发器的状态改变;另一路送锁存器U2(74HC374)的锁存控制端CLK,禁止锁存器的数据锁存。
当并口发送一个数据后,从数据选通输出端/STB输出一个负脉冲,其下降沿经反相后
156
变为上升沿。此上升沿也分两路:一路接D触发器的时钟输入端CP,使触发器的状态翻转。由于触发器的输入端接电源(高电平),则触发器将输出“1”状态(1Q=1,/1Q=0);另一送锁存器的锁存控制端CLK,将并口发送过来的数据锁存在锁存器内。
触发器输出的“1”信号有两个作用:一是1Q=1,此高电平经74HC32的或门2向标准并口发系统忙信息,通知并口现在系统正在读取本次传送的数据,暂不发下一个数据;二是/1Q=0,其下降沿向单片机发中断请求(/INT0),请求单片机读取本次数据。单片机收到此中断请求后,将会在外中断0中断服务子程序中读取本次并口传送过来的数据。
图8-5 并行通信模块
⑶ 系统忙信号BUSY
系统忙信号由74HC32的或门2送出。此信号的产生分两种情况:一是当单片机内部的接收缓冲器满时,从P1.7输出一个高电平,经74HC32或运算后送给并口,通知并口系统忙;二是在单片机的接收缓冲器不满时(P1.7=0),如果系统正在读并口前一次发送的数据,则由触发器74HC74的1Q输出高电平,此信号经74HC32或运算后送给并口,通知并口系统忙,暂不发下一个数据。
⑷ 单片机读取并口数据的过程
单片机接收缓冲器未满(P1.7=0)且未读取并口数据的情况下(无系统忙信号),单片机允许并口发送相应的打印数据。并口发送及单片机接收数据的过程为:
并口先输出一个字节的并行数据,然后发数据选通端信号/STB。/STB经74HC04反相后分两路:一路送锁存器的CLK端将并口输出的数据锁存在锁存器以供单片机读取;另一路送触发器的CP端,使触发器输出“1”状态(1Q=1,/1Q=0)。
触发器的输出中,1Q=1经74HC32的或门2向并口送系统忙信号,通知并口暂不发送下一个数据;/1Q=0向单片机发中断请求,单片机接收并响应该中断请求后,在中断服务子程序里先执行一个读外部数据存储器的指令,使P3.7(/RD)输出一个负脉冲。此负脉的低电平经74HC32的或门2后输出低电平(系统初始化时,置P1.3=1,打开了74HC32的或门2),此低电平分两路:一路送锁存器74HC374的使能端(/OE),使能锁存器,将前面锁存的数据传送给单片机P0口,完成一次数据的读取。另一路送D触发器的复位端(/1RD),使触发器输出“0”状态,触发器“0”状态的1Q=0清除系统忙信号,通知并口可以发送下一下数据;/1Q=1使单片机外中断0输入高电平,准备产生下一次中断。
157
单片机读完一个数据后,P3.7(/RD)变为高电平,此高电平经74HC32的或门1后分两路:一路禁止锁存器74HC374使能,使锁存器输出高阻,与单片机P0口隔绝;另一路开放触发器74HC74,使触发器能正常翻转,为下一次读数据作准备。
3. 打印控制及串行通信模块
打印控制及串行通信模块由单片机、步进电机驱动芯片(FAN8200D)、热敏打印机接口、UART接口及打印机自检信号输入等电路组成。完成步进电机的驱动、打印数据及加热信号的输出、串行打印数据的接收及打印机自检的控制等工作。打印控制及串行通信电路如图8-6所示。
图8-6 打印控制及串行通信模块
⑴ 打印的控制过程
单片机通过自带有串口向热敏打印机发送待打印的数据,串口工作于方式0、移位寄存器方式。当单片机接收到标准并口发送过来的打印数据,经内部程序处理后,送输出缓冲器。在单片机输出缓冲器有数据,且打印机不缺纸的情况下,通过P3.0口(RXD)向热敏打印机接口的DAT端按位输出打印数据,同时由P3.1口(TXD)输出同步移位脉冲。
当一行打印数据(384个位)全部输出完后,由P2.0、P2.1、P2.2口输出加热信号(加热时间的长短由延时电容的充放电时间常数确定),然后运行一段延时程序(确保热敏纸变色)完成一行的打印。一行打印完后,从P1.0、P1.1、P1.2输出FAN8200D选通信号及步进电机走纸命令,使热敏打印纸移动一行,准备下一行的打印。
⑵ 打印机的自检
系统还设计有打印自检的功能。当需要检查打印机是否能正常工作时,可按下按键,给单片机P3.3口输入一个低电平。当系统检测到P3.3口有低电平输入时,执行自检程序,打印预先设定好的自检图形和字符。
⑶ 串行通信
本系统的硬件电路还设计有串行通信接口,在上位机没有标准并口的情况下,可以接收上位机串口发送过来的打印数据(程序需作适当修改)。使用串口接收上位机数据时,单片机工作于串行通信方式1、UART模式,通过P1.5口输出数据装置准备好(DSR)信号,通知上位机可以发送下一个数据。
158
8.6 系统软件
通用热敏打印机驱动系统的软件由主程序(MAIN.C)、外中断程序(EXT.C)、串行通信程序(SERIAL.C)、打印数据输出程序()、定时器中断程序(TIME.C)、打印数据处理程序(CONST.C)及自定义的库函数集组成。其中,打印数据通过单片机自带的串口输出,采用方式0(同步移位寄存器方式),程序用汇编语言编写;串行通信程序主要用于本系统接收上位机从串口发送过来的打印数据,完成串口的初化、接收串口数据等工作。由于系统程序较大,限于篇幅的原因,本书只给出系统主函数、打印数据输出程序、打印机初始化程序、外中断及定时器中断程序等。需要完整程序的读者,可到出版社官方网站下载,也可来函向作者索取。
1. 系统主函数
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:主程序处理
参数:
返回:无
描述:
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void main( void )
{
WDT();
PARA_HAND_BUSY();
DelayTime( 100 );
Ltp_Init(); // 打印机初始化
Ser_Init(); // 串口初始化
Time_Init(); // 定时器初始化
Ext_Init(); // 外中断初始化
VaryInit(); // 变量初始化
PARA_HAND_FREE();
EI();
printf("system power on!!!rn");
while( 1 )
{
WDT();
RxDecode(); // 处理接收的数据
Ltp_CheckPaper(); // 检查打印机是否缺纸
if(bRecordEnd && GetKey()) // 有按键,则打印机自检
{
Do_Self(); // 打印机自检
}
}
}
159
2. 打印数据输出程序(汇编语言程序,同步移位寄存器方式)
NAME LTP
_SendData SEGMENT CODE
PUBLIC _SendData
; /* void SendData( byte *ptr, byte len ) using 2 */
RSEG _SendData
_SendData:
USING 2
PUSH PSW
MOV PSW,#010H
;/* DPTR = ptr */
MOV DPH, R2
MOV DPL, R1
;R5 = len
AGAIN1:
;/* SBUF = *DPTR */
MOVX A, @DPTR
MOV SBUF, A
;/* *DTPR++ = 0 */
CLR A
MOVX @DPTR, A
INC DPTR
;/* while(!TI) ;*/
JNB TI, $
; /* TI = 0 */
CLR TI
; /* while(R3 < 0x30) */
DJNZ R5,AGAIN1
exit:
POP PSW
RET
;==========end of asm==================
END
3. 外中断服务程序
⑴ 外中断初始化
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:外部中断初始化处理
参数: 无
返回:无
描述:
* low interrupt prio
160
* edge triggle
* enable interrupt
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ext_Init( void )
{
byte tmp;
tmp = XBYTE[0x0fff]; // mask 74HC374 normal word status
tmp = XBYTE[0x0fff];
/* exteral interrupt 0 initial */
EXT_EDGE_INT_MODE( 0 );
EXT_CLR_INT_FLAG( 0 );
EXT_LOW_PRIO_INT( 0 );
EXT_INT_EN( 0 );
PARA_READ1_HIGH();
}
⑵ 外中断服务程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:外部中断程序
参数: 无
返回:无
描述:
* 仅仅从并口接收数据,由上层程序处理协议
* 下降沿触发中断
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ext0_Int( void ) interrupt 0 using 1
{
word addr;
#if 1
RxTimeCnt = 0; // rx time and flag reset
#endif
bRxTimeOut = FALSE;
PARA_HAND_BUSY(); // manual busy
RxBufNum++; // rx data num acc
BYTE(addr)[0] = P2; // reserve P2 value
BYTE(addr)[1] = 0xFF;
RxBuf[RxIn++] = XBYTE[addr];
if(RxIn >= RX_BUF_LEN) // adjust in pointer to begin
{
RxIn = 0;
}
if((RX_BUF_LEN - RxBufNum) < RX_FULL_LIMIT) // check buf free or full
{
161
PARA_HAND_BUSY(); // buffer is full
bComBusy = TRUE; // set busy flag
EXT_INT_DI( 0 ); // disable interrupt
DEBUG_LED_ON();
}
else
{
PARA_HAND_FREE(); // buffer is not full, clr manual busy
PARA_ASK_CLK(); // request new data
bComBusy = FALSE; // clr busy flag
}
}
4. 定时器中断服务程序
⑴ 定时器初始化程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:定时器初始化处理
参数:
返回:
描述:
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Time_Init( void )
{
/* time0 initial */
TIME_STOP( 0 ); // time stop
TIME_CLR_INT_FLAG( 0 ); // clr int flag
T0_WORK_MODE(T0_MODE_1, T0_TIME, T0_GATE_DI );
// mode_1, time mode,no gate
TIME_DELAY_TIME( 0, MOTOR_STEP_TIME_00 );
TIME_HIGH_PRIO_INT( 0 ); // high prio
TIME_INT_EN( 0 ); // int enable
TIME_RUN( 0 ); // run
/* time2 initial */
TIME_STOP( 2 ); // time2 stop
TIME_CLR_INT_FLAG( 2 ); // clr int flag
T2_WORK_MODE( T2_TIME, T2_RELOAD,T2_EXT_TRI_DI );
// time,reload, no external trig */
T2_RELOAD_DELAY( TIME2_INT_TIME );
TIME_INT_EN( 2 ); // int enable
TIME_LOW_PRIO_INT( 2 ); // low proi
TIME_RUN( 2 ); // run
}
162
⑵ 定时器0中断服务程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:定时器0中断处理程序
参数:
返回:
描述:
* 打印机走纸,打印,打印优先于走纸
* 打印TEXT, GRAPH, CURVE
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Time0_Int( void ) interrupt 1 using 2
{
byte data tmp;
word data time;
switch( MotorStatus )
{
case MOTOR_LINE_FEED_S: // line feed num step
FeedNumber = 0;
MotorStatus = MOTOR_STOP_S;
break;
case MOTOR_PRINT_S: // print buffer data
LTP_DST_HEAT_OFF(); // heat off all element
/* change motor phase */
PhaseIdx++;
PhaseIdx %= MOTOR_PHASE_NUM;
MOTOR_PHASE( MotorPhaseTbl[ PhaseIdx ]);
/* dec total print line */
TotalLine--;
/* print head pointer change */
if(BackPrnHead != PrnHead)
{
BackPrnHead = PrnHead;
if(PrnBufPtr == NULL)
{
/* get next line pointer and send num */
tmp = MOD( PrnRear, PRINT_BUF_NUM );
/* get next line buffer pointer */
PrnBufPtr = PrnBuf[tmp];
PreSendNum = PRINT_BUF_LEN / PrnRepeatCnt[PrnRear];
}
}
if(PrnBufPtr != NULL)
{
SendData( PrnBufPtr, PreSendNum );
PrnBufPtr += PreSendNum;
}
163
/* dec repeat print count */
if(--PrnRepeatCnt[PrnRear] == 0)
{
PrnRear = MOD( PrnRear, PRINT_BUF_NUM );
if(PrnHead == PrnRear)
MotorStatus = MOTOR_STOP_S;
else
{
LTP_STB_CLK(); // latch next line print data
/* get next line pointer */
tmp = MOD( PrnRear, PRINT_BUF_NUM );
if(tmp != PrnHead)
{
/* get next line buffer pointer */
PrnBufPtr = PrnBuf[tmp];
PreSendNum = PRINT_BUF_LEN / PrnRepeatCnt[PrnRear];
}
else
PrnBufPtr = NULL;
}
}
/* acc or dec speed, if SpeedIdx == LineFeedNum, no change speed */
if(SpeedIdx < TotalLine)
{
/* acc speed and const speed */
SpeedIdx = (SpeedIdx >= MotorMaxSpeed) ? MotorMaxSpeed : (SpeedIdx + 1);
}
else if(SpeedIdx > TotalLine)
SpeedIdx--;
LPT_DST_HEAT_ON(); // heat on all element
/* set interrupt time */
TIME_STOP( 0 );
BYTE(time)[0] = TH0;
BYTE(time)[1] = TL0;
time += MotorSpeedTbl[SpeedIdx];
TIME_SET_PARMS( 0, BYTE(time)[0], BYTE(time)[1] );
TIME_RUN( 0 );
break;
case MOTOR_PAUSE_S: // motor pause status
MOTOR_PAUSE_PHASE();
case MOTOR_STOP_S: // motor stop status
LTP_DST_HEAT_OFF();
if((PrnHead != PrnRear) && (!bPaperStatus))
164
{
/* stop phase or restart stop phase */
MOTOR_PHASE( MotorPhaseTbl[ PhaseIdx ] );
MotorStatus = MOTOR_PRINT_S;
SpeedIdx = 0;
/* send print data to ltp */
SendData( PrnBuf[PrnRear], PRINT_BUF_LEN );
/* latch data */
LTP_STB_CLK();
/* heat on all element */
LPT_DST_HEAT_ON();
/* get next line pointer and number */
tmp = MOD( PrnRear, PRINT_BUF_NUM );
if(tmp != PrnHead)
{
/* get next line buffer pointer */
PrnBufPtr = PrnBuf[tmp];
PreSendNum = PRINT_BUF_LEN / PrnRepeatCnt[PrnRear];
}
else
PrnBufPtr = NULL;
/* save current PrnHead value */
BackPrnHead = PrnHead;
}
else
{
/* enter MOTOR_PAUSE_S status */
MotorStatus = MOTOR_PAUSE_S;
SpeedIdx = 0;
}
/* set interrupt time */
TIME_STOP( 0 );
BYTE(time)[0] = TH0;
BYTE(time)[1] = TL0;
time += MotorSpeedTbl[SpeedIdx];
TIME_SET_PARMS( 0, BYTE(time)[0], BYTE(time)[1] );
TIME_RUN( 0 );
break;
default:
MotorStatus = MOTOR_STOP_S;
break;
}
}
165
⑶ 定时器2中断服务程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:定时器2中断处理程序
参数:
返回:
描述:
* 一般定时器使用
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Time2_Int( void ) interrupt 5 using 1
{
TIME_CLR_INT_FLAG( 2 ); // clr interrupt flag
GeneralCnt++; // inc count
if(RxTimeCnt < RX_DATA_TIME_OUT) // check rx time out
{
RxTimeCnt++;
if(RxTimeCnt >= RX_DATA_TIME_OUT)
{
/* rx already time out and paper present */
bRxTimeOut = TRUE;
}
}
}
5. 打印机初始化及缺纸检测程序
⑴ 打印机初始化程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:打印机初始化处理
参数:
返回:
描述:
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ltp_Init( void )
{
/* hardware init */
LTP_STB_HIGH();
LTP_DST_HEAT_OFF(); // close all dst segment
/* init start phase and pause phase*/
MOTOR_PHASE( MotorPhaseTbl[ 0 ]);
MOTOR_PAUSE_PHASE();
/* vary init */
MotorStatus = MOTOR_STOP_S;
SpeedIdx = 0;
PhaseIdx = 0;
166
}
MotorMaxSpeed = 3; // motor speed 25mm/s
⑵ 打印机缺纸检测程序
/*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*
功能:检测打印机的纸状态,缺纸/有纸
参数:
* TRUE: 缺纸
* FALSE: 有纸
返回:无
描述:
* 必须周期性的调用
*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*=====*/
void Ltp_CheckPaper( void )
{
byte i;
/* check paper present */
if(GET_PAPER_STATUS() != bPaperStatus)
{
/* delay a little time */
for(i = 0; i < 100; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
if(GET_PAPER_STATUS() != bPaperStatus)
{
/* confirm change,level steady */
bPaperStatus = GET_PAPER_STATUS();
}
}
}
167