第74节:在液晶屏中让字体跨区域无缝对接显示的算法程序

发布者:平凡的梦想最新更新时间:2016-03-16 来源: eefocus关键字:液晶屏  字体跨区域  无缝对接显示  算法程序 手机看文章 扫描二维码
随时随地手机看文章
开场白:

细心的网友会发现,这种12864液晶屏在显示自造字库时普遍有个毛病,在坐标轴x方向上是以每16个点阵为一个单位的,如果显示两个8x16字符”V”和”5”,虽然它们的x坐标轴是相邻的,但是实际显示的效果是中间隔了8个点阵。另外,这种12864液晶屏是由上半屏和下半屏组成的,软件上的坐标体系并没有做到跟物理的坐标体系一致,需要转换的。如果我们想把一个整体字符的一半显示在上半屏,另一半显示在下半屏,那怎么办?

这一节就要教给大家这个算法程序:

为了实现跨区域无缝显示,就先在某个区域显示一块画布,我们只要在这块画布数组中插入字模数组,就可以达到跨区域无缝显示的目的。

具体内容,请看源代码讲解。

(1)硬件平台:

基于朱兆祺51单片机学习板。

(2)实现功能:开机上电后,看到液晶屏所有的点阵都显示。正中间露出一小方块空白的32x16点阵画布,从左到右分别显示“V5”两个字符。这两个字符是紧紧挨在一起的,中间并没有8个点阵的空格,同时这两个字符的上半部分显示在上半屏,下半部分显示在下半屏。实现了真正的跨区域无缝对接显示。

(3)源代码讲解如下:

#include "REG52.H"

sbit LCDCS_dr = P1^6; //片选线

sbit LCDSID_dr = P1^7; //串行数据线

sbit LCDCLK_dr = P3^2; //串行时钟线

sbit LCDRST_dr = P3^4; //复位线

void SendByteToLcd(unsigned char ucData); //发送一个字节数据到液晶模块

void SPIWrite(unsigned char ucWData, unsigned char ucWRS); //模拟SPI发送一个字节的命令或者数据给液晶模块的底层驱动

void WriteCommand(unsigned char ucCommand); //发送一个字节的命令给液晶模块

void LCDWriteData(unsigned char ucData); //发送一个字节的数据给液晶模块

void LCDInit(void); //初始化 函数内部包括液晶模块的复位

void display_clear(unsigned char ucFillDate); // 清屏 全部显示空填充0x00 全部显示点阵用0xff

void insert_buffer_to_canvas(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount);//把字模插入画布.

void display_lattice(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount,unsigned int uiOffSetAddr); //显示任意点阵函数

void delay_short(unsigned int uiDelayshort); //延时

code unsigned char Zf816_V[]= /*V 横向取模 8x16点阵 每一行只要1个字节,共16行 */

{

0x00,

0x00,

0x00,

0xE7,

0x42,

0x42,

0x44,

0x24,

0x24,

0x28,

0x28,

0x18,

0x10,

0x10,

0x00,

0x00,

};

code unsigned char Zf816_5[]= /*5 横向取模 8x16点阵 每一行只要1个字节,共16行 */

{

0x00,

0x00,

0x00,

0x7E,

0x40,

0x40,

0x40,

0x58,

0x64,

0x02,

0x02,

0x42,

0x44,

0x38,

0x00,

0x00,

};

/* 注释一:

* 为了实现跨区域无缝显示,就先在某个区域显示一块画布,我们只要在这块画布数组中插入字模数组,

* 就可以达到跨区域无缝显示的目的。根据上几节的介绍,12864液晶屏由上下两半屏组成,以下这块画布

* 显示在上半屏和下半屏之间。横向4个字节,纵向16行。其中上半屏显示8行,下半屏显示8行。注意,这个数组

* 不带code关键字,是全局变量,这样可读可写。画布的横向x坐标范围是0至3,因为画布的横向只要4个字节。

* 画布的纵向y坐标范围是0至15,因为画布的纵向只有16行。

*/

unsigned char ucCanvasBuffer[]= //画布显示数组。注意,这里没有code关键字,是全局变量。初始化全部填充0x00

{

0x00,0x00,0x00,0x00, //上半屏

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

//------------上半屏和下半屏的分割线-----------

0x00,0x00,0x00,0x00, //下半屏

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,

};

