嵌入式c/c++打印机标准指令TSPL指令书写

/*
 * 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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值