Test.txt内容:
参考打印到文档功能:
初识打印机驱动
http://www.cnblogs.com/MrDing/p/4078189.html
热敏打印头打印原理和C实现黑白位图的放大
https://www.jianshu.com/p/c754bfa377e4
ascii码 :
十六进制 | 十进制 | 字符 | 含义 |
---|---|---|---|
0a | 10 | \n | LF |
0d | 13 | \r | CR |
1b | 27 | esc | |
1d | 29 | gs |
热敏打印机参数:
首先佳博GP-L80180I票据打印机技术参数
打印方式 | 直接热敏式 |
---|---|
打印密度 | 576点/行或512点/行 |
打印速度 | 180毫米/秒 |
接口类型 | 串口+USB+网口 |
打印纸宽 | 79.5±0.5毫米 |
纸张厚度 | 0.06~0.08毫米 |
纸卷外径 | 83毫米 |
可靠性 | 100公里 |
使用字库 | 简体中文GB18030大字库 |
条形码类型 | UPC-A/UPC-E/JAN13(EAN13)/JAN8(EAN8)/CODE39/ITF/CODABAR/CODE93/CODE128 |
字符大小 | ANK字符:FontA:12×24点 FontB:9×17点 简体/繁体:24×24点 |
打印命令 | 兼容ESC/POS命令 |
log与流程的对应关系:
对应的代码如下:
// 打印头宽度约为 80mm 的打印函数
BOOL USB_GPL801_PrintInStandardMode80(void)
{
int ret ;
ret = VC_POS_Reset();
printf("VC_POS_Reset ret = %d\r\n",ret);
VC_POS_FeedLine();
VC_POS_FeedLine();
//VC_POS_PreDownloadBmpToRAM("a.BMP",3);
ret = VC_POS_PreDownloadBmpToRAM("Kitty.bmp",3);
printf("VC_POS_PreDownloadBmpToRAM ret = %d\r\n",ret);
int nRet = VC_POS_SetMotionUnit(180, 180);
if(POS_SUCCESS != nRet)
{
return false;
}
VC_POS_SetMode(POS_PRINT_MODE_STANDARD);
VC_POS_FeedLine();
VC_POS_FeedLine();
VC_POS_FeedLine();
VC_POS_S_TextOut("通行卡ID:", 70, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_S_TextOut("3303000012345678", 190, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_FeedLine();
VC_POS_S_TextOut("入口时间:", 70, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_S_TextOut("2018-04-20 10:10:10", 190, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_FeedLine();
VC_POS_S_TextOut("金额:", 70, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_S_TextOut("86.00元", 190, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_FeedLine();
VC_POS_S_TextOut("车牌:", 70, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_S_TextOut("鲁A66001[蓝色]", 190, 1, 1, POS_FONT_TYPE_CHINESE,
POS_FONT_STYLE_NORMAL);
VC_POS_FeedLine();
VC_POS_FeedLine();
//VC_POS_S_PrintBmpInRAM(3,20,POS_BITMAP_PRINT_NORMAL);
VC_POS_S_PrintBmpInRAM(3,20,POS_BITMAP_PRINT_QUADRUPLE);
VC_POS_FeedLine();
VC_POS_FeedLine();
VC_POS_FeedLine();
VC_POS_FeedLine();
VC_POS_FeedLine();
VC_POS_FeedLine();
// 切纸
VC_POS_CutPaper(POS_CUT_MODE_FULL, 0);
return TRUE;
}
设置的太小,容易丢数据
log如下:
打印出来的效果如下:
下面开始分析:
1b 40
0a 0a —– 两次换行
1d 23 03
应该是 定义 ID号为03
1d 2a 10 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
x = 0x10
y = 0x06
下面的是位图数据:
101x46像素
这个文件头 54个字节 可能是理解不对
发送的数据 和 bmp 的数据 有点不一致 ,有空分析一下
16 x 6 x 8 = 768个字节
24 x 32 = 768 字节
继续下面的操作:
1d 50 b4 b4 1b 53 0a 0a 0a
1b 24 46 00 1b 4d 03
1d 42 00
1d 62 00
1d 21 00
1b 45 00
1b 7b 00
1b 2d 00
1c 2d 00
1b 56 00
cd a8 d0 d0 bf a8 49 44 3a
1b 24 be 00
1b 4d 03
1d 42 00
1d 62 00
1d 21 00
1b 45 00
1b 7b 00
1b 2d 00
1c 2d 00 1b 56 00
33 33 30 33 30
30 30 30 31 32 33 34 35 36 37 38 0a
1b 24 46 00
1b 4d 03 1d 42 00 1d 62 00 1d 21 00 1b 45 00 1b
7b 00 1b 2d 00 1c 2d 00 1b 56 00
c8 eb bf da ca b1 bc e4 3a
1b 24 be 00 1b 4d 03 1d 42 00 1d 62
00 1d 21 00 1b 45 00 1b 7b 00 1b 2d 00 1c 2d 00 1b 56 00
32 30 31 38 2d 30 34 2d 32 30 20 20 31
30 3a 31 30 3a 31 30 0a
1b 24 46 00 1b 4d 03 1d 42 00 1d 62 00 1d 21 00 1b 45 00 1b 7b 00 1b 2d
00 1c 2d 00 1b 56 00 bd f0 b6 ee 3a
1b 24 be 00 1b 4d 03 1d 42 00 1d 62 00 1d 21 00 1b 45 00 1b
7b 00 1b 2d 00 1c 2d 00 1b 56 00 38 36 2e 30 30 d4 aa 0a
1b 24 46 00
1b 4d 03 1d 42 00 1d 62 00
1d 21 00 1b 45 00 1b 7b 00 1b 2d 00 1c 2d 00 1b 56 00 b3 b5 c5 c6 3a
1b 24 be 00
1b 4d 03 1d 42
00 1d 62 00 1d 21 00 1b 45 00 1b 7b 00 1b 2d 00 1c 2d 00
1b 56 00
c2 b3 41 36 36 30 30 31 5b c0
b6 c9 ab 5d 鲁A66001[蓝色]
0a 0a
1b 24 14 00 1d 23 03 1d 2f 03 0a 0a 0a 0a 0a 0a 1d 56 00
1d 50 b4 b4
1b 53
1b 24 46 00
0x46 = 70
1b 4d 03 选择中文 字体
1d 42 00
1d 62 00 —- 这个不知道
1d 21 00
1b 45 00
1b 7b 00
1b 2d 00
1c 2d 00
1b 56 00
cd a8 d0 d0 bf a8 49 44 3a
http://www.mytju.com/classcode/tools/encode_gb2312.asp
1b 24 be 00
VC_POS_S_PrintBmpInRAM(3,20,POS_BITMAP_PRINT_QUADRUPLE);
1b 24 14 00
1d 23 03 --- 选择ID 03
1d 2f 03 0a 0a 0a 0a 0a 0a 1d 56 00
1d 2f 03
1d 56 00
《佳博热敏票据打印机编程手册.pdf》有二维码指令 (实验没有成功)
page49
直接USB发送ESCPOS指令代码
win32 工程 vs2013
该代码 打印 二维码 没有成功
佳博GP-L80180 热敏打印机
GPL80_ESCPOS_USB.cpp
代码如下:
// GPL80_ESCPOS_USB.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <string>
#include <IOSTREAM>
#include <winioctl.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
using namespace std;
// SetupDiGetInterfaceDeviceDetail所需要的输出长度,定义足够大
#define INTERFACE_DETAIL_SIZE (1024)
//设备数量上限,假设16台上限
#define MAX_DEVICE 16
//USB类的GUID
const GUID USB_GUID = { 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } };
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath);
////////////////////////////////////////////////////////////////////////////////////////////////////////
//获取CreateFile的USB端口号
////////////////////////////////////////////////////////////////////////////////////////////////////////
// 根据GUID获得设备路径
// lpGuid: GUID指针
// pszDevicePath: 设备路径指针的指针,用于返回找到的路径
// 返回: 成功得到的设备路径个数,可能不止1个
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath)
{
HDEVINFO hDevInfoSet;
SP_DEVINFO_DATA spDevInfoData;
SP_DEVICE_INTERFACE_DATA ifData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
int nCount;
int nTotle;
BOOL bResult;
TCHAR* strUSBPrint = TEXT("USB 打印支持");
// 取得一个该GUID相关的设备信息集句柄
hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, // class GUID
NULL, // 无关键字
NULL, // 不指定父窗口句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
// 失败...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
printf("failed \r\n");
return 0;
}
// 申请设备接口数据空间
pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
nTotle = -1;
nCount = 0;
bResult = TRUE;
// 设备序号=0,1,2... 逐一测试设备接口,到失败为止
while (bResult)
{
nTotle++;
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
// 枚举符合该GUID的设备接口
bResult = ::SetupDiEnumDeviceInfo(
hDevInfoSet, // 设备信息集句柄
(ULONG)nTotle, // 设备信息集里的设备序号
&spDevInfoData); // 设备接口信息
if (bResult)
{
DWORD DataT;
TCHAR buf[MAX_PATH];
DWORD nSize = 0;
// get Friendly Name or Device Description
if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
}
else if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) {
}
else {
lstrcpy(buf, _T("Unknown"));
}
_tprintf(_T("buf = %s \r\n"), buf);
//是否是要找的设备类型
if (_tcscmp(buf, strUSBPrint) != 0)
continue;
_tprintf(_T("OK\r\n"));
ifData.cbSize = sizeof(ifData);
// 枚舉符合該GUID的設備接口
bResult = ::SetupDiEnumDeviceInterfaces(
hDevInfoSet, // 設備信息集句柄
NULL, // 不需額外的設備描述
lpGuid, // GUID
(ULONG)nTotle, // 設備信息集里的設備序號
&ifData); // 設備接口信息
if (bResult)
{
// 取得该设备接口的细节(设备路径)
bResult = SetupDiGetInterfaceDeviceDetail(
hDevInfoSet, // 设备信息集句柄
&ifData, // 设备接口信息
pDetail, // 设备接口细节(设备路径)
INTERFACE_DETAIL_SIZE, // 输出缓冲区大小
NULL, // 不需计算输出缓冲区大小(直接用设定值)
NULL); // 不需额外的设备描述
if (bResult)
{
// 复制设备路径到输出缓冲区
::_tcscpy_s(pszDevicePath[nCount],256, pDetail->DevicePath);
// 调整计数值
nCount++;
_tprintf(_T("Cnt = %d,pDetail->DevicePath =%s\r\n"), nCount, pDetail->DevicePath);
}
}
}
}
// 释放设备接口数据空间
::GlobalFree(pDetail);
// 关闭设备信息集句柄
::SetupDiDestroyDeviceInfoList(hDevInfoSet);
return nCount;
}
HANDLE hPort = NULL; //句柄
int WriteData(string meg)
{
DWORD dwWrite;
return WriteFile(hPort, meg.c_str(), (DWORD)meg.length(), &dwWrite, NULL);
}
int WriteBuf(char *buf, int len)
{
DWORD dwWrite;
return WriteFile(hPort, buf, len, &dwWrite, NULL);
}
int POS_Reset(void)
{
string s;
s = "\x1B\x40";
WriteData(s);
return 0;
}
int POS_FeedLine(void)
{
string s;
s = "\x0A";
WriteData(s);
return 0;
}
int POS_SetMotionUnit(int x,int y)
{
string s;
s = "\x1D\x50\xB4\xB4";
WriteData(s);
s = "\x1B\x53";
WriteData(s);
return 0;
}
int POS_S_TextOut(string &abc)
{
string s;
char SetAbsPos[4] = {0x1B,0x24,0x46,0x00};
WriteBuf(SetAbsPos,4);
char SelctFontType[3] = { 0x1B, 0x4D, 0x03 };
WriteBuf(SelctFontType, 3);
char SelctOutMode[3] = { 0x1D, 0x21, 0x00 };
WriteBuf(SelctOutMode, 3);
WriteData(abc);
return 0;
}
int POS_CutPaper()
{
char CutPaperMode[4] = { 0x1D, 0x56, 0x41,0x00 };
WriteBuf(CutPaperMode, 4);
return 0;
}
int POS_OutQRCode()
{
char QRCode1[8] = { 0x1d, 0x28 ,0x6b ,0x03, 0x00, 0x31 ,0x43, 0x05 };
char QRCode2[16] = { 0x1d, 0x28, 0x6b, 0x0b, 0x00, 0x31, 0x50, 0x30, 0x47, 0x70, 0x72, 0x69,
0x6e, 0x74, 0x65, 0x72 };
char QRCode3[8] = { 0x1d, 0x28, 0x6b, 0x03, 0x00, 0x31, 0x51, 0x30 };
WriteBuf(QRCode1, 8);
WriteBuf(QRCode2, 16);
WriteBuf(QRCode3, 8);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
//遍历USB设备,找到POS打印机路径
int i, nDevice;
TCHAR * szDevicePath[MAX_DEVICE]; // 设备路径
// string Port; //串口端口号
setlocale(LC_CTYPE, "chs");//设置中文字符
TCHAR * Port;
// 分配需要的空间
for (i = 0; i < MAX_DEVICE; i++)
{
szDevicePath[i] = new TCHAR[256];
}
// 取设备路径
nDevice = GetDevicePath((LPGUID)&USB_GUID, szDevicePath);
i = 0;
while (i < nDevice){
Port = szDevicePath[i++];
_tprintf(_T("device.Port = %s\n"), Port);
}
hPort = CreateFile(Port, GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hPort == INVALID_HANDLE_VALUE)
{ // 打开端口失败
return false;
}
DWORD iBytesLength;
string s;
POS_Reset();
POS_FeedLine();
POS_FeedLine();
POS_SetMotionUnit(180, 180);
s = "你好";
POS_S_TextOut(s);
POS_FeedLine();
s = "123abc";
POS_S_TextOut(s);
POS_FeedLine();
s = "666";
POS_S_TextOut(s);
POS_FeedLine();
POS_FeedLine();
POS_OutQRCode();
//s = "777";
//POS_S_TextOut(s);
POS_FeedLine();
POS_FeedLine();
POS_FeedLine();
POS_FeedLine();
POS_CutPaper();
return 0;
}
打印效果: