硬件、固件和測試軟件設計
LPC1768:
ARM Cortex M3內核。CPU頻率最高100Mhz,用到的主要資源包括SPI接口讀寫外部flash字庫數據芯片,USB device(HID協議)免驅通信,通用IO控制等。
ARM芯片接收到USB指令時,解析打印任務,並通過查找外部字庫芯片數據轉換打印點陣,然后復位打印頭並開始逐行打印。
EPSON M-150II :
EPSON推出的一款微型點陣針式打印頭,主要用於地磅小票,出租車小票等打印機上面。工作電壓5V左右。
溫度范圍:0 to 50℃
MCBF:5*10五次方 lines
73.2*42.6*12.8mm
點陣間距:0.35mm
一行點陣:96個
紙帶寬度:44.5mm,厚度約0.07mm
打印速度:大約100ms一個點陣行(4.5VDC)
打印頭電機電壓:4.5+0.5/-0.7 VDC
電流:0.17A,峰值0.8A
打印頭針頭電壓:4.5+0.5/-1.2 VDC
電阻:1.5¡À0.15 Ω
電流:峰值3A
通電時間:0.2-2.5ms,通常0.6ms
2.打印頭針包括 A-B-C-D
A(24dots)+B(24dots)+C(24dots)+D(24dots)
一、ARM系統硬件
包括了ARM芯片、時鍾、復位、ISP模式、SPI外部flash芯片、紅外反射管電路
二、USB和通信接口
USB Device( HID免驅動協議 )、預留藍牙模塊、電源輸入口
三、EPSON打印頭驅動
包括了打印頭針式驅動,原點檢測以及電機控制
四、PCB layout
五、固件設計
main:
/* Layer specfication ------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------- -- -- This layer for initialization -- ----------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------*/ #include "includes.h" /************************************************************************************************ * * Description: This function is * Made it by yourself * * Arguments : * Returns : ************************************************************************************************/ int main(void) { ErrType err; INT8U receive_buf[128],para_buf[128]; INT32U TimerCount; //TKIT init #ifdef __APP_CODE__ TKIT_Init( TKITMODE_APP,2017,12,1,00,00,00); #else TKIT_Init( TKITMODE_BOOT ,2017,12,1,00,00,00); #endif //Check app code >>>>>>>>>>>>>>>>>>>>>>>>>>>> //Check app code >>>>>>>>>>>>>>>>>>>>>>>>>>>> #ifndef __APP_CODE__ //Check app firmware in FATFS #if TKIT_FATFS_EN while( SD_Exist ) { if( TKIT_SUCCESS!=t_fat_PathCheck(FAT_PATH_SYS,FALSE) ){break;} #ifndef __APP_CODE__ PrintfDebug("<boot>Check app code[%s]...\r\n",FAT_PATH_SYS); if( TRUE==b_FileFirmwareCheck(FAT_PATH_SYS,"AMH-AMH",FALSE) ) { PrintfDebug("<boot>Find available app code in disk\r\n"); b_FileFirmwareCheck(FAT_PATH_SYS,"AMH-AMH",TRUE); } #endif break; } #endif //TKIT_FATFS_EN PrintfDebug("<boot>Check app code and jump...\r\n"); TKIT_ErrUpdate( t_TKIT_AppCheck( TKIT_DLY_3S, &FrmRead ) ); #endif //__APP_CODE__ //Check app code <<<<<<<<<<<<<<<<<<<<<<<<<<<< //Check app code <<<<<<<<<<<<<<<<<<<<<<<<<<<< #ifdef __APP_CODE__ PrintfDebug("<app>app code start.\r\n"); #else PrintfDebug("<boot>Bootloader start.\r\n"); #endif //Create task. Task_Init(); //TKIT_TaskCreate("EPSON Task",Task, NULL); TKIT_TaskStart(); TKIT_TimeOutInit( &TimerCount ); while( 1 ) { Task(); if( TKIT_TimeOutCheckClr( &TimerCount,TKIT_DLY_1S) ) { TKIT_IO_SetBurstCnt(IO_LED,1); } #if TKIT_TERMINAL_EN if(ReadsExt(receive_buf,para_buf)) { Terminal_Handler(receive_buf,para_buf); } #endif //TKIT_TERMINAL_EN #if TKIT_PROBUS_EN FrmRead.Alt.Port.u16 = BUS_PORT_USBHID|BUS_PORT_WIFI; //接收一個幀 err = t_ProBus_ReadFrame( &FrmRead , TKIT_DLY_20MS ); if( TKIT_SUCCESS==err ) { t_ProBus_CmdHandler( &FrmRead ); TKIT_IO_SetBurstCnt(IO_LED,3); } #endif ///////Probus command handler } }
task:
/* Layer specfication ------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------- -- -- This layer for initialization -- ----------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------*/ #include "task.h" #include "Task_ErrorCode.h" TKIT_EVENT TaskEvent; INT32U TaskTimerCount; INT32U LongTimeTestCount=0; INT16U g_SpaceHeight = 0; INT16U g_SpaceWidth = 0; char bmp_buf[1024*4]; BMP bmp; char bmpZoom_buf[1024*4]; BMP bmpZoom; #define MAX_STRLEN 480 //縱向取模,最低位是圖像的第一行 //元 0xD4AA // [0]=D4, [1]=AA static INT8U DOT_Yuan[] ={0x44,0x3D,0x05,0x7D,0x44}; //¥ static INT8U DOT_Symbol[] ={0x15,0x16,0x7C,0x16,0x15}; //拷貝字庫點陣到圖片 BOOLEAN FontInsertDot(BMP* const p_bmp,INT8U *DotBuf,INT32U x,INT32U y,INT32U Height,INT32U Width) { INT8U u8; INT8U *p_des; INT8U *p_src; INT32U i,j; //拷貝字庫數據//由於沒有對齊,只能一個點為單位拷貝 for( i=0; i<Height;i++ ) { //Printf("DotInsert. i=%d\r\n",i); //圖片數據地址 //p_des = p_bmp->SetBuf + (p_bmp->info.biHeight-y-1-i)*DOT_BYTES_LINE(p_bmp->info.biWidth); p_des = p_bmp->SetBuf + (p_bmp->info.biHeight-y-1-i)*BMP_LINE_BYTES(p_bmp); for( j=0;j<Width;j++ ) { //縱向取模 向低位對齊 //else { p_src = DotBuf + j*DOT_BYTES_LINE(Height) + i/8; u8 = *p_src & ( 0x01<<(i%8) ) ; } //Printf("DotInsert. j=%d,Data=0x%02x\r\n",j,u8 ); //目標點數據//////////////////////////// if( u8 ) { *(p_des+(j+x)/8) &= ~( 0x80 >> ((j+x)%8) ); } else { *(p_des+(j+x)/8) |= ( 0x80 >> ((j+x)%8) ); } } } return TRUE; } /********************************************************************************************************** * Task Init * * Description: Task * * Arguments : * * Returns : **********************************************************************************************************/ void Task_Init(void) { //TKIT_ErrType err; PrintfDebug("EPSON task init\r\n"); TaskEvent = NULL; TKIT_TimeOutInit( &TaskTimerCount ); } /********************************************************************************************************** * Check power * * Description: Task * * Arguments : * * Returns : **********************************************************************************************************/ TKIT_ErrType fDevice_PwrCheck(void) { if( ADC_TO_REAL_MV(ADC_Get(ADC_CHANNEL2)) * 2 < 4500 )return W_UNIT_PRTPWR; return TKIT_SUCCESS; } /********************************************************************************************************** * Task Init * * Description: Task * * Arguments : * * Returns : **********************************************************************************************************/ TKIT_ErrType Task_SetPrtData (INT16U cmd,INT8U *p,INT16U len) { TKIT_ErrType err = TKIT_SUCCESS; BOOLEAN result; INT32U u32 = 0; INT32U x,y; INT32U bmp_line=0; MHFILE font,font_asc; BMP* p_bmp=NULL; //如果打印數據長度為0 //if( 0==len )err = E_UNIT_PRTLEN; if( len>MAX_STRLEN )return E_UNIT_PRTLEN; //設備是否空閑檢查 if( EPSON_UNIT_IDLE!=EPSON_UnitState )err = W_UNIT_BUSY; //檢查設備電源是否正常 // err = fDevice_PwrCheck();//檢查電源 //顯示打印數據 *(p+len) = 0; //Printf(" Set Data(%d):%s\r\n",len,p); //創建BMP圖片模板 if( TKIT_SUCCESS==err ) { bmp.SetBuf = (INT8U*)bmp_buf; bmp.SetBufLen = sizeof(bmp_buf); result = BMP_CreateInit(&bmp,EPSON_HEAD_NOZZLES,200,1,0xFF); if( FALSE==result ) { Printf(" Create BMP file error!\r\n"); err = E_UNIT_PRTCREATE; } p_bmp = &bmp; } //不同的命令不同的打印模式 if( TKIT_SUCCESS==err && CMDUSER_PRT_TAXI==cmd ) { //#define TAXI_LINE_Y (7+1+5) #define TAXI_LINE_Y (7+g_SpaceHeight) Printf("Taxi print\r\n"); u32 = 0; bmp_line = TAXI_LINE_Y; x = 1; y = 0; while( u32<len && *(p+u32) ) { if( (x+5)>bmp.info.biWidth ) { if( *(p+u32)==0x0d || *(p+u32)==0x0a ) { //continue; } else { x = 1; y += TAXI_LINE_Y; bmp_line += TAXI_LINE_Y; } } //////////////////////////////// if( '$'==*(p+u32) ) { FontInsertDot(&bmp,DOT_Symbol,x,y,7,5); } else if( *(p+u32)>0x80 ) { FontInsertDot(&bmp,DOT_Yuan,x,y,7,5); u32++; } else if( *(p+u32)==0x0d || *(p+u32)==0x0a ) { if( *(p+u32)==0x0d ) { x=1; y += TAXI_LINE_Y; bmp_line += TAXI_LINE_Y; } u32++; continue; } else { BMP_FontInsert(&bmp,x,y,NULL,NULL,(p+u32), 1); } //////////////////////////////// x += (5+g_SpaceWidth); u32++; } if(u32==0)bmp_line=0; } //常用中英文字符串打印功能 if( TKIT_SUCCESS==err && CMDUSER_PRT_STR==cmd ) { Printf("String print\r\n"); if( len>MAX_STRLEN )return E_UNIT_PRTLEN; //讀取字庫文件 Font_ReadHeader(&font, MEMADDR_FONT); Font_ReadHeader(&font_asc,MEMADDR_FONTASCII); //是否支持配置行間距 和 字符間距 if( 0!=g_SpaceHeight || 0!= g_SpaceWidth ) { font.Alt.SpaceHeight = g_SpaceHeight; font.Alt.SpaceWidth = g_SpaceWidth; font_asc.Alt.SpaceHeight = g_SpaceHeight; font_asc.Alt.SpaceWidth = g_SpaceWidth; } //將字體插入圖片 bmp_line = BMP_FontInsert(&bmp,1,0,&font,&font_asc,p, len); if( 0==bmp_line ){Printf(" BMP insert font error!\r\n");} } //打印BMP圖片 if( TKIT_SUCCESS==err && CMDUSER_PRT_BMP==cmd ) { result = BMP_Readfile(&bmp, MEMADDR_BMP, NULL , NULL ); if( result==FALSE || bmp.info.biBitCount>1 ) { err = E_UNIT_PRTBMP; } bmp_line = bmp.info.biHeight; } //打印二維碼 if( TKIT_SUCCESS==err && CMDUSER_PRT_QR==cmd ) { bmp_line = 0; Printf("QR Print[%d]:%s\r\n",len,p); //字符串轉QR if( BMP_QRCreate(p,&bmp,0) ) { bmpZoom.SetBuf = (INT8U*)bmpZoom_buf; bmpZoom.SetBufLen = sizeof(bmpZoom_buf); BMP_CreateInit(&bmpZoom,EPSON_HEAD_NOZZLES,200,1,0xFF); //是否考慮放大二維碼 if( bmp.info.biWidth <= 45 ) { if( BMP_Zoom(&bmp,&bmpZoom, EPSON_HEAD_NOZZLES*100/bmp.info.biWidth ) ) { p_bmp=&bmpZoom; } else { err = E_UNIT_QRCREATE; } } bmp_line = p_bmp->info.biHeight; } else { err = E_UNIT_QRCREATE; } } //////////////////////////////////////////////////////////////// if( TKIT_SUCCESS==err && bmp_line ){result = EPSON_PrintStart(p_bmp,bmp_line);} return err; } /********************************************************************************************************** * 設置字符間距 * * Description: Task * * Arguments : * * Returns : **********************************************************************************************************/ void Task_SetSpace (INT16U Height,INT16U Width) { g_SpaceHeight = Height; g_SpaceWidth = Width; } /********************************************************************************************************** * Task * * Description: Task * * Arguments : * * Returns : **********************************************************************************************************/ void Task(void) { INT32U msg=0; BOOLEAN result; INT8U buf[64]; //任務消息 msg = TKIT_EventPend( &TaskEvent,IOBIT_MASKALL, 0 ); //打印測試圖片 if( msg==EVENT_PRTTEST ) { bmp.SetBuf = (INT8U*)bmp_buf; bmp.SetBufLen = sizeof(bmp_buf); result = BMP_Readfile(&bmp,0x00080000,NULL,NULL); if(TRUE==result)result = EPSON_PrintStart(&bmp,0); if( FALSE==result ){TKIT_ErrSet(E_UNIT_PRINTTEST);} } //老化程序 if( msg==EVENT_AGE ) { if(0==LongTimeTestCount) LongTimeTestCount=100; else LongTimeTestCount = 0; } if( LongTimeTestCount ) { if( EPSON_UNIT_IDLE==EPSON_UnitState ) { if( TKIT_TimeOutCheckClr( &TaskTimerCount,TKIT_DLY_3S) ) { String_printf((char*)buf,"LONG-TIME-TEST:12345\r\nCount=%5d",LongTimeTestCount ); Task_SetPrtData(CMDUSER_PRT_STR,buf,String_Len(buf)); LongTimeTestCount--; } } } //電機進紙 if( msg==EVENT_FEED ){EPSON_ResetStart(0,100);} if( msg==EVENT_STOP ){EPSON_Stop();} ///////////////////////////////////////////////////////// }
六、實物展示