74hc595+4根IO口线驱动1602,带PWM调光

发布者:yuehui最新更新时间:2015-07-16 来源: 51hei关键字:74hc595  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 //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系列上的表现,相当的不错
* 在传统51上面。PWM占空比低于50%将会出现扫描线。12系列的,很高兴的告诉大家。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();
}
[page]
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!='')
    {//等待末尾
        if(len >= 16)
        {
            lcd_wcmd(0x80+0x40);//下排第一位,换行
            len=0;
        }
        if(*str=='
')
        {
            lcd_wcmd(0x80+0x40);//下排第一位,换行
        }
        else
        {
            lcd_wdat(*str);    
        }
        str++;
        len++;
    }
}//写字符串函数
void PWM() __interrupt 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

下面上图片:


自己DIY的最小系统,旁边是串口转接器。这个板子上有两个晶振跳线选择
外加一个外界晶振。现在这个晶振跳在内置的11.0592上。

关键字:74hc595  PWM调光 引用地址:74hc595+4根IO口线驱动1602,带PWM调光

上一篇:STC单片机的下载协议
下一篇:用单片机+DAC0832来解码wav音乐C51程序

推荐阅读最新更新时间:2024-03-16 14:25

STC89C52单片机1602液晶驱动
///////////////////////////////////////////////////////////////////////// 实现功能: 驱动开发板上的1602液晶,在1602液晶上显示两组字符,所显示的两 组字符一两秒钟的时间来回循环 实验板型号:BS-XYD-C52 实验名称: 1602液晶显示实验 编写人: 谢应东 编写日期: 2012-5-2 ///////////////////////////////////////////////////////////////////////// #include reg52.h #include in
[单片机]
51单片机:定时器与LCD1602的运用,做一个简易时钟
#include regx52.h #include LCD1602.h void Delay(int time) { while(time--) //while循环一次需要10us { } } void Timer0Init(void) //1毫秒@11.0592MHz { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x66; //设置定时初值 TH0 = 0xFC; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0
[单片机]
51单片机:定时器与LCD<font color='red'>1602</font>的运用,做一个简易时钟
ATMEGA16A单片机1602字符显示程序
* 【编译环境】: ICCAVR * 【函数功能】: 1602字符显示 * 【晶 振】: 8M * 【芯 片】: ATMEGA16A #include iom16v.h #define uchar unsigned char #define uint unsigned int uchar wz ={ mcustudio1com-cn }; uchar gd ={ Tel:15980xx5601 }; #define uchar unsigned char #define uint unsigned int #define RS 0 #define RW 1 #define E
[单片机]
51单片机驱动1602液晶的C程序
# include AT89x51.h /***************************************** 电路连接 P1------DB0~DB7 P2.0------RS P2.1------RW P2.2------E *****************************************/ # define LCD_DB P1 sbit LCD_RS=P2^0; sbit LCD_RW=P2^1; sbit LCD_E=P2^2; /******定义函数****************/ # define ucharunsign
[单片机]
51单片机之IO口扩展——74HC595芯片串行转并行实验
我们都知道通信从大的方面有两种:串行和并行。串行的最大优点是占用总线少,但是传输速率低;并行恰恰相反,占用总线多,传输速率高。市面上有很多这样的芯片,有串入并出的(通俗讲就是 一个一个进,最后一块出来),有并入串出的(相对前者而言)。具体用哪种类型要根据我们得实际情况。比如利用单片机显示数码管单纯的显示一个数码管如果仅仅是为了显示 那么动用单片机一个端口(如P0或P1/P2/P3)那没有什么,当然这里我说的数码管是8段的(如果利用BCD类型 16进制数码管那么只需四个即可)就拿51类型的单片机来说,总共32个I/O口,一般如果不是做太大的工程是完全够用的,但有些时候你会恨单片机怎么不多长几条“腿”,怎么省还是不够用。这个时候就需要
[单片机]
51单片机之IO口扩展——<font color='red'>74HC595</font>芯片串行转并行实验
自制51单片机常用头文件(LCD1602)
/*-------------------------------------------------------------------------- LCD1602.H The user function is C51. Copyright (c) 1988-2004 Keil Elektronik GmbH sum zhaojun All rights reserved. --------------------------------------------------------------------------*/ #ifndef __LCD1602_H__ #define __LCD1602_H__ /*连接线
[单片机]
LCD1602动态显示
仿真元原理图如下: /*------------------------------------- 功能:LCD1602局部动态显示 描述:在屏幕的第二行固定位置显示count: 后面接着动态显示按键次数(00 ~ 99) Author: Zhang Kaizhou Date: 2019-6-5 10:50:22 -------------------------------------*/ #include reg52.h #include string.h #define uchar unsigned char #define uint unsigned int uchar code table0 = { Press
[单片机]
LCD<font color='red'>1602</font>动态显示
1602 AVR单片机版 报警指示功能
使用的是ATMEGA16芯片 功能说明:正常状态下,8个LED不停闪烁,1602显示normal indication指示 报警状态下, 8个LED全发亮不闪烁,1602显示alarm报警,只有按复位按钮才能解除报警. alarm状态时,由于PB口的低3位和,1602时能,读写,数据指令寄存器选择位复用,所以有点暗. #include iom16.h #include intrinsics.h #define uchar unsigned char #define uint unsigned int #define RS1 PORTB_Bit0=1 //数据指令寄存器
[单片机]
<font color='red'>1602</font> AVR单片机版 报警指示功能
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved