裸机系列——s3c2440lcd汉字显示

来源:互联网 发布:淘宝秒杀显示无法购买 编辑:程序博客网 时间:2024/06/07 01:33

1、lcd裸机写好后在来弄lcd的字符显示就容易多了,理解字符其实就是一副图,比如16*16的汉子显示就是长宽16的一个正方形中用点来显示一个汉字,这样就只有弄清楚哪些点是要显示的就行了,比如第一行要显示一个点我们就可以 xxxxxxxoxxxxxxxx 现在只有把中间的圈显示其他的不显示这个点就出来了,那好我们就可以用一个数组来保存哪些是要显示的点,每一位表示是否要显示,当然这一位要显示什么颜色就是前面lcd的内容了。这里只是说明这个点要不要显示的问题,具体用什么颜色显示是可以设置的。

2、对于字模数组的提取现在已经有很多好用的字模提取软件,字库软件的,到网上搜一个然后就很容易了,只要输入想要显示的汉字软件就帮你把字模的数组显示好了,你只有把这个字模数组放到程序当中去就可以了。当然这里要注意字模提取的顺序,还有有些字模软件中可以设置要不要倒序的问题,这里我用的是 ZIMO221.EXE 这个软件,我的lcd的取模方式是 横向取模,字节不倒序,C51格式 ,当然要是有很多汉字要显示的话一个一个字去提取就不容易了,现在已经有人或者有一些标准已经把汉字弄成了一些字库,像16*16的话就标准库GB2312 ,但是注意,这些库好像要么是没有后缀名要么是数据库形式,对于裸机还是比较不方便,这里的话可以去找一下有人把这些做成了C语言数组形式这样就比较好用了,不过这样有点占内存,16*16 / 8 = 32 就是一个字占32个字节,常用汉字字符库的话一般有6 7千个,那么简单算一下应该就需要差不多200k的内存,对于单片机来说还是比较难以消化的。

3、有了字库我们就只需要找个我们需要的汉字然后取出来显示就好了,但是怎么找这么汉字,当然这么问题别人早已经解决了,首先对于汉字用俩个字节来编码的这一点要明白,然后GB2312将代码表分为94个区,对应第一字节(0xa1-0xfe);每个区94个位(0xa1-0xfe),对应第二字节,两个字节的值分别为区号值和位号值加32(2OH),因此也称为区位码。01-09区为符号、数字区,16-87区为汉字区(0xb0-0xf7),10-15区、88-94区是有待进一步标准化的空白区。GB2312将收录的汉字分成两级:第一级是常用汉字计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区,按部首/笔画顺序排列。故而GB2312最多能表示6763个汉字。这样我们查找汉字是就比较方便了,首先我们通过区号找个是属于哪个区,然后再通过位号找个属于哪个位就可以找到汉字了,注意上面说的区号值和位号值加32(2OH)才是分别对于编码汉字的俩个字节值,然后还有一点那就是找到位号后,因为一个汉字占32个字节,所以最后的索引位置还有乘以32,最后汉字在字库中的位置[94×区号+位号]×32 。

4、我们了解了上面的字库知识后还有一个问题,那是我们不是直接使用字库,而是把字库中的汉字提取出来做成了数组,这里存在俩个问题,一是,数组的索引是从0开始的,而字库是从1开始,所以索引的时候需要减1;二是有时候只需要用到汉字所以做成的数组就会把前面的字符去掉,或者我们手上只有汉字字库的数组的时候我们就要注意,这里因为前面去掉了字符和一些空的内容,索引值应该从第16个区开始,前面去掉了15个区,15个区,每个区94个位,15 x 94 = 1410 所以我们索引到时候还需要减去1410个位,得到的最后的索引就是[( 94*(qh-1)+(wh-1) -1410 )*32] ,qh 是区号 ,wh 是位号 。如果没有去掉前面15个区的内容的话那么索引就是 [94×(区号-1)+(位号-1)]×32 综合前面得到的区号和位号就可以得到字库的位置了。GB2312的编码范围为2121H-777EH,与ASCII有重叠,通行方法是将GB码两个字节的最高位置1以示区别。

代码:

