/* * lcd_5110_solution.c * * Created on: 2012-2-2 * Author: Administrator */ #include "lcd_5110_solution.h" #include "main.h" #include "Delay.h" #include "SPI-SD/Lcd/font.h" #include "SPI-SD/Fatfs/ff.h" char n5110_string[6][14]; //6行,每行13byte #define CMD 0x00 #define DATA 0x01 #define LCD_X 84 #define LCD_Y 48 #define MAX_HZ_POSX LCD_X #define MAX_HZ_POSY LCD_Y #define MAX_CHAR_POSX LCD_X #define MAX_CHAR_POSY LCD_Y //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////* 以下是基本操作和初始化函数 *////// #if 0 //write a byte void LcdWrite(alt_u8 data,alt_u8 d_c) { alt_u8 i; //chose the chip IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x00); //chose data mode or command mode IOWR_ALTERA_AVALON_PIO_DATA(D_C_BASE, d_c); //sent 8 bits for(i = 0;i < 8;i ++) { IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x00); IOWR_ALTERA_AVALON_PIO_DATA(SDIN_BASE, data >> (7 - i)); IOWR_ALTERA_AVALON_PIO_DATA(SCLK_BASE, 0x01); } //release the chip IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x01); } //initial the 5110 void InitLcd() { usleep(1000); //sent a reset pulse(low) to reset all internal registers IOWR_ALTERA_AVALON_PIO_DATA(REST_BASE, 0x00); usleep(1); IOWR_ALTERA_AVALON_PIO_DATA(REST_BASE, 0x01); usleep(1); //chose the chip IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x00); usleep(1); //release the chip IOWR_ALTERA_AVALON_PIO_DATA(SCE_BASE, 0x01); usleep(1); //function set PD = 0 and V = 0, select extended instruction set(H = 1 mode) LcdWrite(0x21,CMD); //set VOP: VOP is set to a + 65 × b [V] LcdWrite(0xbf,CMD); //RECOMMENDED MUX RATE(1:24),you can chose other MUX RATE LcdWrite(0x15,CMD); //function set PD = 0 and V = 0, select normal instruction set(H = 0 mode) LcdWrite(0x20,CMD); //display control set normal mode (D=1andE=0) LcdWrite(0x0c,CMD); //clear screen LcdClearAll(); } #else //write a byte void LcdWrite(alt_u8 data,alt_u8 d_c) { alt_u8 i; //chose the chip LCD_CE = 0; // 使能LCD //chose data mode or command mode LCD_DC = d_c?1:0; //0.命令;1.数据 //sent 8 bits for(i = 0;i < 8;i ++) { SCLK = 0; SDIN = (data&(1<<(7-i)))?1:0; SCLK = 1; } //release the chip LCD_CE = 1; // 关闭LCD } //initial the 5110 void InitLcd(void) { delay_ms ( 1 ); //sent a reset pulse(low) to reset all internal registers LCD_RST = 0; delay_us ( 1 ); // 产生一个让LCD复位的低电平脉冲 LCD_RST = 1; //chose the chip delay_us ( 1 ); LCD_CE = 0;// 关闭LCD //release the chip delay_us ( 1 ); LCD_CE = 1;// 使能LCD delay_us ( 1 ); #if 0 //function set PD = 0 and V = 0, select extended instruction set(H = 1 mode) LcdWrite(0x21,CMD); //set VOP: VOP is set to a + 65 × b [V] LcdWrite(0xbf,CMD); //RECOMMENDED MUX RATE(1:24),you can chose other MUX RATE LcdWrite(0x15,CMD); //function set PD = 0 and V = 0, select normal instruction set(H = 0 mode) LcdWrite(0x20,CMD); //display control set normal mode (D=1andE=0) LcdWrite(0x0c,CMD); //clear screen LcdClearAll(); #else LcdWrite ( 0x21, 0 ); // 使用扩展命令设置LCD模式 LcdWrite ( 0xc8, 0 ); // 设置偏置电压 LcdWrite ( 0x06, 0 ); // 温度校正 LcdWrite ( 0x13, 0 ); // 1:48 LcdWrite ( 0x20, 0 ); // 使用基本命令 LcdClearAll(); // 清屏 LcdWrite ( 0x0c, 0 ); // 设定显示模式,正常显示 #endif //开启背光灯 BACKLIGHT = 1; } #endif //set the x axis and y axis void SetXY(alt_u8 x,alt_u8 y) { if(x > 83) x = 0; if(y > 5) y = 0; //set y axis LcdWrite(0x40 | y,CMD); //set y axis LcdWrite(0x80 | x,CMD); } //clear all screen void LcdClearAll() { alt_u16 i; SetXY(0,0); //write space continually for(i = 0;i < LCD_X * LCD_Y / 8;i ++) { LcdWrite(0,DATA); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////* 以下是高度为8的各种操作函数 *////// //* 包括6*8字符和字符串,6*8符号,10*8图标 *// //every row contains 14 characters,there are 6 rows (font = 6 * 8)// ///////////////////////////////////////////////////////////////////////////////////////////////////// ///////// x ///////// //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 0 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 1 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 2 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 3 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 4 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 5 ///////////////////////////////////////////////////////////////////////////////////////////////////// //write a char(6*8),don't need coordinates void WriteChar(alt_u8 value) { alt_u8 i; for(i = 0;i < 6;i ++) LcdWrite(ASCII_6_8[value - 0x20][i],DATA); } //write a char(6*8),need coordinates void PutChar(alt_u8 value,alt_u8 x,alt_u8 y) { if(x > 13) x = 0; SetXY(6 * x,y); WriteChar(value); } //write a string(6*8),don't need coordinates void WriteStr(char * str) { while(*str) { WriteChar(*str ++); } } //write a string(6*8),need coordinates,auto line breaks void PutStr(char * str,alt_u8 x,alt_u8 y) { if(x > 13) x = 0; SetXY(6 * x,y); WriteStr(str); } //draw a sign(6*8),don't need coordinates void WriteSign(char * sign) { alt_u8 i; for(i = 0;i < 6;i ++) LcdWrite(sign[i],DATA); } //draw a sign(6*8),need coordinates void DrawSign(char * sign,alt_u8 x,alt_u8 y) { SetXY(x,y); WriteSign(sign); } //draw a sign(10*8),don't need coordinates void WriteIcon(char * icon) { alt_u8 i; for(i = 0;i < 10;i ++) LcdWrite(icon[i],DATA); } //draw a sign(10*8),need coordinates,x is between 0 and 74 void DrawIcon(char * icon,alt_u8 x,alt_u8 y) { //if need line breaks if(x > 74) { x = 0; y += 1; } SetXY(x,y); //draw a sign(10*8) WriteIcon(icon); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////* 以下是高度为16的各种操作函数 *////// //* 包括8*16字符和字符串,16*16汉字 *// //every row contains 10 characters,there are 3 rows (font = 8 * 16)// /////////////////////////////////////////////////////////////////////////////////////////////////// ///////// x /////////// //0 1 2 3 ... 81 82 83// y = 0 //0 1 2 3 ... 81 82 83// //0 1 2 3 ... 81 82 83// y = 1 //0 1 2 3 ... 81 82 83// //0 1 2 3 ... 81 82 83// y = 2 //0 1 2 3 ... 81 82 83// /////////////////////////////////////////////////////////////////////////////////////////////////// //write a char(8*16) void WriteChar_8_16(alt_u8 value,alt_u8 x,alt_u8 y) { alt_u8 i; //draw the first row SetXY(x,y * 2); for(i = 0;i < 8;i ++) LcdWrite(ASCII_8_16[value - 0x20][i],DATA); //draw the second row SetXY(x,y * 2 + 1); for(i = 8;i < 16;i ++) LcdWrite(ASCII_8_16[value - 0x20][i],DATA); } //write a string(8*16),auto line breaks,x is between 0 and 76 void WriteStr_8_16(char * str,alt_u8 x,alt_u8 y) { alt_u8 i = 0; while(*str) { //if need line breaks if(x + (8 * i) > 76) { x = 0; i = 0; y += 2; } //write a char(8*16) WriteChar_8_16(*str,x + (8 * i),y); str ++; i ++; } } //every row contains 5 characters,there are 3 rows (font = 16 * 16)// /////////////////////////////////////////////////////////////////////////////////////////////////// ///////// x /////////// //0 1 2 3 ... 81 82 83// y = 0 //0 1 2 3 ... 81 82 83// //0 1 2 3 ... 81 82 83// y = 1 //0 1 2 3 ... 81 82 83// //0 1 2 3 ... 81 82 83// y = 2 //0 1 2 3 ... 81 82 83// /////////////////////////////////////////////////////////////////////////////////////////////////// //write a Chinese character(16*16) void WriteHanzi(char Hanzi[],alt_u8 x,alt_u8 y) { alt_u8 i; //write the first row SetXY(x,y * 2); for(i = 0;i < 16;i ++) LcdWrite(Hanzi[i],DATA); //write the second row SetXY(x,2 * y + 1); for(i = 16;i < 32;i ++) LcdWrite(Hanzi[i],DATA); } //write a Chinese sentence(16*16),auto line breaks,x is between 0 and 58 void WriteHanziStr(char Hanzi[],alt_u8 x,alt_u8 y,alt_u8 num) { alt_u8 num_i,i = 0; for(num_i = 0;num_i < num;num_i ++) { //if need line breaks if(x + (16 * num_i) > 58) { x = 0; i = 0; y += 1; } //write a Chinese character(16*16) WriteHanzi(Hanzi + 32 * num_i,x + (16 * i),y); i ++; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////* 以下是画图的各种操作函数 *////// //* 包括84*48,高度为8的倍数的图片 *// ///////////////////////////////////////////////////////////////////////////////////////////////////// ///////// x ///////// //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 0 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 1 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 2 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 3 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 4 //0 1 2 3 4 5 6 7 8 9 10 11 12 13// y = 5 ///////////////////////////////////////////////////////////////////////////////////////////////////// //draw a picture(84*48),don't need coordinates void DrawPicture(char bitmap[]) { alt_u16 i; for(i = 0;i < LCD_X * LCD_Y / 8;i ++) LcdWrite(bitmap[i],DATA); } //列行扫描(每列=8bit,n行) //draw a picture(width*height(a multiple of 8)),need coordinates void DrawBitmap(char bitmap[],alt_u8 x,alt_u8 y,alt_u8 width,alt_u8 height) { alt_u8 width_i,height_i; //draw the height_i row for(height_i = 0;height_i < height / 8;height_i ++) { SetXY(x,y + height_i); //draw a row(width column) for(width_i = 0;width_i < width;width_i ++) { LcdWrite(bitmap[width_i + height_i * width],DATA); } } } //列扫描 void DrawBitmap_col(char bitmap[],alt_u8 x,alt_u8 y,alt_u8 width,alt_u8 height) { alt_u8 i,j,z; if(height%8 == 0) //必须是8bit的整数倍 { for(i=0; iMAX_CHAR_POSX){x=0;y+=size;} /*超出X轴字体最小单位,换行*/ if(y>MAX_CHAR_POSY){y=x=0;LCD_Clear(WHITE);} /*超出Y轴字体最小单位,回到原点,并且清屏*/ //LCD_ShowChar(x, y, *p, size, PenColor, BackColor); /*0表示非叠加方式*/ PutChar(*p ,x, y); //WriteChar_8_16(*p ,x, y); } /********************************************************************************* *名称: u16 findHzIndex(u8 *hz) *参数:hz *功能:索引汉字存储的内存地址 *备注: *********************************************************************************/ u16 findHzIndex(u8 *hz) /* 在自定义汉字库在查找所要显示 */ /* 的汉字的位置 */ { u16 i=0; FNT_GB16 *ptGb16 = (FNT_GB16 *)GBHZ_16; /*ptGb16指向GBHZ_16*/ while(ptGb16[i].Index[0] > 0x80) { if ((*hz == ptGb16[i].Index[0]) && (*(hz+1) == ptGb16[i].Index[1])) /*汉字用两位来表示地址码*/ { return i; } i++; if(i > (sizeof((FNT_GB16 *)GBHZ_16) / sizeof(FNT_GB16) - 1)) /* 搜索下标约束 */ { break; } } return 0; } #if 0 /********************************************************************************* *名称:void WriteOneHz(uint16_t x0, uint16_t y0, uint8_t *pucMsk, uint16_t PenColor, uint16_t BackColor) *参数:x0,y0 起始坐标 *pucMsk 指向 PenColor 字符颜色 BackColor 背景颜色 *功能: *备注:此函数不能单独作为汉字字符显示 *********************************************************************************/ void WriteOneHz(u16 x0, u16 y0, u8 *pucMsk, u16 PenColor, u16 BackColor) { u16 i,j; u16 mod[16]; /* 当前字模 16*16 */ u16 *pusMsk; /* 当前字库地址 */ u16 y; u16 size = 16; /*汉字默认大小16*16*/ pusMsk = (u16 *)pucMsk; for(i=0; i<16; i++) /* 保存当前汉字点阵式字模 */ { mod[i] = *pusMsk; /* 取得当前字模,半字对齐访问 */ mod[i] = ((mod[i] & 0xff00) >> 8) | ((mod[i] & 0x00ff) << 8);/* 字模交换高低字节*/ pusMsk = pusMsk+1; } y = y0; LCD_WindowMax(x0,y0,x0+size,y0+size); /*设置窗口*/ LCD_SetCursor(x0,y0); /*设置光标位置 */ LCD_WriteRAM_Prepare(); /*开始写入GRAM*/ for(i=0; i<16; i++) /* 16行 */ { for(j=0; j<16; j++) /* 16列 */ { if((mod[i] << j) & 0x8000) /* 显示第i行 共16个点 */ { LCD_WriteRAM(PenColor); } else { LCD_WriteRAM(BackColor); /* 用读方式跳过写空白点的像素*/ } } y++; } LCD_WindowMax(0x0000,0x0000,240,320); /*恢复窗体大小*/ } #endif /********************************************************************************* *名称:void LCD_ShowHzString(u16 x0, u16 y0, u8 *pcStr, u16 PenColor, u16 BackColor) *参数:x0,y0 起始坐标 pcStr 指向 PenColor 字体颜色 BackColor 字体背景 *功能:显示汉字字符串 *备注:这个函数不能单独调用 *********************************************************************************/ void LCD_ShowHzString(u16 x0, u16 y0, u8 *pcStr, u16 PenColor, u16 BackColor) { u16 usIndex; u8 size = 16; FNT_GB16 *ptGb16 = 0; ptGb16 = (FNT_GB16 *)GBHZ_16; if(x0>MAX_HZ_POSX){x0=0;y0+=size;} /*超出X轴字体最小单位,换行*/ if(y0>MAX_HZ_POSY){y0=x0=0;LCD_Clear(WHITE);} /*超出Y轴字体最小单位,回到原点,并且清屏*/ usIndex = findHzIndex(pcStr); //WriteOneHz(x0, y0, (u8 *)&(ptGb16[usIndex].Msk[0]), PenColor, BackColor); /* 显示字符 */ WriteHanzi((char *)&(ptGb16[usIndex].Msk[0]), x0, y0); } /********************************************************************************* *名称:void LCD_ShowString(u16 x0, u16 y0, u8 *pcstr, u16 PenColor, u16 BackColor) *参数:x0 y0 起始坐标 pcstr 字符串指针 PenColor 字体颜色 BackColor 字体背景色 *功能:调用字符和汉字显示函数,实现字符串显示 *备注: *********************************************************************************/ void LCD_ShowString(u16 x0, u16 y0, u8 *pcStr, u16 PenColor, u16 BackColor) { while(*pcStr!='\0') { if (x0>MAX_HZ_POSX) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y0+=16; x0=0; } if (y0>MAX_HZ_POSY) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y0=0; } if(*pcStr>0x80) /*显示汉字*/ { LCD_ShowHzString(x0, y0, pcStr, PenColor, BackColor); pcStr += 2; x0 += 16; } else /*显示字符*/ { LCD_ShowCharString(x0, y0, pcStr, PenColor, BackColor); pcStr +=1; x0+= 8; } } } void RefreshLCD ( void ) { #if LCD_def u8 i; for ( i = 0; i < 6; i++ ) { PutStr(n5110_string[i], 0, i); } #endif } /*--------------下面三个函数 实现字库的调用及显示-------------------*/ FATFS fs; FIL fsrc; /* file objects */ UINT br; // File R/W count enum ziType{ ziType_12, ziType_16, ziType_24, ziType_Max }; static u8 SPI_FLASH_BufferRead(char* getStr, char* zi, char ziType) { FRESULT res; u8 error[]="Cann't file HZK bin."; u8 zi_h = zi[0]; u8 zi_l = zi[1]; unsigned long int findAddr, ziSize; if(ziType == ziType_12){//12*12 = 24 findAddr = (unsigned long int)(((zi_h-0xa1)*94)+(zi_l-0xa1))*24; ziSize = 24; } else if(ziType == ziType_16){//16*16 = 32 findAddr = (unsigned long int)(((zi_h-0xa1)*94)+(zi_l-0xa1))*32+(unsigned long int)0x2FEB0; ziSize = 32; } else if(ziType == ziType_24){//24*24 = 72 findAddr = (unsigned long int)(((zi_h-0xa1)*94)+(zi_l-0xa1))*72+(unsigned long int)0x6FCF0; ziSize = 72; } else return 0; f_mount(0, &fs); //HZK16.bin /* Infinite loop */ res = f_open(&fsrc, "/sys/HZK.bin", FA_OPEN_EXISTING | FA_READ); /* 在SD卡里搜索HZK16.bin*/ if(res != 0) { PutStr((char *)error, 0, 0); return 0; } f_lseek(&fsrc, findAddr); f_read(&fsrc, getStr, ziSize, &br); f_close(&fsrc); f_mount(0, NULL); return 1; } static uint8_t Find_Chinese(uint8_t* str, uint8_t* p) { uint8_t High8bit,Low8bit; FRESULT res; uint8_t error[]="Please put the sys folder which include the font file HZK16.bin into the SD card root directory. "; High8bit=*str; /* 高8位数据 */ Low8bit=*(str+1); /* 低8位数据 */ f_mount(0, &fs); //HZK16.bin /* Infinite loop */ res = f_open(&fsrc, "/sys/ZK_1212_1616_2424.bin", FA_OPEN_EXISTING | FA_READ); /* 在SD卡里搜索HZK16.bin*/ if(res != 0) { LCD_ShowString(0,0,error,RED ,BLACK ); return 0; } f_lseek(&fsrc,32*((High8bit-0xa0-1)*94+(Low8bit-0xa0-1))); f_read(&fsrc, p, 32, &br); f_close(&fsrc); f_mount(0, NULL); return 1; } /********************************************************************************* * 名 称:void PutChinese(u16 x, u16 y, u8 *c, u32 PenColor, u32 BackColor) * 入口参数:u16 x,u16 y 字符坐标位置 u8 *c 汉字的指针 u32 PenColor画笔颜色 u32 BackColor背景颜色 * 出口参数:无 * 功 能:从SPI_FLASH里查找汉字基地址, 并将32字节的点阵数据送到LCD显示 * 说 明:只能被GUI_Put调用 *********************************************************************************/ u8 buffer_r[32]; u8 *c_r; void PutChinese(u16 x, u16 y, u8 *c, u32 PenColor, u32 BackColor) { //u16 i=0; //u16 j=0; u8 buffer[32]; //u16 tmp_char=0; if(!Find_Chinese(c,buffer)) { c_r = c; memcpy(buffer_r,buffer,32); WriteHanzi((char *)&buffer, x, y); #if 0 LCD_WindowMax(x,y,x+16,y+16); /*设置窗口*/ LCD_SetCursor(x,y); /*设置光标位置 */ LCD_WriteRAM_Prepare(); /* 16*16汉字点阵,共有16行 每行16个点,存储的时候是以字节为单位 需合并成字*/ for (i=0;i<16;i++) { tmp_char=buffer[i*2]; tmp_char=(tmp_char<<8); tmp_char|=buffer[2*i+1]; /*现在tmp_char存储着一行的点阵数据*/ for (j=0;j<16;j++) { if((tmp_char<>(15-i)?1:0; PlayBuffer[i] |= res<<(15-j); } } for (i=0;i<16;i++) { outBuffer2[i*2] = (PlayBuffer[i]&0xFF00)>>8; outBuffer2[i*2+1] = PlayBuffer[i]&0x00FF; } memcpy(inBuffer, outBuffer2, 32); } char hz_1[][32]={ // 我(0) 们(1) {0x04,0x20,0x04,0x20,0x44,0x42,0x44,0x41,0x7F,0xFE,0x84,0x80,0x84,0x80,0x04,0x08, 0x04,0x08,0xFF,0x10,0x04,0xE0,0x44,0x58,0x35,0x84,0x04,0x02,0x04,0x0F,0x00,0x00},/*"我",0*/ {0x01,0x00,0x02,0x00,0x0F,0xFE,0x38,0x00,0xC0,0x00,0x0F,0xFE,0x80,0x00,0x70,0x00, 0x20,0x00,0x00,0x00,0x20,0x00,0x20,0x04,0x20,0x02,0x3F,0xFC,0x00,0x00,0x00,0x00},/*"们",1*/ {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},/*"们",1*/ }; /********************************************************************************* * 名 称:void GUI_Put(u16 x, u16 y, u8 *str,u32 PenColor, u32 BackColor) * 入口参数:u16 x,u16 y 字符坐标位置 u8 *c 汉字的指针 u32 PenColor画笔颜色 u32 BackColor背景颜色 * 出口参数:无 * 功 能:计算汉字显示坐标 * 说 明: *********************************************************************************/ char hzk_buffer[32]; void DispOneChs12x12(u8 row,u8 addr,u8 *p); void GUI_Put(u16 x, u16 y, u8 *str,u32 PenColor, u32 BackColor) { //x:0~84 y:0~6 do { if ( *str < 0x80) /* 显示字符,字符点阵直接从font.h里调用,大小为16*8 */ { if (x>LCD_X) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y+=1; x=0; } if (y>LCD_Y) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y=0; } //6*8 DrawBitmap((char *)&ASCII_6_8[*str - 0x20][0], x, y, 6, 8); x+=6; str++; } else /*大于等于0x80判断为汉字字符*/ { if (x>LCD_X-12) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y+=1; x=0; } if (y>LCD_Y-1) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y=0; } #if 0 //16*16 if(Find_Chinese(str, hzk_buffer)) { xing2lie(hzk_buffer); DrawBitmap_col(hzk_buffer, x, y, 16, 16); //DrawBitmap(hzk_buffer, x, y, 16, 16); } #else if(SPI_FLASH_BufferRead(hzk_buffer,(char *)str,ziType_12)) { //DrawBitmap(hzk_buffer, x, y, 16, 16); DispOneChs12x12(y, x, hzk_buffer); } #endif x+=12;//16; str += 2; delay_ms(500); } }while(*str!=0); } /**********************************************************************/ u8 Y0Ram[84]; //第0行汉字的临时缓存 u8 Y1Ram[84]; u8 Y2Ram[84]; u8 Y3Ram[84]; #define Lcd5110SetXY(x,y) SetXY(x,y) #define Lcd5110WriteDta(x) LcdWrite(x,DATA) /*--------------------------------------------- 在某行某地址显示中文字符, -----------------------------------------------*/ void DispOneChs12x12(u8 row,u8 addr,u8 *p) { u8 i, LocalHalfWidth,LocalFullWidth; //半宽字体,全宽字体 if (row==0)//按照4行显示,首行为0,地址就是0-3行,不是控制器的地址 { Lcd5110SetXY(addr, row);// 列,页 for (i=0; i<12;i++) //上半部分 12个像素 { Lcd5110WriteDta(p[i]); } Lcd5110SetXY(addr, row+1); /*字体的下半部分需要存储起来*/ for (i=12; i<24;i++) //下半部分 12个像素 { Y0Ram[addr+i-12]=p[i]; //第0行的下半部分12个字节存起来,数组要保存文字的下半部分和这些数据在什么位置 0-83 Lcd5110WriteDta(Y0Ram[addr+i-12] | Y1Ram[addr+i-12]<<4 ); } } if (row==1) { Lcd5110SetXY(addr, row);// 列,页 for (i=0; i<12;i++) //上半部分 12个像素 { Y1Ram[addr+i]=p[i];//第1行上半部分存起来 Lcd5110WriteDta(Y1Ram[ addr+i]<<4 |Y0Ram[addr+i]); } Lcd5110SetXY(addr, row+1);// 列,页 for (i=12; i<24;i++) //下半部分 12个像素 { Lcd5110WriteDta(p[i]<<4 | p[i-12]>>4 ); } } if (row==2)//按照4行显示,首行为0,地址就是0-3行,不是控制器的地址 { Lcd5110SetXY(addr, row+1);// 列,页 for (i=0; i<12;i++) //上半部分 12个像素 { Lcd5110WriteDta(p[i]); } Lcd5110SetXY(addr, row+2); /*字体的下半部分需要存储起来*/ for (i=12; i<24;i++) //下半部分 12个像素 { Y2Ram[addr+i-12]=p[i]; //第0行的下半部分12个字节存起来,数组要保存文字的下半部分和这些数据在什么位置 0-83 Lcd5110WriteDta(Y2Ram[addr+i-12] | Y3Ram[addr+i-12]<<4 ); } } if (row==3) { Lcd5110SetXY(addr, row+1);// 列,页 for (i=0; i<12;i++) //上半部分 12个像素 { Y3Ram[addr+i]=p[i];//第1行上半部分存起来 Lcd5110WriteDta(Y3Ram[ addr+i]<<4 |Y2Ram[addr+i]); } Lcd5110SetXY(addr, row+2);// 列,页 for (i=12; i<24;i++) //下半部分 12个像素 { Lcd5110WriteDta(p[i]<<4 | p[i-12]>>4 ); } } }