简介:

随着我国国民经济的快速发展,生活节奏不断加快,生活方式发生变化,人们花在厨房里的时间越来越少,对冷冻,冷藏食品的需求大幅上涨.据数据显示我国的冷藏冷冻食品的总量以每年10%的比例增长,冷藏冷冻食品的销售量占到食品销售总量的10%左右.初级农产品,各类水产品,速冻食品,包装熟食,奶制品的产量和流通量逐年增加,相关的冷链物流运作越来越受到关注,冷链物流对保持食品和药品等敏感物品的新鲜度和有效性至关重要;
本文介绍了一种冷链记录仪方案:记录仪采用GX75C/GX311/GXHT30等传感器、精确采集温度/温湿度记录、并自动生成报表的方案,通过USB插入电脑导出PDF文件即可清楚的知道物流、存储的每个环节的温度、湿度有无异常、确保没有发生食品变质的问题;

在这里插入图片描述

技术指标

在这里插入图片描述

原理设计

USB数据记录仪比较重要的几个指标如下:
温度精度:温度传感器采用GX311D,最低测温可达-55℃,低温精度±0.3℃,常温精度可达±0.1℃
湿度精度:GXM052U-2支持湿度采集、传感器采用GXHT30,湿度精度3%
待机功耗:由于记录仪需要纽扣电池供电长期工作,因此功耗特别重要,本方案可在极短的时间内精确采集温湿度后立即进入睡眠模式,5分钟周期的平均功耗低至8uA,可连续工作一年 以上;
数据容量:数据采用外置FLASH,可记录30000条数据,并生成PDF文件,通过USB插入电脑即可导出PDF报告
时钟精度:采用外置32.768k石英晶体,精度12ppm;
在这里插入图片描述

PDF报告

在这里插入图片描述
在这里插入图片描述

软件方案

MCU采用合宙AIR32F103:
*fatfs文件系统、
*USBdevice ;
*PDF0.0.4;

在#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "pdflib.h"
#include "./flash/bsp_spi_flash.h"

static char pdf_buf[1024];

#define LPDF_VERSIOIN_TEXT          "0.0.4"
#define LPDF_FILE_HEADER_LEN        15
#define LPDF_BASEFONT_NUM           14

const char LPDF_FILE_HEADER[] = "%%PDF-1.4\n%%\xAA\xBB\xCC\xDD\n";

const char *font_list[] = {
    "Courier",
    "Courier-Bold",
    "Courier-Oblique",
    "Courier-BoldOblique",
    "Helvetica",
    "Helvetica-Bold",
    "Helvetica-Oblique",
    "Helvetica-BoldOblique",
    "Times-Roman",
    "Times-Bold",
    "Times-Italic",
    "Times-BoldItalic",
    "Symbol",
    "ZapfDingbats",
    NULL
};



const char * LPDF_GetVersion(void)
{
    return LPDF_VERSIOIN_TEXT;
}

