基於LPC1768的EPSON M-150II針式打印頭控制板設計


硬件、固件和測試軟件設計

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();}
    /////////////////////////////////////////////////////////
}

 

六、實物展示

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM