• 方案介绍
  • 附件下载
  • 相关推荐
申请入驻 产业图谱

【嵌入式外设】 单片机驱动热敏打印机打印曲线/双曲线

08/15 08:59
656
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

联系方式.docx

共1个文件

一、前言

今天记录一下使用单片机驱动热敏打印机的功能,这篇是驱动打印曲线和双曲线,当然折现也可以实现的,主要用于记录思考过程,每款打印器的协议驱动可能不同,仅作参考

二、介绍

我使用的这款再淘宝上就可以购买到,这个有两种驱动方式,不过我使用的是串口进行通信控制

效果


单片机驱动答应及打印双曲线

关注微信公众号--星之援工作室 发送关键字(DP-EH700

代码含重要注释,开源,可自行移植
????452c0cf75b1d4e4895194df8a5022c34.png

三、思路

第一步,首先是前面的网格线,思路就是画一条长的平行线,然后在画横线,横线需要有一个间隔点进行区别
第二步,就是曲线部分,这部分比较复杂,但是拆分一下,实际上就是同时画两个点,因为打印机上都是像素点来模拟的,那么我们显示就需做一个同时画两点的函数,做完一个
第三步,也是比较麻烦的一步,我们需要如何才能得到一个看似曲线的线呢,首先需要理解到,曲线就是低到高再到低的过程,那么就好办了,我们可以采取点位进行控制,采取的分点位越多,那弧形就约平滑,
第四步,理解了这个形成之后,那如果我们的点位不够用的情况下,我们就可以采用 固定点-平均点-固定点 的思路 这个样也可以实现我们的曲线效果

四、代码

串口

这里我采用的是串口2进行驱动,代码的话就不附录了,比较基础。重点把这几个函数附录进去

/*********************************************************************************
 发送一个字节
**********************************************************************************/
void Usart_SendByte(USART_TypeDef *pUSARTx, uint8_t ch)
{
	/* 发送一个字节数据到USART */
	USART_SendData(pUSARTx, ch);

	/* 等待发送数据寄存器为空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
		;
}
/*********************************************************************************
 发送8位的数组
**********************************************************************************/
void Usart_SendArray(USART_TypeDef *pUSARTx, char *array, uint16_t num)
{

	uint8_t i;
	for (i = 0; i < num; i++)
	{
		/* 发送一个字节数据到USART */
		Usart_SendByte(pUSARTx, array[i]);
	}
	/* 等待发送完成 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET)
		;
}
/*********************************************************************************
发送字符串
**********************************************************************************/
void Usart_SendString(USART_TypeDef *pUSARTx, char *str)
{

	unsigned int k = 0;

	do
	{
		Usart_SendByte(pUSARTx, *(str + k));
		k++;
	} while (*(str + k) != '?');

	/* 等待发送完成 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET)
	{
	}
}

打印驱动函数

前期准备调用,为后续双曲线和表格做准备

// 打印机初始化
void printerInit() {
    uint8_t cmd[] = {0x1B, 0x40};  // ESC @
    sendData((char *)cmd, sizeof(cmd));
}
// 发送单字节
void sendByte(uint8_t b) {
    sendData((char*)&b, 1);
}

// 绘制单行的多条水平线段
// n: 本行条数, data[]: 按 [起点L 起点H 终点L 终点H] 顺序
void sendCurveLine(uint8_t n, uint8_t *data) {
    sendByte(0x1D);
    sendByte(0x27);
    sendByte(n);
    for (int i=0; i<n*4; i++) {
        sendByte(data[i]);
    }
}

// 绘制多条竖直线
// xStart: 第一个竖直线的 X 坐标
// count: 竖直线数量
// xGap: 相邻竖直线的间隔(水平点)
// yStart, yEnd: Y 坐标范围(点)
void drawVerticalLines(uint16_t xStart, uint8_t count, uint16_t xGap, uint16_t yStart, uint16_t yEnd) {
    uint8_t buf[4 * 8]; // 每行最多 8 条竖直线
    if (count > 8) count = 8;

    for (uint16_t y = yStart; y <= yEnd; y++) {
        uint8_t lineCount = 0;
        for (uint8_t i = 0; i < count; i++) {
            uint16_t x = xStart + i * xGap;
            buf[lineCount*4+0] = x & 0xFF;
            buf[lineCount*4+1] = x >> 8;
            buf[lineCount*4+2] = x & 0xFF;
            buf[lineCount*4+3] = x >> 8;
            lineCount++;
        }
        sendCurveLine(lineCount, buf);
    }
}
// 绘制 4 条竖直点线,第 1、3 条固定,第 2、4 条可变
// uint16_t *xPositions 可以考虑使用坐标
void drawVerticalDots(uint16_t yStart, uint16_t yEnd, 
                      uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4) {
    uint8_t buf[8];
    uint8_t n = 1; // 一行只画1段

    for (uint16_t y = yStart; y <= yEnd; y++) {
        // 1 固定第 1 条
        buf[0] = (uint8_t)(x1 & 0xFF);
        buf[1] = (uint8_t)(x1 >> 8);
        buf[2] = buf[0]; // 起始点 == 结束点
        buf[3] = buf[1];
        sendCurveLine(n, buf);

        // 2 可变第 2 条
        buf[0] = (uint8_t)(x2 & 0xFF);
        buf[1] = (uint8_t)(x2 >> 8);
        buf[2] = buf[0];
        buf[3] = buf[1];
        sendCurveLine(n, buf);

        // 3 固定第 3 条
        buf[0] = (uint8_t)(x3 & 0xFF);
        buf[1] = (uint8_t)(x3 >> 8);
        buf[2] = buf[0];
        buf[3] = buf[1];
        sendCurveLine(n, buf);

        // 4 可变第 4 条
        buf[0] = (uint8_t)(x4 & 0xFF);
        buf[1] = (uint8_t)(x4 >> 8);
        buf[2] = buf[0];
        buf[3] = buf[1];
        sendCurveLine(n, buf);
    }
}
// 画多条平行竖直线
// xPositions[]: 存放每条竖线的 X 坐标
// count: 竖线数量
// yStart, yEnd: Y 起止像素行
void drawMultipleVerticalLines(uint16_t *xPositions, uint8_t count, uint16_t yStart, uint16_t yEnd)
{
    uint8_t buf[64];

    for (uint16_t y = yStart; y <= yEnd; y++) {
        uint8_t lineCount = 0;

        // 每条竖线 1 个点
        for (uint8_t i = 0; i < count; i++) {
            uint16_t x = xPositions[i];
            buf[lineCount*4+0] = x & 0xFF;
            buf[lineCount*4+1] = x >> 8;
            buf[lineCount*4+2] = x & 0xFF;
            buf[lineCount*4+3] = x >> 8;
            lineCount++;
        }

        // 发送这一行的所有点
        sendCurveLine(lineCount, buf);
    }
}

// 绘制一条水平线
// startX: 线的起始 X 坐标
// endX: 线的结束 X 坐标
// y: 线的 Y 坐标
void drawHorizontalLine(uint16_t startX, uint16_t endX, uint16_t y) {
    uint8_t buf[4]; // 2条水平线 * 4字节

    // 确保起始点小于结束点
    if (startX > endX) {
        uint16_t temp = startX;
        startX = endX;
        endX = temp;
    }

    // 设置线的起点和终点
    buf[0] = startX & 0xFF;
    buf[1] = startX >> 8;
    buf[2] = endX & 0xFF;
    buf[3] = endX >> 8;

    // 发送绘制一条水平线的指令
    sendCurveLine(1, buf);
}

双曲线

可以拓展,我这里只体现同加同减方式,还有另外两种可以补充

// 计算曲线
// cvs 对应曲线的变量数据
void mathCvs(float cvs1,float cvs2,float cvs3,float cvs4){
	float x1,y1,z1;
	float x2,y2,z2;
	x1 = cvs1; // 赋值
	x2 = cvs3; // 赋值
	// 获取绝对值
	z1 = fabs(cvs1 - cvs2);
	z2 = fabs(cvs3 - cvs4);
	// 先判断 大小 分16段-小-中-平均值-中-小
	if(cvs1 < cvs2 && cvs3 < cvs4){
		// ++
		for(int i= 0;i <18;i++){
			if(i < 2){
				y1 = x1+1;
				y2 = x2+1;
			}
			else if(i < 4){
				y1 = x1+3;
				y2 = x2+3;
			}
			else if(i < 14){
				y1 = x1+(z1-16)/10.f;
				y2 = x2+(z2-16)/10.f;
			}
			else if(i < 16){
				y1 = x1+3;
				y2 = x2+3;
			}
			else if(i < 18){
				y1 = x1+1;
				y2 = x2+1;
			}
			drawHorizontalLine(x1, y1, 1);	
			x1=y1;
			drawHorizontalLine(x2+192, y2+192, 1);	
			x2=y2;
		}
	}else if(cvs1 > cvs2 && cvs3 > cvs4){
		// --
		for(int i= 0;i <18;i++){
			if(i < 2){
				y1 = x1-1;
				y2 = x2-1;
			}
			else if(i < 4){
				y1 = x1-3;
				y2 = x2-3;
			}
			else if(i < 14){
				y1 = x1-(z1-16)/10.f;
				y2 = x2-(z2-16)/10.f;
			}
			else if(i < 16){
				y1 = x1-3;
				y2 = x2-3;
			}
			else if(i < 18){
				y1 = x1-1;
				y2 = x2-1;
			}
			drawHorizontalLine(x1, y1, 1);	
			x1=y1;
			drawHorizontalLine(x2+192, y2+192, 1);	
			x2=y2;
		}
		
	}
}
	

整体调用

已经封装好了,直接需要调用的函数位置进行调用即可,直接输入变量数据即可

// 尝试曲线
void printfXYAxis(void){
  printerInit();

		// ===== 绘制X轴(第一列和第二列) =====
		drawHorizontalLine(0, 360, 1);	
		// 从顶部 0 像素开始画,8 条线,48 像素间隔,384 像素宽
		drawVerticalLines(0, 8, 48, 0, 10);
		mathCvs(0,100,20 ,160);
		mathCvs(100,50,160 ,50);
		mathCvs(50,130,50 ,150);
		mathCvs(130,80,150 ,20);
		mathCvs(80,100,20 ,30);


		printNewLine();
		printNewLine();
    printNewLine();
}

联系方式 微信号:13648103287

  • 联系方式.docx
    下载

相关推荐