4根IO口线驱动1602(带PWM调光)

合集下载

4根IO口线驱动1602(带PWM调光)

4根IO口线驱动1602(带PWM调光)

4根IO口线驱动1602(带PWM调光)呵呵,不用我说你们也知道为什么只需要4根线:因为咱用了74hc595啊!因为74HC595最近我手里一抓一大把。

但是STC的单片机IO口紧缺。

就算使用4线驱动模式也要8个IO(还要算上背光PWM)。

这一次我几乎做到了他的一半。

如果不用PWM的话。

大概只需要3个IO,如果需要PWM就四个罗。

MCU当然是老掉牙的死特惨89C52罗~画原理图实在是不方便。

就不画了。

另外求酷~也可以在595后面级联类似三极管开关……继电器之类的玩意。

当然友情提醒,别超过4个595.否则速度会慢的可怕。

我现在1个595.写1602都可以丢掉延时函数了。

这一次硬件设计的比较简单,但是IO全反了。

所以需要占用额外的CPU时间修正,但是毕竟方便洞洞板嘛。

还有大家别看到我给A和B赋了好几次值而去“优化”代码。

如果您“优化”的话,那么就根本驱动不起来,因为51的加法减法乘除都要经过ACC和B,如果不去重新赋值的话,那么就会发生改变的现象。

不过我这种位寻址软件修正可比那种xx=xx & xx的效率高多了。

如果我这么写的话。

恐怕刷一个屏幕没1秒下不来啊。

12T的51就这个速度……不过这一次焊板子实在是太仓促了。

对比度电位器焊在液晶下面,结果初始化成功了显示两排方块。

晕了半天。

调试半天还是没用。

后来捅了一下背面就好了……晕……!上代码:#include <stc89c5x.h>//STC89C52//串行驱动1602,powered by 595#define LCD1602_BACKLIGHT P1_3//背光#define LCD1602_SDA P1_0//数据输入#define LCD1602_SCK P1_1//移位时钟,SHCP,11pin#define LCD1602_SCL P1_2//锁存时钟,STCP,12pin/** 硬件连接:* 74HC595 Q7 - 1602 RS* GND - 1602 RW(595没有输入功能,所以判定忙只能靠延时,另外就是MCU的速度比较的慢。

1602的AVR的C驱动(4线方式)

1602的AVR的C驱动(4线方式)

