//实验目的:熟悉LCD1602 4线的使用方法
//LCD循环显示本产品名称和公司网站地址
//硬件要求:跳线全部跳好(LCD低4位开路)
//所有拨码开关置OFF
//调节电位器VR2到LCD1602能正常显示。
#include <p30f6014.h> //dsPIC30F6014标准头文件
_FOSC(CSW_FSCM_OFF & XT_PLL4); //4倍频晶振,Failsafe 时钟关闭
_FWDT(WDT_OFF); //关闭看门狗定时器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉电复位禁止,MCLR复位使能。
_FGS(CODE_PROT_OFF); //代码保护禁止
#define uchar unsigned char
#define uint unsigned int
#define rs LATBbits.LATB4 //定义LCD控制位(注意这里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e LATBbits.LATB6
#define LCD_data LATD
#define lcd_busy_IO _TRISD7
#define lcd_busy_BIT _RD7
const int web[ ]={ ,W,W,W,.,P,I,C,1,6,.,C,O,M, , };
//定义公司web地址
const int name[ ]={ , , , ,Q,L,d,s,P,I,C,3, , , , };
//定义公司产品名称
void init(); //申明I/O口初始化函数
void lcd_init(); //申明LCD初始化函数
void write_web(); //申明显示公司web地址函数
void write_name(); //申明显示产品名字函数
void write(unsigned int x); //申明显示1字节数据函数
void lcd_enable(uchar data ); //申明LCD显示设置函数
void delay(); //申明延时函数
//---------------------------------------
//主函数
int main(void)
{ uchar i;
while(1)
{
init(); //调用I/O口初始化函数
for(i=0;i<5;i++)
{
delay(15000);
lcd_init(); //调用LCD初始化函数
}
write_name(); //调用显示产品名字函数
lcd_enable(0xC0); //设置第2行显示地址 调用LCD显示设置函数
write_web(); //调用显示公司tel函数
while(1);
}
}
//---------------------------------------
//I/O口初始化函数
void init()
{
TRISB=0x0000; //设置B口为输出
TRISD=0x0000; //设置D口为输出
}
//---------------------------------------
//LCD初始化函数
void lcd_init()
{
lcd_enable(0x28); //8位2行5*7点阵
delay(40);
lcd_enable(0x1); //清除显示
delay(2000);
lcd_enable(0x0e); //显示开,光标开,闪烁
delay(40);
lcd_enable(0x06); //文字不动,光标右移
delay(40);
lcd_enable(0x80); //产品名字显示地址
}
//--------------------------------------
//显示公司web地址
void write_web()
{
unsigned char i,j;
for(i=0;i<16;i++) //一共16字节数据
{
write(web[i]); //查表获取数据并调用写一个字节数据函数送LCD显示
for(j=0;j<5;j++) //延时一段时间(主要是为了控制显示的速度)
{delay(10000);}
}
}
//--------------------------------------
//显示产品名字函数
void write_name()
{
unsigned char i,j;
for(i=0;i<0x10;i++) //一共显示16字节数据
{
write(name[i]); //查表获取数据并调用写一个字节数据函数送LCD显示
for(j=0;j<5;j++)
{delay(10000);}
}
}
/**********************************************************
* 检查LCD忙状态
* lcd_busy为1时,忙,等待。
* lcd-busy为0时,闲,可写指令与数据
**********************************************************/
unsigned char lcd_busy()
{ unsigned char busy=0;
lcd_busy_IO=1;
rs = 0;
rw = 1;
e = 0;
delay(5);
e = 1;
delay(5);
if(lcd_busy_BIT) busy = 1;
lcd_busy_IO=0;
return(busy);
}
//--------------------------------------
//写一个字节数据函数
//在电平发生改变后需要插入一段延时时间,否则LCD反应不过来。
void write(unsigned int x)
{unsigned int i=2000;
while(i&&lcd_busy())i--;
rs=1; //该字节数据为数据,而不是命令
delay(5);
rw=0; //此次操作为写,而不是读
delay(5);
e=1; //拉低使能信号
LCD_data=x; //待显示数据送PORTD口
delay(10); //保持使能信号为低一段时间
e=0; //拉高使能信号,建立LCD操作所需要的下降沿
delay(5);
e=1; //拉低使能信号
LCD_data=x<<4; //待显示数据送PORTD口
delay(10); //保持使能信号为低一段时间
e=0; //拉高使能信号,建立LCD操作所需要的下降沿
}
//写入控制命令子程序
//LCD显示设置函数
//在电平发生改变后需要插入一段延时时间,否则LCD反应不过来。
void lcd_enable(uchar data )
{ unsigned int i=2000;
while(i&&lcd_busy())i--;
rs=0; //该字节数据为命令,而不是数据
delay(5);
rw=0; //此次操作为写,而不是读
delay(5);
e=1; //拉低使能信号
LCD_data=data;
delay(10); //保持使能信号为低一段时间
e=0; //拉高使能信号,建立LCD操作所需要的下降沿
delay(5);
e=1; //拉低使能信号
LCD_data=data<<4;
delay(10); //保持使能信号为低一段时间
e=0; //拉高使能信号,建立LCD操作所需要的下降沿
}
//--------------------------------------
//延时函数
void delay(unsigned int i)
{
while(i--){Nop();Nop();Nop();Nop();}
}