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_hanzi
-
function 显示16*16汉字 和 16*8 ASCII码字符
-
硬件设备 mini2440开发板
-
索尼X-35 3.5寸液晶屏
-
lcd参数 宽和高 240x320
-
TFT 16bpp显示
-
完成时间 2011-08-10
-
作者 周茂夫
-
problem 暂无
-
修改记录 暂无
-
*************************************************/
-
#define GLOBAL_CLK 1
-
-
#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
-
-
#define LCD_WIDTH 240
-
#define LCD_HEIGHT 320
-
//#define LCD_CLKCAL 17 //这个我计算出来是17参考程序给的是4 测试俩个都可以
-
//影响不大 测试25 30 都还可以
-
#define LCD_CLKCAL 17
-
-
#define LCD_RIGHT_MARGIN 25
-
#define LCD_LEFT_MARGIN 0
-
#define LCD_HSYNC_LEN 4
-
-
#define LCD_UPPER_MARGIN 0
-
#define LCD_LOWER_MARGIN 4
-
#define LCD_VSYNC_LEN 9
-
-
#define LCD_XSIZE LCD_WIDTH
-
#define LCD_YSIZE LCD_HEIGHT
-
#define SCR_XSIZE LCD_WIDTH
-
#define SCR_YSIZE LCD_HEIGHT
-
-
extern 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位
-
#define LCD_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 parity
-
rUCON0 = 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 byte
-
void UART_send_byte(char Tx_data)
-
{
-
while(!(rUTRSTAT0&0x2)) ;//wait Tx empty
-
if(Tx_data == '\n') //Tx '\n'
-
{
-
rUTXH0 = 0x0d ;
-
while(!(rUTRSTAT0&0x2)) ;
-
rUTXH0 = 0x0a ;
-
}
-
else
-
{
-
rUTXH0 = Tx_data ;
-
}
-
}
-
//UART send string
-
void UART_send_string(const char *str)
-
{
-
while(*str)
-
{
-
UART_send_byte(*str) ;
-
str++ ;
-
}
-
}
-
//UART receive byte
-
void UART_receive_byte(void)
-
{
-
char temp ;
-
-
while(!(rUTRSTAT0&0x1)) ; //wait RX ready
-
-
temp = 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 led
-
UART_receive_byte();
-
}
-
/****************************************************************
-
function initialize LCD IO port VD[0:15] VM VLINE VCLK VFREAM
-
input void
-
return void
-
*****************************************************************/
-
static void Lcd_port_init(void)
-
{
-
rGPCUP = 0xffffffff ; //Disable Pull-up register
-
rGPCCON = 0xaaaa02a8 ; //Initialize VD[7:0],VM,VFREAM,VLINE,VCLK
-
-
rGPDUP = 0xffffffff ; //Disable Pull-up register
-
rGPDCON = 0xaaaaaaaa ; //Initialize VD[15:8]
-
-
}
-
/****************************************************************
-
function configarution LCDCON1-5 LCDSADDR1-3 LCD INTERRUPT TPAL
-
etc register TFT 16bpp
-
input void
-
return void
-
*****************************************************************/
-
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见地址对应关系 16bpp
-
rLCDSADDR2 = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2)>>1) ;
-
rLCDSADDR3 = LCD_WIDTH ;
-
-
rLCDINTMSK |= 3 ; //屏蔽中断
-
rTCONSEL = 0 ; //LPC3600 LCC3600 无效
-
rTPAL = 0 ; //禁止临时调色板
-
}
-
/****************************************************************
-
function Envid turn on or off
-
input onoff 1,Envid turn on
-
return void
-
*****************************************************************/
-
static void Lcd_EnvidOnOff(int onoff)
-
{
-
if(onoff==1)
-
rLCDCON1 |= 1 ; //ENVID ON
-
else
-
rLCDCON1 &= ~(1<<0) ; //ENBID OFF
-
}
-
/****************************************************************
-
function LCD power enable
-
input pwren 1, enable lcd power
-
return void
-
*****************************************************************/
-
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 使能
-
}
-
/****************************************************************
-
function Filling sole colour into LCD background
-
input c colour
-
return void
-
*****************************************************************/
-
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 ;
-
}
-
}
-
}
-
/****************************************************************
-
function Paint picture
-
input x0 y0 assign start bit
-
level vertical the wide and high of picture
-
*bmp the picture string
-
return void
-
*****************************************************************/
-
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 ;
-
}
-
}
-
}
-
/****************************************************************
-
function Display 像素点
-
input x y display start bit
-
col color of the char
-
return void
-
*****************************************************************/
-
static void PutPixel(U32 x, U32 y, U16 col)
-
{
-
LCD_BUFFER[y][x] = col ;
-
}
-
/****************************************************************
-
function Display 汉字 hzk16 16*16
-
input x y display start bit
-
col color of the char
-
ch[] 字模数组
-
return void
-
*****************************************************************/
-
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 ;
-
}
-
}
-
}
-
/****************************************************************
-
function Display ASCII 字符 16*8
-
input x y display start bit
-
col color of the char
-
ch[] 字模数组
-
return void
-
*****************************************************************/
-
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 ;
-
}
-
}
-
}
-
/****************************************************************
-
function Display 汉字字符 16*16
-
input x y display start bit
-
col color of the char
-
str[] 字符数组
-
strlen 字符串长度 字节表示
-
return void
-
*****************************************************************/
-
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); //405MHZ
-
ChangeClockDivider(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 ;
-
}
阅读(6872) | 评论(0) | 转发(3) |