1602的AVR的C驱动(4线方式)2009-06-19 21:03参考了OURAVR的程序,自己写了一个,加上光标和屏幕滚动代码#define LCD_EN_PORT PORTA //以下2个要设为同一个口#define LCD_EN_DDR DDRA#define LCD_RS_PORT PORTA //以下2个要设为同一个口#define LCD_RS_DDR DDRA#define LCD_DATA_PORT PORTA //以下3个要设为同一个口#define LCD_DATA_DDR DDRA //一定要用高4位#define LCD_DATA_PIN PINA#define LCD_RS (1<<PA1) //0x02 portA1 out#define LCD_EN (1<<PA3) //0x08 portA3 out#define LCD_DATA ((1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7))//0xf0 portA4/5/6/7 outuchar LCD="1" ; //是否让LCD显示 0,不显示;;;1显示/*--------------------------------------------------------------------------------------------------函数说明--------------------------------------------------------------------------------------------------*/void LCD_init(void);void LCD_en_write(void);void LCD_write_command(unsigned char command) ;void LCD_write_data(unsigned char data);void LCD_set_xy (unsigned char x, unsigned char y);void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s); void LCD_write_char(unsigned char X,unsigned char Y,unsigned char data);void LCD_Init(void) //液晶初始化{LCD_DATA_DDR|=LCD_DATA; //数据口方向为输出LCD_EN_DDR|=LCD_EN; //设置EN方向为输出LCD_RS_DDR|=LCD_RS; //设置RS方向为输出CLI();PORTA&=~0x04;//RW=0DDRA=0xff;LCD_write_command(0x30);Delay_nms(10);LCD_write_command(0x30);Delay_nms(5);LCD_write_command(0x30);Delay_nms(5);LCD_write_command(0x28);//写指令,4位数据线,5*10字体LCD_en_write();Delay_nms(4);LCD_write_command(0x28); //4位显示LCD_en_write();LCD_write_command(0x0c); //显示开光标关,字符不闪烁LCD_en_write();SEI();Delay_nms(2);}void LCD_en_write(void) //液晶使能{LCD_EN_PORT|=LCD_EN; //Delay_nus(1);LCD_EN_PORT&=~LCD_EN; // 给出下降沿}void LCD_write_command(unsigned char command) //写指令 E下降,RS=0,RW=0{Delay_nms(6);LCD_RS_PORT&=~LCD_RS; //RS=0LCD_DATA_PORT&=0X0f; //清高四位LCD_DATA_PORT|=command&0xf0; //写高四位LCD_en_write(); //E下降command="command"<<4; //低四位移到高四位LCD_DATA_PORT&=0x0f; //清高四位LCD_DATA_PORT|=command&0xf0; //写这次低四位到数据线高4位LCD_en_write();}void LCD_write_data(unsigned char data) //写数据 E下降,RS=1,RW=0 {Delay_nms(6);LCD_RS_PORT|=LCD_RS; //RS=1LCD_DATA_PORT&=0X0f; //清高四位LCD_DATA_PORT|=data&0xf0; //写高四位LCD_en_write();data="data"<<4; //低四位移到高四位LCD_DATA_PORT&=0X0f; //清高四位LCD_DATA_PORT|=data&0xf0; //写低四位LCD_en_write();}void LCD_set_xy( unsigned char x, unsigned char y ) //写地址函数{unsigned char address;if (y == 0) address = 0x80 + x; // 最高位是1,另七位才是地址故有+0x80else address = 0xc0 + x;LCD_write_command( address);}void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s) //列x=0~15,行y=0,1{LCD_set_xy( X, Y ); //写地址while (*s) // 写显示字符{LCD_write_data( *s );s ++;}}void LCD_write_char(unsigned char X,unsigned char Y,unsigned char data) //列x=0~15,行y=0,1{LCD_set_xy( X, Y ); //写地址LCD_write_data( data);}/*光标移动*/void CursorScroll(void){LCD_write_command(0x10); //光标左移}/*画面滚动*/void ScreenScroll(void){//while(1){LCD_write_command(0x18); //画面左滚Delay_nms(300);}}。

Arduino对LCD1602的4线驱动例程

Arduino对LCD1602的4线驱动例程

