1602的程序
,很高兴的告诉大家。T0X12开了以后。不会有扫描线出现。但是如果一定要在传统51上使用的话,请把10级调光改成4级。谢谢合作!
* 74HC595 Q6 - 1602 EN
* 74HC595 Q5~Q2 - 1602 D5~D7(这一次硬件设计不合理,才只能搞软件修正了。不过好处就是直接就可以洞洞板上对着联,减少了烧坏595的概率。坏处就是CPU时间消耗的多了点。但是可以取消延时函数啦~
* 1602 D1~D4 直接悬空
* LCD_BACKLIGHT加一级PNP三极管射随器加到液晶的A上,如果无需调光可以去掉这一部分电路和代码
* 至于595的连接,只要不弄反SCL和SCK,就没有问题啦~
*/
__sbit __at 0xE0 A_0;//方便位操作,硬件设置真的是
__sbit __at 0xE1 A_1;
__sbit __at 0xE2 A_2;
__sbit __at 0xE3 A_3;
__sbit __at 0xE4 A_4;
__sbit __at 0xE5 A_5;
__sbit __at 0xE6 A_6;
__sbit __at 0xE7 A_7;
__sbit __at 0xF1 B_1;
__sbit __at 0xF2 B_2;
__sbit __at 0xF3 B_3;
__sbit __at 0xF4 B_4;
__sbit __at 0xF5 B_5;
__sbit __at 0xF6 B_6;
__sbit __at 0xF7 B_7;
unsigned char PWM_Cycle=0;//PWM占空比
unsigned char PWM_T=0;//PWM当前所处周期
unsigned char OutBuf=0xff;//输出缓冲
#define LCD_OFF lcd_wcmd(0x08)
#define LCD_CUR lcd_wcmd(0x0E)
#define LCD_FCUR lcd_wcmd(0x0F)
void delay(unsigned int n)
{
unsigned int x,y;
for(x=n;x>0;x--)
for(y=100;y>0;y--);
}
void Send595()
{
unsigned char i,j;
j=0x80;
LCD1602_SCK=0;
for(i=0;i<8;i++)
{
LCD1602_SDA=OutBuf & j;
j=j>>1;
LCD1602_SCK=1;
LCD1602_SCK=0;
}
LCD1602_SDA=1;
LCD1602_SCL=0;
LCD1602_SCL=1;
}
void lcd_en()
{
//OutBuf=OutBuf|0x40;//E=1
B=OutBuf;
B_6=1;
OutBuf=B;
Send595();//输出数据
B=OutBuf;
B_6=0;
OutBuf=B;//E=0
Send595();
}
/**********************************************************/
void lcd_wcmd(unsigned char i)
{
//写命令
B=OutBuf;
B_7=0;//RS=0,RW=0;
OutBuf=B;
Send595();
//--------------
B=OutBuf;
ACC=i;
B_2=A_7;//D7=D7
B_3=A_6;//D6=D6
B_4=A_5;//D5=D5
B_5=A_4;//D4=D4
OutBuf=B;
Send595();
lcd_en();
//================
ACC=i;
B=OutBuf;
B_2=A_3;//D7=D3
B_3=A_2;//D6=D2
B_4=A_1;//D5=D1
B_5=A_0;//D4=D0
OutBuf=B;
Send595();
lcd_en();
}
void lcd_wdat(unsigned char i)
{
//写数据
B=OutBuf;
B_7=1;//RS=0,RW=0;
OutBuf=B;
Send595();
//--------------
B=OutBuf;
ACC=i;
B_2=A_7;//D7=D7
B_3=A_6;//D6=D6
B_4=A_5;//D5=D5
B_5=A_4;//D4=D4
OutBuf=B;
Send595();
lcd_en();
//================
ACC=i;
B=OutBuf;
B_2=A_3;//D7=D3
B_3=A_2;//D6=D2
B_4=A_1;//D5=D1
B_5=A_0;//D4=D0
OutBuf=B;
Send595();
lcd_en();
}
void lcd_putchar(unsigned char addr,unsigned char ch)
{//写一个字
lcd_wcmd(0x80+addr);
lcd_wdat(ch);
}
void lcd_display(unsigned char *l1,unsigned char *l2)
{//写一屏幕
unsigned char i=0;
lcd_wcmd(0x80); //显示地址设为80H(即00H,)上排第一位
for(i=0;i<16;i++)
{
lcd_wdat(l1[i]);
}
lcd_wcmd(0x80+0x40); //重新设定显示地址为0xc0,即下排第1位
for(i=0;i<16;i++)
{
lcd_wdat(l2[i]);
}
}
void lcd_cls()
{
lcd_wcmd(0x01); //清屏延时函数可以省略
}
//米有读函数,但是功能可以由上面的函数扩展哦~
void lcd_init()
{
OutBuf=0xff;
Send595();//复位VIO,这段代码必须加。否则MCU忽然RESET会导致液晶乱码
lcd_wcmd(0x30);//复位1602,这段代码必须加,同上
lcd_en();//唤醒
lcd_wcmd(0x20);
lcd_en();//唤醒
lcd_wcmd(0x28); //四位,5x7
lcd_wcmd(0x0c); //开启显示屏,关光标,光标不闪烁
lcd_wcmd(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
lcd_wcmd(0x01); //清屏
//调试的时候被设计失误的对比度电位器坑死了:就是两排小方块死都不显示
//查了半天都不知道
//最后捅了下电位器就正常了……
}
void lcd_print(unsigned char *str)
{
unsigned char addr=0x80,len=0;
lcd_wcmd(addr); //显示地址设为80H(即00H,)上排第一位
while(*str!='\0')
{//等待末尾
if(len >= 16)
{
lcd_wcmd(0x80+0x40);//下排第一位,换行
len=0;
}
if(*str=='\n')
{
lcd_wcmd(0x80+0x40);//下排第一位,换行
}
else
{
lcd_wdat(*str);
}
str++;
len++;
}
}//写字符串函数
void PWM() __ 1 __using 1
{
ET0=0;
TF0=0;//CLR
TR0=0;
EA=0;
TH0=0xFC;TL0=0x00;//十级调光,频率400Hz
if(PWM_T>10) {PWM_T=0;}
if(PWM_Cycle>PWM_T){ LCD1602_BACKLIGHT=0;}
if(PWM_Cycle
PWM_T++;
TR0=1;
ET0=1;
EA=1;
}
void main()
{//主函数
TMOD = 0x01 ;
TH0=0xFC;TL0=0x00;
TR0=1;ET0=1;
EA=1;//开中断
//-----------------
lcd_init();
PWM_Cycle=10;//背光100%
//液晶初始化---------
while(1)
{
lcd_display(" Hello world! ","Serial mode 1602");
delay(2000);
lcd_display("Drive by 74HC595","Design by rgwan ");
delay(2000);
lcd_display("Website address:"," www.rwzy.co.cc ");
delay(2000);
lcd_display("Backlight ctl by"," T0 PWM 400Hz ");
delay(2000);
}
}
,很高兴的告诉大家。T0X12开了以后。不会有扫描线出现。但是如果一定要在传统51上使用的话,请把10级调光改成4级。谢谢合作!
* 74HC595 Q6 - 1602 EN
* 74HC595 Q5~Q2 - 1602 D5~D7(这一次硬件设计不合理,才只能搞软件修正了。不过好处就是直接就可以洞洞板上对着联,减少了烧坏595的概率。坏处就是CPU时间消耗的多了点。但是可以取消延时函数啦~
* 1602 D1~D4 直接悬空
* LCD_BACKLIGHT加一级PNP三极管射随器加到液晶的A上,如果无需调光可以去掉这一部分电路和代码
* 至于595的连接,只要不弄反SCL和SCK,就没有问题啦~
*/
__sbit __at 0xE0 A_0;//方便位操作,硬件设置真的是
__sbit __at 0xE1 A_1;
__sbit __at 0xE2 A_2;
__sbit __at 0xE3 A_3;
__sbit __at 0xE4 A_4;
__sbit __at 0xE5 A_5;
__sbit __at 0xE6 A_6;
__sbit __at 0xE7 A_7;
__sbit __at 0xF1 B_1;
__sbit __at 0xF2 B_2;
__sbit __at 0xF3 B_3;
__sbit __at 0xF4 B_4;
__sbit __at 0xF5 B_5;
__sbit __at 0xF6 B_6;
__sbit __at 0xF7 B_7;
unsigned char PWM_Cycle=0;//PWM占空比
unsigned char PWM_T=0;//PWM当前所处周期
unsigned char OutBuf=0xff;//输出缓冲
#define LCD_OFF lcd_wcmd(0x08)
#define LCD_CUR lcd_wcmd(0x0E)
#define LCD_FCUR lcd_wcmd(0x0F)
void delay(unsigned int n)
{
unsigned int x,y;
for(x=n;x>0;x--)
for(y=100;y>0;y--);
}
void Send595()
{
unsigned char i,j;
j=0x80;
LCD1602_SCK=0;
for(i=0;i<8;i++)
{
LCD1602_SDA=OutBuf & j;
j=j>>1;
LCD1602_SCK=1;
LCD1602_SCK=0;
}
LCD1602_SDA=1;
LCD1602_SCL=0;
LCD1602_SCL=1;
}
void lcd_en()
{
//OutBuf=OutBuf|0x40;//E=1
B=OutBuf;
B_6=1;
OutBuf=B;
Send595();//输出数据
B=OutBuf;
B_6=0;
OutBuf=B;//E=0
Send595();
}
/**********************************************************/
void lcd_wcmd(unsigned char i)
{
//写命令
B=OutBuf;
B_7=0;//RS=0,RW=0;
OutBuf=B;
Send595();
//--------------
B=OutBuf;
ACC=i;
B_2=A_7;//D7=D7
B_3=A_6;//D6=D6
B_4=A_5;//D5=D5
B_5=A_4;//D4=D4
OutBuf=B;
Send595();
lcd_en();
//================
ACC=i;
B=OutBuf;
B_2=A_3;//D7=D3
B_3=A_2;//D6=D2
B_4=A_1;//D5=D1
B_5=A_0;//D4=D0
OutBuf=B;
Send595();
lcd_en();
}
void lcd_wdat(unsigned char i)
{
//写数据
B=OutBuf;
B_7=1;//RS=0,RW=0;
OutBuf=B;
Send595();
//--------------
B=OutBuf;
ACC=i;
B_2=A_7;//D7=D7
B_3=A_6;//D6=D6
B_4=A_5;//D5=D5
B_5=A_4;//D4=D4
OutBuf=B;
Send595();
lcd_en();
//================
ACC=i;
B=OutBuf;
B_2=A_3;//D7=D3
B_3=A_2;//D6=D2
B_4=A_1;//D5=D1
B_5=A_0;//D4=D0
OutBuf=B;
Send595();
lcd_en();
}
void lcd_putchar(unsigned char addr,unsigned char ch)
{//写一个字
lcd_wcmd(0x80+addr);
lcd_wdat(ch);
}
void lcd_display(unsigned char *l1,unsigned char *l2)
{//写一屏幕
unsigned char i=0;
lcd_wcmd(0x80); //显示地址设为80H(即00H,)上排第一位
for(i=0;i<16;i++)
{
lcd_wdat(l1[i]);
}
lcd_wcmd(0x80+0x40); //重新设定显示地址为0xc0,即下排第1位
for(i=0;i<16;i++)
{
lcd_wdat(l2[i]);
}
}
void lcd_cls()
{
lcd_wcmd(0x01); //清屏延时函数可以省略
}
//米有读函数,但是功能可以由上面的函数扩展哦~
void lcd_init()
{
OutBuf=0xff;
Send595();//复位VIO,这段代码必须加。否则MCU忽然RESET会导致液晶乱码
lcd_wcmd(0x30);//复位1602,这段代码必须加,同上
lcd_en();//唤醒
lcd_wcmd(0x20);
lcd_en();//唤醒
lcd_wcmd(0x28); //四位,5x7
lcd_wcmd(0x0c); //开启显示屏,关光标,光标不闪烁
lcd_wcmd(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
lcd_wcmd(0x01); //清屏
//调试的时候被设计失误的对比度电位器坑死了:就是两排小方块死都不显示
//查了半天都不知道
//最后捅了下电位器就正常了……
}
void lcd_print(unsigned char *str)
{
unsigned char addr=0x80,len=0;
lcd_wcmd(addr); //显示地址设为80H(即00H,)上排第一位
while(*str!='\0')
{//等待末尾
if(len >= 16)
{
lcd_wcmd(0x80+0x40);//下排第一位,换行
len=0;
}
if(*str=='\n')
{
lcd_wcmd(0x80+0x40);//下排第一位,换行
}
else
{
lcd_wdat(*str);
}
str++;
len++;
}
}//写字符串函数
void PWM() __ 1 __using 1
{
ET0=0;
TF0=0;//CLR
TR0=0;
EA=0;
TH0=0xFC;TL0=0x00;//十级调光,频率400Hz
if(PWM_T>10) {PWM_T=0;}
if(PWM_Cycle>PWM_T){ LCD1602_BACKLIGHT=0;}
if(PWM_Cycle
PWM_T++;
TR0=1;
ET0=1;
EA=1;
}
void main()
{//主函数
TMOD = 0x01 ;
TH0=0xFC;TL0=0x00;
TR0=1;ET0=1;
EA=1;//开中断
//-----------------
lcd_init();
PWM_Cycle=10;//背光100%
//液晶初始化---------
while(1)
{
lcd_display(" Hello world! ","Serial mode 1602");
delay(2000);
lcd_display("Drive by 74HC595","Design by rgwan ");
delay(2000);
lcd_display("Website address:"," www.rwzy.co.cc ");
delay(2000);
lcd_display("Backlight ctl by"," T0 PWM 400Hz ");
delay(2000);
}
}