LPDF_BOOL LPDF_HasDoc(LPDF_Doc pdf)
{
    if(!pdf)
        return LPDF_FALSE;

    if(pdf->error != LPDF_NOERROR) 
    {
        return LPDF_FALSE;
    } 
    else
        return LPDF_TRUE;
}
LPDF_Doc LPDF_New(void)
{
		static LPDF_Doc_Rec pdf;
		LPDF_INT length = 0, i = 0;
		LPDF_UINT writeBytes = 0;
		FRESULT fr;
		char name[64];
		sprintf(name,"1:%d.pdf",atoi(flash_cfg.device_id));
		fr = LPDF_FOPEN(&pdf.file,name,FA_CREATE_ALWAYS|FA_WRITE);
		if(fr)
		{
			return NULL;
		}
		LPDF_PRINTF("create tmp.pdf ok!\r\n");


    LPDF_FPRINTF(&pdf.file,LPDF_FILE_HEADER);   /* 写入文件头 */
    pdf.offset = LPDF_FILE_HEADER_LEN;
		LPDF_PRINTF("LPDF_FPRINTF!\r\n");
		
    pdf.obj[0].offset = pdf.offset;
    length = LPDF_SPRINTF(pdf_buf,"1 0 obj\n<<\n/Type /Catalog\n/Pages 17 0 R\n>>\nendobj\n\n");
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;
    
    pdf.obj[1].offset = pdf.offset;
    length = LPDF_SPRINTF(pdf_buf,"2 0 obj\n<<\n/Creator (light pdf library %s)\n"
                    "/Auther (anobodykey)\n>>\nendobj\n\n",LPDF_VERSIOIN_TEXT);
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;
    
    for(i = 0; i < LPDF_BASEFONT_NUM-2; i++)
    {
        pdf.obj[2+i].offset = pdf.offset;
        length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n"
                        "/BaseFont /%s\n/Encoding /WinAnsiEncoding\n>>\n"
                        "endobj\n\n",3+i,font_list[i]);
        LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
        pdf.offset += length;
    }
    for(; i < LPDF_BASEFONT_NUM; i++)
    {
        pdf.obj[2+i].offset = pdf.offset;
        length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n"
                        "/BaseFont /%s\n>>\nendobj\n\n",3+i,font_list[i]);
        LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
        pdf.offset += length;
    }
    /* 添加中文字体,只支持一种 */
    pdf.obj[2+i].offset = pdf.offset;
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /Type0\n"
                        "/BaseFont /SimSun\n/Encoding /GB-EUC-H\n/DescendantFonts [ %d 0 R ]\n"
                        ">>\nendobj\n\n",3+i,4+i);
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    pdf.obj[3+i].offset = pdf.offset;
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Font\n/Subtype /CIDFontType0\n"
                        "/BaseFont /SimSun\n/DW 1000\n/DW2 [ 880 -1000 ]\n"
                        "/W [ 668 [ 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 ]",4+i);
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    length = LPDF_SPRINTF(pdf_buf," 696 [ 500 500 500 500 ] 814 [ 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500");
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    length = LPDF_SPRINTF(pdf_buf," 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500");
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    length = LPDF_SPRINTF(pdf_buf," 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500");
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    length = LPDF_SPRINTF(pdf_buf," 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 ] 7716 [ 500 ] ]\n");
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    length = LPDF_SPRINTF(pdf_buf,"/FontDescriptor %d 0 R\n/CIDSystemInfo <<\n/Registry (Adobe)\n"
                        "/Ordering (GB1)\n/Supplement 0\n>>\n>>\nendobj\n\n",5+i);
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    pdf.obj[4+i].offset = pdf.offset;
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /FontDescriptor\n/FontName /SimSun\n/Ascent 859\n"
                        "/Descent -140\n/CapHeight 683\n/MissingWidth 500\n/Flags 7\n"
                        "/FontBBox [ 0 -140 996 855 ]\n/ItalicAngle 0\n/StemV 78\n>>\nendobj\n\n",5+i);
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;

    pdf.objNumber = 6+i; /* 空出5+i留作pages对象 */
    pdf.pagesNumber = 5+i; /* 记录pages对象的目标号 */

    pdf.obj[0].offset = pdf.offset;
    length = LPDF_SPRINTF(pdf_buf,"1 0 obj\n<<\n/Type /Catalog\n/Pages %d 0 R\n>>\nendobj\n\n",pdf.pagesNumber+1);
    LPDF_FWRITE(&pdf.file,pdf_buf,length,&writeBytes);
    pdf.offset += length;
		
    return (LPDF_Doc)&pdf;
}

