引言
温室监控的最终目标是给作物提供适宜的生长条件,对温室环境进行实时监控,是实现高效生产和管理的基础。通过对监测数据的分析,结合作物生长发育和病虫害发生规律,控制环境条件,达到作物优质、高产、高效的栽培目的。
温室环境信息被采集后,可以通过各种显示方式提供给用户,液晶显示器由于其低压、微功耗、平板型结构、长寿命等特点,在此方面被大量使用。目前温室环境监控系统所使用的液晶显示器大多是字符型和点阵型:字符型液晶显示器只能显示ASCII码字符,无法显示汉字,给对于国内大多数需要有汉字和图形显示的用户带来诸多不便;普通点阵型液晶显示器可以显示汉字和图形,但其显示汉字需要大量的字模存储空间,而且字模的提取和显示也很繁琐,大大增加了开发人员的工作量。
1.基于ST7920A控制器的中文字库液晶显示模块
OCMJ2×8C是128×32点阵型液晶显示模块,控制芯片是ST7920A,内置16×16点阵国标GB2312码全部简体中文字库(包括全角的各种常用符号、特殊数字符号、英文字母、罗马字母、俄文字母、日文字母、汉语拼音音标字母和制表符等)、128个8×16点阵半角ASCII字符和128×32点阵显示RAM(GDRAM),可显示2×8个汉字(或全角字符)和128×32点阵的图形。
可与单片机直接接口,提供两种连接方式:8位并行方式和串行方式。
提供硬件光标及其闪烁控制电路,可光标显示、反白显示、画面卷动、睡眠模式等。
可实现汉字、半角ASCII码字符、图形的同屏显示。
单一+5V电源供电,无需提供负电源。
控制指令分为基本指令和扩展指令,满足不同需要,简单易用。
2.硬件接口
OCMJ2×8C硬件提供以下对外接口:
逻辑支持电源:+5V(VDD、VSS);
背光板电源:+4.1V(LEDA、LEDK);
并行、串行方式选择:PSB;
复位:/RST;
并行方式数据:DB0-DB7;
并行方式控制:RS、R/W、E。如果使用串行方式,则只使用RS、R/W、E三线。
单片机可以通过数据总线与控制信号、采用外部数据存储器访问形式控制该液晶显示模块,也可以用3线串行方式控制。本文以51系列单片机兼容的华邦公司的W78E54微控制器为例,采用并行连接方式控制,见图1。
W78E54用地址A1作为R/W信号控制数据总线的数据流向;用地址A0作为数据/指令信号控制寄存器的选择;E信号由W78E54的读信号/RD、写信号/WR以及地址译码信号Y6合成。
图1并行连接方式
OCMJ2×8C液晶模块控制器ST7920A一共有18条指令,从作用上可分为两类,显示状态设置指令和数据、写操作指令,可以完成各种字符、图形的显示以及反白显示、屏幕卷动、光标定位闪烁等动作。详细指令系统可查看图形液晶显示器产品有关手册。接口部信号端的逻辑功能组合表如表1所示,其中地址是指按图1并行连接方式时,各指令反映在外部数据存储器的地址。
表1 逻辑功能组合表
3.软件设计
OCMJ2×8C模块在软件编程时需注意以下几个问题:
A.模块的复位时间、清屏指令和地址计数器归零指令的执行时间较长,请根据所使用的晶振频率给以适当延时。
B.当模块在接受指令前,微处理器必须先确认模块内部处于非忙碌状态,即读取BF标志时BF需为0,方可接受新的指令;如果在送出一个指令前并不检查BF标志,那么在前一个指令和这个指令中间必须延迟一段较长的时间,即等待前一个指令确实执行完成。
C.以点阵字符方式使用OCMJ2×8C模块时,先写入单字节地址,再写入单字节数据(半角ASCII字符:20H-7FH)或双字节数据(全角字符:A1A0H-A9F0H;汉字字符:B0A0H-D7FEH)。
D.以点阵绘图方式使用OCMJ2×8C模块时,方法和普通点阵液晶基本相同,先连续写入水平与垂直的坐标值,再写入两个字节数据值到绘图RAM。写入绘图RAM之前,绘图显示必须关闭,数据写入完成后再打开绘图显示功能。
以点阵字符方式同屏显示汉字和各种全角、半角字符的具体程序框图见图2。
图2
4.应用实例
笔者在智能数显传感器的开发中,成功地应用了内置ST7920A控制器的中文字库液晶显示模块。为方便读者,将已经在实际应用中通过的C51程序列出。
#include<各类头文件>
#defineWRITE_LCD_CONTROLXBYTE[0xc000]
#defineWRITE_LCD_DATA XBYTE[0xc001]
#defineREAD_LCD_STATUSXBYTE[0xc002]
#defineREAD_LCD_DATAXBYTE[0xc003]
sbitLCD_BF=ACC^7; /*定义模块忙碌标志位BF*/
sbitLCD_RESET=P1^1; /*定义复位连接*/
voidwrite_control(charcontrol) /*写指令或地址函数*/
{ do { ACC=READ_LCD_STATUS;} /*读取模块状态*/
while(LCD_BF==1); /*判断模块控制器是否忙*/
WRITE_LCD_CONTROL=control;/*写指令或地址*/
}
voidwrite_data(charddata)/*写数据函数*/
{ do { ACC=READ_LCD_STATUS;}/*读取模块状态*/
while(LCD_BF==1);/*判断模块控制器是否忙*/
WRITE_LCD_DATA=ddata;/*写数据*/
}
voidinit_lcd(void)
{ LCD_RESET=0;delay_200ms(); /*液晶模块复位*/
LCD_RESET=1;delay_200ms();
write_control(0x30);/**/
write_control(0x0c);/**/
write_control(0x01);/**/
write_control(0x06);/**/
}
voidstart_display(void)
{ write_control(0x80); /*第一行字符起始位置*/
write_data(0xb9);write_data(0xfa);/*国*/
write_data(0xbc);write_data(0xd2);/*家*/
write_data(0xc5);write_data(0xa9);/*农*/
write_data(0xd2);write_data(0xb5);/*业*/
write_data(0xd0);write_data(0xc5);/*信*/
write_data(0xcf);write_data(0xa2);/*息*/
write_data(0xd6);write_data(0xd0);/*中*/
write_data(0xd0);write_data(0xc4);/*心*/
write_control(0x90); /*第二行字符起始位置*/
write_data(0xa1);write_data(0xe6);/* ℃ */
write_data(0xa1);write_data(0xed);/* № */
write_data(0xa2);write_data(0xd0);/* ⑿ */
write_data(0xa2);write_data(0xde);/* ⑥ */
write_data(0xa2);write_data(0xea);/* 六 */
write_data(0xa4);write_data(0xc1);/* ち */
write_data(0xa6);write_data(0xce);/* ξ */
write_data(0x1a);write_data(0x1b);/* →←(半角) */
}
voidmain(void)
{
init_lcd();
start_display();
}