一、LCD结构体
定义LCD为LCD_TypeDef类型的指针,指向0x6C000000的地址空间(bank1分区4的地址范围)。
为什么需要并上0x000007FE呢?
因为虽然驱动SRAM的时序和16位8080接口时序(驱动LCD时序)很像,但是8080的RS(寄存器选择)信号需要解决,解决方法是使用SRAM地址信号中的A10作为RS位。
0x000007FE是内部地址,指向一个8位的存储空间。同时也是A10引脚的偏移值,因为A10是外部存储器16位的地址,所以我们要先把该地址变成外部地址(右移一位或除以2),也就是说
111 1111 1110 -> 011 1111 1111
也就是该结构体变量的首地址是011 1111 1111(对于外部存储器来说),那么结构体变量成员LCD_REG的地址就是011 1111 1111,而LCD_RAM的地址是外部地址加1,即100 0000 0000。
这种设计使得,两个变量所在地址空间的A10不同,解决了RS的问题。
二、lcddev结构体
用来设置LCD的结构体。
三、底层接口函数
四、LCD初始化函数
五、LCD坐标设置函数
六、LCD画点函数
七、LCD字符显示函数
以下是针对图片中 LCD_ShowChar
函数的逐行解析,结合其功能实现和硬件交互逻辑:
1. 函数功能概述
void LCD_ShowChar(u16 x, u16 y, u8 num, u8 size, u8 mode)
- 作用:在LCD屏幕的指定位置
(x,y)
显示一个ASCII字符。 - 参数:
x, y
:字符左上角起始坐标(像素单位)。num
:要显示的字符(ASCII码,范围从空格' '
到'~'
)。size
:字体大小(12/16/24像素)。mode
:显示模式(0
非叠加,1
叠加。叠加模式下保留背景,仅绘制字符像素)。
2. 关键变量与初始化
u8 temp, t1, t;
u16 y0 = y; // 保存起始y坐标
u8 csize = (size/8 + ((size%8)?1:0)) * (size/2); // 计算字符点阵数据占用的字节数
num = num - ' '; // ASCII字库偏移(字库从空格开始存储)
**
csize
计算逻辑:
字体点阵通常按行存储**,每行像素用1字节表示(每bit代表1像素)。例如:- 12像素字体:每行12像素 → 占用2字节(12/8=1.5 → 向上取整为2字节)。
- 总字节数 =
(行字节数) * (行数)
=(size/8 + 余数处理) * (size/2)
。
**
num
偏移**:
字库数组(如asc2_1206
)从空格字符(ASCII 32)开始存储,减去' '
得到正确的索引。
3. 字符点阵数据获取
for(t=0; t<csize; t++) {if(size==12) temp = asc2_1206[num][t]; // 12像素字体else if(size==16) temp = asc2_1608[num][t]; // 16像素字体else if(size==24) temp = asc2_2412[num][t]; // 24像素字体else return; // 不支持的字体大小
- 字库结构:
字库为二维数组(如asc2_1206[字符数][点阵字节数]
),每个字符的点阵数据按行排列。 - 示例:
若显示字符'A'
(ASCII 65),则num = 65 - 32 = 33
,从字库中获取第33个字符的点阵。
4. 逐像素绘制字符
for(t1=0; t1<8; t1++) {if(temp & 0x80) LCD_Fast_DrawPoint(x, y, POINT_COLOR); // 当前bit=1,绘制字符颜色else if(mode==0) LCD_Fast_DrawPoint(x, y, BACK_COLOR); // 非叠加模式,绘制背景色temp <<= 1; // 左移检查下一bity++; // 移动到下一行像素if(y >= lcddev.height) return; // 超出屏幕高度if((y - y0) == size) { // 完成一列绘制y = y0; // y坐标复位x++; // 移动到下一列if(x >= lcddev.width) return; // 超出屏幕宽度break;}
}
- 像素绘制逻辑:
- 检查最高位(
temp & 0x80
):- 若为1,调用
LCD_Fast_DrawPoint
绘制字符颜色(POINT_COLOR
)。 - 若为0且
mode=0
,绘制背景色(BACK_COLOR
,覆盖原有内容)。
- 若为1,调用
- 坐标更新:
- 每处理1bit,
y++
向下移动一行像素。 - 当
y - y0 == size
时,表示一列像素绘制完成,复位y
并右移一列(x++
)。
- 每处理1bit,
- 检查最高位(
5. 边界检查与优化
- 屏幕边界处理:
每次更新坐标后检查x
和y
是否超出屏幕尺寸(lcddev.width/height
),避免越界。 - 性能优化:
LCD_Fast_DrawPoint
应为优化后的快速画点函数(可能直接操作FSMC或显存)。
6. 字库与硬件交互
- 字库存储:
字库数组(如asc2_1206
)通常存储在代码区(Flash)或外部SPI Flash,通过查表获取点阵。 - LCD写入:
LCD_Fast_DrawPoint
内部通过FSMC或GPIO模拟8080接口,向LCD显存写入像素颜色值。
总结:字符显示流程
- 参数校验 → 2. 计算字模数据位置 → 3. 逐字节读取点阵 →
- 逐bit绘制像素 → 5. 坐标更新与边界检查 → 6. 循环直至字符绘制完成。
此函数通过硬件加速的像素操作和高效的字模解析,实现了灵活的字符显示功能。如需显示中文或自定义图形,需扩展字库和绘制逻辑。