LPDF_STATUS LPDF_SaveToFile(LPDF_Doc pdf,const char *file_name)
{
    LPDF_UINT16 i = 0, child_pages = 0;
    LPDF_INT length = 0;
		LPDF_UINT writeBytes = 0;

    pdf->obj[pdf->pagesNumber].offset = pdf->offset;
    
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Pages\n/Kids [ ",pdf->pagesNumber+1);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    for(i = pdf->pagesNumber+1; i < pdf->objNumber; i++)
    {
		if(LPDF_OBJ_PAGE == pdf->obj[i].type)
		{
			length = LPDF_SPRINTF(pdf_buf,"%d 0 R\n",i+1);
        	LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
        	pdf->offset += length;
			child_pages += 1;
		}
    }
    length = LPDF_SPRINTF(pdf_buf,"]\n/Count %d\n>>\nendobj\n\n",child_pages);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    
    LPDF_FPRINTF(&pdf->file,"xref\n0 %d\n0000000000 65535 f\r\n",pdf->objNumber+1);
    for(i = 0 ; i < pdf->objNumber; i++)
    {
        LPDF_FPRINTF(&pdf->file,"%010d 00000 n\r\n",pdf->obj[i].offset);
    }
    LPDF_FPRINTF(&pdf->file,"trailer\n<<\n/Size %d\n/Root 1 0 R\n/Info 2 0 R\n>>\nstartxref\n%d\n%%%%EOF",
                pdf->objNumber+1,pdf->offset);
    LPDF_FCLOSE(&pdf->file);
    LPDF_REMOVE(file_name);
    LPDF_RENAME("tmp.pdf",file_name);
    return LPDF_OK;
}

LPDF_STATUS LPDF_Free(LPDF_Doc pdf)
{
    memset(pdf,sizeof(LPDF_Doc_Rec),0);
    return LPDF_OK;
}
/**
  * @brief 添加一个新的page到pdf文档中,此时添加的page不写入文件,等到保存页面时再写入
  */
LPDF_Page LPDF_AddPage(LPDF_Doc pdf)
{
    LPDF_INT length = 0;
    LPDF_Page page = NULL;
	LPDF_UINT writeBytes = 0;
    
	if(!LPDF_HasDoc(pdf))
		return NULL;
    page = (LPDF_Page)&pdf->obj[pdf->objNumber];
	page->type = LPDF_OBJ_PAGE;
	page->number = pdf->objNumber;
    page->attr[LPDF_PAGE_WIDTH] = 595;
    page->attr[LPDF_PAGE_HEIGHT] = 842;
	page->attr[LPDF_PAGE_CTX_LENGTH] = 0;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_PAGE_DESCRIPTION;
    page->attr[LPDF_PAGE_FONTTYPE] = LPDF_FONT_INVALID;
	page->attr[LPDF_PAGE_FONTSIZE] = 0;
    page->doc = pdf;
	
	pdf->obj[pdf->objNumber+1].offset = pdf->offset;
	length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<</Length %d 0 R>>\nstream\n",
                        pdf->objNumber+2, pdf->objNumber+3);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
	pdf->offset += length;
	pdf->objNumber+=3;
    return page;
}

LPDF_Image LPDF_AddImage(uint8_t * img_arr)
{
  LPDF_INT length = 0;
  LPDF_Image image = NULL;
	LPDF_UINT writeBytes = 0;
    
	image->type = LPDF_OBJ_PAGE;
	image->number = 1;
	image->attr[LPDF_IMAGE_COLORSPACE] = 0;
  image->attr[LPDF_IMAGE_LENGTH] = 0;
	image->doc = img_arr;
	
  return image;
}

LPDF_STATUS LPDF_Page_SaveParams(LPDF_Page page)
{
  LPDF_INT length;
	LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_INVALID);
    if(LPDF_OK != ret)
        return ret;
    
    /* 对于每个page来说该接口只能调用一次即在GMODE为INVALID的模式下 */
    length = LPDF_SPRINTF(pdf_buf,"/MediaBox [ 0 0 %d %d ]\n>>\nendobj\n\n",
                        page->attr[LPDF_PAGE_WIDTH], page->attr[LPDF_PAGE_HEIGHT]);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    pdf->objNumber = pdf->offset;
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<</Length %d 0 R>>\nstream\n",
                        pdf->objNumber+2, pdf->objNumber+3);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH]= 0;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_PAGE_DESCRIPTION;
    return LPDF_OK;
}