Arduino对LCD1602的4线驱动例程学前说明:对于初学者来说,驱动液晶屏并不简单首先要清楚液晶屏各管脚定义:其次要了解1602的操作时序:最后还要清楚1602的指令码:程序内有指令注解实现效果:在1602液晶显示模块上输出字符该代码套用性很强,在以后的程序中,可利用该代码,在LCD上输出数据.声明:本程序不是我写的,本人只是对程序进行注解,方便大家理解,学习原文地址:/blog/user_2005/1229/archives/2008/200859213442.shtml/********************************************************************/int LCD1602_RS=12;//数据/命令选择端int LCD1602_RW=11;//读写选择端int LCD1602_EN=10;//使能信号int DB[] = { 6, 7, 8, 9};//数据输入输出端char str1[]="Coloz's";char str2[]="Robot";/********************************************************************//********************************************************************/void LCD_Command_Write(int command)//LCD指令控制,{int i,temp;digitalWrite( LCD1602_RS,LOW);digitalWrite( LCD1602_RW,LOW);//RS低,RW低,E高脉冲(下面为脉冲信号生成),写指令digitalWrite( LCD1602_EN,LOW);temp=command & 0xf0;//0xf0,设置数据D4-7方向为输出,D0-3为输入for (i=DB[0]; i <= 9; i++){digitalWrite(i,temp & 0x80);//0x80+地址,设置LCD第一行的数据指针初始地址temp <<= 1;}digitalWrite( LCD1602_EN,HIGH);delayMicroseconds(1);digitalWrite( LCD1602_EN,LOW);//生成脉冲信号temp=(command & 0x0f)<<4;for (i=DB[0]; i <= 10; i++){digitalWrite(i,temp & 0x80);//0x80+地址,设置LCD第一行的数据指针初始地址temp <<= 1;}digitalWrite( LCD1602_EN,HIGH);delayMicroseconds(1);digitalWrite( LCD1602_EN,LOW);//生成脉冲信号}/********************************************************************/void LCD_Data_Write(int dat){int i=0,temp;digitalWrite( LCD1602_RS,HIGH);digitalWrite( LCD1602_RW,LOW);digitalWrite( LCD1602_EN,LOW);temp=dat & 0xf0;for (i=DB[0]; i <= 9; i++){digitalWrite(i,temp & 0x80);//0x80+地址,设置LCD第一行的数据指针初始地址temp <<= 1;}digitalWrite( LCD1602_EN,HIGH);delayMicroseconds(1);digitalWrite( LCD1602_EN,LOW);//生成脉冲信号temp=(dat & 0x0f)<<4;for (i=DB[0]; i <= 10; i++){digitalWrite(i,temp & 0x80);//0x80+地址,设置LCD第一行的数据指针初始地址temp <<= 1;}digitalWrite( LCD1602_EN,HIGH);delayMicroseconds(1);digitalWrite( LCD1602_EN,LOW);//生成脉冲信号}/********************************************************************/void LCD_SET_XY( int x, int y )//设置光标位置,X为横,Y为竖{int address;if (y ==0) address = 0x80 + x;//0x80+地址,设置LCD第一行的数据指针初始地址,表示在1602第一行显示else address = 0xc0 + x;//0xc0+地址,设置LCD第二行的数据指针初始地址,表示在1602第二行显示LCD_Command_Write(address);}/********************************************************************/void LCD_Write_Char( int x,int y,int dat){LCD_SET_XY( x, y );LCD_Data_Write(dat);}/********************************************************************/void LCD_Write_String(int X,int Y,char *s)//打印*s,X为横,Y为竖,*s为输出字符{LCD_SET_XY( X, Y ); //设置地址while (*s) //写字符串{LCD_Data_Write(*s);s ++;}}/********************************************************************/void setup (void){int i = 0;for (i=6; i <= 12; i++){pinMode(i,OUTPUT);}//delay(100);LCD_Command_Write(0x01);//0x01清屏:数据指针清零,所有显示清零//delay(50);LCD_Command_Write(0x28);//0x28设置4位数据接口//delay(50);LCD_Command_Write(0x06);//0x06显示开,当读或写一个字符后,地址指针自动加1, //delay(50);LCD_Command_Write(0x0c);//0x0c+地址,设置LCD第二行的数据指针初始地址//delay(50);LCD_Command_Write(0x80);//0x80+地址,设置LCD第一行的数据指针初始地址//delay(50);}/********************************************************************/void loop (void){LCD_Command_Write(0x02);//回车,数据指针清零delay(50);LCD_Write_String(3,0,str1);//第1行,第4个地址起,打印str1 delay(50);LCD_Write_String(1,1,str2);//第2行,第2个地址起,打印str2 while(1);}。

atmega16驱动1602(4位数据线)

atmega16驱动1602(4位数据线)
while(1)
{
zhiling(0x83); /////0x83地址开始写入
shuju(zhongwen[0]);
shuju(zhongwen[1]);
shuju(' ');
shuju(' ');
shuju(zhongwen[2]);
shuju(zhongwen[3]);
#define RS_1 PORTD|=BIT(rs)
#define RW_0 PORTD&=~BIT(rw)
#define RW_1 PORTD|=BIT(rw)
#define E_0 PORTD&=~BIT(e)
#define E_1 PORTD|=BIT(e)
uchar zhongwen[]="我叫吴越辉以后请多多指教";
#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define rs PD0
#define rw PD1
#define e PD2
#define RS_0 PORTD&=~BIT(rs)
zhiling(0x0c); //开显示指令
qingping(); //清屏
zhiling(0x02); //游标回归原点
}
void main()
{
int i;
init(); //调用初始化函数进行初始化操作
// while(1);
}

