首頁 > 評測 > 【CuriosityNano測評報告】+墨水屏的顯示驅(qū)動

【CuriosityNano測評報告】+墨水屏的顯示驅(qū)動

  
  • 作者:
  • 來源:
  • [導讀]
  • #申請原創(chuàng)# AVR64DD32 CuriosityNano是一款小巧的開發(fā)板,為這款開發(fā)板配上一款1.54寸的墨水屏是一個不錯的選擇。目前以PIC的產(chǎn)品對墨水屏的支持并不多,為此決定將它移植到AVR64DD32開發(fā)板。比較有意思的是,與常
#申請原創(chuàng)#
AVR64DD32 CuriosityNano是一款小巧的開發(fā)板,為這款開發(fā)板配上一款1.54寸的墨水屏是一個不錯的選擇。
目前以PIC的產(chǎn)品對墨水屏的支持并不多,為此決定將它移植到AVR64DD32開發(fā)板。
比較有意思的是,與常規(guī)的顯示器件不同,墨水屏在寫入顯示內(nèi)容后,在移除電源后會保持顯示的內(nèi)容,這也是為什么墨水屏被用于做電子標簽的主要原因?芍^是省電沒商量,一旦擁有恒久流傳。

圖1 顯示效果
該墨水屏共有8個引腳,它與開發(fā)板的連接關(guān)系如下:
SCL---PD7
SDA---PD6
RST---PD3
DC ---PD2
CS ---PD1
BUSY ---PF4
在這8個引腳中,除BUSY引腳外均以輸出模式使用,而BUSY則是以輸入模式使用,故相關(guān)的語句定義為:
  1. #define EPD_CLK_init() do { PORTD.OUTSET = PIN7_bm; PORTD.DIRSET = PIN7_bm; } while (0)
  2. #define EPD_MOSI_init() do { PORTD.OUTSET = PIN6_bm; PORTD.DIRSET = PIN6_bm; } while (0)
  3. #define EPD_RST_init() do { PORTD.OUTSET = PIN3_bm; PORTD.DIRSET = PIN3_bm; } while (0)
  4. #define EPD_DC_init() do { PORTD.OUTSET = PIN2_bm; PORTD.DIRSET = PIN2_bm; } while (0)
  5. #define EPD_CS_init() do { PORTD.OUTSET = PIN1_bm; PORTD.DIRSET = PIN1_bm; } while (0)

  6. #define GetValue() (VPORTF.IN & (0x1 << 4))
  7. #define SetPullUp() do { PORTF_PIN4CTRL  |= PORT_PULLUPEN_bm; } while(0)
  8. #define SetDigitalInput() do { PORTF_DIRCLR = 0x10; } while(0)
復制代碼


由于該顯示屏的分辨率為200*200像素點,故其幾何的參數(shù)定義為:
#define EPD_1IN54_WIDTH        200
#define EPD_1IN54_HEIGHT    200
相關(guān)引腳輸出高低電平的語句定義為:
  1. #define EPD_CLK_0   do { PORTD.OUTCLR = PIN7_bm; } while (0)    //CLK
  2. #define EPD_CLK_1   do { PORTD.OUTSET = PIN7_bm; } while (0)
  3. #define EPD_MOSI_0   do { PORTD.OUTCLR = PIN6_bm; } while (0)   //DIN
  4. #define EPD_MOSI_1   do { PORTD.OUTSET = PIN6_bm; } while (0)

  5. #define EPD_RST_0   do { PORTD.OUTCLR = PIN3_bm; } while (0)    //RST
  6. #define EPD_RST_1   do { PORTD.OUTSET = PIN3_bm; } while (0)
  7. #define EPD_DC_0    do { PORTD.OUTCLR = PIN2_bm; } while (0)    //DC
  8. #define EPD_DC_1    do { PORTD.OUTSET = PIN2_bm; } while (0)

  9. #define EPD_CS_0    do { PORTD.OUTCLR = PIN1_bm; } while (0)    //C S
  10. #define EPD_CS_1    do { PORTD.OUTSET = PIN1_bm; } while (0)
復制代碼
顯示屏的復位函數(shù)為:
  1. void EPD_1IN54_Reset(void)
  2. {
  3.     EPD_RST_1;
  4.     DEV_Delay_ms(200);
  5.     EPD_RST_0;
  6.     DEV_Delay_ms(20);
  7.     EPD_RST_1;
  8.     DEV_Delay_ms(200);
  9. }
復制代碼
判別顯示屏是否處于忙的狀態(tài)的函數(shù)為:
  1. void EPD_1IN54_ReadBusy(void)
  2. {
  3.     while(GetValue()==1) {
  4.        DEV_Delay_ms(100);
  5.     }
  6. }
復制代碼
進入和退出墨水屏工作模式的函數(shù)為:
  1. int DEV_Module_Init(void)
  2. {
  3.     EPD_DC_0;
  4.     EPD_CS_0;
  5.     EPD_RST_1;
  6.     return 0;
  7. }

  8. void DEV_Module_Exit(void)
  9. {
  10.     EPD_DC_0;
  11.     EPD_CS_0;
  12.     EPD_RST_0;
  13. }