LPDF_STATUS LPDF_Page_SetHeight(LPDF_Page page, LPDF_UINT16 value)
{
	if(value < 3 || value > 14400)
	{
		return LPDF_PAGE_INVALID_SIZE;
	}	
    page->attr[LPDF_PAGE_HEIGHT] = value;
    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_SetWidth(LPDF_Page page, LPDF_UINT16 value)
{
	if(value < 3 || value > 14400)
	{
		return LPDF_PAGE_INVALID_SIZE;
	}	
    page->attr[LPDF_PAGE_WIDTH] = value;
    return LPDF_OK;
}

LPDF_UINT16 LPDF_Page_GetHeight(LPDF_Page page)
{
    if(page)
    {
        return page->attr[LPDF_PAGE_HEIGHT];
    }
    
    return 0;
}

LPDF_UINT16 LPDF_Page_GetWidth(LPDF_Page page)
{
    if(page)
    {
        return page->attr[LPDF_PAGE_WIDTH];
    }
    
    return 0;
}

LPDF_STATUS LPDF_Page_CheckState(LPDF_Page page, LPDF_UINT mode)
{
    if(!page)
        return LPDF_INVALID_OBJECT;
    if(!(page->attr[LPDF_PAGE_GMODE]&mode))
        return LPDF_FAILED;

    return LPDF_OK;
}

LPDF_STATUS LPDF_Page_SetFontAndSize(LPDF_Page page,
                           const char *font_name, LPDF_UINT8 size)
{
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_INT i = 0,length = 0;
	LPDF_UINT writeBytes = 0;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
    if(LPDF_OK != ret)
        return ret;
 
    while(font_list[i])
    {
        if(0 == strcmp(font_list[i],font_name))
        {
            page->attr[LPDF_PAGE_FONTTYPE] = i;
            page->attr[LPDF_PAGE_FONTSIZE] = size;
            length = LPDF_SPRINTF(pdf_buf,"/F%d %d Tf\n",i+1,size);
            LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
            pdf->offset += length;
            page->attr[LPDF_PAGE_CTX_LENGTH] += length;
            return LPDF_OK;
        }
        i+=1;
    }
    
    /* 检测中文字体 */
    if(0 == strcmp("SimSun",font_name))
    {
        page->attr[LPDF_PAGE_FONTTYPE] = i;
        page->attr[LPDF_PAGE_FONTSIZE] = size;
        length = LPDF_SPRINTF(pdf_buf,"/F%d %d Tf\n",i+1,size);
        LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
        pdf->offset += length;
        page->attr[LPDF_PAGE_CTX_LENGTH] += length;
        return LPDF_OK;
    }
    return LPDF_PAGE_INVALID_FONT;
}

/**
  * @brief 保存page内容,在每个page内容结束之后调用一次
  */
LPDF_STATUS LPDF_Page_SaveContext(LPDF_Page page)
{
    LPDF_INT length, i = 0,size = 0;
	LPDF_UINT writeBytes = 0;
	LPDF_BOOL hasImage = LPDF_FALSE;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
    if(LPDF_OK != ret)
        return ret;
     /* 对于每个page来说该接口只能调用一次即在GMODE为PAGE_DESCRIPTION的模式下 */
    length = LPDF_SPRINTF(pdf_buf,"endstream\nendobj\n\n");
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes); 
    pdf->offset += length;
	pdf->obj[page->number+2].offset = pdf->offset;
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n%d\nendobj\n\n",
                        page->number+3,page->attr[LPDF_PAGE_CTX_LENGTH]);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_OVER;
	
	/* 检测该page是否有添加image */
	for(i = 20; i < pdf->objNumber; i++)
	{
		/* 遍历全部obj对象 */
		if((LPDF_OBJ_IMAGE == pdf->obj[i].type) && 
			(page == (LPDF_Page)pdf->obj[i].attr[LPDF_IMAGE_OWNER]))
		{
			hasImage = LPDF_TRUE;
			pdf->obj[i].offset = pdf->offset;	/* 加载image obj 偏移地址 */
			length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /XObject\n/Name /Image%d\n"
								"/Subtype /Image\n/ColorSpace /",i+1,pdf->obj[i].attr[LPDF_IMAGE_NUMBER]); 
			LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
			pdf->offset += length;
			switch(pdf->obj[i].attr[LPDF_IMAGE_COLORSPACE])
			{
				case LPDF_CS_DEVICE_CMYK:
					break;
				case LPDF_CS_DEVICE_GRAY:
					LPDF_FPRINTF(&pdf->file,"DeviceGray\n");
					pdf->offset += 11;
					break;
				case LPDF_CS_DEVICE_RGB:
					LPDF_FPRINTF(&pdf->file,"DeviceRGB\n");
					pdf->offset += 10;
					break;
				default:
					break;
			}
			size = pdf->obj[i].attr[LPDF_IMAGE_WIDTH]*pdf->obj[i].attr[LPDF_IMAGE_HEIGHT]*pdf->obj[i].attr[LPDF_IMAGE_BITS]/8;
			length = LPDF_SPRINTF(pdf_buf,"/Width %d\n/Height %d\n/BitsPerComponent %d\n"
								"/Length %d\n>>\nstream\n",pdf->obj[i].attr[LPDF_IMAGE_WIDTH],
								pdf->obj[i].attr[LPDF_IMAGE_HEIGHT],pdf->obj[i].attr[LPDF_IMAGE_BITS],
								size);
			LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
			pdf->offset += length;
			LPDF_FWRITE(&pdf->file,(LPDF_BYTE *)pdf->obj[i].attr[LPDF_IMAGE_ADDR],size,&writeBytes);
			pdf->offset += size;
			length = LPDF_SPRINTF(pdf_buf,"\nendstream\nendobj\n\n");
			LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
			pdf->offset += length;
		}
	}
	
	/* 最后写入page对象 */
	page->offset = pdf->offset;	/* 加载page obj 地址 */
    length = LPDF_SPRINTF(pdf_buf,"%d 0 obj\n<<\n/Type /Page\n/Parent %d 0 R\n/Contents %d 0 R\n"
                    "/Resources <<\n/ProcSet [/PDF /TEXT /ImageB /ImageC /ImageI]\n"
                    "/Font <<\n",page->number+1,pdf->pagesNumber+1, page->number+2);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
	i = 0;
    while(font_list[i])
    {
        length = LPDF_SPRINTF(pdf_buf,"/F%d %d 0 R\n",i+1,3+i);
        LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
        pdf->offset += length;
        i+=1;
    }
    /* 追加中文字体对象 */
    length = LPDF_SPRINTF(pdf_buf,"/F%d %d 0 R\n",i+1,3+i);
	LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    LPDF_FPRINTF(&pdf->file,">>\n");
    pdf->offset += 3;
	if(hasImage)
	{
		LPDF_FPRINTF(&pdf->file,"/XObject <<\n");
		pdf->offset += 12;
		for(i = 20; i < pdf->objNumber; i++)
		{
			/* 遍历全部obj对象 */
			if((LPDF_OBJ_IMAGE == pdf->obj[i].type) && 
				(page == (LPDF_Page)pdf->obj[i].attr[LPDF_IMAGE_OWNER]))
			{
				length = LPDF_SPRINTF(pdf_buf,"/X%d %d 0 R\n",pdf->obj[i].attr[LPDF_IMAGE_NUMBER],i+1);
				LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
				pdf->offset += length;
			}
		}
		LPDF_FPRINTF(&pdf->file,">>\n");
		pdf->offset += 3;
	}
	LPDF_FPRINTF(&pdf->file,">>\n");
	pdf->offset += 3;
	length = LPDF_SPRINTF(pdf_buf,"/MediaBox [ 0 0 %d %d ]\n>>\nendobj\n\n",
                        page->attr[LPDF_PAGE_WIDTH], page->attr[LPDF_PAGE_HEIGHT]);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    return LPDF_OK;
}

