/***************************************************************************
申明
经过测试J204A(也称2004A,每行20字符,显示4行)液晶屏和1602液晶屏的
使用方法几乎是一样的,不过也是有区别的,在1602液晶屏中,用来寄存待显
示字符代码的DDRAM共有80个字节,而J204A能够一次性显示的字符是80字
节,这里不是巧合,即J204A只是将LCD1602的DDRAM的80个字符全部显示出
来而已。
第一行首地址 :0x80
第二行首地址 :0x80+0x40
第三行首地址 :0x80+20
第四行首地址 :0x80+0x40+20
可以注意到,第一行和第三行、第二行和第四行的地址是分别连续的。 经过
实验验证,可以得出这样的结论:J204A是将LCD1602的DDRAM的0x00~0x13地址
的数据映射显示在J204A的第一行,LCD1602的DDRAM的0x14~0x27地址的数据映
射显示在第三行 ; LCD1602的DDRAM的0x40~0x53地址的数据映射显示在J204A
的第二行,将LCD1602的DDRAM的0x54~0x67地址的数据映射显示在J204A的第四行。
----------------------------------------------------------------------------
J204A的程序和LCD1602的程序很相似,这里的程序是由LCD1602程序修改而来。
----------------------------------------------------------------------------
***************************************************************************/
/***************************************************************************
Module :lcd2004.c
Purpose :Implementation of lcd2004 module.
Version :0.01 2014/02/13 12:00(OK)
Complier:Keil 8051 C complier V9.01
MCU :STC12C5A60S2
Author :yangrui
QQ :279729201
Email :yangrui90s@163.com
Modification:
=================
2014/04/31 20:09
Reson:
1.解决大工程中,因未安装LCD2004而导致的工程卡死在函数
lcd2004CheckBusy()的问题,将
do{
;
}while( (lcd2004ReadStatus()) & 0x80));
修改为
do{
i++;
}while( ((lcd2004ReadStatus()) & 0x80) && (i<10));
因为在未安装LCD2004时,通过"读状态"函数lcd2004ReadStatus()读回来的是0xff,
如果采用第一种算法,会导致程序"卡死"。
=================
=================
2014/02/27 08:25
Reson:
1.修改函数SB8 lcd2004AddressWriteByte(...)
{
if(column<0|| column > 19|| \
( (row != LCD2004_ROW0) &&(row != LCD2004_ROW1))&& \
(row != LCD2004_ROW2) &&(row != LCD2004_ROW3)) \
)
{
return -1;
}
......
return 0 ;
}
为
void lcd2004AddressWriteByte(UB8 row,UB8 column,UB8 dataCode)
{
//省略if判断
//无返回值
}
这里省略判断是因为LCD2004和LCD1602的特殊关系,在LCD1602的DDRAM中
共有80个字符,每一行的显示缓存有40个字符长度,为了调用的安全性,
在lcd1602.c中相同功能的函数是有if判断,但是对于LCD2004,第三行和
第四行所显示的内容分别就是LCD1602的DDRAM的第一行的显示缓冲DDRAM的
后20个字符、第二行的显示缓冲DDRAM的后20个字符。这可以通过以下方法
验证:
首先,省略if判断,然后调用函数
lcd2004AddressWriteString(LCD2004_ROW2,0,"2014/02/27");
和调用函数
lcd2004AddressWriteString(LCD2004_ROW0,20,"2014/02/27");
效果是一样的
为了调用的灵活性,这里省略了if判断,并将函数改为无返回值的类型。
=================
=================
2014/02/24 23:44
Reson:
1.增加函数lcd2004AddressWriteString(...)
=================
***************************************************************************/
#include <reg52.h>
#include <intrins.h>
#include <string.h>
#include "lcd2004.h"
/*外部接口函数在lcd2004.h中声明*/
/*****************内部函数******************/
static void delay1msForLcd2004(void) ;
static UB8 lcd2004ReadStatus(void) ;
static void lcd2004CheckBusy(void) ;
/**********************************************/
/******************************************************
Function :delay1msForLcd2004
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :crystal frequency is 11.0592MHZ
******************************************************/
static void delay1msForLcd2004(void)
{
unsigned char i, j;
_nop_();
_nop_();
i = 12;
j = 168;
do
{
while (--j);
} while (--i);
}
/******************************************************
Function :lcd2004ReadStatus
Input :N/A
Output :N/A
Return :lcd2004 status value
Description :N/A
Note :N/A
******************************************************/
static UB8 lcd2004ReadStatus(void)
{
UB8 statusCode ;
lcd2004_en_bit = LCD2004_DISABLE ;
lcd2004_rs_bit = LCD2004_COMMAND_OPERATION ;
lcd2004_rw_bit = LCD2004_READ_OPERATION ;
LCD2004_DATA_PORT = 0xff ;
delay1msForLcd2004() ;
lcd2004_en_bit = LCD2004_ENABLE ;
delay1msForLcd2004() ;
statusCode = LCD2004_DATA_PORT ;
lcd2004_en_bit = LCD2004_DISABLE ;
return statusCode ;
}
/******************************************************
Function :lcd2004CheckBusy
Input :N/A
Output :N/A
Return :N/A
Description :check lcd2004 busy or free,if busy,wait !
Note :when LCD2004_DATA_PORT[7]==1,lcd2004 is busy,
LCD2004_DATA_PORT[7]==0,lcd2004 is free.
补充:这里的“10”是经过测试的,测试中,利用串口打印
可知,“清除屏幕显示”命令“lcd2004CleanAll()”用时最长,
此命令下i值为1,这里设置i为10,足够大了
******************************************************/
static void lcd2004CheckBusy(void)
{
UW16 i=0 ;
do{
i++;
}while( (lcd2004ReadStatus() & 0x80) && (i<10));
}
/******************************************************
Function :lcd2004WriteCommand
Input :command code
Output :N/A
Return :N/A
Description :write command to lcd2004
Note :N/A
******************************************************/
void lcd2004WriteCommand(UB8 commandCode)
{
lcd2004CheckBusy();
lcd2004_en_bit = LCD2004_DISABLE ;
lcd2004_rs_bit = LCD2004_COMMAND_OPERATION ;/*command*/
lcd2004_rw_bit = LCD2004_WRITE_OPERATION ; /*write*/
LCD2004_DATA_PORT = commandCode ;
//delay1msForLcd2004();
lcd2004_en_bit = LCD2004_ENABLE ;
//delay1msForLcd2004();
lcd2004_en_bit = LCD2004_DISABLE ;
}
/******************************************************
Function :lcd2004WriteData
Input :data code
Output :N/A
Return :void
Description :write data to lcd2004
Note :N/A
******************************************************/
void lcd2004WriteData(UB8 dataCode)
{
lcd2004CheckBusy() ;
lcd2004_en_bit = LCD2004_DISABLE ;
lcd2004_rs_bit = LCD2004_DATA_OPERATION ; /*data*/
lcd2004_rw_bit = LCD2004_WRITE_OPERATION ; /*write*/
LCD2004_DATA_PORT = dataCode;
//delay1msForLcd2004();
lcd2004_en_bit = LCD2004_ENABLE ;
//delay1msForLcd2004();
lcd2004_en_bit = LCD2004_DISABLE ;
}
/******************************************************
Function :lcd2004CleanAll
Input :N/A
Output :N/A
Return :N/A
Description :clean lcd2004 display
Note :清除屏幕显示,光标归位(左上角),地址计数器AC设为0
******************************************************/
void lcd2004CleanAll(void)
{
lcd2004WriteCommand(LCD2004_CLEAN_ALL_DISPALY);
}
/******************************************************
Function :lcd2004CursorHoming
Input :N/A
Output :N/A
Return :N/A
Description :curosr homing to the 0x80
Note :光标归位,当屏幕移动显示时,lcd2004显示所有数据后,
调用此函数,屏幕显示的所有东西都会归位。光标在第一
个位置(0x80)。
******************************************************/
void lcd2004CursorHoming(void)
{
lcd2004WriteCommand(LCD2004_CURSOR_RETURN_TO_ORIGIN);
}
/******************************************************
Function :lcd2004Init
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :N/A
******************************************************/
void lcd2004Init(void)
{
lcd2004_en_bit = LCD2004_DISABLE ;
lcd2004CleanAll();
lcd2004WriteCommand(LCD2004_DEFAULT_DISPALY_MODE);
lcd2004WriteCommand(LCD2004_DEFAULT_DISPLAY_AND_CURSOR_MODE);
lcd2004WriteCommand(LCD2004_DEFAULT_POINT_AND_POINT_ADDRESS_MODE);
/*可忽略,在lcd2004CleanAll()中隐含了该功能*/
lcd2004WriteCommand(LCD2004_ROW0_ADDRESS_START);
lcd2004_en_bit = LCD2004_DISABLE ;
}
/******************************************************
Function :lcd2004AddressWriteByte
Input :行位置
列位置
数据
Output :N/A
Return :N/A
Description :N/A
Note :N/A
******************************************************/
void lcd2004AddressWriteByte(UB8 row,UB8 column,UB8 dataCode)
{
if(row == LCD2004_ROW0)
{
lcd2004WriteCommand(LCD2004_ROW0_ADDRESS_START+column) ;
}
else if(row == LCD2004_ROW1)
{
lcd2004WriteCommand(LCD2004_ROW1_ADDRESS_START+column) ;
}
else if(row == LCD2004_ROW2)
{
lcd2004WriteCommand(LCD2004_ROW2_ADDRESS_START+column) ;
}
else if(row == LCD2004_ROW3)
{
lcd2004WriteCommand(LCD2004_ROW3_ADDRESS_START+column) ;
}
lcd2004WriteData(dataCode);
}
/******************************************************
Function :lcd2004AddressWriteString
Input :首个字符显示的行,列地址,字符串
Output :N/A
Return :N/A
Description :N/A
Note :这里使用的是strlen,而不是sizeof
******************************************************/
void lcd2004AddressWriteString(UB8 row,UB8 column,UB8 *stringCode)
{
UB8 length = strlen(stringCode) ;
if(row == LCD2004_ROW0)
{
lcd2004WriteCommand(LCD2004_ROW0_ADDRESS_START+column) ;
}
else if(row == LCD2004_ROW1)
{
lcd2004WriteCommand(LCD2004_ROW1_ADDRESS_START+column) ;
}
if(row == LCD2004_ROW2)
{
lcd2004WriteCommand(LCD2004_ROW2_ADDRESS_START+column) ;
}
else if(row == LCD2004_ROW3)
{
lcd2004WriteCommand(LCD2004_ROW3_ADDRESS_START+column) ;
}
while(length--)
{
lcd2004WriteData(*stringCode);
stringCode++;
}
}
|