復制代碼
以GPIO口模擬SPI發(fā)送發(fā)送字節(jié)數(shù)據(jù)的函數(shù)為:
  1. void DEV_SPI_WriteByte(unsigned char value)
  2. {
  3.     u8 i;
  4.     for(i=0; i<8;i++)
  5.     {
  6.         EPD_CLK_0;
  7.         if(value & 0x80)
  8.         EPD_MOSI_1;
  9.         else
  10.         EPD_MOSI_0;
  11.         EPD_CLK_1;
  12.         value = (value << 1);
  13.     }
  14.     EPD_CLK_0;
  15. }
復制代碼
向墨水屏發(fā)送指令和數(shù)據(jù)的函數(shù)為:
  1. void EPD_1IN54_SendCommand(u8 Reg)
  2. {
  3.     EPD_DC_0;
  4.     EPD_CS_0;
  5.     DEV_SPI_WriteByte(Reg);
  6.     EPD_CS_1;
  7.     delay_us(4);
  8. }

  9. void EPD_1IN54_SendData(u8 Data)
  10. {
  11.     EPD_DC_1;
  12.     EPD_CS_0;
  13.     DEV_SPI_WriteByte(Data);
  14.     EPD_CS_1;
  15.     delay_us(4);
  16. }
復制代碼
墨水屏的初始化函數(shù)為:
  1. void EPD_1IN54_Init(u8 Mode)
  2. {
  3.     u16 i;
  4.     EPD_1IN54_Reset();
  5.     EPD_1IN54_SendCommand(0x01);
  6.     EPD_1IN54_SendData((EPD_1IN54_HEIGHT - 1) & 0xFF);
  7.     EPD_1IN54_SendData(((EPD_1IN54_HEIGHT - 1) >> 8) & 0xFF);
  8.     EPD_1IN54_SendData(0x00);
  9.     EPD_1IN54_SendCommand(0x0C);
  10.     EPD_1IN54_SendData(0xD7);
  11.     EPD_1IN54_SendData(0xD6);
  12.     EPD_1IN54_SendData(0x9D);
  13.     EPD_1IN54_SendCommand(0x2C);
  14.     EPD_1IN54_SendData(0xA8);
  15.     EPD_1IN54_SendCommand(0x3A);
  16.     EPD_1IN54_SendData(0x1A);
  17.     EPD_1IN54_SendCommand(0x3B);
  18.     EPD_1IN54_SendData(0x08);
  19.     EPD_1IN54_SendCommand(0x11);
  20.     EPD_1IN54_SendData(0x03);
  21.     EPD_1IN54_SendCommand(0x32);
  22.     if(Mode == EPD_1IN54_FULL){
  23.         for ( i = 0; i < 30; i++) {
  24.            EPD_1IN54_SendData(EPD_1IN54_lut_full_update[i]);
  25.         }
  26.     }else if(Mode == EPD_1IN54_PART){
  27.         for ( i = 0; i < 30; i++) {
  28.            EPD_1IN54_SendData(EPD_1IN54_lut_partial_update[i]);
  29.         }
  30.     }else{
  31.    
  32.     }
  33. }
復制代碼
開啟墨水屏顯示的函數(shù)為:
  1. void EPD_1IN54_TurnOnDisplay(void)
  2. {
  3.     EPD_1IN54_SendCommand(0x22);
  4.     EPD_1IN54_SendData(0xC4);
  5.     EPD_1IN54_SendCommand(0x20);
  6.     EPD_1IN54_SendCommand(0xFF);
  7.     EPD_1IN54_ReadBusy();
  8. }
復制代碼
至此,前面的努力是否會奏效呢?
方法就是先去驗證一下,如果無效,恐怕前面的工作就算交學費。
怎么驗證呢?
用清屏函數(shù),通常情況下清屏函數(shù)是為清除屏幕內(nèi)容服務(wù)的,這里是反其道而行之,就是讓它在屏上留下一些痕跡來判別驅(qū)動程序是是否有效。

為此,需將清屏函數(shù)改造為一個繪制直線的函數(shù),其內(nèi)容如下:
  1. void EPD_1IN54_Clear(void)
  2. {
  3.     u16 Width, Height,i,j;
  4.     Width = (EPD_1IN54_WIDTH%8== 0)? (EPD_1IN54_WIDTH/8):(EPD_1IN54_WIDTH/8+1);
  5.     Height = EPD_1IN54_HEIGHT;
  6.     EPD_1IN54_SetWindow(0, 0, EPD_1IN54_WIDTH, EPD_1IN54_HEIGHT);
  7.     for (j = 0; j < Height; j++) {
  8.         EPD_1IN54_SetCursor(0, j);
  9.         EPD_1IN54_SendCommand(0x24);
  10.         for (i = 0; i < Width; i++) {
  11.             EPD_1IN54_SendData(0XFE);
  12.         }
  13.     }
  14.     EPD_1IN54_TurnOnDisplay();
  15. }