LPDF_STATUS LPDF_Page_BeginText(LPDF_Page page)
{
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
    if(LPDF_OK != ret)
        return ret;
    LPDF_FPRINTF(&pdf->file,"BT\n");
    pdf->offset += 3;
    page->attr[LPDF_PAGE_CTX_LENGTH] += 3;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_TEXT_OBJECT;
    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_EndText(LPDF_Page page)
{
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    LPDF_FPRINTF(&pdf->file,"ET\n");
    pdf->offset += 3;
    page->attr[LPDF_PAGE_CTX_LENGTH] += 3;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_PAGE_DESCRIPTION;
    return LPDF_OK;
}

LPDF_STATUS LPDF_Page_ShowText(LPDF_Page page, const char *text)
{
    LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_BOOL isCNSInside = LPDF_FALSE;
    LPDF_UINT8 *pStr = (LPDF_UINT8 *)text;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    if(LPDF_FONT_INVALID == page->attr[LPDF_PAGE_FONTTYPE])
        return LPDF_OK;
    /* 检测显示字符中是否包含中文,即多字节编码的数据 */
    while(*pStr)
    {
        if(*pStr >= 0x80)
        {
            isCNSInside = LPDF_TRUE;
            break;
        }
        pStr++;
    }
    if(isCNSInside)
    {
        LPDF_FPRINTF(&pdf->file,"<");
        length = 1;
        while(*text)
        {
            LPDF_FPRINTF(&pdf->file,"%02X",(LPDF_UINT8)*text);
            text+=1;
            length+=2;
        }
        LPDF_FPRINTF(&pdf->file,"> Tj\n");
        length += 5;
    }
    else
    {
    length = LPDF_SPRINTF(pdf_buf,"(%s) Tj\n",text);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    }
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    return LPDF_OK;
    
}
LPDF_STATUS LPDF_Page_MoveTextPos(LPDF_Page page,
                        LPDF_INT x, LPDF_INT y)
{
    LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    length = LPDF_SPRINTF(pdf_buf,"%d %d Td\n",x,y);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;

    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_TextOut(LPDF_Page page, 
                        LPDF_UINT16 x, LPDF_UINT16 y,
                        const char *text)
{
    return LPDF_OK;
}

LPDF_STATUS LPDF_Page_SetRGBStroke(LPDF_Page page,
                         LPDF_REAL r,
                         LPDF_REAL g,
                         LPDF_REAL b)
{
    LPDF_INT length = 0;
		LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
    if(LPDF_OK != ret)
        return ret;

    length = LPDF_SPRINTF(pdf_buf,"%.1f %.1f %.1f RG\n",r,g,b);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    return LPDF_OK;
}

LPDF_STATUS LPDF_Page_SetRGBFill(LPDF_Page page,
                         LPDF_REAL r,
                         LPDF_REAL g,
                         LPDF_REAL b)
{
    LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_TEXT_OBJECT|LPDF_GMODE_PAGE_DESCRIPTION);
    if(LPDF_OK != ret)
        return ret;

    length = LPDF_SPRINTF(pdf_buf,"%.1f %.1f %.1f rg\n",r,g,b);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_MoveTo (LPDF_Page page,
                         LPDF_UINT16 x,
                         LPDF_UINT16 y)
{
    LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION|LPDF_GMODE_PATH_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    length = LPDF_SPRINTF(pdf_buf,"%d %d m\n",x,y);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_PATH_OBJECT;
    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_LineTo (LPDF_Page page,
                         LPDF_UINT16 x,
                         LPDF_UINT16 y)
{
    LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PATH_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    length = LPDF_SPRINTF(pdf_buf,"%d %d l\n",x,y);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_Stroke(LPDF_Page page)
{
    LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PATH_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    LPDF_FPRINTF(&pdf->file,"S\n");
    pdf->offset += 2;
    page->attr[LPDF_PAGE_CTX_LENGTH] += 2;
    page->attr[LPDF_PAGE_GMODE] = LPDF_GMODE_PAGE_DESCRIPTION;
    return LPDF_OK;
}
LPDF_STATUS LPDF_Page_DrawImage(LPDF_Page page,
                      LPDF_Image image,
                      LPDF_UINT16 x,
                      LPDF_UINT16 y,
                      LPDF_UINT16 width,
                      LPDF_UINT16 height)
{
    LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
	LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION);
    if(LPDF_OK != ret)
        return ret;
    length = LPDF_SPRINTF(pdf_buf,"q\n%d 0 0 %d %d %d cm\n/X%d Do\nQ\n",
                        width,height,x,y,image->attr[LPDF_IMAGE_NUMBER]);
    LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    image->attr[LPDF_IMAGE_OWNER] = (LPDF_UINT32)page;
    return LPDF_OK;
}
LPDF_Image LPDF_LoadRawImageFromFile(LPDF_Doc pdf,
                      const char *filename,
                      LPDF_UINT width,
                      LPDF_UINT height,
                      LPDF_ColorSpace color_space)
{	
	if(!LPDF_HasDoc(pdf))
        return NULL;
    
    return NULL;
}
/**
  * @brief
  * @param 
  */
LPDF_Image LPDF_LoadRawImageFromMem(LPDF_Doc pdf,
                      const LPDF_BYTE *buf,
                      LPDF_UINT width,
                      LPDF_UINT height,
                      LPDF_ColorSpace color_space,
                      LPDF_UINT bits_per_component)
{
    LPDF_Image image = NULL;
    
    if(!LPDF_HasDoc(pdf))
        return NULL;

    if((1 != bits_per_component) && (2 != bits_per_component) &&
       (4 != bits_per_component) && (8 != bits_per_component))
    {
        pdf->error = LPDF_INVALID_IMAGE;
        return NULL;
    }
    
    if((LPDF_CS_DEVICE_RGB != color_space) && (LPDF_CS_DEVICE_GRAY != color_space) &&
       (LPDF_CS_DEVICE_CMYK != color_space))
    {
        pdf->error = LPDF_INVALID_COLOR_SPACE;
        return NULL;
    }
    
    if(0 != ((width*bits_per_component)%8))
    {
        pdf->error = LPDF_INVALID_IMAGE_WIDTH;
        return NULL;
    }
    
    image = (LPDF_Image)&pdf->obj[pdf->objNumber];
    image->type = LPDF_OBJ_IMAGE;
		image->number = pdf->objNumber;
    image->attr[LPDF_IMAGE_WIDTH] = width;
    image->attr[LPDF_IMAGE_HEIGHT] = height;
    image->attr[LPDF_IMAGE_BITS] = bits_per_component;
    image->attr[LPDF_IMAGE_COLORSPACE] = color_space;
    image->attr[LPDF_IMAGE_ADDR] = (LPDF_UINT32)buf;
    image->attr[LPDF_IMAGE_NUMBER] = ++pdf->imageNumber;
    image->doc = pdf;
		pdf->objNumber+=1;
    return image;
}

LPDF_STATUS LPDF_Page_SetLineWidth(LPDF_Page page,
                         LPDF_REAL line_width)
{
	LPDF_INT length = 0;
	LPDF_UINT writeBytes = 0;
	LPDF_Doc pdf = (LPDF_Doc)page->doc;
    LPDF_STATUS ret = LPDF_Page_CheckState(page,LPDF_GMODE_PAGE_DESCRIPTION|LPDF_GMODE_PATH_OBJECT);
    if(LPDF_OK != ret)
        return ret;
    length = LPDF_SPRINTF(pdf_buf,"%.1f w\n",line_width);
		LPDF_FWRITE(&pdf->file,pdf_buf,length,&writeBytes);
    pdf->offset += length;
    page->attr[LPDF_PAGE_CTX_LENGTH] += length;
    return LPDF_OK;
}
这里插入代码片

以下是温湿度传感器代码段



#include "GXHTC3.h"
#include "bsp_i2c_gpio.h"



static uint8_t CRC_8(uint8_t *Crc_ptr,uint8_t LEN)
{
	uint8_t CRC_Value = 0xFF;
	uint8_t i = 0,j = 0;

	for(i=0;i<LEN;i++)
	{
		CRC_Value ^= *(Crc_ptr+i);
		for(j=0;j<8;j++)
		{
			if(CRC_Value & 0x80)
				CRC_Value = (CRC_Value << 1) ^ 0x31;
			else
				CRC_Value = (CRC_Value << 1);
		}
	}
	return CRC_Value;
}



static int WriteReg(unsigned short int cmd)
{

	i2c_Start();
	
	i2c_SendByte(GXTHC3_SENSOR_ADDR_W);
	if(i2c_WaitAck())
	 goto __error;
	 	
	i2c_SendByte(cmd>>8);
	if(i2c_WaitAck())
	 goto __error;	 
	 
	i2c_SendByte(cmd);
	if(i2c_WaitAck())
	 goto __error;
	 	
	i2c_Stop();
	return 1;

__error: 
	i2c_Stop();	
	return 0;


}


int gxhtc3_sleep(void)
{
	return WriteReg(0xb098);
}

int gxhtc3_wakeup(void)
{
	return WriteReg(0x3517);
}

//循环测量
int gxthc3_SetPeriodicMeasurement(void)
{
	return WriteReg(0x7CA2);
}

int gxthc3_SetLowpowerMeasurement(void)
{
	return WriteReg(0x6458);
}

int gxthc3_Reset(void)
{
	return WriteReg(0x805d);
}


int gxthc3_ReadResults( int *temp, int  *humi)
{ 
	int i;
	unsigned char buf[6];
	//if(gxthc3_SetLowpowerMeasurement()==0)
	if(gxthc3_SetPeriodicMeasurement()==0)
	 goto __error;
	for(i=0;i<200000;i++);
	i2c_Start();
	i2c_SendByte(GXTHC3_SENSOR_ADDR_R);
	if(i2c_WaitAck())
	 goto __error;
	 
	buf[0] = i2c_ReadByte();
	i2c_Ack();
	buf[1] = i2c_ReadByte();
	i2c_Ack();
	buf[2] = i2c_ReadByte();
	i2c_Ack();
	buf[3] = i2c_ReadByte();
	i2c_Ack();
	buf[4] = i2c_ReadByte();
	i2c_Ack();
	buf[5] = i2c_ReadByte();
	i2c_NAck();
	i2c_Stop();

	if(CRC_8(buf, 2) == buf[2] && CRC_8(buf + 3, 2) == buf[5])
	{

		*temp =  buf[0]*256 + buf[1];
		*humi =  buf[3]*256 + buf[4];
	}
	else
	{
		return 0;
	}
	
		
	return 1;

__error: i2c_Stop();
	return 0;
}  


在这里插入代码片
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