void main()

{

LCDInit(); //初始化12864 内部包含液晶模块的复位

display_clear(0xff); // 清屏 全部显示空填充0x00 全部显示点阵用0xff

insert_buffer_to_canvas(0,0,Zf816_V,0,1,16);//把的字模插入画布

insert_buffer_to_canvas(1,0,Zf816_5,0,1,16);//把<5>的字模插入画布

display_lattice(3,24,ucCanvasBuffer,0,4,8,0); //显示上半屏的画布,最后的参数0是偏移量

display_lattice(11,0,ucCanvasBuffer,0,4,8,32); //显示下半屏的画布,最后的参数32是偏移量

while(1)

{

;

}

}

void display_clear(unsigned char ucFillDate) // 清屏 全部显示空填充0x00 全部显示点阵用0xff

{

unsigned char x,y;

WriteCommand(0x34); //关显示缓冲指令

WriteCommand(0x34); //关显示缓冲指令 故意写2次,怕1次关不了 这个是因为我参考到某厂家的驱动程序也是这样写的

y=0;

while(y<32) //y轴的范围0至31

{

WriteCommand(y+0x80); //垂直地址

WriteCommand(0x80); //水平地址

for(x=0;x<32;x++) //256个横向点,有32个字节

{

LCDWriteData(ucFillDate);

}

y++;

}

WriteCommand(0x36); //开显示缓冲指令

}

/* 注释二:

* 把字模插入画布的函数.

* 这是本节的核心函数,读者尤其要搞懂x_amount和y_amount对应的显示关系。

* 第1,2个参数x,y是在画布中的坐标体系。

* x的范围是0至3,因为画布的横向只要4个字节。y的范围是0至15,因为画布的纵向只有16行。

* 第3个参数*ucArray是字模的数组。

* 第4个参数ucFbFlag是反白显示标志。0代表正常显示,1代表反白显示。

* 第5,6个参数x_amount,y_amount分别代表字模数组的横向有多少个字节,纵向有几横。

*/

void insert_buffer_to_canvas(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount)

