#include "nokia_5110.h" #include "english_6x8_pixel.h" #include "write_chinese_string_pixel.h" #include "stdio.h" #include "stdlib.h" #include "delay.h" #include "SPI-SD/Lcd/font.h" #include "SPI-SD/Fatfs/ff.h" char n5110_string[6][14]; //6行,每行13byte /*----------------------------------------------------------------------- LCD_init : 3310LCD初始化 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -----------------------------------------------------------------------*/ void LCD_init ( void ) { #if LCD_def // 产生一个让LCD复位的低电平脉冲 LCD_RST = 0; delay_us ( 1 ); LCD_RST = 1; // 关闭LCD LCD_CE = 0; delay_us ( 1 ); // 使能LCD LCD_CE = 1; delay_us ( 1 ); LCD_write_byte ( 0x21, 0 ); // 使用扩展命令设置LCD模式 LCD_write_byte ( 0xc8, 0 ); // 设置偏置电压 LCD_write_byte ( 0x06, 0 ); // 温度校正 LCD_write_byte ( 0x13, 0 ); // 1:48 LCD_write_byte ( 0x20, 0 ); // 使用基本命令 LCD_clear(); // 清屏 LCD_write_byte ( 0x0c, 0 ); // 设定显示模式,正常显示 // 关闭LCD LCD_CE = 0; //开启背光灯 BACKLIGHT = 1; #endif } /*----------------------------------------------------------------------- LCD_clear : LCD清屏函数 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -----------------------------------------------------------------------*/ void LCD_clear ( void ) { unsigned int i; LCD_write_byte ( 0x0c, 0 ); LCD_write_byte ( 0x80, 0 ); for ( i = 0; i < 504; i++ ) LCD_write_byte ( 0, 1 ); } /*----------------------------------------------------------------------- LCD_set_XY : 设置LCD坐标函数 输入参数:X :0-83 Y :0-5 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -----------------------------------------------------------------------*/ void LCD_set_XY ( unsigned char X, unsigned char Y ) { LCD_write_byte ( 0x40 | Y, 0 ); // column LCD_write_byte ( 0x80 | X, 0 ); // row } /*----------------------------------------------------------------------- LCD_write_char : 显示英文字符 输入参数:c :显示的字符; 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -----------------------------------------------------------------------*/ void LCD_write_char ( unsigned char c ) { unsigned char line; c -= 32; for ( line = 0; line < 6; line++ ) LCD_write_byte ( font6x8[c][line], 1 ); } /*----------------------------------------------------------------------- LCD_write_english_String : 英文字符串显示函数 输入参数:*s :英文字符串指针; X、Y : 显示字符串的位置,x 0-83 ,y 0-5 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -----------------------------------------------------------------------*/ void LCD_write_english_string ( unsigned char X, unsigned char Y, char *s ) { #if LCD_def LCD_set_XY ( X, Y ); while ( *s ) { LCD_write_char ( *s ); s++; } #endif } /*----------------------------------------------------------------------- LCD_write_chinese_string: 在LCD上显示汉字 输入参数:X、Y :显示汉字的起始X、Y坐标; ch_with :汉字点阵的宽度 num :显示汉字的个数; line :汉字点阵数组中的起始行数 row :汉字显示的行间距 编写日期 :2004-8-11 最后修改日期 :2004-8-12 测试: LCD_write_chi(0,0,12,7,0,0); LCD_write_chi(0,2,12,7,0,0); LCD_write_chi(0,4,12,7,0,0); -----------------------------------------------------------------------*/ void LCD_write_chinese_string ( unsigned char X, unsigned char Y, unsigned char ch_with, unsigned char num, unsigned char line, unsigned char row ) { unsigned char i, n; LCD_set_XY ( X, Y ); //设置初始位置 for ( i = 0; i < num; ) { for ( n = 0; n < ch_with * 2; n++ ) //写一个汉字 { if ( n == ch_with ) //写汉字的下半部分 { if ( i == 0 ) LCD_set_XY ( X, Y + 1 ); else LCD_set_XY ( ( X + ( ch_with + row ) *i ), Y + 1 ); } LCD_write_byte ( write_chinese[line + i][n], 1 ); } i++; LCD_set_XY ( ( X + ( ch_with + row ) *i ), Y ); } } /*----------------------------------------------------------------------- LCD_draw_map : 位图绘制函数 输入参数:X、Y :位图绘制的起始X、Y坐标; *map :位图点阵数据; Pix_x :位图像素(长) Pix_y :位图像素(宽) 编写日期 :2004-8-13 最后修改日期 :2004-8-13 -----------------------------------------------------------------------*/ void LCD_draw_bmp_pixel ( unsigned char X, unsigned char Y, unsigned char *map, unsigned char Pix_x, unsigned char Pix_y ) { unsigned int i, n; unsigned char row; if ( Pix_y % 8 == 0 ) row = Pix_y / 8; //计算位图所占行数 else row = Pix_y / 8 + 1; for ( n = 0; n < row; n++ ) { LCD_set_XY ( X, Y ); for ( i = 0; i < Pix_x; i++ ) { LCD_write_byte ( map[i + n * Pix_x], 1 ); } Y++; //换行 } } /*----------------------------------------------------------------------- LCD_write_byte : 使用SPI接口写数据到LCD 输入参数:data :写入的数据; command :写数据/命令选择; 编写日期 :2004-8-10 最后修改日期 :2004-8-13 -----------------------------------------------------------------------*/ void LCD_write_byte ( unsigned char dat, unsigned char command ) { unsigned char i; //PORTB &= ~LCD_CE ; // 使能LCD LCD_CE = 0; if ( command == 0 ) // PORTB &= ~LCD_DC ; // 传送命令 LCD_DC = 0; else // PORTB |= LCD_DC ; // 传送数据 LCD_DC = 1; for ( i = 0; i < 8; i++ ) { if ( dat & 0x80 ) SDIN = 1; else SDIN = 0; SCLK = 0; dat = dat << 1; SCLK = 1; } // SPDR = data; // 传送数据到SPI寄存器 //while ((SPSR & 0x80) == 0); // 等待数据传送完毕 //PORTB |= LCD_CE ; // 关闭LCD LCD_CE = 1; } void RefreshLCD ( void ) { #if LCD_def u8 i; for ( i = 0; i < 6; i++ ) { LCD_write_english_string ( 0, i, n5110_string[i] ); } #endif } #define LCD_Clear(c) LCD_clear() /********************************************************************************* 名称:void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor) 参数:x,y 起始坐标 p 指向字符串起始地址 PenColor 字符颜色 BackColor 背景颜色 功能: 备注:用16字体,可以调节 此函数不能单独调用 *********************************************************************************/ void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor) { uint8_t size = 16; /*---字符大小默认16*8---*/ if(x>MAX_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表示非叠加方式*/ LCD_set_XY ( x, y ); LCD_write_char(*p); } /********************************************************************************* *名称: 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); /* 显示字符 */ LCD_draw_bmp_pixel(x0, y0, (u8 *)&(ptGb16[usIndex].Msk[0]),16, 16 ); } /********************************************************************************* *名称: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; } } } /*--------------下面三个函数 实现字库的调用及显示-------------------*/ FATFS fs; FIL fsrc; /* file objects */ UINT br; // File R/W count 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); /* Infinite loop */ res = f_open(&fsrc, "/sys/HZK16.bin", FA_OPEN_EXISTING | FA_READ); /* 在SD卡里搜索HZK16.bin*/ if(res != 0) { LCD_ShowString(32,100,error,RED ,BLACK ); return 1; } 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 0; } /********************************************************************************* * 名 称: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); LCD_draw_bmp_pixel(x,y,(u8 *)buffer,16,16); #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<MAX_HZ_POSX) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y+=16; x=0; } if (y>MAX_HZ_POSY) /*保证剩余的空间能放下一个16*16的字,否则换行 */ { y=0; } if ( *str < 0x80) /* 显示字符,字符点阵直接从font.h里调用,大小为16*8 */ { LCD_ShowCharString(x, y, str, PenColor, BackColor); x+= 8; str++; } else /*大于等于0x80判断为汉字字符*/ { PutChinese(x, y, str++, PenColor, BackColor); str++; x+=16; } }while(*str!=0); }