/*
* printer.c
*
* Created on: 2023年5月8日
* Author: Ray July
*
*/
#include "sintt_app.h"
#include <string.h>
#pragma pack(1)
typedef struct {
unsigned short signature; // 文件类型,必须为"BM"
unsigned int filesize; // 文件大小,整个文件的大小
unsigned short reserved1; // 保留字段1,一般为0
unsigned short reserved2; // 保留字段2,一般为0
unsigned int dataoffset; // 数据偏移量,即图像数据相对于文件起始处的偏移
} BMPFileHeader;
typedef struct {
unsigned int headersize; // 头信息长度,对于Windows位图,一般为40
signed int width; // 图像宽度,单位为像素
signed int height; // 图像高度,单位为像素
unsigned short planes; // 图像平面数,一般为1
unsigned short bitdepth; // 每个像素所使用的位数,一般为24
unsigned int compression; // 图像数据的压缩方式,一般为0(表示不压缩)
unsigned int imagesize; // 图像数据的实际大小,以字节为单位
signed int horizontalres; // 水平分辨率,单位为像素每米
signed int verticalres; // 垂直分辨率,单位为像素每米
unsigned int numcolors; // 所有颜色的数量,0表示使用默认取值
unsigned int importantcolors; // 重要颜色的数量,0表示所有颜色都重要
} BMPInfoHeader;
#if __arm__
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<stdio.h>
#endif
// 将单色BMP图片转换为字节数组
int dataSize; // 图片数据大小
int rowSize; //图片宽Bit
int colheigth; //图片像素高
char* Bitmapdata; //图片数据指针
/*
设计标签
以下代码内容为一个最简单标签的必备要素,以此为例,详解设计标签时必备的内容和要点。
SIZE 58 mm,30 mm
GAP 2 mm
CLs
TEXT 50,50,"4",0,1,1,"DEMO FOR TEXT”
PRINT 1
一张标签通常包含三个部分,即系统设定(SIZE,GAP,CLS)、打印内容设定(TEXT)和执行打印指令(PRINT)。
系统设定包括标签尺寸(SIZE、GAP)和清除缓冲区数据指令(CLS)等。打印内容设定可以参考本文档卷标内容设计指令内容,本例中系打印文本。
执行打印指令用于打印出设计好的标签,在此指令发送后打印机才执行打印动作。需要特别注意,在每一条指令结尾需要加入换行符,即字符串“\rin”或16进制0xOD 0x0A
!!!!注意1mm=8bit
*/
void utf8_to_gb18030(const char *utf8, size_t utf8len, char *gb18030, size_t gb18030len) {
iconv_t cd = iconv_open("GB18030", "UTF-8");
char *inbuf = (char *)utf8;
size_t inbytesleft = utf8len;
char *outbuf = gb18030;
size_t outbytesleft = gb18030len * 2; // 每个汉字占两个字节,因此需要将 gb18030len 乘以 2
iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
iconv_close(cd);
}
struct printer {
char name[32];
uint8_t command[1024*1024+100];
int command_length;
};
// 打印初始化
void printer_init(struct printer *p) {
memset(p, 0, sizeof(struct printer));
strncpy(p->name, "标签模式", sizeof(p->name));
}
// 转化为命令数组
void printer_add_command(struct printer *p, const char *content, int length) {
memcpy(p->command + p->command_length, content, length);
p->command_length += length;
}
// 设置标签大小 @pageWidth:纸张宽度(单位mm)@pageHeight:纸张高度(单位mm)
void printer_set_size(struct printer *p, int pageWidth, int pageHeight) {
char data[32];
int length = snprintf(data, sizeof(data), "SIZE %d mm,%d mm\r\n", pageWidth, pageHeight);
printer_add_command(p, data, length);
}
// 设置标签间距 @gapDistance:纸张间距(单位mm)
void printer_set_gap(struct printer *p, int gapDistance) {
char data[32];
int length = snprintf(data, sizeof(data), "GAP %d mm\r\n", gapDistance);
printer_add_command(p, data, length);
}
//往前推指定距离 @n:1≤n≤9999,单位dot
void printer_feed(struct printer *p,int n){
char data[32];
int length = snprintf(data, sizeof(data), "FEED %d \r\n",n);
printer_add_command(p,data,length);
}
//往后卷指定距离 @n:1≤n≤9999,单位dot
void printer_backfeedup(struct printer *p,int n,int m){
char data[32];
int length = snprintf(data, sizeof(data), "BACKFEED %d BACKUP %d \r\n",n,m);
printer_add_command(p,data,length);
}
/*打印文本 参数说明@x:文字X方向起始点坐标 @y:文字Y方向起始点坐标
* @font:字体名称 1 8×12 dot英数字体,2 12×20 dot英数字体,3 16×24 dot英数字体,4 24×32 dot英数字体,5 32×48 dot英数字体,6 14×19 dot英数字体OCR-B,7 21×27 dot英数字体OCR-B,8 14×25 dot英数字体OCR-A,9 9×17 dot英数字体,10 12×24 dot英数字体
TST24.BF2繁体中文24×24Font(大五码)、TSS24.BF2:简体中文24×24Font(GB码) K:韩文24×24Font (KS码)
*@rotation文字旋转角度(顺时针方向):0 0度,90 90 度,180 180 度,270 270度
*@x-multiplication:X方向放大倍率1-10
*@y-multiplication:Y方向放大倍率1-10
*/
void printer_draw_text(struct printer *p, int x, int y, const char *font, int rotation, int x_mul, int y_mul, const char *text) {
char data[256];
char gb18030[256];
utf8_to_gb18030(text, strlen(text)+1, gb18030, sizeof(gb18030));
int length = snprintf(data, sizeof(data), "TEXT %d,%d,\"%s\",%d,%d,%d,\"%s\" \r\n", x, y, font, rotation, x_mul, y_mul, gb18030);
printer_add_command(p, data, length);
}
/*打印线条
*@x: 左上角X坐标,单位dot
*@y:线条左上角Y坐标,单位dot
*@width:线宽,单位dot
*@height:线高,单位dot
*/
void printer_draw_bar(struct printer *p, int x, int y, int width, int height){
char data[256];
int length = snprintf(data,sizeof(data), "BAR %d,%d,%d,%d,\r\n", x, y, width, height);
printer_add_command(p, data, length);
}
/*打印二维码
*@X:二维码水平方向起始点坐标
*@y:二维码垂直方向起始点坐标
*@ECC level:选择QRCODE纠错等级 L 7%,M 15%,Q 25%,H 30%
*@cell width:二维码宽度1-10
*@mode:手动/自动编码 A,Auto M,Manual
*@rotation:旋转角度(顺时针方向)0 0度,90 90 度,180 180度,270 270度
*@data string:编码的字符串
*/
void printer_draw_qrcode(struct printer *p, int x, int y, char ecclevel, int cellwidth, char mode, int rotation, const char *datastring){
char data[256];
int length = snprintf(data,sizeof(data), "QRCODE %d,%d,%c,%d,%c,%d,\"%s\"\r\n", x, y, ecclevel, cellwidth, mode, rotation, datastring);
printer_add_command(p, data, length);
}
/*打印一维条码
*@X:二维码水平方向起始点坐标
*@y:二维码垂直方向起始点坐标
*@codetype: 常用数字 39 常用字幕 128
*@height:条形码高度,以点(dot)表示
*@rotation:(顺时针方向)0 0度,90 90 度,180 180度,270 270度
*@narrow:窄bar宽度,以点(dot)表示
*@wide:宽bar宽度,以点(dot)表示
*@content:条码文本 */
void printer_draw_barcode(struct printer *p, int x, int y, char *codetype, int height, int humanreadable, int rotation, int narrow, int wide, char *content){
char data[256];
int length = snprintf(data,sizeof(data), "BARCODE %d,%d,\"%s\",%d,%d,%d,%d,%d,\"%s\"\r\n", x, y, codetype, height, humanreadable, rotation, narrow, wide, content);
printer_add_command(p, data, length);
}
//打印图片,图片需要已经下载到打印缓存(有些打印机不支持)
void printer_putbmp(struct printer *p, int x, int y, char *filename){
char data[256];
int length = snprintf(data,sizeof(data), "PUTBMP %d,%d,\"%s\"\r\n", x, y, filename);
printer_add_command(p, data, length);
}
//指定区域反向打印
void printer_reverse(struct printer *p, int x_start, int y_start, int x_width, int y_height){
char data[256];
int length = snprintf(data,sizeof(data), "REVERSE %d,%d,%d,%d\r\n", x_start, y_start, x_width, y_height);
printer_add_command(p, data, length);
}
//绘制方框 单位都是dos
void printer_box(struct printer *p, int X_start, int Y_start, int X_end, int Y_end, int linethickness) {
char data[32];
int length = snprintf(data, sizeof(data), "BOX %d,%d,%d,%d,%d\r\n", X_start,Y_start,X_end,Y_end,linethickness);
printer_add_command(p, data, length);
}
//打印指令
void printer_print(struct printer *p, int m, int n) {
char data[64];
int length = snprintf(data, sizeof(data), "PRINT %d,%d\r\n", m, n);
if (length >= sizeof(data)) {
printf("命令缓冲区空间不足!\n");
return;
}
printer_add_command(p, data, length);
}
//切断参数
void printer_cutter(struct printer *p, char *OFForBATCHorPieces){
char data[32];
int length = snprintf(data, sizeof(data), "SET CUTTER \"%s\"\r\n",OFForBATCHorPieces);
printer_add_command(p, data, length);
}
//设置到间隙处
void printer_tear(struct printer *p, char *tearONorOFF){
char data[32];
int length = snprintf(data, sizeof(data), "SET TEAR \"%s\"\r\n",tearONorOFF);
printer_add_command(p, data, length);
}
//数据取反函数
void invertBytes(char* array, int length) {
for (int i = 0; i < length; i++) {
array[i] = ~array[i];
}
}
/*位图打印指令(不包含数据部分) 位图与windos单色位图黑白是相反的 请自行修改
* !!如果难以修改 请不要把位图数据取反invertBytes() 请修改位图像素宽度为32的倍数把图片镜像翻转即可正常打印
*@X:位图水平方向起始点坐标
*@y:位图垂直方向起始点坐标
*@width:水平方向位图的宽度,单位 byte(bmpToByteArray自动计算)
*@height:位图的高度,单位dot(bmpToByteArray自动计算)
*/
void printer_bitmap(struct printer *p, int x, int y, int width, int height) {
char command[32];
int length=snprintf(command, sizeof(command),"BITMAP %d,%d,%d,%d,0,", x, y, width, height);
printer_add_command(p, command,length);
}
//读取bmp函数 注意!!!bmp图片大小不宜超过1M(如超过1M图片,请重新改写打印指令内存)
void bmpToByteArray(const char* filename)
{
//构建bmp文件结构体和信息结构体
BMPFileHeader BMPFileHeader;
BMPInfoHeader BMPInfoHeader;
//打开文件
FILE* file = fopen(filename, "rb"); // 以二进制只读模式打开文件
if (!file)
{
printf("无法打开文件:%s\n", filename);
return NULL;
}
//读头文件结构体数据
fread(&BMPFileHeader, 1,sizeof(BMPFileHeader), file); // 读取BMP文件头
// 移动文件指针到信息结构体
fseek(file, sizeof(BMPFileHeader), SEEK_SET);
fread(&BMPInfoHeader, 1,sizeof(BMPInfoHeader), file);
if (BMPFileHeader.signature != 0x4D42 || BMPInfoHeader.planes != 1)
{
printf("不是单色BMP图片\n");
fclose(file);
return NULL;
}
// 移动文件指针到像素数据的位置
fseek(file, BMPFileHeader.dataoffset, SEEK_SET);
// 计算像素数据所占字节数(win位图宽不足4个字节补齐4个字节)
//如果是用bitmap指令打印 如果宽度像素不是32的倍速 自动补齐部分会是一条黑线
rowSize = ((BMPInfoHeader.width + 31) / 32) * 4;
colheigth=BMPInfoHeader.height;
//数据的总字节数
dataSize = rowSize * BMPInfoHeader.height;
// 动态分配内存来存储像素数据
Bitmapdata=(char*)malloc(dataSize);
// 读取像素数据
readsize=fread(Bitmapdata,1,dataSize,file);
//关闭文件
fclose(file);
}
void saveByteArrayToFile(const char* filename, const uint8_t* byteArray, int32_t size)
{
FILE* file = fopen(filename, "w"); // 以写入模式打开文件
if (!file)
{
PRINTF("无法打开文件:%s\n", filename);
perror("无法打开文件");
return;
}
// 逐个字节写入文件
for (int i = 0; i < size; i++)
{
fprintf(file, "%d ", byteArray[i]);
}
fclose(file);
}
//标签打印组合
void printer_label(){
struct printer p;
printer_init(&p);
printer_set_size(&p, 60,100 ); // 设置打印机尺寸为60mm x 100mm
printer_set_gap(&p, 2); //设置打印间距为2mm
printer_cutter(&p, "BATCH"); // 设置切刀模式为批量模式
printer_tear(&p,"ON"); // 打开撕纸功能
printer_add_command(&p, "CLS\r\n", 5); // 添加打印机命令"CLS"(清除缓冲区)到打印机对象p中
uart_obj1.mSend(&uart_obj1, p.command, p.command_length);
#if __arm__
int fd = open("/dev/lp0",O_RDWR);
if(fd){
int ret = write(fd, p.command,p.command_length);
close(fd);
}
#endif
};
//标签打印组合
void printer_label1(){
struct printer p;
printer_init(&p);
printer_set_size(&p, 60,100 ); // 设置打印机尺寸为60mm x 100mm
printer_set_gap(&p, 2); //设置打印间距为2mm
printer_cutter(&p, "BATCH"); // 设置切刀模式为批量模式
printer_tear(&p,"ON"); // 打开撕纸功能
printer_add_command(&p, "CLS\r\n", 5); // 添加打印机命令"CLS"(清除缓冲区)到打印机对象p中
printer_draw_text(&p, 32, 14+50, "TSS24.BF2", 0, 3, 3, "标签");
printer_draw_text(&p, 52, 118+50, "TSS24.BF2", 0, 1, 1, "商品标签");
printer_draw_text(&p, 20, 170+50, "TSS24.BF2", 0, 1, 1, "名称");
printer_draw_text(&p, 220, 110+50, "2", 0, 1, 1, "1-DN-223L-00002");
printer_draw_qrcode(&p,300,70,'L',3,'A',0,"simtutai.com");
printer_print(&p, 1, 1);
uart_obj1.mSend(&uart_obj1, p.command, p.command_length);
#if __arm__
int fd = open("/dev/lp0",O_RDWR);
if(fd){
int ret = write(fd, p.command ,p.command_length);
close(fd);
}
#endif
}
//标签打印组合
void printer_label2(){
//图片路径 此路径为arm下图片路径 bmp单色图放图片文件夹即可
#ifdef __arm__
bmpToByteArray("/customer/prm/images/QQ.bmp");
#else
//图片路径 此路径为win下图片路径
bmpToByteArray("C:/Users/zzzlll/Desktop/QQ.bmp");
#endif
struct printer p;
printer_init(&p);
printer_set_size(&p, 20,20 ); // 设置打印机尺寸为60mm x 100mm
printer_set_gap(&p, 2); //设置打印间距为2mm
printer_add_command(&p, "CLS\r\n", 5); // 添加打印机命令"CLS"(清除缓冲区)到打印机对象p中
printer_bitmap(&p,100,20,rowSize,colheigth);
invertBytes(Bitmapdata,rowSize*colheigth);
printer_add_command(&p, Bitmapdata,rowSize*colheigth);
free(Bitmapdata);
printer_add_command(&p, "\r\n", 2);
printer_print(&p, 1, 1);
#if __arm__
int fd = open("/dev/lp0",O_RDWR);
if(fd){
int ret = write(fd,p.command,p.command_length);
//invertBytes(temp, 3200);
// ret = write(fd, temp ,3200);
close(fd);
}
#endif
}
/* do something for Button的点击事件*/
/* struct printer p;
printer_init(&p);
printer_box(&p,0,50,480,450,4); // 在标签上绘制一个矩形框(左上角坐标为(0, 50),宽度为480,高度为450,线宽为4)
// 以下多行代码用于在标签上绘制一系列的水平线条
printer_draw_bar(&p,0,100+50,200,4);
printer_draw_bar(&p,0,160+50,480,4);
printer_draw_bar(&p,0,200+50,480,4);
printer_draw_bar(&p,0,240+50,480,4);
printer_draw_bar(&p,0,280+50,480,4);
printer_draw_bar(&p,0,320+50,480,4);
printer_draw_bar(&p,0,360+50,480,4);
// 以下多行代码用于在标签上绘制一系列的垂直线条
printer_draw_bar(&p,200,50,4,160);
printer_draw_bar(&p,80,160+50,4,240);
printer_draw_bar(&p,240,200+50,4,200);
printer_draw_bar(&p,320,200+50,4,200);
printer_draw_text(&p, 32, 14+50, "TSS24.BF2", 0, 3, 3, "标签");
printer_draw_text(&p, 52, 118+50, "TSS24.BF2", 0, 1, 1, "商品标签");
printer_draw_text(&p, 20, 170+50, "TSS24.BF2", 0, 1, 1, "名称");
printer_draw_text(&p, 220, 110+50, "2", 0, 1, 1, "1-DN-223L-00002");
printer_draw_qrcode(&p,300,70,'L',3,'A',0,"simtutai.com");
printer_print(&p, 1, 1);
printer_set_size(&p, 60,100 );
printer_set_gap(&p, 2);
printer_add_command(&p, "CLS\r\n", 5);
// printer_download(&p,"imageTest.BMP");
// printer_putbmp(&p,50,50,"imageTest.BMP" );
// printer_reverse(&p,50,560,240,240);
//printer_draw_bar(&p,50,640,8,240);
// printer_draw_text(&p, 50, 160, "TSS24.BF2", 0, 1, 1, "武汉鑫通态");
// printer_draw_barcode(&p,50,240,"39",96,1,0,2,4,"1000");
// printer_draw_barcode(&p,50,560,"128",48,1,0,2,2,"ABCD101EFGH");
// printer_draw_qrcode(&p,50,400,'L',3,'A',0,"www.3c");
// printer_print(&p, 1);
struct printer p;
printer_init(&p);
printer_set_size(&p, 60,100 );
printer_set_gap(&p, 2);
printer_feed(&p,800);
uart_obj1.mSend(&uart_obj1, p.command, p.command_length);
struct printer p;
printer_init(&p);
printer_set_size(&p, 60,100 );
printer_set_gap(&p, 2);
printer_backfeedup(&p,800,800);
uart_obj1.mSend(&uart_obj1, p.command, p.command_length);
// 打印指令集合
for (int i = 0; i < p.command_length; i++) {
PRINTF("%02X ", p.command[i]);
}
PRINTF("\n");
uart_obj1.mSend(&uart_obj1, p.command, p.command_length);
*/
————————————————
版权声明:本文为CSDN博主「花生保安队队长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_59609466/article/details/132161358
嵌入式c/c++打印机标准指令TSPL指令书写
于 2023-08-08 10:26:09 首次发布