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
#include
#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)<
//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 for(x=0; 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 for(x=0; x col = bmp[p+1] | (bmp[p]<<8) ; //16bpp 一个像素点用俩个字节 if( ((x0+x) 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 ;
上一篇:S3c2440裸机程序【1】跑马灯
下一篇:S3C2440开发板裸机程序系列07—NAND FLASH存储器
推荐阅读最新更新时间:2024-11-17 16:25
设计资源 培训 开发板 精华推荐
- LT6656BIDC-3 的典型应用,用于基本连接的 3V 电压基准
- 基于IP5306的单片机电源模块方案
- ESP32WROVER测试烧录座(兼容ESP32WROOM)
- LTC2912 的典型应用 - 单路 UV/OV 电压监视器
- USB-SDP-CABLEZ,串行接口板提供 USB 连接,USB 2.0 高速连接到计算机
- 使用 NXP Semiconductors 的 PCA9533D 的参考设计
- 使用 Infineon Technologies AG 的 OM7800IH 的参考设计
- AD9518-3A/PCBZ,AD9518-3A 评估板,2000 MHz 极低噪声 PLL 时钟合成器
- 数字电路制作09-NE555八音电子琴
- MAXREFDES1149:12V/1A、同步、无光耦、隔离POE DC-DC转换器