LCD1602是很常用的液晶显示屏。在网络上已经有不少应用于51等单片机的程序。在这里Donald用的是Freescale的MC9SDG128,已经成功显示。

Donald使用的是如下引脚的1602。以前用的是横排管脚的封装。而本次用的是这种管脚排列,可气的是,网上给资料竟然和Donald手头的这个模块不同,其中1脚是VDD,接+5V电源,2脚是VSS,接地。Donald看了很多类似的模块,基本是和本人手里的模块一样,也就是说网上的资料基本是抄来抄去的,可以连试都没试过。
另外的3到14脚的作用如下。
第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。调程序时,别忘了适当调整电位器。Donald在调试时,开始时老是显示不出来,经过各种检查程序,还是不行,最后没办法调了下电位器,发现已经显示在上面了,晕!
第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:D0~D7为8位双向数据线。
还有两个引脚没有引出来,他们是"A"和"K",为背光引脚,"A"接正,"K"接负便会点亮背光灯。
这里,Donald由于自己腐蚀的扩展板是单面板,需考虑最小系统板和引线方便。就让RS引脚接PORTE_BIT2,RW接的是PORTH的PTH0,E连接的是PTH2,并行数据口接的是PORTA。这些都在头文件中做了宏定义,可方便地应用于其它端口。
因为16位MCU的I/O口通常不像51那样直接输入输出,其具有多种功能。所以在使用时要经常对其数据方向寄存器进行配置。为了方便,Donald做了如下定义:
#define LCDIO_DIR DDRA
#define LCDIO_DIR_IN 0x00
#define LCDIO_DIR_OUT 0xFF
这样,当需要变换端口数据传输方向时,只需用如下语句:
LCDIO_DIR = LCDIO_DIR_IN;
or
LCDIO_DIR = LCDIO_DIR_OUT;
以下为头文件。
/*-------------------------------------------------------
LCD1602 Module (head file)
Donald
Apr 30, 2007
-------------------------------------------------------*/
#ifndef _LCD1602_14P
#define _LCD1602_14P
#define LINE1 0
#define LINE2 1
#define LINE1_HEAD 0x80
#define LINE2_HEAD 0xC0
#define DATA_MODE 0x38 // 8 bit data transmission mode, double line
// LCD1602 Command Macro
#define CLR 0x01
#define BUSY 0x80 // LCD Busy Tag
#define CURSOR_RESET 0x02
#define INPUTMODE_CUR_R 0x06
#define INPUTMODE_CUR_L 0x04
#define INPUTMODE_ALL_E 0x05
#define INPUTMODE_ALL_D 0x04
#define SCREEN_OPEN 0x0C
#define SCREEN_OPEN_CUR 0x02
#define SCREEN_OPEN_TWI 0x01
#define SCSHIFT_CUR_L 0x10 // Screen or Cursor shift
#define SCSHIFT_CUR_R 0x14
#define SCSHIFT_SCR_L 0x18
#define SCSHIFT_SCR_R 0x1C
// LCD1602 Pins
#define LCD1602_RS PORTE_BIT2 //Data Command Pin 1 data 0 command
#define LCD1602_RW PTH_PTH0 //Read Write Pin 1 read 0 write
#define LCD1602_EN PTH_PTH2 //LCD Enable Signal
#define LCDIO PORTA
#define LCDIO_DIR DDRA
#define LCDIO_DIR_IN 0x00
#define LCDIO_DIR_OUT 0xFF
void LcdCommand(unsigned char command,unsigned char BusyC); //write command function
void LcdData(unsigned char temp,unsigned char BusyC); //write data function
void LcdSetXY( unsigned char x, unsigned char y ); //set display address function
void LcdWriteChar( unsigned char x,unsigned char y,unsigned char dat);//write lcd a character function
void LcdWriteStr(unsigned char X,unsigned char Y,char *s);//write lcd string function
void LcdInit(void); //LCD initize function
unsigned char ReadStatus(void);
void LcdDelay(void); //LCD Delay Function
#endif
头文件结束。
以下是源文件。
/*-------------------------------------------------------
LCD1602 Module
Donald
Apr 30, 2007
-------------------------------------------------------*/
#include <hidef.h> /* common defines and macros */
#include <mc9s12dg128.h> /* derivative information */
#include "LCD1602_14P.h"
void LcdInit(){
DDRH = 0xff;
DDRE = 0xff;
LCDIO_DIR = LCDIO_DIR_OUT;
LcdDelay();
LcdCommand(CLR,0); //clear screen
LcdCommand(DATA_MODE,1); //set 8 bit data transmission mode
LcdCommand(INPUTMODE_CUR_R | INPUTMODE_ALL_D, 1); // cursor right, disable moving
LcdCommand(SCREEN_OPEN
| SCREEN_OPEN_CUR
| SCREEN_OPEN_TWI
, 1); //open display (enable lcd display)
LcdCommand(LINE1_HEAD,1); //set lcd first display address
LcdCommand(CLR,1); //clear screen
}
////////////////////////////////////////////////////////////////////
// write command function
//
void LcdCommand(unsigned char command,unsigned char BusyC){
if (BusyC) ReadStatus(); //Test it busy or not
LCDIO=command;
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_EN=0;
LCD1602_EN=0;
LCD1602_EN=1;
}
unsigned char ReadStatus(void)
{
unsigned char cRtn;
LCDIO_DIR = LCDIO_DIR_IN;
LCD1602_RS = 0;
LCD1602_RW = 1;
LCD1602_EN = 0;
LCD1602_EN = 0;
LCD1602_EN = 1;
while (LCDIO & BUSY); //Test Busy State
cRtn = LCDIO_DIR; // if Not save the port value, it should be change
LCDIO_DIR = LCDIO_DIR_OUT;
return(cRtn);
}
void LcdDelay(void){
word i, j;
for (i = 0; i < 300; i++)
for(j = 0; j < 3000; j++);
}
////////////////////////////////////////////////////////////////////
// write data function
//
void LcdData(unsigned char dat,unsigned char BusyC)
{
if (BusyC) ReadStatus(); //Test it busy or not
LCDIO=dat;
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_EN=0;
LCD1602_EN=0;
LCD1602_EN=1;
}
////////////////////////////////////////////////////////////////////
// write lcd a character function
//
void LcdWriteChar( unsigned char x,unsigned char y,unsigned char dat){
LcdSetXY(x, y);
LcdData(dat,1);
}
////////////////////////////////////////////////////////////////////
// set display address function
//
void LcdSetXY( unsigned char x, unsigned char y ){
unsigned char address;
if (y == LINE1)
address = LINE1_HEAD + x;
else
address = LINE2_HEAD + x;
LcdCommand(address,1);
}
////////////////////////////////////////////////////////////////////
// write lcd string function
//
void LcdWriteStr(unsigned char X,unsigned char Y,char *s)
{
LcdSetXY( X, Y ); //set address
while (*s) // write character
{
LcdData(*s, 1);
s++;
}
}
源文件结束。
附:LCD1602手册(该种资料可从网上搜到,有的是)