/*********************************************************************
*
* lcd1602.c
*
*********************************************************************
* 描 述: 2*16液晶模块驱动函数,如果要移植,只需要根据硬件连接方式对lcd1602.h和top51.h作适当修改,
* 开发平台: TOP51开发板+KEIL C51
* 公 司: 爱晶电子
* 网 址: http://www.ajdz.net
* 作者 日期 注释
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 王伟民 09/04/01 原始文件
* 王伟民 09/10/20 v1.1
********************************************************************/
/*函数实现*/
#include"stc.h"/*包含STC单片机头文件*/
//#include"top51.h"/*包含TOP51开发板头文件*/
#include "lcd1602.h"/*包含2*16液晶模块驱动函数头文件*/
//#include <stdlib.h>/*包含标准库函数头文件*/
#include "delay.h"/*包含爱晶电子提供延时函数头文件*/
#include <intrins.h>/*包含含有_nop_()函数的头文件*/
char code cgtab[64]={0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,
0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,
0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00,
0x11,0x0a,0x04,0x1f,0x04,0x1f,0x04,0x00,
0x0e,0x00,0x1f,0x0a,0x0a,0x0a,0x13,0x00,
0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00,
0x04,0x0a,0x15,0x04,0x04,0x04,0x04,0x00,
0x01,0x03,0x1d,0x15,0x1d,0x03,0x01,0x00}; /*年、月、日、¥、元、℃、↑、小喇叭图标*/
/*产生一个LCD模块的使能脉冲*/
/*该函数只在本文件内使用,不会被其他文件调用,因此放在本文件的最前面,不在H文件中声明了*/
void LCD_E_toggle(void)
{
EN=0;
SOME_NOP;
EN=1;
SOME_NOP;
}
void LCD_init(void)
{
delayms(100);/*???延时100ms*/
//delay1s();/*???延时100ms*/
LCD_CTR_OUT;/*???设置单片机LCD控制引脚RW\RS\EN全为输出*/
LCD_wrcmd(LCD_MODE_STD);/*LCD标准工作模式:8位数据传送,2行显示,字符点阵5*7*/
LCD_wrcmd(DISP_OFF);/*显示关闭*/
LCD_wrcmd(DISP_CLR);/*清屏*/
/*清屏和光标归位需要较长的时间*/
LCD_wrcmd(CUR_AUTO_R);/*设置光标在文字插入后自动右移*/
LCD_wrcmd(DISP_ON & CUR_OFF & BLINK_OFF);/*显示开,无光标, 光标不闪烁*/
//LCD_wrcmd(DISP_ON & CUR_ON & BLINK_ON);/*显示开,光标, 光标闪烁*/
CG_Write();/*建立自定义字符块*/
}
//void LCD_wrcmd(Uchar cmd)/*写入控制命令*/
void LCD_wrcmd(uchar cmd)/*写入控制命令*/
{
SOME_NOP;
wait_until_LCDready();
SOME_NOP;
LCD_DATA_OUT;/*???单片机的LCD数据口设置为全输出*/
SOME_NOP;
EN=0;
SOME_NOP;
RS=0;
SOME_NOP;
RW=0;
SOME_NOP;
LCD_DATA=cmd;
SOME_NOP;
EN=1;
SOME_NOP;
SOME_NOP;
EN=0;
SOME_NOP;
}
void LCD_wrchar(char str)/*写入要显示的字符*/
{
SOME_NOP;
wait_until_LCDready();
SOME_NOP;
LCD_DATA_OUT;/*???单片机的LCD数据口设置为全输出*/
SOME_NOP;
EN=0;
SOME_NOP;
RS=1;
SOME_NOP;
RW=0;
SOME_NOP;
LCD_DATA=str;
SOME_NOP;
EN=1;
SOME_NOP;
SOME_NOP;
EN=0;
SOME_NOP;
}
void LCD_setxy(char x,char y) /*设定显示位置,行x=1/2,列y=1~16的任意整数*/
{
char temp;
if(x==1)
{
temp=0x80+y-1;
LCD_wrcmd(temp);
}
else
{
temp=0xC0+y-1;
LCD_wrcmd(temp);
}
}
void LCD_wrstr(char code *s)/*写入要显示的字符串*/
{
for(;*s!='\0';s++)LCD_wrchar(*s);
}
void LCD_wrul(unsigned long num)/*写入要显示的无符号长整型数*/
{
unsigned long temp;
unsigned char i;
LCD_wrcmd(CUR_AUTO_L);/*设置光标在文字插入后自动左移*/
for(i=0;i<10;i++)
{
if(num!=0)
{
temp=num/10;
LCD_wrchar(num-temp*10+'0');
num=temp;
}
else/*往前写满10位,也就是前面都写空格*/
{
LCD_wrchar(0x20);
}
}
LCD_wrcmd(CUR_AUTO_R);/*设置光标在文字插入后自动右移*/
}
void LCD_wrlval(unsigned long num,unsigned char bits,unsigned char dp)/*写入要显示的长变量*/
{
char str[10];/*无符号长整型数转换为字符串是10个,所以需要10个单元存储*/
unsigned long temp;
unsigned char i;
LCD_wrcmd(CUR_AUTO_L);/*设置光标在文字插入后自动左移*/
for(i=0;i<bits;i++)
{
if(num!=0)
{
temp=num/10;
str[i]=num-temp*10+'0';
num=temp;
}
else/*往前写*/
{
if(i>=dp)str[i]=0x20;/*小数点前零都变空格*/
else str[i]='0';/*小数点后零保留*/
}
}
i=0;
if (num!=0)/*要显示的数据比规定的显示位数多,数据显示溢出*/
{
while(i<bits)/*往前写满规定的位数,也就是前面都写空格,直到规定的位数*/
{
LCD_wrchar('-'); /*规定的位全部写-,表示数据溢出*/
i++;
if (i==dp) LCD_wrchar('.');/*插入小数点*/
}
}
else
{
while(i<bits)/*显示前面的有效数字*/
{
if ((i==dp)&(str[dp]==0x20))
{
LCD_wrchar('.');/*插入小数点*/
LCD_wrchar('0');/*小数点前为0时要补写0*/
}
else
{
if ((i==dp)&(i!=0)) LCD_wrchar('.');/*插入小数点*/
LCD_wrchar(str[i]);
}
i++;
}
}
LCD_wrcmd(CUR_AUTO_R);/*设置光标在文字插入后自动右移*/
}
void wait_until_LCDready(void) /*检测忙标志,忙则等待*/
{
EN=0;/*此句必须加,否则后面RS RW输出电平后,液晶屏出现光标复位的现象*/
RS=0;
LCD_DATA_IN;/*???单片机的LCD数据口设置为全输入*/
RW=1;
EN=1;/*读状态的时候,E始终保持高电平即可*/
SOME_NOP;
while(LCD_BUSY==1);/*LCD忙,则原地等待*/
EN=0;
}
void CG_Write(void)/*建立自定义字符块*/
{
int i;
LCD_wrcmd(SET_ADDR_CGRAM);/*字符发生器CGRAM地址设置*/
for(i=0;i<64;i++)
{
LCD_wrchar(cgtab[i]);
};
}