用尽量少的IO来驱动1602

用尽量少的IO来驱动1602

上次发了个人肉驱动LCD1602的帖子,没什么技术含量,居然得裤子,有点不好意思,正好这几天有点时间,于是就再做一个小试验,用尽量少的IO来驱动16 02,以适应在某些引脚较少的MCU,如Tiny系列等。

废话少说,先上图,如果大家觉得有意思请起个哄...(原文件名:001.jpg)引用图片(原文件名:002.jpg)引用图片说明一下,连接LCD1602的四根引线,除了红黑两根电源,两根黄色的就是信号线,其中一根传送RS和E信号,另一根传送D4~D7信号,即用四位总线驱动。

电路和程序整理中,迟些上传。

[已上传]===================================================================== ================================================【59楼】更新:挑战一下极限,再减少一根线,仍然好使,不过要另加一个电容和一个二极管。

(原文件名:003.jpg)引用图片===================================================================== ================================================【167楼】更新:无线馈电及传送数据。

资料邮回复引用回编辑2010-10-03,23:08:10编辑删除2010-10-03,23:10:1资料邮件回复引用回沙渺编辑删除2010-10-03,23:1资料邮件回复引用回编辑删除2010-10-03,23:资料邮件回复引用回编辑删除2010-10-03,23:资料邮件回复引用回【5楼】JQ_Lin2010-10-03,23:46:3资料邮件回复引用回编辑删除编辑删除2010-10-04,00:资料邮件回复引用回编辑删除2010-10-04,00:资料邮件回复引用回2010-10-04,00:资料邮件回复引用回编辑删除v编辑删除2010-10-04,00:3资料邮件回复引用回积分:3205派别:等级:------来自:(原文件名:2wire_1602.PNG)引用图片示范程序很简单,不用多注释应该都能看懂。

1602液晶的驱动方法

1602液晶的驱动方法

之前,必须查看 BF 是否为 0。 6. AC 为地址计数器(AddressCounter,简称 AC),负责计数写入/读出 CGRAM 或 DDRAM 的数据地址,AC 依照 MCLI 对 LCD 的设置值而自动修改它本身的内 容。 3、1602 的接口定义 1602 采用标准的 16 脚接口,其中: 第 1 脚:VSS 为电源地。 第 2 脚:VDD 接 5V 正电源。 第 3 脚:V0 为液晶显示器对比度调整端,接正电源时对比度最弱,接地示器, 是用于显示数字、图形符号及少量自定义符号的显示器。 l602 可分为 2 行共显示 32 个字符,每行显示 16 个字符。 第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第 5 脚:R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W 共同为低电平时可以写入指令或者显示地址, 当 RS 为低电平 R/W 为高电平时可以读忙信号,当 RS 为高电平 R/W 为低电平时可以写入数 据。 第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。 第 7~14 脚:D0~D7 为 8 位双向数据线。 第 15~16 脚:背光。 4、1602 的结构简述 1)模块特点可与 8 位或 4 位微处理器连接;内藏式字符发生器 ROM,可提供 160 种工 业标准字符,包括全部大小写字母、阿拉伯数字及日文片假名,以及 32 个特殊字符 或符号的显示;内藏 RAM 可根据用户的需要,由用户自定义字符或符号;+5V 单 电源供电;低功耗(10mW)。 2)1602 内部结构由 DDRAM、CGROM、IR、DR、BF、AC 等大规模集成电路组 成。 1. DDRAM 为数据显示用的 RAM(DataDisplayRAM,简称 DDRAM).用以存放 要 LCD 显示的数据,只要将标准的 ASCII 码放入 DDRAM,内部控制_线路就 会自动将数据传送到显示器上,并显示出该 ASCII 码对应的字符。

基于msp430g2553的1602四线驱动C源码

基于msp430g2553的1602四线驱动C源码

/*--------------------------------------------------------------*/基于msp430G2553de LCD1602四线驱动由于G2系列的IO口过于少,所以我们采用了四线驱动LCD1602的方法程序附后①液晶显示原理液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。

液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。

②液晶显示器的分类液晶显示的分类方法有很多种,通常可按其显示方式分为段式、字符式、点阵式等。

除了黑白显示外,液晶显示器还有多灰度有彩色显示等。

如果根据驱动方式来分,可以分为静态驱动(Static)、单纯矩阵驱动(Simple Matrix)和主动矩阵驱动(Active Matrix)三种。

③液晶显示器各种图形的显示原理:线段的显示点阵图形式液晶由M×N个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共16×8=128个点组成,屏上64×16个显示单元与显示RAM区1024字节相对应,每一字节的内容和显示屏上相应位置的亮暗对应。

例如屏的第一行的亮暗由RAM区的000H——00FH的16字节的内容决定,当(000H)=FFH 时,则屏幕的左上角显示一条短亮线,长度为8个点;当(3FFH)=FFH时,则屏幕的右下角显示一条短亮线;当(000H)=FFH,(001H)=00H,(002H)=00H,……(00EH)=00H,(00FH)=00H时,则在屏幕的顶部显示一条由8段亮线和8条暗线组成的虚线。

这就是LCD显示的基本原理。

字符的显示用LCD显示一个字符时比较复杂,因为一个字符由6×8或8×8点阵组成,既要找到和显示屏幕上某几个位置对应的显示RAM区的8字节,还要使每字节的不同位为“1”,其它的为“0”,为“1”的点亮,为“0”的不亮。

1602 四线制驱动程序

1602 四线制驱动程序

/************************************************************************** 1602 四线制驱动程序--基于MSP430F149File Name: LCD1602x4_mps.hAuthor: HuNB***************************************************************************/#include<msp430x14x.h>#define set(x) P6OUT |=x#define clr(x) P6OUT &=~x#define rs BIT2 //RA1#define rw BIT3 //RA2#define e BIT4 //RA3/*--------------------------------------------------------------------------------------------------函数说明--------------------------------------------------------------------------------------------------*/void init(); //申明I/O口初始化函数void delay_nus(unsigned int n); //N nS延时函数void delay_nms(unsigned int n); //N mS延时函数void LCD_init(void); //LCD初始化函数void LCD_en_write(void); //LCD写入使能函数void LCD_write_command(unsigned char command) ; //LCD写入命令函数void LCD_write_data(unsigned char Recdata); //LCD写入数据函数void LCD_set_xy (unsigned char x, unsigned char y); //LCD设置显示位置函数void LCD_write_char(unsigned char X,unsigned char Y,unsigned char Recdata); //LCD显示字符函数int LCD_PutStr(unsigned char *DData,int pos); //LCD显示字符串函数//int LCD_PutNum(unsigned long num,int XS,int pos);//LCD显示数字函数int p=0;//---------------------------------------//---------------------------------------//I/O口初始化函数void init(){//ADCON1=0X07; //设置A口为普通I/O口//TRISA=0X00; //设置A口为输出//TRISD=0X00; //设置D口为输出P4DIR=0xff;P6DIR=0x1c; //设置A口为输出WDTCTL = WDTPW + WDTHOLD; //杀狗}void delay_1us(void) //1us延时函数{_NOP();}void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1us();}void delay_1ms(void) //1ms延时函数{unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}void LCD_en_write(void) //液晶使能{set(e);delay_nus(1);clr(e);}void LCD_write_command(unsigned char command) //写指令{unsigned char temp;temp=command>>4; //高四位移到低四位delay_nus(16);clr(rs); //RS=0 选择指令地址clr(rw); //RW=0 写操作P4OUT&=0Xf0; //清低四位P4OUT|=temp&0x0f; //写高四位//command&0x0f;LCD_en_write();P4OUT&=0xf0; //清高四位P4OUT|=command&0x0f; //写低四位LCD_en_write();set(rw); //RW=1 结束写操作}void LCD_write_data(unsigned char Recdata) //写数据{ unsigned char temp;temp=Recdata>>4; //高四位移到低四位delay_nus(16);set(rs); //RS=1 选择数据地址clr(rw); //RW=0 写操作P4OUT&=0Xf0; //清高四位P4OUT|=temp&0x0f; //Recdata&0xf0写高四位LCD_en_write();// Recdata=Recdata<<4; //低四位移到高四位P4OUT&=0Xf0; //清高四位P4OUT|=Recdata&0x0f; //写低四位LCD_en_write();set(rw); //RW=1 结束写操作}void LCD_set_xy( unsigned char x, unsigned char y ) //写地址函数{unsigned char address;if (y == 0) address = 0x80 + x;else address = 0xc0 + x;LCD_write_command(address);}void LCD_init(void) //液晶初始化{LCD_write_command(0x28);delay_nus(40);LCD_write_command(0x28);delay_nus(40);LCD_write_command(0x28);delay_nus(40);LCD_en_write();delay_nus(40);LCD_write_command(0x28); //4位显示LCD_write_command(0x0c); //显示开LCD_write_command(0x01); //清屏delay_nms(5);}void LCD_write_char(unsigned char X,unsigned char Y,unsigned char Recdata) //列x=0~15,行y=0,1{LCD_set_xy(X, Y); //写地址LCD_write_data(Recdata);}int LCD_PutStr(unsigned char *DData,int pos){unsigned char i;if(pos==-1){LCD_write_command(0x01); //清屏delay_nms(2);pos=0;}while((*DData)!='\0'){switch(*DData){case '\n': //如果是\n,则换行{if(pos<17){for(i=pos;i<16;i++)LCD_write_char(i%16, i/16, ' ');pos=16;}else{for(i=pos;i<32;i++) LCD_write_char(i%16, i/16, ' ');pos=32;}break;}case '\b': //如果是\b,则退格{if(pos>0) pos--;LCD_write_char(pos%16, pos/16, ' ');break;}default:{if((*DData)<0x20){*DData=' ';}LCD_write_char(pos%16, pos/16,*DData);pos++;break;}}DData++;}return(pos);}/*----------------------------以下函数用于输出数字---------------------int LCD_PutNum(unsigned long num,int XS,int pos){ //从右边数,保留几位小数unsigned long tmp=0;unsigned char numbits=0;if(pos==-1){LCD_write_command(0x01);delay_nms(2);pos=0;}if(num==0){LCD_write_char(pos%16, pos/16, '0');pos++;}else{if(num<0){LCD_write_char(pos%16, pos/16, '-');num*=(-1);pos++;}while(num){tmp=tmp*10+(num%10);num=num/10;numbits++;}while(tmp){LCD_write_char(pos%16, pos/16, (tmp%10)+48);tmp=tmp/10;pos++;numbits--;if(numbits==XS) pos=LCD_PutStr(".",pos); //显示小数点 }while(numbits--){LCD_write_char(pos%16, pos/16, '0');pos++;}}return(pos);}**/。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

4根IO口线驱动1602(带PWM调光)呵呵,不用我说你们也知道为什么只需要4根线:因为咱用了74hc595啊!因为74HC595最近我手里一抓一大把。

但是STC的单片机IO口紧缺。

就算使用4线驱动模式也要8个IO(还要算上背光PWM)。

这一次我几乎做到了他的一半。

如果不用PWM的话。

大概只需要3个IO,如果需要PWM就四个罗。

MCU当然是老掉牙的死特惨89C52罗~画原理图实在是不方便。

就不画了。

另外求酷~也可以在595后面级联类似三极管开关……继电器之类的玩意。

当然友情提醒,别超过4个595.否则速度会慢的可怕。

我现在1个595.写1602都可以丢掉延时函数了。

这一次硬件设计的比较简单,但是IO全反了。

所以需要占用额外的CPU时间修正,但是毕竟方便洞洞板嘛。

还有大家别看到我给A和B赋了好几次值而去“优化”代码。

如果您“优化”的话,那么就根本驱动不起来,因为51的加法减法乘除都要经过ACC和B,如果不去重新赋值的话,那么就会发生改变的现象。

不过我这种位寻址软件修正可比那种xx=xx & xx的效率高多了。

如果我这么写的话。

恐怕刷一个屏幕没1秒下不来啊。

12T的51就这个速度……不过这一次焊板子实在是太仓促了。

对比度电位器焊在液晶下面,结果初始化成功了显示两排方块。

晕了半天。

调试半天还是没用。

后来捅了一下背面就好了……晕……!上代码:#include <stc89c5x.h>//STC89C52//串行驱动1602,powered by 595#define LCD1602_BACKLIGHT P1_3//背光#define LCD1602_SDA P1_0//数据输入#define LCD1602_SCK P1_1//移位时钟,SHCP,11pin#define LCD1602_SCL P1_2//锁存时钟,STCP,12pin/** 硬件连接:* 74HC595 Q7 - 1602 RS* GND - 1602 RW(595没有输入功能,所以判定忙只能靠延时,另外就是MCU的速度比较的慢。

所以也可以直接去掉延时。

但是在STC12系列上的表现,我可不知道会怎么样* 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=1B=OutBuf;B_6=1;OutBuf=B;Send595();//输出数据B=OutBuf;B_6=0;OutBuf=B;//E=0Send595();}/**********************************************************/ 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=D7B_3=A_6;//D6=D6B_4=A_5;//D5=D5B_5=A_4;//D4=D4OutBuf=B;Send595();lcd_en();//================ACC=i;B=OutBuf;B_2=A_3;//D7=D3B_3=A_2;//D6=D2B_4=A_1;//D5=D1B_5=A_0;//D4=D0OutBuf=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=D7B_3=A_6;//D6=D6B_4=A_5;//D5=D5B_5=A_4;//D4=D4OutBuf=B;Send595();lcd_en();//================ACC=i;B=OutBuf;B_2=A_3;//D7=D3B_3=A_2;//D6=D2B_4=A_1;//D5=D1B_5=A_0;//D4=D0OutBuf=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(){lcd_wcmd(0x20);lcd_en();//唤醒lcd_wcmd(0x28); //四位,5x7lcd_wcmd(0x0c); //开启显示屏,关光标,光标不闪烁lcd_wcmd(0x06); //显示地址递增,即写一个数据后,显示位置右移一位lcd_wcmd(0x01); //清屏//调试的时候被设计失误的对比度电位器坑死了:就是两排小方块死都不显示//查了半天都不知道//最后捅了下电位器就正常了……}void PWM() __interrupt 1 __using 1{ET0=0;TF0=0;//CLRTR0=0;EA=0;TH0=0xFC;TL0=0x00;//十级调光,频率400Hzif(PWM_T>10) {PWM_T=0;}if(PWM_Cycle>PWM_T){ LCD1602_BACKLIGHT=0;}if(PWM_Cycle<PWM_T) {LCD1602_BACKLIGHT=1;}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:"," ");delay(2000);lcd_display("Backlight Ctl by"," T0 PWM 400Hz ");delay(2000);}}自己DIY的最小系统,旁边是串口转接器。

这个板子上有两个晶振跳线选择外加一个外界晶振。

现在这个晶振跳在内置的11.0592上。

背面,没布局好,那飞线……接口在左边是GND,VCC,BACKLIGHT.前面是SCK SCL SDA.万致远原创。

第二发于amoBBS(OURDEV)转载请注明出处~下一次做一个串行驱动12864……。

相关文档
最新文档