这个是三星的主控S6D1121彩屏(240*320*18bit,262Kcr)的彩屏的驱动程序.
采用的是80System+16bit接口
不知道是什么原因, 这个主控网上很少有资料,我也是看了好久的DS才明白了一些(全英文, 基本没中文资料, 反正是不好找到)
这是我接触的第一块彩屏哦~~
如果有用这个芯片的, 可能会有些方便, 也方便交流下使用经验.
这里总共分4个文件:
common.c,common.h:一些公共的包含与定义,函数
s6d1121.c,s6d1121.h:主控芯片驱动程序
//common.h - 一些公用的定义,函数等 #ifndef __COMMON_H__ #define __COMMON_H__ #include <reg52.h> #include <intrins.h> typedef unsigned int uint; typedef unsigned char uchar; void delay_us(uint us); void delay_ms(uint ms); #endif// !__COMMON_H__
//common.c #include "common.h" void delay_ms(uint ms) { uchar k; while(ms--){ for(k=125; k>0; k--){ _nop_(); } } } void delay_us(uint us) { while(us--){ _nop_(); } }
//s6d1121.h //S6D1121.h //S6D1121驱动程序 //应用层请不要调用 //应调用GDI接口 // //女孩不哭 QQ:191035066 //2012-11-05 #ifndef __S6D1121_H__ #define __S6D1121_H__ #include "common.h" void LCD_SetAddress(uint x, uint y, uint width, uint height); void LCD_WriteBus(uint dat); void LCD_WriteCmdWithData(uchar cmd, uint value); void LCD_WriteData(uint dat); void LCD_WriteCmd(uchar cmd); uint LCD_ReadBus(void); uint LCD_ReadData(void); void LCD_Init(void); #endif// !__S6D1121_H__
//s6d1121.c /* 文件:S6D1121.c * 功能:三星S6D1121主控彩屏驱动程序 * 版本:1.0 * 作者:女孩不哭 * Q--Q:191035066 * 时间:2012-11-05 * 说明:这里是底层驱动程序,用户不应该随便调用 * 请调用编写的图形接口程序 * 参考:http://www.elecfreaks.com/wiki/index.php?title=2.4%22_TFT_LCD:_TFT01-2.4 */ #include "common.h" #include "s6d1121.h" //I/O口定义,除*_RST外,均Active Low sbit LCD_RST= P2^0; //复位 sbit LCD_CS = P2^1; //片选 sbit LCD_RD = P2^2; //读取 sbit LCD_WR = P2^3; //写入 sbit LCD_RS = P2^4; //寄存器/数据选择 //数据总线端口定义 //如果使用16位总线,需要宏定义:BUS_16 //当使用8位总线时,仅*_HI有效 #define LCD_DATA_PORT_HI P0 #define LCD_DATA_PORT_LOW P1 //初始化,初始化之前 //MCU应该延时一段时间 //以使电源稳定 void LCD_Init(void) { LCD_RST = 1; delay_ms(5); LCD_RST = 0; delay_ms(5); LCD_RST = 1; LCD_CS = 1; LCD_RD = 1; LCD_WR = 1; delay_ms(5); LCD_CS = 0;//片选使能 //详细的说明见一开始的网址 LCD_WriteCmdWithData(0x11,0x2004); LCD_WriteCmdWithData(0x13,0xcc00); LCD_WriteCmdWithData(0x15,0x2600); LCD_WriteCmdWithData(0x14,0x252a); LCD_WriteCmdWithData(0x12,0x0033); LCD_WriteCmdWithData(0x13,0xcc04); delay_ms(1); LCD_WriteCmdWithData(0x13,0xcc06); delay_ms(1); LCD_WriteCmdWithData(0x13,0xcc4f); delay_ms(1); LCD_WriteCmdWithData(0x13,0x674f); LCD_WriteCmdWithData(0x11,0x2003); delay_ms(1); LCD_WriteCmdWithData(0x30,0x2609); LCD_WriteCmdWithData(0x31,0x242c); LCD_WriteCmdWithData(0x32,0x1F23); LCD_WriteCmdWithData(0x33,0x2425); LCD_WriteCmdWithData(0x34,0x2226); LCD_WriteCmdWithData(0x35,0x2523); LCD_WriteCmdWithData(0x36,0x1C1A); LCD_WriteCmdWithData(0x37,0x131D); LCD_WriteCmdWithData(0x38,0x0B11); LCD_WriteCmdWithData(0x39,0x1210); LCD_WriteCmdWithData(0x3A,0x1315); LCD_WriteCmdWithData(0x3B,0x3619); LCD_WriteCmdWithData(0x3C,0x0D00); LCD_WriteCmdWithData(0x3D,0x000D); LCD_WriteCmdWithData(0x16,0x0007); LCD_WriteCmdWithData(0x02,0x0013); LCD_WriteCmdWithData(0x03,0x0003); LCD_WriteCmdWithData(0x01,0x0127); delay_ms(1); LCD_WriteCmdWithData(0x08,0x0303); LCD_WriteCmdWithData(0x0A,0x000B); LCD_WriteCmdWithData(0x0B,0x0003); LCD_WriteCmdWithData(0x0C,0x0000); LCD_WriteCmdWithData(0x41,0x0000); LCD_WriteCmdWithData(0x50,0x0000); LCD_WriteCmdWithData(0x60,0x0005); LCD_WriteCmdWithData(0x70,0x000B); LCD_WriteCmdWithData(0x71,0x0000); LCD_WriteCmdWithData(0x78,0x0000); LCD_WriteCmdWithData(0x7A,0x0000); LCD_WriteCmdWithData(0x79,0x0007); LCD_WriteCmdWithData(0x07,0x0053); LCD_WriteCmdWithData(0x79,0x0000); LCD_WriteCmd(0x22); LCD_CS = 1;//关闭片选 delay_ms(50); LCD_CS = 0; } /* 函数:写命令 * 参数:uchar cmd:寄存器地址 * 返回:(无) * 说明:RS为低为写寄存器 */ void LCD_WriteCmd(uchar cmd) { LCD_RS = 0;//写命令模 LCD_WriteBus((uint)cmd); } /* 函数:写数据值 * 参数:uint dat:16位的数据 * 返回:(无) * 说明:RS应为高 */ void LCD_WriteData(uint dat) { LCD_RS = 1;//写数据 LCD_WriteBus(dat); } /*uint LCD_ReadData(void) { LCD_RS = 1; return LCD_ReadBus(); } uint LCD_ReadBus(void) { uint ret=0; #ifdef BUS_16 LCD_RD = 0; LCD_RD = 1; ret = LCD_DATA_PORT_HI; ret <<= 8; ret |= LCD_DATA_PORT_LOW; #else LCD_RD = 0; LCD_RD = 1; ret = LCD_DATA_PORT_HI; ret <<= 8; LCD_RD = 0; LCD_RD = 1; ret |= LCD_DATA_PORT_HI; #endif return ret; }*/ /* 函数:写寄存器 * 参数: * uchar cmd:寄存器地址(8位) * uint value:写给寄存器的值(16位) * 返回:(无) */ void LCD_WriteCmdWithData(uchar cmd, uint value) { LCD_WriteCmd((uchar)cmd); //写寄存器地址 LCD_WriteData(value); //写寄存器值 } //把命令/数据向总线写入 void LCD_WriteBus(uint dat) { #ifdef BUS_16 //16位总线模式 LCD_DATA_PORT_HI = (uchar)(dat>>8); LCD_DATA_PORT_LOW = (uchar)dat; LCD_WR = 0; LCD_WR = 1; //S6D1121在每次的WR的上升沿读取数据 #else //此时仅高字节有效 //先写高字节,再写低字节 LCD_DATA_PORT_HI = (uchar)(dat>>8); LCD_WR = 0; LCD_WR = 1; LCD_DATA_PORT_HI = (uchar)dat; LCD_WR = 0; LCD_WR = 1; #endif } /* * 函数:设定写入数据的区域 * 参数: * int x:X坐标(范围:0~239) * int y:Y坐标(范围:0~319) * uint width:宽 * uint height:高 * 返回:(无) * 说明:(x1,y1; x2,y2)两点构成一个矩形 * 设定好区域后,在下一个指令前应该写缓冲区 */ void LCD_SetAddress(uint x, uint y, uint width, uint height) { LCD_WriteCmdWithData(0x46, (x+width-1)<<8|x); //一次性设定x1,x2(高) LCD_WriteCmdWithData(0x47, y+height-1); //y2 LCD_WriteCmdWithData(0x48, y); //y1 LCD_WriteCmdWithData(0x20, x); //设定RAM开始写的地址 LCD_WriteCmdWithData(0x21, y); LCD_WriteCmd(0x22); //设定好写寄存器,开始写 }XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
上一篇随笔贴出了驱动程序, 这篇文章的代码主要就是针对上层的调用了, 但是, 其实, 只要是底层的驱动程序能能够工作了, 图形设备接口应该就可以随便移植的咯~
一般彩屏的操作方式应该都是差不多的吧?
说明下, 本人不是很擅长图形方面的算法设计, 有些程序采用了大师们写的程序, 有些则是我自己写的(写得很差), 不过还是能够实现功能的哈~
我测试程序时是用的死太惨的51单片机测试的, ROM比较小, 只有60KB(整个字库有大约225KB), 完全没法装进去的, 所以就把要用的保存进去了, 所以会有ascii.c/.h文件的存在, 当然, 如果后来会用SD/MMC/U盘, 那就太好了, 不过, 很遗憾的是, SD卡我一直没有能够成功读取~ 慢慢来吧.
代码文件:
ascii.c/ascii.h:字库文件
common.c/common.h:一些公共的头文件/类型声明等等(和前面那篇随笔是一样的,没贴出)
gdi.c/gdi.h:图形设备接口的实现
有了这四个文件, 再加上前面的驱动程序, 把她们放到一个项目下, 就可以写程序调用了哈, 很方便的说~
//ascii.h #ifndef __ASCIII_H__ #define __ASCIII_H__ uchar* asc_get_char(uchar uch); uchar* asc_get_word(uchar* word); uchar* asc_tpow(void); #endif// !__ASCIII_H__
//ascii.c #include "common.h" //这个是two's pow(2的次方), 其实没什么必要的, 可以忽略 uchar code t_p[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //这个是标准ASCII字符对应的像素值了 //应该有注意到, 我这里是宽8*高12的, 而我却在上下各加 //两个空行, 形成了宽8*高16的字符, 这样做的目的主要是为了方便 //因为我的中文字库是用的16*16(不是很小) //是我从别人那里直接拷过来的, 看起来字体不是很好看 //这个是不需要程序获取的, 程序只需做的是调用asc_get_char(your_char) //来得到一个字符数组的偏移就行了 uchar code ascii[][12] = { /* */{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ! */{0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00}, /* " */{0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* # */{0x00,0x00,0x28,0x28,0xFC,0x28,0x50,0xFC,0x50,0x50,0x00,0x00}, /* $ */{0x00,0x20,0x78,0xA8,0xA0,0x60,0x30,0x28,0xA8,0xF0,0x20,0x00}, /* % */{0x00,0x00,0x48,0xA8,0xB0,0x50,0x28,0x34,0x54,0x48,0x00,0x00}, /* & */{0x00,0x00,0x20,0x50,0x50,0x78,0xA8,0xA8,0x90,0x6C,0x00,0x00}, /* ' */{0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ( */{0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x04,0x00}, /* ) */{0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00}, /* * */{0x00,0x00,0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00,0x00,0x00}, /* + */{0x00,0x00,0x20,0x20,0x20,0xF8,0x20,0x20,0x20,0x00,0x00,0x00}, /* , */{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80}, /* - */{0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00}, /* . */{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00}, /* / */{0x00,0x08,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00}, /* 0 */{0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 1 */{0x00,0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00}, /* 2 */{0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x40,0x80,0xF8,0x00,0x00}, /* 3 */{0x00,0x00,0x70,0x88,0x08,0x30,0x08,0x08,0x88,0x70,0x00,0x00}, /* 4 */{0x00,0x00,0x10,0x30,0x50,0x50,0x90,0x78,0x10,0x18,0x00,0x00}, /* 5 */{0x00,0x00,0xF8,0x80,0x80,0xF0,0x08,0x08,0x88,0x70,0x00,0x00}, /* 6 */{0x00,0x00,0x70,0x90,0x80,0xF0,0x88,0x88,0x88,0x70,0x00,0x00}, /* 7 */{0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x20,0x20,0x20,0x00,0x00}, /* 8 */{0x00,0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00}, /* 9 */{0x00,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x48,0x70,0x00,0x00}, /* : */{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x00}, /* ; */{0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x00}, /* < */{0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00}, /* = */{0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, /* > */{0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00}, /* ? */{0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00}, /* @ */{0x00,0x00,0x70,0x88,0x98,0xA8,0xA8,0xB8,0x80,0x78,0x00,0x00}, /* A */{0x00,0x00,0x20,0x20,0x30,0x50,0x50,0x78,0x48,0xCC,0x00,0x00}, /* B */{0x00,0x00,0xF0,0x48,0x48,0x70,0x48,0x48,0x48,0xF0,0x00,0x00}, /* C */{0x00,0x00,0x78,0x88,0x80,0x80,0x80,0x80,0x88,0x70,0x00,0x00}, /* D */{0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0x48,0xF0,0x00,0x00}, /* E */{0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x48,0xF8,0x00,0x00}, /* F */{0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x40,0xE0,0x00,0x00}, /* G */{0x00,0x00,0x38,0x48,0x80,0x80,0x9C,0x88,0x48,0x30,0x00,0x00}, /* H */{0x00,0x00,0xCC,0x48,0x48,0x78,0x48,0x48,0x48,0xCC,0x00,0x00}, /* I */{0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00}, /* J */{0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0xE0,0x00}, /* K */{0x00,0x00,0xEC,0x48,0x50,0x60,0x50,0x50,0x48,0xEC,0x00,0x00}, /* L */{0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x44,0xFC,0x00,0x00}, /* M */{0x00,0x00,0xD8,0xD8,0xD8,0xD8,0xA8,0xA8,0xA8,0xA8,0x00,0x00}, /* N */{0x00,0x00,0xDC,0x48,0x68,0x68,0x58,0x58,0x48,0xE8,0x00,0x00}, /* O */{0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* P */{0x00,0x00,0xF0,0x48,0x48,0x70,0x40,0x40,0x40,0xE0,0x00,0x00}, /* Q */{0x00,0x00,0x70,0x88,0x88,0x88,0x88,0xE8,0x98,0x70,0x18,0x00}, /* R */{0x00,0x00,0xF0,0x48,0x48,0x70,0x50,0x48,0x48,0xEC,0x00,0x00}, /* S */{0x00,0x00,0x78,0x88,0x80,0x60,0x10,0x08,0x88,0xF0,0x00,0x00}, /* T */{0x00,0x00,0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00}, /* U */{0x00,0x00,0xCC,0x48,0x48,0x48,0x48,0x48,0x48,0x30,0x00,0x00}, /* V */{0x00,0x00,0xCC,0x48,0x48,0x50,0x50,0x30,0x20,0x20,0x00,0x00}, /* W */{0x00,0x00,0xA8,0xA8,0xA8,0x70,0x50,0x50,0x50,0x50,0x00,0x00}, /* X */{0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x50,0x50,0xD8,0x00,0x00}, /* Y */{0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x20,0x20,0x70,0x00,0x00}, /* Z */{0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x40,0x48,0xF8,0x00,0x00}, /* [ */{0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00}, /* \ */{0x00,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x00,0x00}, /* ] */{0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00}, /* ^ */{0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* _ */{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC}, /* ` */{0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* a */{0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x38,0x48,0x3C,0x00,0x00}, /* b */{0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00}, /* c */{0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x40,0x40,0x38,0x00,0x00}, /* d */{0x00,0x00,0x18,0x08,0x08,0x38,0x48,0x48,0x48,0x3C,0x00,0x00}, /* e */{0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00}, /* f */{0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x78,0x00,0x00}, /* g */{0x00,0x00,0x00,0x00,0x00,0x3C,0x48,0x30,0x40,0x78,0x44,0x38}, /* h */{0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0xEC,0x00,0x00}, /* i */{0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x00}, /* j */{0x00,0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0}, /* k */{0x00,0x00,0xC0,0x40,0x40,0x5C,0x50,0x70,0x48,0xEC,0x00,0x00}, /* l */{0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00}, /* m */{0x00,0x00,0x00,0x00,0x00,0xF0,0xA8,0xA8,0xA8,0xA8,0x00,0x00}, /* n */{0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0xEC,0x00,0x00}, /* o */{0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00}, /* p */{0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0x70,0x40,0xE0}, /* q */{0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x1C}, /* r */{0x00,0x00,0x00,0x00,0x00,0xD8,0x60,0x40,0x40,0xE0,0x00,0x00}, /* s */{0x00,0x00,0x00,0x00,0x00,0x78,0x40,0x30,0x08,0x78,0x00,0x00}, /* t */{0x00,0x00,0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x18,0x00,0x00}, /* u */{0x00,0x00,0x00,0x00,0x00,0xD8,0x48,0x48,0x48,0x3C,0x00,0x00}, /* v */{0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x00,0x00}, /* w */{0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x70,0x50,0x50,0x00,0x00}, /* x */{0x00,0x00,0x00,0x00,0x00,0xD8,0x50,0x20,0x50,0xD8,0x00,0x00}, /* y */{0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x20,0xC0}, /* z */{0x00,0x00,0x00,0x00,0x00,0x78,0x10,0x20,0x20,0x78,0x00,0x00}, /* { */{0x00,0x18,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x10,0x18,0x00}, /* | */{0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}, /* } */{0x00,0x60,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x60,0x00}, /* ~ */{0x40,0xA4,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }; //用了一个结构体来索引 //因为没有足够的空间来保存字库 //所以就不能按照平常的区位码来索引汉字的代码了 //which[3]:保存一个中文汉字,what[32]:保存的代码 //生成方式:http://www.cnblogs.com/nbsofer/archive/2012/11/01/2749026.html //同样是内部使用, 外部程序只需要调用 asc_get_word(相对于*_char而言)(见下) struct wmap_s{ uchar which[3]; uchar what[32]; } code wmap[] = { {"我",{0x04,0x80,0x0E,0xA0,0x78,0x90,0x08,0x90,0x08,0x84,0xFF,0xFE,0x08,0x80,0x08,0x90,0x0A,0x90,0x0C,0x60,0x18,0x40,0x68,0xA0,0x09,0x20,0x0A,0x14,0x28,0x14,0x10,0x0C}}, {"的",{0x10,0x40,0x10,0x40,0x22,0x44,0x7F,0x7E,0x42,0x84,0x43,0x04,0x42,0x04,0x42,0x84,0x7E,0x64,0x42,0x24,0x42,0x04,0x42,0x04,0x42,0x04,0x7E,0x04,0x42,0x28,0x00,0x10}}, {"是",{0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,0x00,0x04,0xFF,0xFE,0x01,0x00,0x09,0x20,0x09,0xF0,0x09,0x00,0x15,0x00,0x23,0x06,0x40,0xFC}}, {"现",{0x00,0x08,0x09,0xFC,0xFD,0x08,0x11,0x28,0x11,0x28,0x11,0x28,0x11,0x28,0x7D,0x48,0x11,0x48,0x11,0x48,0x10,0x40,0x1C,0xA0,0xF0,0xA0,0x41,0x22,0x02,0x22,0x0C,0x1E}}, {"在",{0x02,0x00,0x02,0x00,0x02,0x04,0xFF,0xFE,0x04,0x00,0x04,0x40,0x08,0x40,0x08,0x50,0x13,0xF8,0x30,0x40,0x50,0x40,0x90,0x40,0x10,0x40,0x10,0x44,0x17,0xFE,0x10,0x00}}, {"时",{0x00,0x08,0x04,0x08,0x7E,0x08,0x44,0x08,0x47,0xFE,0x44,0x08,0x44,0x08,0x7C,0x88,0x44,0x48,0x44,0x48,0x44,0x08,0x44,0x08,0x7C,0x08,0x44,0x48,0x00,0x28,0x00,0x10}}, {"间",{0x20,0x04,0x1B,0xFE,0x08,0x04,0x40,0x24,0x4F,0xF4,0x48,0x24,0x48,0x24,0x48,0x24,0x4F,0xE4,0x48,0x24,0x48,0x24,0x48,0x24,0x4F,0xE4,0x48,0x24,0x40,0x14,0x40,0x08}}, {"温",{0x00,0x08,0x43,0xFC,0x32,0x08,0x12,0x08,0x83,0xF8,0x62,0x08,0x22,0x08,0x0B,0xF8,0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x20,0x00}}, {"度",{0x01,0x00,0x00,0x84,0x3F,0xFE,0x22,0x20,0x22,0x28,0x3F,0xFC,0x22,0x20,0x23,0xE0,0x20,0x00,0x2F,0xF0,0x22,0x20,0x21,0x40,0x20,0x80,0x43,0x60,0x8C,0x1E,0x30,0x04}}, {"初",{0x20,0x00,0x10,0x00,0x10,0x04,0x05,0xFE,0xFC,0x44,0x08,0x44,0x10,0x44,0x34,0x44,0x58,0x44,0x94,0x44,0x10,0x44,0x10,0x84,0x10,0x84,0x11,0x04,0x12,0x28,0x14,0x10}}, {"始",{0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x80,0xFC,0x88,0x25,0x04,0x27,0xFE,0x24,0x02,0x24,0x04,0x49,0xFE,0x29,0x04,0x11,0x04,0x29,0x04,0x45,0x04,0x85,0xFC,0x01,0x04}}, {"化",{0x08,0x80,0x08,0x80,0x08,0x80,0x10,0x88,0x10,0x98,0x30,0xA0,0x50,0xC0,0x90,0x80,0x11,0x80,0x12,0x80,0x14,0x80,0x10,0x80,0x10,0x82,0x10,0x82,0x10,0x7E,0x10,0x00}}, }; //函数:asc_get_word(uchar* pword) //用来获取一个中文汉字的代码保存位置偏移 //如果不存在, 返回NULL了(这里直接用0代替了) uchar* asc_get_word(uchar* pword) { uint k; uint len = sizeof(wmap)/sizeof(wmap[0]); for(k=0; k<len; k++){ if(wmap[k].which[0] == pword[0] && wmap[k].which[1] == pword[1]) { return &wmap[k].what[0]; } } return 0; } //同上, 不过这个是用来获取ASCII字符的 //应该注意到的是:我是根据标准ASCII的顺序来索引ASCII字符的 //所以,上面的ASCII字符代码表不能再添加/删除 //当然, 中文字库不存在这个限制 //使用:传入一个ASCII字符,返回编码的偏移(没有的话返回0) uchar* asc_get_char(char uch) { char idx; idx = (uch-32);//从空格算起, 控制字符就没用了,回车在其它程序中已经单独处理 if(idx<0 || idx>sizeof(ascii)/sizeof(ascii[0])) return 0; return &ascii[idx][0]; } //返回2的次方, 用得着的时候就用吧 //比如: uchar* tp = asc_tpow(); //tp[0]=2^7,tp[1]=2^6, ... uchar* asc_tpow(void) { return &t_p[0]; }
//gdi.h #ifndef __GDI_H__ #define __GDI_H__ #include "common.h" #include "s6d1121.h" //颜色描述表(前景色, 背景色) typedef struct color_table_s{ uint fgc; uint bgc; }color_table; //很有用的rgb(r,g,b) 宏 rgb(红,绿,蓝) #define rgb(r,g,b) ((uint)(\ ((uint)(uchar)(r)<<8 & 0xf800|(uchar)(r)>>7)|\ ((uint)(uchar)(g)<<3 & 0x7e00)|\ ((uint)(uchar)(b)>>2 | (uchar)(b)>>7))) //function prototype //函数的说明直接见各函数 void rectangle(int left, int top, int width, int height, uint color); void line(int x1, int y1, int x2, int y2, uint color); void triangle(int x1, int y1, int x2, int y2, int x3, int y3, uint color); void set_pixel(uint x, uint y, uint color); void fill_rect(uint left, uint top, uint width, uint height, uint color); void clear_screen(uint color); void char_out(int x, int y, char ch, uint fgc, uint bgc); void word_out(int x, int y, uchar* pword, uint fgc, uint bgc); void text_out(int x, int y, uchar* str, uint fgc, uint bgc, color_table* pct); int cirpot(int x0,int y0,int x,int y,uint color); void circle(int x0,int y0,int r,uint color); float sin(float rad); uchar* itoa(int x); //some useful function macros //一些有用的宏,主要是用于把应用层的程序和驱动层的程序隔离 //其实还是是调用的该驱动层的函数 /* 设定待写入/读取数据的缓冲区:X坐标,Y坐标,宽,高 */ #define set_area(x,y,width,height) LCD_SetAddress((x),(y),(width),(height)) /* 在 set_area 调用后, 写入数据的操作 */ #define set_data(dat) LCD_WriteData((dat)) //初始化彩屏 #define init_lcd LCD_Init //清屏 #define clr_scr clear_screen //设定彩屏主控内部寄存器的值(不应该暴露给应用层的,以后再更新,必然的) #define set_reg(reg,value) LCD_WriteCmdWithData((reg),(value)) #endif// !__GDI_H__
//gdi.c #include "common.h" #include "gdi.h" #include "s6d1121.h" #include "ascii.h" //用来把指定的整数转换为字符串 //保存在静态变量buf中并返回给调用者 //显示0还是显示空格在于自己了 uchar* itoa(int x) { static uchar buf[6]; buf[0] = x/10000+'0'; x %= 10000; buf[1] = x/1000+'0'; x %= 1000; buf[2] = x/100+'0'; x %= 100; buf[3] = x/10+'0'; x %= 10; buf[4] = x+'0'; buf[5] = 0; return &buf[0]; } //画矩形的函数 //参数:左上角的X坐标,左上角的Y坐标, 宽, 高, 颜色(有一些常用的颜色应该被定义, //下次再修改, 51的刷屏速度忍无可忍) void rectangle(int left, int top, int width, int height, uint color) { int x2,y2; x2 = left+width-1; y2 = top+height-1; //必须保存在有效范围内 if(left<0 || top<0 || x2>239 || y2>319) return; //看到了吧, 实现就是转换成画直线 //所以:最关键的怎样画点,直线 line(left, top, x2, top, color); line(x2, top, x2, y2, color); line(x2, y2, left, y2, color); line(left, y2, left, top, color); } //画三角形, 参数为三个坐标点+颜色 //其实还是是转换成画三条直线 void triangle(int x1, int y1, int x2, int y2, int x3, int y3,uint color) { line(x1,y1,x2,y2, color); line(x2,y2,x3,y3, color); line(x1,y1,x3,y3, color); } //画直线, 可怜这是我自己写的算法, 效率太低了 //而且,如果不仔细读读代码, 很难明白的 //以后还是换成大师们已经写好了的吧 //参数:两点成线, 不用多说, 当然, 颜色有要有的 //画线就是转换成画点,所以关键是怎么画点,set_pixel再介绍 void line(int x1, int y1, int x2, int y2, uint color) { int w,h;//记录长宽 float rate1,rate2;//高与宽的比率 int xaxis, yaxis, k; int ffalling = 0;//直线是否为下降沿 if(x1>x2){ k = x1; x1 = x2; x2 = k; k = y1; y1 = y2; y2 = k; } w = x2-x1+1;//get horizontal distance h = y2-y1;//get vertical distance if(h<0) h = -h; h = h+1; rate1 = (float)h/w;//根据相似三角形计算坐标 rate2 = (float)w/h; if(w>h){//宽大于高 ffalling = y1-y2; if(y1 == y2) ffalling = 0; for(k=0; k<w; k++){ if(ffalling<0){ //+0.5是作四四舍五入 yaxis = y2-(uint)((w-k)*rate1+0.5)+1; }else if(ffalling>0){ yaxis = y1-(uint)(k*rate1+0.5)+1; }else{ yaxis = y1; } set_pixel(k+x1,yaxis, color); } }else{ //h>w ffalling = y1-y2; if(x1==x2) ffalling = 0; for(k=0; k<h; k++){ if(ffalling<0){ xaxis = x1+(uint)(k*rate2+0.5)+1; }else if(ffalling>0){ xaxis = x1+((h-k)*rate2+0.5)+1; }else{ xaxis = x1; } set_pixel(xaxis, (y1<y2?y1:y2)+k, color); } } } //这个就是画点函数了 //set_area,set_data 完工 void set_pixel(uint x, uint y, uint color) { if(x>239 || y>319) return; set_area(x, y, 1, 1); set_data(color); } //填充一块矩形为指定颜色 void fill_rect(uint left, uint top, uint width, uint height, uint color) { uint a,b; if(left>239 || top>319) return; if(left+width-1>239) width = 239-left+1;//clip x border if(top+height-1>319) height = 319-top+1;//clip y border set_area(left, top, width, height); for(a=0; a<height; a++){ for(b=0; b<width; b++){ set_data(color); } } } //用 颜色 color 清屏 void clear_screen(uint color) { uint i,j; set_area(0,0,240,320); for(i=0;i<320;i++){ for (j=0;j<240;j++){ set_data(color); } } } //在指定位置输出一个ASCII字符 //属于内部调用函数 //参数:X坐标,Y坐标,字符,前景色,背景色 //如果不知道是怎样写字的, 看去看看我那篇 //介绍字库的使用的文章吧(在前面) void char_out(int x, int y, char ch, uint fgc, uint bgc) { char k,i; uchar* pch = 0; uchar* t_p = asc_tpow(); pch = asc_get_char(ch); if(!pch) return; //我的字库是8*12的 //但是我把它转换成了8*16 set_area(x, y, 8, 16); //所以我先写三行空白行 for(k=0; k<24; k++){ set_data(bgc); } for(k=0; k<12; k++){ for(i=0; i<8; i++){ set_data(*pch&t_p[i]?fgc:bgc); } pch++; } //再写一行空白行,用背景色填充 for(k=0; k<8; k++){ set_data(bgc); } } //前面是输出ASCII字符 //这个是在指定位置输出指定的汉字 //属于内部调用函数 //参数:X坐标,Y坐标,一个汉字的数组(uchar数组,3个字符,2个最好,节约嘛),前景色,背景色 void word_out(int x, int y, uchar* pword, uint fgc, uint bgc) { uchar xx,k,yy; uchar* pch = 0; uchar* t_p = asc_tpow(); //"汉字两个都>=0xa0, 不然就是错的" if(pword[0]<0xa0 || pword[1]<0xa0) return; pch = asc_get_word(pword); if(!pch) return; //"需要检测x+15,y+15是否出界,则k应为实际打印的行/列数" //"并设定一个参数为是否依然打印不能完整打印的char/word" set_area(x,y,16,16); //16*2*8:32个字节就这样写进去咯 for(k=0; k<16; k++){//16行 for(yy=0; yy<2; yy++){//一行2个字节(16位) for(xx=0; xx<8; xx++){//一个字节8个位 set_data(*pch&t_p[xx]?fgc:bgc); } pch++; } } } //这个都是真正的输出文本的函数的 //参数:X坐标,Y坐标,字符串指针,前景色,背景色,颜色索引表(可选) //说明:如果x,y均等于-1,则程序在上一次的结尾接着输出 //仅可用的控制字符:'\n',换行 void text_out(int x, int y, uchar* str, uint fgc, uint bgc, color_table* pct) { uchar* pch = str; uint k; uint fgcolor, bgcolor; //保存最近一次调用时的坐标 static uchar lastx=0; static uint lasty=0; //判断是否为接着输出 if(x==-1 && y==-1){ x = lastx; y = lasty; } if(!pch) return; //遍历每个字符调用 // char_out 进行字符输出 // word_out 进行中文输出 for(;*pch;){ if(pct){ fgcolor = pct->fgc; bgcolor = pct->bgc; }else{ fgcolor = fgc; bgcolor = bgc; } if(*pch >= 0xa0){//word word_out(x, y, pch, fgcolor, bgcolor); x += 16;//more 8 pixels than chars pch++; }else if(*pch == '\n'){//换行处理 x = 0; y += 16; }else{//char char_out(x, y, *pch, fgcolor, bgcolor); x += 8; } pch++; //check if return //word to next line //这里是当输出的汉字/字符不能完全显示是的处理(换行) if(/*x==240*/(*pch>=0xa0&&x>224) || x>232){//to next line if(*pch){ set_area(x,y,240,320); for(k=0; k<16*(239-x+1); k++){ set_data(bgcolor); } } x = 0; y += 16; } if(/*y==320*/y>304){//is bottom if(*pch){ set_area(x,y,240,320); for(k=0; k<240*(319-y+1); k++){ set_data(bgcolor); } } y = 0; } if(pct) pct++; } lastx = x; lasty = y; } /* float sin(float rad) { float x1 = rad; float x3 = x1*rad*rad; float x5 = x3*rad*rad; float x7 = x5*rad*rad; return x1/1-x3/6+x5/120-x7/5040; } */ /*float cos(float rad) { }*/ //画圆函数 //大师写的哦~ 膜拜 //基本没看懂 //不记得名字了, 好像是叫Bruce...画圆算法 void circle(int x0,int y0, int r,uint color) { int x,y,d; x=0; y=(int)r; d=(int)(3-2*r); while(x<y){ cirpot(x0,y0,x,y,color); if(d<0){ d+=4*x+6; }else{ d+=4*(x-y)+10; y--; } x++; } if(x==y) cirpot(x0,y0,x,y,color); } int cirpot(int x0,int y0,int x,int y,uint color) { set_pixel((x0+x),(y0+y), color); set_pixel((x0+y),(y0+x), color); set_pixel((x0+y),(y0-x), color); set_pixel((x0+x),(y0-y), color); set_pixel((x0-x),(y0-y), color); set_pixel((x0-y),(y0-x), color); set_pixel((x0-y),(y0+x), color); set_pixel((x0-x),(y0+y), color); return 0; } /*int abs(int a, int b) { if(a>b) return a-b; else return b-a; }*/