/*************************************************file name LCD_hanzifunction显示16*16汉字 和 16*8 ASCII码字符硬件设备mini2440开发板索尼X-35 3.5寸液晶屏lcd参数宽和高 240x320TFT 16bpp显示完成时间2011-08-10作者周茂夫problem暂无修改记录暂无*************************************************/#defineGLOBAL_CLK1#include <stdlib.h>#include <string.h>#include "def.h"#include "option.h"#include "2440addr.h"#include "2440lib.h"#include "2440slib.h"#include "mmu.h"#include "profile.h"#include "memtest.h"#include "zifu.h"#define baudrate 115200 #defineLCD_WIDTH240#defineLCD_HEIGHT320//#define LCD_CLKCAL17//这个我计算出来是17参考程序给的是4 测试俩个都可以//影响不大 测试25 30 都还可以#define LCD_CLKCAL17#defineLCD_RIGHT_MARGIN 25#defineLCD_LEFT_MARGIN  0#defineLCD_HSYNC_LEN    4#defineLCD_UPPER_MARGIN 0#defineLCD_LOWER_MARGIN 4#defineLCD_VSYNC_LEN 9#defineLCD_XSIZELCD_WIDTH#defineLCD_YSIZELCD_HEIGHT#defineSCR_XSIZELCD_WIDTH#defineSCR_YSIZELCD_HEIGHTextern const unsigned char sunflower_240x320[] ;extern const unsigned char GB2312Dot16X16[] ;volatile static unsigned short LCD_BUFFER[SCR_YSIZE][SCR_XSIZE] ; //LCD BUFFER#define M5D(n)((n)&0x1fffff)  //设置显示缓存区时取地址的低21位#defineLCD_ADDR((U32)(LCD_BUFFER))/********横向取模,字节不倒序,C51格式 *******/unsigned char zhou[] = {0x00,0x00,0x1F,0xFC,0x10,0x84,0x13,0xE4,0x10,0x84,0x10,0x84,0x17,0xF4,0x10,0x04,0x13,0xE4,0x12,0x24,0x12,0x24,0x13,0xE4,0x22,0x24,0x20,0x04,0x40,0x14,0x80,0x08,} ;unsigned char mao[] = {0x04,0x40,0x04,0x40,0xFF,0xFE,0x04,0x40,0x00,0xA0,0x00,0x90,0x3F,0xFE,0x20,0x80,0x20,0x84,0x20,0x48,0x20,0x50,0x20,0x60,0x20,0xA0,0x43,0x12,0x4C,0x0A,0x80,0x04,} ;unsigned char Y[] ={0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,} ;unsigned char zhao[] = {0x00,0x00,  0xF7,0x7E,  0x95,0x04,  0x95,0x04,  0x96,0x74,  0x96,0x54,  0x95,0x54,  0x95,0x54,  0x95,0x54,  0xF5,0x54,  0x97,0x74,  0x04,0x04,  0x04,0x04,  0x04,0x04,  0x04,0x14,  0x04,0x08,} ;/**********************************void delay(int times){int i = 1000 ;while(times--){for(; i>0; --i);}}************************************//***********************************UART_int初始化led IO端口GPBCON5-8初始化GPBHCON为串口通信配置串口通信寄存器配置中断寄存器************************************/void UART_int_init(void){/********configuration LED IO port**********/rGPBCON &= ~(0xff<<10) ;rGPBCON |= 0x55<<10 ;/*******configuration GPHCON to UART*******/rGPHCON &= ~(0xf<<4) ;rGPHCON |=  0xa<<4 ;/****configuration UART0 communication register******/rULCON0 = 0x03 ;//8-bits,1 stop bit, no parityrUCON0  = 0x05 ;rUBRDIV0= (int)(PCLK/baudrate/16) -1 ;//configuration UART baudrate/*****clean interrupt bit clea RX_INT******/rSUBSRCPND |= 0x1 ;rSRCPND |= 1<<28 ;rINTPND |= 1<<28 ;/******open UART interrupt*********/rINTSUBMSK &= ~(0x1) ;rINTMSK &= ~(0x1<<28) ;}//UART send bytevoid UART_send_byte(char Tx_data){while(!(rUTRSTAT0&0x2)) ;//wait Tx emptyif(Tx_data == '\n')//Tx '\n'{rUTXH0 = 0x0d ;while(!(rUTRSTAT0&0x2)) ;rUTXH0 = 0x0a ;}else{rUTXH0 = Tx_data ;}}//UART send stringvoid UART_send_string(const char *str) {while(*str){UART_send_byte(*str) ;str++ ;}}//UART receive bytevoid UART_receive_byte(void) {char temp ;while(!(rUTRSTAT0&0x1)) ;//wait RX readytemp = rURXH0 ;switch(temp)//测试发送单个字符{case 's': rGPBDAT &= ~(0xf<<5) ; break ;case 'p': rGPBDAT |= (0xf<<5) ; break ;}UART_send_byte(temp) ;}/*******************************************中断处理函数置1清除中断,注意顺序,先子中断后父中断点亮led灯********************************************/void __irq UART0_interrupt(void){/******clean interrupt bit*************/rSUBSRCPND |= 0x1 ;rSRCPND |= 1<<28 ;rINTPND |= 1<<28 ;rGPBDAT &= ~(0xf<<5) ;//lighten ledUART_receive_byte(); }/****************************************************************functioninitialize LCD IO port VD[0:15] VM VLINE VCLK VFREAMinput voidreturnvoid*****************************************************************/static void Lcd_port_init(void){rGPCUP= 0xffffffff ; //Disable Pull-up registerrGPCCON= 0xaaaa02a8 ; //Initialize VD[7:0],VM,VFREAM,VLINE,VCLKrGPDUP= 0xffffffff ; //Disable Pull-up registerrGPDCON= 0xaaaaaaaa ; //Initialize VD[15:8]}/****************************************************************functionconfigarution LCDCON1-5 LCDSADDR1-3 LCD INTERRUPT TPALetc register TFT 16bppinput voidreturnvoid*****************************************************************/static void Lcd_init(void){rLCDCON1 = (LCD_CLKCAL<<8) | (3<<5) | (12<<1) ;   rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);   rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH  - 1) <<  8) | (LCD_LEFT_MARGIN << 0);   rLCDCON4 = (LCD_HSYNC_LEN << 0);   rLCDCON5 = (1<<11) | (1 << 9) | (1 << 8) | (1<<6) | (1 << 3) | (1 << 0) ;rLCDSADDR1= ((LCD_ADDR>>22)<<21) | (M5D(LCD_ADDR>>1)) ;//LCDBASEL OFFSIZE=0,PAGEWIDTH=LCD_WIDTH, x2的原因 16bpp 每个像素点2个字节,>>1见地址对应关系 16bpprLCDSADDR2= M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2)>>1) ; rLCDSADDR3= LCD_WIDTH ;  rLCDINTMSK|= 3 ; //屏蔽中断 rTCONSEL= 0 ;  //LPC3600 LCC3600 无效 rTPAL= 0 ;  //禁止临时调色板 }/****************************************************************functionEnvid turn on or offinput onoff1,Envid turn onreturnvoid*****************************************************************/static void Lcd_EnvidOnOff(int onoff){ if(onoff==1) rLCDCON1 |= 1 ; //ENVID ON else rLCDCON1 &= ~(1<<0) ; //ENBID OFF}/****************************************************************functionLCD power enableinput pwren1, enable lcd powerreturnvoid*****************************************************************/static void Lcd_PowerEnable(int pwren){ rGPGUP|= (1<<4) ; //Pull-up Disable rGPGCON|= (3<<8) ; //GPG4 is LCD_PWREN  rLCDCON5&= ~(1<<5) ;//invpwren 正常极性 rLCDCON5 = rLCDCON5 & ~(1<<3)|(pwren<<3) ;//PWREN 使能}/****************************************************************functionFilling sole colour into LCD backgroundinput c colourreturnvoid*****************************************************************/ static void Lcd_FillCor(U16 c){ unsigned int x,y ; for(y=0; y<SCR_YSIZE; y++) { for(x=0; x<SCR_XSIZE; x++) { LCD_BUFFER[y][x] = c ; } }}/****************************************************************functionPaint pictureinput x0 y0assign start bitlevel verticalthe wide and high of picture*bmpthe picture stringreturnvoid*****************************************************************/ static void Paint_BMP(int x0, int y0, int level, int vertical, const unsigned char *bmp) { int x, y ; U32 col ; int p = 0 ;  for(y=0; y<vertical; y++) { for(x=0; x<level; x++) { col = bmp[p+1] | (bmp[p]<<8) ;//16bpp 一个像素点用俩个字节 if( ((x0+x)<SCR_XSIZE) && ((y0+y)<SCR_YSIZE)) LCD_BUFFER[y0+y][x0+x] = col ; p += 2 ; } }}/****************************************************************functionDisplay  像素点input x  ydisplay start bitcolcolor of the charreturnvoid*****************************************************************/ static void PutPixel(U32 x, U32 y, U16 col){LCD_BUFFER[y][x] = col ;}/****************************************************************functionDisplay 汉字 hzk16 16*16input x  ydisplay start bitcolcolor of the charch[]字模数组returnvoid*****************************************************************/ static void Draw_Text16(U32 x, U32 y, U16 col, const unsigned char ch[]){unsigned short i, j ;unsigned char mask, tem ;for(i=0; i<16; i++){mask= 0x80 ;tem= ch[i*2] ;//俩个字节一组16位,取第一个字节for(j=0; j<8; j++){if(tem & mask){PutPixel(x+j, y+i, col) ;}mask = mask >> 1 ;} mask = 0x80 ;tem = ch[i*2 + 1] ;for(j=0; j<8; j++){if(tem & mask){PutPixel(x+j+8, y+i, col) ;}mask = mask >> 1 ;}}}/****************************************************************functionDisplay ASCII 字符  16*8input x  ydisplay start bitcolcolor of the charch[]字模数组returnvoid*****************************************************************/ static void Draw_ASCII(U32 x, U32 y, U16 col, const unsigned char ch[]){unsigned short i, j ;unsigned char temp, mask ;for(i=0; i<16; i++){mask = 0x80 ;temp = ch[i] ;for(j=0; j<8; j++){if(mask & temp){PutPixel(x+j, y+i, col) ;}mask = mask >> 1 ;}}}/****************************************************************functionDisplay 汉字字符  16*16input x  ydisplay start bitcolcolor of the charstr[]字符数组strlen 字符串长度 字节表示returnvoid*****************************************************************/ static void Draw_ch_lib(U32 x, U32 y, U16 col, const unsigned char str[], unsigned int strlen){int loc, i ;unsigned char qh, wh ;const unsigned char *pchlib ;for(loc=0, i=0; i<strlen; i++){if(str[i] & 0x80){qh = str[i]  - 0xa0 ;wh = str[i+1] - 0xa0 ;pchlib = &GB2312Dot16X16[( 94*(qh-1)+(wh-1) -1410 )*32]  ;Draw_Text16( x+loc, y, col, pchlib ) ;i++ ;loc += 16 ;}}}/*******************************************************************串口UART是挂在PCLK总线上的,需要设置PCLK时钟,即需要设置2440时钟。首先需要设置PLLCON寄存器设置CPU时钟(FCLK),然后设置FCLK HCLK PCLK的分频比,确定好PCLK时钟。*****************************************************************/int Main(void){unsigned int length ;unsigned char display[] = "啊周茂夫是个大笨蛋"  ;/*****************【CLOCK】******************/MMU_Init();ChangeMPllValue(127,2,1);//405MHZChangeClockDivider(13,12);        //1:3:6/**************【UART】**********************/UART_int_init() ;UART_send_string("wo zhen de hen yun si \n") ;pISR_UART0 = (U32)UART0_interrupt ;/*************【LCD】************************/Lcd_port_init() ;Lcd_init() ;Lcd_PowerEnable(1) ;Lcd_EnvidOnOff(1) ;UART_send_string("LCD initial \n") ;Lcd_FillCor(0xffff) ;Draw_Text16(16, 20, 0x0, zhou) ;Draw_Text16(32, 20, 0x0, mao) ; //汉字后需要16位Draw_ASCII (48, 20, 0x0, Y ) ;Draw_ASCII (56, 20, 0x0, Y ) ;Draw_Text16 (100, 20, 0x0, zhao ) ;Draw_Text16(80, 20, 0x0, zhou) ;length = sizeof(display) - 1 ; //用sizeof可以直接算出数组占内存的字节数,减去1//字符串结束符占一个字节Draw_ch_lib(10, 100,0x0, display, length) ;while(1) {//Lcd_FillCor((0x00<<11) | (0x00<<5) | (0x00<<0)) ; //clear screen//Paint_BMP(0,0,240,320,sunflower_240x320) ;//filling picture sunflower}return 0 ;}




原创粉丝点击