LCD输出字符的原理就是根据字模,然后画出字符来。
第一步:了解ASC编码规则,也就是字符在ASC码表中对应的位置。 具体可参考相关文档,网上有很多。 我用的字模是 16 X 8 的,所以我的代码中计算位置的方法是 位置 = 字符 X 16
第二步:生成ASC码表,这个网上也有,找不到的可以用我的代码里的。
第三步:用取到的字模画出相应的字符即可。
说的有点简单,请看代码吧。
整个工程文件我已经上传到我的资源中了。
Lcd.h文件
#define ELFIN_DMA_BASE 0x75000000
#define ELFIN_LCD_BASE 0x77100000
#define ELFIN_USB_HOST_BASE 0x74300000
#define ELFIN_I2C_BASE 0x7f004000
#define ELFIN_I2S_BASE 0x7f002000
#define ELFIN_ADC_BASE 0x7e00b000
#define ELFIN_SPI_BASE 0x7f00b000
#define ELFIN_HSMMC_0_BASE 0x7c200000
#define ELFIN_HSMMC_1_BASE 0x7c300000
#define ELFIN_HSMMC_2_BASE 0x7c400000
#define __REG(x) (*(volatile unsigned *)(x))
#define S3C_VIDCON0 (*(unsigned long volatile *)0x77100000)
#define S3C_VIDCON1 (*(unsigned long volatile *)0x77100004)
#define S3C_VIDTCON0 (*(unsigned long volatile *)0x77100010)
#define S3C_VIDTCON1 (*(unsigned long volatile *)0x77100014)
#define S3C_VIDTCON2 (*(unsigned long volatile *)0x77100018)
#define S3C_WINCON0 (*(unsigned long volatile *)0x77100020)
#define S3C_WINCON1 (*(unsigned long volatile *)0x77100024)
#define S3C_WINCON2 (*(unsigned long volatile *)0x77100028)
#define S3C_WINCON3 (*(unsigned long volatile *)0x7710002C)
#define S3C_WINCON4 (*(unsigned long volatile *)0x77100030)
#define S3C_VIDW00ADD2 (*(unsigned long volatile *)0x77100100)
#define ELFIN_GPIO_BASE 0x7f008000
#define GPICON_OFFSET 0x100
#define GPIPUD_OFFSET 0x108
#define GPJCON_OFFSET 0x120
#define GPJPUD_OFFSET 0x128
#define SPCON_OFFSET 0x1A0
#define GPICON_REG __REG(ELFIN_GPIO_BASE+GPICON_OFFSET)
#define GPIPUD_REG __REG(ELFIN_GPIO_BASE+GPIPUD_OFFSET)
#define GPJCON_REG __REG(ELFIN_GPIO_BASE+GPJCON_OFFSET)
#define GPJPUD_REG __REG(ELFIN_GPIO_BASE+GPJPUD_OFFSET)
#define SPCON_REG __REG(ELFIN_GPIO_BASE + SPCON_OFFSET)
#define S3C_WINCONx_ENWIN_F_ENABLE 0x1
#define ELFIN_LCD_BASE 0x77100000
#define S3C_LCDREG(x) __REG((x) + ELFIN_LCD_BASE)
#define MIFPCON_REG __REG(0x7410800C)
#define SPCON_REG __REG(ELFIN_GPIO_BASE + SPCON_OFFSET)
/* LCD control registers */
#define S3C_VIDOSD0A S3C_LCDREG(0x40) /* Video OSD0 A register */
#define S3C_VIDOSD0B S3C_LCDREG(0x44) /* Video OSD0 B register */
#define S3C_VIDOSD0C S3C_LCDREG(0x48) /* Video OSD0 C register */
#define S3C_VIDOSD1A S3C_LCDREG(0x50) /* Video OSD1 A register */
#define S3C_VIDOSD1B S3C_LCDREG(0x54) /* Video OSD1 B register */
#define S3C_VIDOSD1C S3C_LCDREG(0x58) /* Video OSD1 C register */
#define S3C_VIDOSD1D S3C_LCDREG(0x5C) /* Video OSD1 D register */
#define S3C_VIDOSD2A S3C_LCDREG(0x60) /* Video OSD2 A register */
#define S3C_VIDOSD2B S3C_LCDREG(0x64) /* Video OSD2 B register */
#define S3C_VIDOSD2C S3C_LCDREG(0x68) /* Video OSD2 C register */
#define S3C_VIDOSD2D S3C_LCDREG(0x6C) /* Video OSD2 D register */
#define S3C_VIDOSD3A S3C_LCDREG(0x70) /* Video OSD3 A register */
#define S3C_VIDOSD3B S3C_LCDREG(0x74) /* Video OSD3 B register */
#define S3C_VIDOSD3C S3C_LCDREG(0x78) /* Video OSD3 C register */
#define S3C_VIDOSD4A S3C_LCDREG(0x80) /* Video OSD4 A register */
#define S3C_VIDOSD4B S3C_LCDREG(0x84) /* Video OSD4 B register */
#define S3C_VIDOSD4C S3C_LCDREG(0x88) /* Video OSD4 C register */
#define S3C_VIDW00ADD0B0 S3C_LCDREG(0xA0) /* Video WINDOW 0 ADDRESS 0 BUFFER 0 register */
#define S3C_VIDW00ADD0B1 S3C_LCDREG(0xA4) /* Video WINDOW 0 ADDRESS 0 BUFFER 1 register */
#define S3C_VIDW01ADD0B0 S3C_LCDREG(0xA8) /* Video WINDOW 1 ADDRESS 0 BUFFER 0 register */
#define S3C_VIDW01ADD0B1 S3C_LCDREG(0xAC) /* Video WINDOW 1 ADDRESS 0 BUFFER 1 register */
#define S3C_VIDW02ADD0 S3C_LCDREG(0xB0) /* Video WINDOW 2 ADDRESS 0 BUFFER register */
#define S3C_VIDW03ADD0 S3C_LCDREG(0xB8) /* Video WINDOW 3 ADDRESS 0 BUFFER register */
#define S3C_VIDW04ADD0 S3C_LCDREG(0xC0) /* Video WINDOW 4 ADDRESS 0 BUFFER register */
#define S3C_VIDW00ADD1B0 S3C_LCDREG(0xD0) /* Video WINDOW 0 ADDRESS 1 BUFFER 0 register */
#define S3C_VIDW00ADD1B1 S3C_LCDREG(0xD4) /* Video WINDOW 0 ADDRESS 1 BUFFER 1 register */
#define S3C_VIDW01ADD1B0 S3C_LCDREG(0xD8) /* Video WINDOW 1 ADDRESS 1 BUFFER 0 register */
#define S3C_VIDW01ADD1B1 S3C_LCDREG(0xDC) /* Video WINDOW 1 ADDRESS 1 BUFFER 1 register */
#define S3C_VIDW02ADD1 S3C_LCDREG(0xE0) /* Video WINDOW 2 ADDRESS 1 BUFFER register */
#define S3C_VIDW03ADD1 S3C_LCDREG(0xE8) /* Video WINDOW 3 ADDRESS 1 BUFFER register */
#define S3C_VIDW04ADD1 S3C_LCDREG(0xF0) /* Video WINDOW 4 ADDRESS 1 BUFFER register */
#define S3C_VIDW01ADD2 S3C_LCDREG(0x104) /* Video WINDOW 1 ADDRESS SIZE register */
#define S3C_VIDW02ADD2 S3C_LCDREG(0x108) /* Video WINDOW 2 ADDRESS SIZE register */
#define S3C_VIDW03ADD2 S3C_LCDREG(0x10C) /* Video WINDOW 3 ADDRESS SIZE register */
#define S3C_VIDW04ADD2 S3C_LCDREG(0x110) /* Video WINDOW 4 ADDRESS SIZE register */
#define S3C_VIDINTCON0 S3C_LCDREG(0x130) /* Video WINDOW INT0 register */
#define S3C_VIDINTCON1 S3C_LCDREG(0x134) /* Video WINDOW INT1 register */
#define S3C_DITHMODE S3C_LCDREG(0x170)
#define S3C_VIDCON0_ENVID_ENABLE (0x1<<1) /* VIDCON0 */
#define S3C_VIDCON0_ENVID_F_ENABLE 0x1 /* VIDCON0 */
#define S3C_WINCONx_ENWIN_F_ENABLE 0x1 /* WINCON */
#define SEL_BYPASS_MASK (0x1<<3) /* MIFPCON_REG */
#define LCD_SEL_MASK 0x3 /* SPCON_REG */
#define RGB_IF_STYLE_MASK 0x1 /* SPCON_REG */
#define S3C_VIDCON0_INTERLACE_F_PROGRESSIVE (0x0<<29) /* VIDCON0 */
#define S3C_VIDCON0_VIDOUT_RGB_IF ((0x0<<27) | (0x0<<26)) /* VIDCON0 */
#define S3C_VIDCON0_PNRMODE_RGB_P ((0x0<<18) | (0x0<<17)) /* VIDCON0 */
#define S3C_VIDCON0_CLKVALUP_ST_FRM (0x1<<16) /* VIDCON0 */
#define S3C_VIDCON0_CLKVAL_F0 (0x0<<5) /* VIDCON0 */
#define S3C_VIDCON0_CLKDIR_DIRECTED (0x0<<4) /* VIDCON0 */
#define S3C_VIDCON0_CLKSEL_F_HCLK ((0x0<<3) | (0x0<<2)) /* VIDCON0 */
#define U32 unsigned int
#define U16 unsigned short
#define S32 int
#define S16 short int
#define U8 unsigned char
#define S8 char
#define X_SIZE 480
#define Y_SIZE 272
volatile static U32 LCD_BUFFER[Y_SIZE][X_SIZE];
struct LCDState
{
int x;
int y;
int color;
int row;
int col;
};
struct LCDState g_lcdState;
void Init();
void lcd_disable(void);
void lcd_Enable(void);
void fill();
void Print(S8* buf);
void Draw_Point(int x, int y, int color);
void GunDong();
void NextRow();
void GunDong2(void);
Lcd.c文件
#include "Lcd.h"
#include "zimo.h"
void Init()
{
int i = 0;
int j = 0;
for(i = 0; i < Y_SIZE; i++)
{
for(j = 0; j < X_SIZE; j++)
{
LCD_BUFFER[i][j] = 0;
}
}
g_lcdState.x = 0;
g_lcdState.y = 0;
g_lcdState.color = 0xFF0000;
g_lcdState.col = 0;
g_lcdState.row = 0;
//设置VD0~15
GPICON_REG = 0XAAAAAAAA; //设置GPI0~15为LCD VD0~15
GPIPUD_REG = 0; // 下拉电阻屏蔽
//设置VD16~23和HSYNC、VSYNC、VDEN、VCLK
GPJCON_REG = 0XAAAAAAAA;
GPJPUD_REG =0; // 下拉电阻屏蔽
// 关闭LCD
lcd_disable();
// 窗口0控制器 关闭视频输出
S3C_WINCON0 &= (~(S3C_WINCONx_ENWIN_F_ENABLE));
//LCD寄存器设置 手册上写着必须这么设置SPCON寄存器
SPCON_REG &= (~0x3);
SPCON_REG |= 0x01;
// 手册上写着必须这么设置MIFPCON寄存器
MIFPCON_REG &= ~(1<<3); //设置LCD支路为一般模式
// 第六位是确定CLKVAL_F值,第四位用CLKVAL_F选择时钟源
S3C_VIDCON0 = (13 << 6) | (1 << 4);
// 第五位指明VSYNC为反向, 第六位HSYNC为反向
S3C_VIDCON1 = (1 <<6) | (1 <<5);
//设置屏的时序
S3C_VIDTCON0 = (1 << 16) | (1 << 8) | 9;
S3C_VIDTCON1 = (1 << 16) | (1 << 8) | 40;
S3C_VIDTCON2 = (271<<11)|(479<<0);
//设置窗口格式
S3C_WINCON0 = 11<<2; //设置24BPP
//设置窗口位置
S3C_VIDOSD0A = (0<<11)|(0<<0); // 左上角坐标,0-10位是纵坐标 11-21是横坐标
S3C_VIDOSD0B = ((479)<<11) | ((271)<<0); // 右下角坐标
S3C_VIDOSD0C = 480 * 272 ; // 窗口尺寸
//设置窗口1的开始和结束的缓存地址与地址在内存中的存放地址以及缓存的大小
S3C_VIDW00ADD0B0 = (U32)LCD_BUFFER;
S3C_VIDW00ADD1B0 = ((U32)LCD_BUFFER + 480 * 272 * 4 ) & 0xffffff;
S3C_VIDW00ADD2 = (0 << 13)|(480 * 4 );
lcd_Enable();
S3C_WINCON0 |= S3C_WINCONx_ENWIN_F_ENABLE;
S3C_WINCON1 = 0;
S3C_WINCON2 = 0;
S3C_WINCON3 = 0;
S3C_WINCON4 = 0;
}
void lcd_disable(void)
{
S3C_VIDCON0 &= (~(S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE));
}
/**************************************************************
480*272 TFT LCD
**************************************************************/
void lcd_Enable(void)
{
S3C_VIDCON0 |= (S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE);
}
void fill()
{
int i = 0;
int j = 0;
for(i = 0; i < Y_SIZE / 2; i++)
{
for(j = 0; j < X_SIZE; j++)
{
U8 r = 255;
U8 g = 0;
U8 b = 0;
U32 co = ((r << 16) | (g << 8) | b);
LCD_BUFFER[i][j] = co;
}
}
}
void Print(S8* buf)
{
while(*buf != '\0')
{
S8 word = *buf;
buf++;
// 由于ASC是7位编码所以最高为肯定是0,如果不是0则认为是汉子
if(word & 0x80)
{
}else
{
// 计算该字符在字模中的位置
int va = (word - 32) * 16;
// 行列
int x = 0;
int y = 0;
if(word < 32)
{
if((word=='\n')||(word=='\r'))
{
NextRow();
//g_lcdState.col = 0;
}
}else
{
// 开始-行
for(y = (g_lcdState.row * 16); y < (g_lcdState.row * 16) + 16; y++)
{
// 从ASC字模中取出一行(一个字节), 一个字符共16行,8列
int zmData = nAsciiDot[va] & 0xff;
// 开始-列
for(x = (g_lcdState.col * 8); x < g_lcdState.col * 8 + 8; x++)
{
if(zmData & 0x80) // 1时则说明有信息
{
Draw_Point(x, y, g_lcdState.color);
}
// 切到下一列
zmData<<=1;
}
// 切到下一行
va++;
}
if(g_lcdState.col > 50)
{
// 屏幕纵坐标切换到下一行
//g_lcdState.col = 0;
NextRow();
}else
{
// 屏幕横坐标切换到下一列
g_lcdState.col +=1;
}
}
}
}
}
void NextRow()
{
if(g_lcdState.row >= 15)
{
GunDong2();
}else
{
g_lcdState.row += 1;
}
g_lcdState.col = 0;
}
void Draw_Point(int x, int y, int color)
{
LCD_BUFFER[y][x] = color;
}
void GunDong()
{
int i = 0;
int j = 0;
int temp = 0;
for(i = 0; i < (Y_SIZE - 16); i++)
{
for(j = 0; j < X_SIZE; j++)
{
temp = LCD_BUFFER[i + 16][j];
LCD_BUFFER[i][j] = temp;
LCD_BUFFER[i + 16][j] = 0;
}
}
}
void GunDong2(void)
{
U16 x,y;
for(x=0;x<X_SIZE;x++)
for(y=0;y<Y_SIZE-32;y++)
LCD_BUFFER[y+16][x]=LCD_BUFFER[y+32][x];
for(y=256;y<Y_SIZE;y++)
for(x=0;x<X_SIZE;x++)
LCD_BUFFER[y][x]=0;
}