復制代碼
經(jīng)程序的編譯與下載,其運行效果如圖2所示。這說明驅(qū)動是有效的,前期的工作沒白費!
圖2 繪制直線
有了清屏函數(shù)的基礎(chǔ),只需將固定的清屏數(shù)據(jù)改為圖像數(shù)據(jù)就可以顯示圖片了。此外,在顯示圖像時還需選取繪圖模式,其函數(shù)為:
  1. void Paint_SelectImage(u8 *image)
  2. {
  3.     Paint.Image = image;
  4. }
復制代碼
進行圖像繪制的函數(shù)為:
  1. void Paint_DrawBitMap(const unsigned char* image_buffer)
  2. {
  3.     unsigned short  int x, y;
  4.     u32 Addr = 0;
  5.     for (y = 0; y < Paint.HeightByte; y++) {
  6.         for (x = 0; x < Paint.WidthByte; x++) {
  7.             Addr = x + y * Paint.WidthByte;
  8.             Paint.Image[Addr] = (unsigned char)image_buffer[Addr];
  9.         }
  10.     }
  11. }
復制代碼
在配以主程序的情況下,即可進行顯示圖片的測試,其主程序的內(nèi)容為:
  1. u8 BlackImage[5000];
  2. int main(void) {
  3.     EPD_CLK_init();
  4.     EPD_MOSI_init();
  5.     EPD_RST_init();
  6.     EPD_DC_init();
  7.     EPD_CS_init();
  8.     SetDigitalInput();
  9.     SetPullUp();
  10.     DEV_Module_Init();
  11.     EPD_1IN54_Init(EPD_1IN54_FULL);
  12.     //EPD_1IN54_Clear();
  13.     Paint_NewImage(BlackImage, EPD_1IN54_WIDTH, EPD_1IN54_HEIGHT, 270, WHITE);
  14.     Paint_SelectImage(BlackImage);
  15.     Paint_DrawBitMap(gImage_1in54);
  16.     EPD_1IN54_Display(BlackImage);
  17.     DEV_Delay_ms(2000);
  18.     EPD_1IN54_Sleep();
  19.     DEV_Delay_ms(2000);
  20.     while(1);
  21. }
復制代碼
經(jīng)編譯下載,其測試效果就是圖1的顯示內(nèi)容,證明繪圖函數(shù)也成功了!

在添加圖形繪制函數(shù)的情況下,可繪制點、直線、矩形及圓等并可以進行填充處理。此外,在配置字庫的條件下,可實現(xiàn)字符和中文的顯示,其實現(xiàn)的效果如圖3和圖4所示。
圖3 繪制圖形
圖4 顯示字符及數(shù)值

實現(xiàn)顯示效果的主程序為:
  1. int main(void) {
  2.     EPD_CLK_init();
  3.     EPD_MOSI_init();
  4.     EPD_RST_init();
  5.     EPD_DC_init();
  6.     EPD_CS_init();
  7.     SetDigitalInput();
  8.     SetPullUp();
  9.     DEV_Module_Init();
  10.     EPD_1IN54_Init(EPD_1IN54_FULL);
  11.     Paint_NewImage(BlackImage, EPD_1IN54_WIDTH, EPD_1IN54_HEIGHT, 270, WHITE);
  12.     Paint_SelectImage(BlackImage);
  13.     Paint_DrawBitMap(gImage_1in54);
  14.     Paint_Clear(WHITE);
  15.     Paint_DrawPoint(5, 10, BLACK, DOT_PIXEL_1X1, DOT_STYLE_DFT);
  16.     Paint_DrawPoint(5, 25, BLACK, DOT_PIXEL_2X2, DOT_STYLE_DFT);
  17.     Paint_DrawPoint(5, 40, BLACK, DOT_PIXEL_3X3, DOT_STYLE_DFT);
  18.     Paint_DrawPoint(5, 55, WHITE, DOT_PIXEL_4X4, DOT_STYLE_DFT);
  19.    
  20.     Paint_DrawLine(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
  21.     Paint_DrawLine(70, 10, 20, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
  22.     Paint_DrawLine(170, 15, 170, 55, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
  23.     Paint_DrawLine(150, 35, 190, 35, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
  24.    
  25.     Paint_DrawRectangle(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
  26.     Paint_DrawRectangle(85, 10, 130, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
  27.     Paint_DrawCircle(170, 35, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
  28.     Paint_DrawCircle(170, 85, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
  29.    
  30.     EPD_1IN54_Display(BlackImage);
  31.     DEV_Delay_ms(2000);
  32.     EPD_1IN54_Sleep();
  33.     DEV_Delay_ms(2000);
  34.     while(1);
  35. }
復制代碼

這樣在PIC的產(chǎn)品上,墨水屏也可以煥發(fā)出光彩了!

  • 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!

網(wǎng)友評論