Chinaunix首页 | 论坛 | 博客
  • 博客访问: 64985
  • 博文数量: 38
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 138
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-26 16:24
文章分类

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-03-17 16:02: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以示区别。

代码:

  1. /*************************************************
  2. file name     LCD_hanzi
  3. function    显示16*16汉字 和 16*8 ASCII码字符
  4. 硬件设备    mini2440开发板
  5.         索尼X-35 3.5寸液晶屏
  6. lcd参数    宽和高 240x320
  7.         TFT 16bpp显示
  8. 完成时间    2011-08-10
  9. 作者        周茂夫
  10. problem    暂无
  11. 修改记录    暂无
  12. *************************************************/
  13. #define    GLOBAL_CLK        1

  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "def.h"
  17. #include "option.h"
  18. #include "2440addr.h"
  19. #include "2440lib.h"
  20. #include "2440slib.h"
  21. #include "mmu.h"
  22. #include "profile.h"
  23. #include "memtest.h"
  24. #include "zifu.h"

  25. #define baudrate 115200

  26. #define    LCD_WIDTH    240
  27. #define    LCD_HEIGHT    320
  28. //#define LCD_CLKCAL    17    //这个我计算出来是17参考程序给的是4 测试俩个都可以
  29.                             //影响不大 测试25 30 都还可以
  30. #define LCD_CLKCAL    17        

  31. #define    LCD_RIGHT_MARGIN 25
  32. #define    LCD_LEFT_MARGIN 0
  33. #define    LCD_HSYNC_LEN 4

  34. #define    LCD_UPPER_MARGIN 0
  35. #define    LCD_LOWER_MARGIN 4
  36. #define    LCD_VSYNC_LEN 9

  37. #define    LCD_XSIZE    LCD_WIDTH
  38. #define    LCD_YSIZE    LCD_HEIGHT
  39. #define    SCR_XSIZE    LCD_WIDTH
  40. #define    SCR_YSIZE    LCD_HEIGHT

  41. extern const unsigned char sunflower_240x320[] ;
  42. extern const unsigned char GB2312Dot16X16[] ;
  43. volatile static unsigned short LCD_BUFFER[SCR_YSIZE][SCR_XSIZE] ; //LCD BUFFER

  44. #define M5D(n)        ((n)&0x1fffff) //设置显示缓存区时取地址的低21位
  45. #define    LCD_ADDR    ((U32)(LCD_BUFFER))    

  46. /********横向取模,字节不倒序,C51格式 *******/
  47. unsigned char zhou[] =
  48. {
  49. 0x00,0x00,0x1F,0xFC,0x10,0x84,0x13,0xE4,0x10,0x84,0x10,0x84,0x17,0xF4,0x10,0x04,
  50. 0x13,0xE4,0x12,0x24,0x12,0x24,0x13,0xE4,0x22,0x24,0x20,0x04,0x40,0x14,0x80,0x08,
  51. } ;

  52. unsigned char mao[] =
  53. {
  54. 0x04,0x40,0x04,0x40,0xFF,0xFE,0x04,0x40,0x00,0xA0,0x00,0x90,0x3F,0xFE,0x20,0x80,
  55. 0x20,0x84,0x20,0x48,0x20,0x50,0x20,0x60,0x20,0xA0,0x43,0x12,0x4C,0x0A,0x80,0x04,
  56. } ;

  57. unsigned char Y[] =
  58. {
  59. 0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,
  60. } ;

  61. unsigned char zhao[] =
  62. {
  63. 0x00,0x00, 0xF7,0x7E, 0x95,0x04, 0x95,0x04,
  64. 0x96,0x74, 0x96,0x54, 0x95,0x54, 0x95,0x54,
  65. 0x95,0x54, 0xF5,0x54, 0x97,0x74, 0x04,0x04,
  66. 0x04,0x04, 0x04,0x04, 0x04,0x14, 0x04,0x08,
  67. } ;

  68. /**********************************
  69. void delay(int times)
  70. {
  71.     int i = 1000 ;
  72.     while(times--)
  73.     {
  74.         for(; i>0; --i)
  75.             ;
  76.     }
  77. }
  78. ************************************/
  79. /***********************************
  80. UART_int初始化led IO端口GPBCON5-8
  81. 初始化GPBHCON为串口通信
  82. 配置串口通信寄存器
  83. 配置中断寄存器
  84. ************************************/
  85. void UART_int_init(void)
  86. {
  87.     /********configuration LED IO port**********/
  88.     rGPBCON &= ~(0xff<<10) ;
  89.     rGPBCON |= 0x55<<10 ;
  90.     
  91.     /*******configuration GPHCON to UART*******/
  92.     rGPHCON &= ~(0xf<<4) ;
  93.     rGPHCON |= 0xa<<4 ;
  94.     
  95.     /****configuration UART0 communication register******/
  96.     rULCON0 = 0x03 ;                        //8-bits,1 stop bit, no parity
  97.     rUCON0 = 0x05 ;
  98.     rUBRDIV0= (int)(PCLK/baudrate/16) -1 ;    //configuration UART baudrate
  99.     
  100.     /*****clean interrupt bit clea RX_INT******/
  101.     rSUBSRCPND |= 0x1 ;
  102.     rSRCPND |= 1<<28 ;
  103.     rINTPND |= 1<<28 ;

  104.     /******open UART interrupt*********/
  105.     rINTSUBMSK &= ~(0x1) ;
  106.     rINTMSK &= ~(0x1<<28) ;    
  107. }

  108. //UART send byte
  109. void UART_send_byte(char Tx_data)
  110. {
  111.     while(!(rUTRSTAT0&0x2)) ;//wait Tx empty
  112.     if(Tx_data == '\n')        //Tx '\n'
  113.     {
  114.         rUTXH0 = 0x0d ;
  115.         while(!(rUTRSTAT0&0x2)) ;
  116.         rUTXH0 = 0x0a ;
  117.     }
  118.     else
  119.     {
  120.         rUTXH0 = Tx_data ;
  121.     }
  122. }
  123. //UART send string
  124. void UART_send_string(const char *str)
  125. {
  126.     while(*str)
  127.     {
  128.         UART_send_byte(*str) ;
  129.         str++ ;
  130.     }
  131. }
  132. //UART receive byte
  133. void UART_receive_byte(void)
  134. {
  135.     char temp ;
  136.     
  137.     while(!(rUTRSTAT0&0x1)) ;    //wait RX ready
  138.     
  139.     temp = rURXH0 ;
  140.     
  141.     switch(temp)            //测试发送单个字符
  142.     {
  143.         case 's': rGPBDAT &= ~(0xf<<5) ; break ;
  144.         case 'p': rGPBDAT |= (0xf<<5) ; break ;
  145.     }
  146.     UART_send_byte(temp) ;
  147. }
  148. /*******************************************
  149. 中断处理函数
  150. 置1清除中断,注意顺序,先子中断后父中断
  151. 点亮led灯
  152. ********************************************/
  153. void __irq UART0_interrupt(void)
  154. {
  155.     /******clean interrupt bit*************/
  156.     rSUBSRCPND |= 0x1 ;
  157.     rSRCPND |= 1<<28 ;
  158.     rINTPND |= 1<<28 ;
  159.     
  160.     rGPBDAT &= ~(0xf<<5) ;    //lighten led
  161.     UART_receive_byte();
  162. }
  163. /****************************************************************
  164. function    initialize LCD IO port VD[0:15] VM VLINE VCLK VFREAM
  165. input         void
  166. return        void
  167. *****************************************************************/
  168. static void Lcd_port_init(void)
  169. {
  170.     rGPCUP    = 0xffffffff ; //Disable Pull-up register
  171.     rGPCCON    = 0xaaaa02a8 ; //Initialize VD[7:0],VM,VFREAM,VLINE,VCLK
  172.     
  173.     rGPDUP    = 0xffffffff ; //Disable Pull-up register
  174.     rGPDCON    = 0xaaaaaaaa ; //Initialize VD[15:8]
  175.     
  176. }
  177. /****************************************************************
  178. function    configarution LCDCON1-5 LCDSADDR1-3 LCD INTERRUPT TPAL
  179.             etc register TFT 16bpp
  180. input         void
  181. return        void
  182. *****************************************************************/
  183. static void Lcd_init(void)
  184. {
  185.     rLCDCON1 = (LCD_CLKCAL<<8) | (3<<5) | (12<<1) ;    
  186.        rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);
  187.        rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH - 1) << 8) | (LCD_LEFT_MARGIN << 0);
  188.        rLCDCON4 = (LCD_HSYNC_LEN << 0);    
  189.        rLCDCON5 = (1<<11) | (1 << 9) | (1 << 8) | (1<<6) | (1 << 3) | (1 << 0) ;
  190.     
  191.     rLCDSADDR1    = ((LCD_ADDR>>22)<<21) | (M5D(LCD_ADDR>>1)) ;
  192.     //LCDBASEL OFFSIZE=0,PAGEWIDTH=LCD_WIDTH, x2的原因 16bpp 每个像素点2个字节,>>1见地址对应关系 16bpp
  193.     rLCDSADDR2    = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2)>>1) ;
  194.      rLCDSADDR3    = LCD_WIDTH ;
  195.      
  196.      rLCDINTMSK    |= 3 ; //屏蔽中断
  197.      rTCONSEL    = 0 ; //LPC3600 LCC3600 无效
  198.      rTPAL        = 0 ; //禁止临时调色板
  199.  }
  200. /****************************************************************
  201. function    Envid turn on or off
  202. input         onoff    1,Envid turn on
  203. return        void
  204. *****************************************************************/
  205. static void Lcd_EnvidOnOff(int onoff)
  206. {
  207.      if(onoff==1)
  208.          rLCDCON1 |= 1 ; //ENVID ON
  209.      else
  210.          rLCDCON1 &= ~(1<<0) ; //ENBID OFF
  211. }
  212. /****************************************************************
  213. function    LCD power enable
  214. input         pwren    1, enable lcd power
  215. return        void
  216. *****************************************************************/
  217. static void Lcd_PowerEnable(int pwren)
  218. {
  219.      rGPGUP    |= (1<<4) ; //Pull-up Disable
  220.      rGPGCON    |= (3<<8) ; //GPG4 is LCD_PWREN
  221.      
  222.      rLCDCON5&= ~(1<<5) ;    //invpwren 正常极性
  223.      rLCDCON5 = rLCDCON5 & ~(1<<3)|(pwren<<3) ;    //PWREN 使能
  224. }
  225. /****************************************************************
  226. function    Filling sole colour into LCD background
  227. input         c         colour
  228. return        void
  229. *****************************************************************/
  230. static void Lcd_FillCor(U16 c)
  231. {
  232.      unsigned int x,y ;
  233.      for(y=0; y<SCR_YSIZE; y++)
  234.      {
  235.          for(x=0; x<SCR_XSIZE; x++)
  236.          {
  237.              LCD_BUFFER[y][x] = c ;        
  238.          }
  239.      }
  240. }
  241. /****************************************************************
  242. function    Paint picture
  243. input         x0 y0            assign start bit
  244.             level vertical    the wide and high of picture
  245.             *bmp            the picture string
  246. return        void
  247. *****************************************************************/
  248. static void Paint_BMP(int x0, int y0, int level, int vertical, const unsigned char *bmp)
  249. {
  250.      int x, y ;
  251.      U32 col ;
  252.      int p = 0 ;
  253.      
  254.      for(y=0; y<vertical; y++)
  255.      {
  256.          for(x=0; x<level; x++)
  257.          {
  258.              col = bmp[p+1] | (bmp[p]<<8) ;    //16bpp 一个像素点用俩个字节
  259.              if( ((x0+x)<SCR_XSIZE) && ((y0+y)<SCR_YSIZE))
  260.                  LCD_BUFFER[y0+y][x0+x] = col ;
  261.              p += 2 ;
  262.          }
  263.      }
  264. }
  265. /****************************************************************
  266. function    Display 像素点
  267. input         x y    display start bit
  268.             col        color of the char
  269. return        void
  270. *****************************************************************/
  271. static void PutPixel(U32 x, U32 y, U16 col)
  272. {
  273.     LCD_BUFFER[y][x] = col ;
  274. }
  275. /****************************************************************
  276. function    Display 汉字 hzk16 16*16
  277. input         x y    display start bit
  278.             col        color of the char
  279.             ch[]    字模数组
  280. return        void
  281. *****************************************************************/
  282. static void Draw_Text16(U32 x, U32 y, U16 col, const unsigned char ch[])
  283. {
  284.     unsigned short i, j ;
  285.     unsigned char mask, tem ;
  286.     for(i=0; i<16; i++)
  287.     {
  288.         mask= 0x80 ;
  289.         tem    = ch[i*2] ;    //俩个字节一组16位,取第一个字节
  290.         for(j=0; j<8; j++)
  291.         {
  292.             if(tem & mask)
  293.             {
  294.                 PutPixel(x+j, y+i, col) ;
  295.             }
  296.             mask = mask >> 1 ;
  297.         }
  298.         
  299.         mask = 0x80 ;
  300.         tem = ch[i*2 + 1] ;
  301.         for(j=0; j<8; j++)
  302.         {
  303.             if(tem & mask)
  304.             {
  305.                 PutPixel(x+j+8, y+i, col) ;
  306.             }
  307.             mask = mask >> 1 ;
  308.         }
  309.     }
  310. }
  311. /****************************************************************
  312. function    Display ASCII 字符 16*8
  313. input         x y    display start bit
  314.             col        color of the char
  315.             ch[]    字模数组
  316. return        void
  317. *****************************************************************/
  318. static void Draw_ASCII(U32 x, U32 y, U16 col, const unsigned char ch[])
  319. {
  320.     unsigned short i, j ;
  321.     unsigned char temp, mask ;
  322.     for(i=0; i<16; i++)
  323.     {
  324.         mask = 0x80 ;
  325.         temp = ch[i] ;
  326.         for(j=0; j<8; j++)
  327.         {
  328.             if(mask & temp)
  329.             {
  330.                 PutPixel(x+j, y+i, col) ;
  331.             }
  332.             mask = mask >> 1 ;
  333.         }
  334.     }
  335. }
  336. /****************************************************************
  337. function    Display 汉字字符 16*16
  338. input         x y    display start bit
  339.             col        color of the char
  340.             str[]    字符数组
  341.             strlen 字符串长度 字节表示
  342. return        void
  343. *****************************************************************/
  344. static void Draw_ch_lib(U32 x, U32 y, U16 col, const unsigned char str[], unsigned int strlen)
  345. {
  346.     int loc, i ;
  347.     unsigned char qh, wh ;
  348.     const unsigned char *pchlib ;
  349.     
  350.     for(loc=0, i=0; i<strlen; i++)
  351.     {
  352.         if(str[i] & 0x80)
  353.         {
  354.             qh = str[i] - 0xa0 ;
  355.             wh = str[i+1] - 0xa0 ;
  356.             pchlib = &GB2312Dot16X16[( 94*(qh-1)+(wh-1) -1410 )*32] ;
  357.             Draw_Text16( x+loc, y, col, pchlib ) ;
  358.             i++ ;
  359.             loc += 16 ;
  360.         }
  361.     }
  362. }
  363. /*******************************************************************
  364. 串口UART是挂在PCLK总线上的,需要设置PCLK时钟,即需要设置2440时钟。
  365. 首先需要设置PLLCON寄存器设置CPU时钟(FCLK),然后设置FCLK HCLK PCLK的
  366. 分频比,确定好PCLK时钟。
  367. *****************************************************************/
  368. int Main(void)
  369. {
  370.     unsigned int length ;
  371.     unsigned char display[] = "啊周茂夫是个大笨蛋" ;
  372.     /*****************【CLOCK】******************/
  373.     MMU_Init();
  374.     ChangeMPllValue(127,2,1);        //405MHZ
  375.     ChangeClockDivider(13,12); //1:3:6    
  376.     
  377.     /**************【UART】**********************/
  378.     UART_int_init() ;
  379.     UART_send_string("wo zhen de hen yun si \n") ;    
  380.     pISR_UART0 = (U32)UART0_interrupt ;
  381.     /*************【LCD】************************/
  382.     Lcd_port_init() ;
  383.     Lcd_init() ;
  384.     Lcd_PowerEnable(1) ;
  385.     Lcd_EnvidOnOff(1) ;
  386.     UART_send_string("LCD initial \n") ;
  387.     
  388.     Lcd_FillCor(0xffff) ;
  389.     Draw_Text16(16, 20, 0x0, zhou)     ;
  390.     Draw_Text16(32, 20, 0x0, mao)     ;     //汉字后需要16位
  391.     Draw_ASCII (48, 20, 0x0, Y )     ;
  392.     Draw_ASCII (56, 20, 0x0, Y )     ;
  393.     Draw_Text16 (100, 20, 0x0, zhao )     ;    
  394.     Draw_Text16(80, 20, 0x0, zhou)     ;    
  395.     
  396.     length = sizeof(display) - 1 ;     //用sizeof可以直接算出数组占内存的字节数,减去1
  397.                                     //字符串结束符占一个字节
  398.     Draw_ch_lib(10, 100,0x0, display, length) ;

  399.     while(1)
  400.     {
  401.         //Lcd_FillCor((0x00<<11) | (0x00<<5) | (0x00<<0)) ;     //clear screen
  402.         //Paint_BMP(0,0,240,320,sunflower_240x320) ;            //filling picture sunflower
  403.     }
  404.     return 0 ;
  405. }
阅读(212) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~