{

unsigned int j=0;

unsigned int i=0;

unsigned char ucTemp;

for(j=0;j

{

for(i=0;i

{

ucTemp=ucArray[j*x_amount+i];

if(ucFbFlag==0)

{

ucCanvasBuffer[(y+j)*4+x+i]=ucTemp; //这里的4代表画布每一行只有4个字节

}

else

{

ucCanvasBuffer[(y+j)*4+x+i]=~ucTemp; //这里的4代表画布每一行只有4个字节

}

}

}

}

/* 注释三:

* 显示任意点阵函数.

* 注意,本函数在前几节的基础上多增加了第7个参数uiOffSetAddr,它是偏移地址。

* 对于这个函数,读者尤其要搞懂x_amount和y_amount对应的显示关系。

* 第1,2个参数x,y是坐标体系。x的范围是0至15,y的范围是0至31.

* 第3个参数*ucArray是字模的数组。

* 第4个参数ucFbFlag是反白显示标志。0代表正常显示,1代表反白显示。

* 第5,6个参数x_amount,y_amount分别代表字模数组的横向有多少个字节,纵向有几横。

* 第7个参数uiOffSetAddr是偏移地址,代表字模数组的从第几个数据开始显示。

*/

void display_lattice(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount,unsigned int uiOffSetAddr)

{

unsigned int j=0;

unsigned int i=0;

unsigned char ucTemp;

WriteCommand(0x34); //关显示缓冲指令

WriteCommand(0x34); //关显示缓冲指令 故意写2次,怕1次关不了 这个是因为我参考到某厂家的驱动程序也是这样写的

for(j=0;j

{

WriteCommand(y+j+0x80); //垂直地址

WriteCommand(x+0x80); //水平地址

for(i=0;i

{

ucTemp=ucArray[j*x_amount+i+uiOffSetAddr]; //uiOffSetAddr是字模数组的偏移地址

if(ucFbFlag==1) //反白显示

{

ucTemp=~ucTemp;

}

LCDWriteData(ucTemp);

// delay_short(30000); //把上一节这个延时函数去掉,加快刷屏速度

}

}

WriteCommand(0x36); //开显示缓冲指令

}

void SendByteToLcd(unsigned char ucData) //发送一个字节数据到液晶模块

{

unsigned char i;

for ( i = 0; i < 8; i++ )

{

if ( (ucData << i) & 0x80 )

{

LCDSID_dr = 1;

}

else

{

LCDSID_dr = 0;

}

LCDCLK_dr = 0;

LCDCLK_dr = 1;

}

}

void SPIWrite(unsigned char ucWData, unsigned char ucWRS) //模拟SPI发送一个字节的命令或者数据给液晶模块的底层驱动

{

SendByteToLcd( 0xf8 + (ucWRS << 1) );

SendByteToLcd( ucWData & 0xf0 );

SendByteToLcd( (ucWData << 4) & 0xf0);

}

void WriteCommand(unsigned char ucCommand) //发送一个字节的命令给液晶模块

{

LCDCS_dr = 0;

LCDCS_dr = 1;

SPIWrite(ucCommand, 0);

delay_short(90);

}

void LCDWriteData(unsigned char ucData) //发送一个字节的数据给液晶模块

{

LCDCS_dr = 0;

LCDCS_dr = 1;

SPIWrite(ucData, 1);

}

void LCDInit(void) //初始化 函数内部包括液晶模块的复位

{

LCDRST_dr = 1; //复位

LCDRST_dr = 0;

LCDRST_dr = 1;

}

void delay_short(unsigned int uiDelayShort) //延时函数

{

unsigned int i;

for(i=0;i

{

;

}

}

总结陈词:

经过这一节的算法处理后,字符终于可以在x轴上紧紧挨着显示了。也就是把原来x坐标是16个点阵为一个单位,改成了以8个点阵为一个单位。如果要求以1个点阵为单位显示,那该怎么办?这个还真有点难度,因为横向的最小显示单位就是一个字节8个点,不过鸿哥在下一节中照样有办法实现这个功能。欲知详情,请听下回分解-----在12864液晶屏中让字体以1个点阵为单位进行移动显示的算法程序。

关键字:液晶屏  字体跨区域  无缝对接显示  算法程序 引用地址:第74节:在液晶屏中让字体跨区域无缝对接显示的算法程序

上一篇:第73节:在液晶屏中把字体镜像显示的算法程序
下一篇:第75节:液晶屏让字体以1个点阵为单位移动显示的算法程序

推荐阅读最新更新时间:2024-03-16 14:47

第72节:在液晶屏中把字体顺时针旋转90度显示算法程序
开场白: 我曾经遇到过这样的项目,客户由于外壳结果的原因,故意把液晶屏物理位置逆时针旋转了90度,在这种情况下,如果按之前的显示驱动就会发现字体也跟着倒了过来,影响了阅读。当时我的解决办法就是把字体的字库数组通过算法顺时针旋转90度就达到了目的。这一节把这个算法教给大家。 这个算法的本质是:请看以下附图1,附图2,附图3. 第一步:旋转90度的本质,就是把原来横向取模改成纵向去模。先把代表每一行16个点阵数的2个char型数据合并成1个int型数据。 第二步:再把每一列的16个点阵按2个字节分别取到一个数组里,就是纵向取模的过程了。 具体内容,请看源代码讲解。 (1)硬件平台: 基于朱兆祺51单片机学习板。
[单片机]
第72节:在<font color='red'>液晶屏</font>中把<font color='red'>字体</font>顺时针旋转90度<font color='red'>显示</font>的<font color='red'>算法</font><font color='red'>程序</font>
The MathWorks宣布从MATLAB中自动生成可嵌入C 代码功能
        嵌入式 MATLAB 子集转换成有效嵌入式代码 美国马萨诸塞州内蒂克市(NATICK, Mass.) – 2007年10月1日 – The MathWorks 今日推出了嵌入式 MATLAB ――业界领先的 MATLAB 科学计算语言的子集。 嵌入式 MATLAB 子集使 MATLAB 用户能够从 MATLAB 程序中生成高效、可嵌入 C 代码,从而避免了常见的、耗时的和易出错的用 C 代码重写 MATLAB 算法的进程。 嵌入式 MATLAB 子集包括了众多的 MATLAB 功能,有 270 多个 MATLAB 运算符和函数以及90 多个定点工具箱(Fixed-Point Toolbox)函数。嵌入式 MA
[新品]
程序员必知的十大基础实用算法及其讲解
你知道程序员的十大基础实用算法及其讲解吗? 算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个项目要Ο(nlogn)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(nlogn)算法更快,因为它的内部循环(innerloop)可以在大部分的架构上很有效率地被实现出来。 快速排序使用分治法(Divideandconquer)策略来把一个串行(list)分为两个子串行(sub-lists)。 算法步骤: 1、从数列中挑出一个元素,称为“基准”(pivot), 2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相
[单片机]
s3c2440液晶屏驱动 (非内核自带) linux-4.1.24
对于,不想逐一检查内核自带驱动,想自己编写驱动。 1,make menuconfig 去掉 编译到内核,改为 M 编译为 模块(因为要用到里面的3个.ko 驱动) Device Drivers --- Graphics support --- Support for frame buffer devices --- M S3C2410 LCD framebuffer support 2,make uImage && make modules 生成新内核 和 模块文件 烧写新内核或使用 nfs bootm 使用编译为 M 模块的内核启动。 复制 3个 ko 文件到 文件系统,这里用的是 NFS 网络文件
[单片机]
新款iPhone加剧有机EL和液晶屏的争夺战
美国苹果9月12日发布的新款iPhone系列正在影响半导体内存等电子零部件的行情。 在推高NAND型记忆卡和有机EL面板价格上升的同时,被有机EL面板夺走部分需求的液晶面板则持续降价。 但记忆卡的供应短缺迹象明显,有可能对苹果的销售战略造成影响。   最高端机型「iPhone X」首次采用了有机EL面板。 充分发挥了设计自由度较高的特性,5.8英吋的屏幕几乎占满了正面的全部。   有机EL面板还对终端的薄型化和鲜艳的色彩显示做出了贡献。   有机EL面板的价格据称在100美元左右,是此前液晶面板的近2倍。 由于是韩国三星电子独家供货,IHS Technology高级总监早濑宏等众多观点认为「价格今后难以下降」。   「iPhone
[手机便携]
一个51单片机的键盘扫描程序算法简单有效
/**************************************** 键盘_不采用定时器_不延时 特点: 按键在松手后有效,灵敏度高,消耗资源少,运行效率高 独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7; 矩阵键盘为:行(上到下)_P2.3_P2.2_P2.1_P2.0 列(左到右)_P2.7_P2.6_P2.5_P2.4 提供的操作函数: //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key extern unsigned char keyboard_self(); //矩阵键盘.无按键动作时其返回值num_key=0,否则
[单片机]
基于SYSTEM C的FPGA设计方法
一、概述    随着VLSI的集成度越来越高,设计也越趋复杂。一个系统的设计往往不仅需要硬件设计人员的参与,也需要有软件设计人员的参与。软件设计人员与硬件设计人员之间的相互协调就变的格外重要,它直接关系到工作的效率以及整个系统设计的成败。传统的设计方法没有使软件设计工作与硬件设计工作协调一致,而是将两者的工作割裂开来。软件算法的设计人员在系统设计后期不能为硬件设计人员的设计提供任何的帮助。同时现在有些大规模集成电路设计中往往带有DSP Core或其它CPU Core。这些都使得单纯地用原理图或硬件描述语言来设计、仿真这么复杂的系统变得十分困难。System C就是在这些矛盾的背景下提出的。它的出现为复杂的系统设计提供了一条有效的
[应用]
第82节:调用液晶屏内部字库把一个任意数值的变量显示出来
开场白: 本来这一节打算开始讲调用液晶屏内部字库时的反显程序,但是我担心跳跃太大,恐怕很多初学者跟不上,所以多插入这一节讲讲后面菜单程序中经常用到的基本功能,在调用内部字库的情况下,如何把一个任意数值的变量显示在液晶屏上。这一节的功能需求跟前面第76节是一模一样的,只不过前面的不是用自带字库,现在的是用自带字库而已。我们还是需要做一个变量转换成ASCII码的函数,以后只要调用这个转换函数就可以了。这一节就要把这个转换函数和框架思路教给大家。 具体内容,请看源代码讲解。 (1)硬件平台: 基于朱兆祺51单片机学习板。 (2)实现功能:我们定义一个char型的全局变量,把它默认初始化为218,开机上电后,能看到正中间恰好显示这个
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved