本帖最后由 Angus 于 2022-9-30 11:11 编辑
走纸有多快,打印就可以有多快! NUC123 是如何实现高速打印的? 且听我慢慢道来。
虚拟串口模式,按键打测试页
NUC123_VCOM_Printer_V1.03.zip
(3.31 MB, 下载次数: 2472)
USB 电脑打印机模式
NUC123_USB_Printer_V1.10.zip
(3.27 MB, 下载次数: 1865)
含原理图,PC机驱动,字库写入软件等。
写字库工具软件的 C++ 源代码
ZKT-Sorce.zip
(1.47 MB, 下载次数: 3576)
写字库的 NUC123 的源代码
NUC123SeriesBSP_SPI_Flash.zip
(1.35 MB, 下载次数: 3585)
字库改组:
字库中数据排列是:左一byte,右一byte;左二byte,右二byte;左三byte,右三byte............为了便于处理,我们对字模进行如下改组:
把 16 X 16 汉字的字模数据,分成先存放左边从上到下16个字节,再存放右边16个字节,目的是可以把一个汉字当成两个 16X8 字符(字母或数字)处理。
1行字符有16行点数据,打印数据(点的数据)在 RAM 中依次存放,前16bytes是第一个字符数据,接下来16个字节是第二个字符的数据,然后是第3个字符的数据。。。。。,打印点的数据从RAM读出送往打印头,无论是汉字还是字母或数字,第n行点的数据是: n, n+16, n+16*2, n+16*3......一行取48个字节, 58mm打印头一行是 8*48=384 个点。一行可打印48个字符、或24个楷体汉字,字模数据排列如下
把 24 X 24 汉字,分成左边从上到下 24行 X 12列个点, 和右边 24 X 12个点的数据,一行 12bit 数据存放在16bit 半字中的低12bit, 左右半边都是一个 24行 X 16列的"一个字符的点数据",有48 个字节,一个24X24汉字变成96个字节了。如此,可把一个汉字当成两个字母( 24 X 16点阵)来处理。第n行点的数据就是 n,n+24,n+24*2,n+24*3......,字模数据从RAM中按16位读出,但从SPI只传出低12位。传输32次,打印头收到 12bit*32=384 个点,即一行可打 32个字母,或16个宋体字。
字模存入 SPI FLASH 时,完成以上变换。打印时,16X16汉字按字节从RAM中读出再写入打印头,24X24汉字按16bit读出,写入打印头时只传低12位,减少了数据处理时间。
高速 SPI 接口传输数据
打印时,字模数据要从SPI FLASH W25Q16 中通过 SPI 接口读出,再通过另一个 SPI 接口传输给打印头。1个字符行有16个行点(16X16楷体字),或者24个行点(24X24 宋体字)
一行 16个宋体字有 16*96 = 1536 个字节。"字符行"与行之间一般空三行点,走纸最快时 90mm/秒,694us 走一行点,在这个时间内要读取所有 1536个字节,放入 RAM 打印缓冲区。代码中,把 SPI 配置成 28.8Mbps 从FLASH 中读取字模,为便于用示波器查看波形,每次收发 16bit, 中间插入一个空闲 CLK,收发完 1536 Byte 要经过 1536/2 = 768 次 17bit 时钟,时间为 768*17/28.8 = 453us。代码中,使能 SPI 的 FiFo,同时配置 PDMA 来完成 SPI 收发,读一行字符的1536个字节数据,时间连续,中间没有等待
打印头最快数据率是5Mbps, SPI 速率就配置为 4.8Mbps,一行384个点。数据传输时间约为 384/4.8 = 80us,走纸最快 90毫米/秒时,走一行点的时间是 694us,数据早传完了。走纸速度再快一倍也来得及。
USB 打印机模式
USB 打印模式,上位机传输过来的,是图形点阵数据与命令混在一起,无需从 SPI FLASH 中读字模,只要把点数据从USB数据流里分离出来,移入打印头即可。代码中定义了一个 4096 字节的环形缓冲区。
USB 数据中断: 分析数据流,见函数 PTR_Data_Receive(), 遇图形点阵数据流,写入环形缓冲区。遇命令立即执行,或为执行做好准备。若有打印命令或走纸命令,就把 “走纸行数” 通过全局变量 StepIncrease 传给主循环代码。
主循环里,1>若传过来的走纸行数 StepIncrease 不为0,就启动走纸。2>若已在走纸,就检查环形缓冲区是否有待打印数据,若有,就在纸每走过一行时,把数据送入打印头并加热打印。
走纸,加热和数据传输,三者同时处理的时序
需要走纸时,只要设定速度值全局变量 pStepM_TimLimit,然后调用走纸启动函数 PaperRollStart() 就开始走纸了,何时走下一行,何时停止,都在 Timer1 中断代码里处理。中断外面无需再处理走纸的事。
需要说明的是:有一个走纸剩余行数全局变量 RemainderStep, 在此变量非0时表明正在走纸,可以随时加大这个值,加长走纸行数。
再来看何时把数据串入打印头,何时加热,下图用鼠标点击可放大。
打印开始时,先启动Timer1中断处理走纸过程,然后启动SPI把第一行点数据,写入打印头,一行数据80us后传完,就等待纸走到第三行——前面空三行,只要一走到第三行,立即加热并启动定时,不等加热结束就去读写下一行点数据。
每次在走到新的一行点时(实际是步进电机走两步算一行), 都立即启动这一行数据的加热,加热开始后就立即去准备下一行点数据。 何时加热停止呢? 不用担心,由 Timer2 中断代码处理。
打印开始时,必须知道要走纸几行, 一行 16 X 16 字符,16行点,要走 32 步(行),一般还要加上开头和结尾的空行。
连续打印时,只要剩余行数 RemainderStep 不为0——走纸未停,可以随时增加这个值,加长走纸行数,继续打印后续数据。
由以上分析可知,走纸是独立的,想走多快,设定一个速度就可以了,走纸的同时,处理打印数据。所以,走纸有多快,打印就可以有多快!
|