1. 專注電子技術(shù)學習與研究
      當前位置:單片機教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

      74hc595+4根IO口線驅(qū)動1602,帶PWM調(diào)光

      作者:佚名   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2012年08月09日   【字體:

             呵呵,不用我說你們也知道為什么只需要4根線:因為咱用了74hc595。∫驗74HC595最近我手里一抓一大把。但是STC的單片機IO口緊缺。就算使用4線驅(qū)動模式也要8個IO(還要算上背光PWM)。這一次我?guī)缀踝龅搅怂囊话搿H绻挥肞WM的話。大概只需要3個IO,如果需要PWM就四個羅。
            MCU當然是老掉牙的死特慘89C52羅~

            也可以在595后面級聯(lián)類似三極管開關(guān)……繼電器之類的玩意。當然友情提醒,別超過4個595.否則速度會慢的可怕。我現(xiàn)在1個595.寫1602都可以丟掉延時函數(shù)了。
             這一次硬件設(shè)計的比較簡單,但是IO全反了。所以需要占用額外的CPU時間修正,但是畢竟方便洞洞板嘛。還有大家別看到我給A和B賦了好幾次值而去“優(yōu)化”代碼。如果您“優(yōu)化”的話,那么就根本驅(qū)動不起來,因為51的加法減法乘除都要經(jīng)過ACC和B,如果不去重新賦值的話,那么就會發(fā)生改變的現(xiàn)象。不過我這種位尋址軟件修正可比那種xx=xx & xx的效率高多了。如果我這么寫的話?峙滤⒁粋屏幕沒1秒下不來啊。12T的51就這個速度……
             不過這一次焊板子實在是太倉促了。對比度電位器焊在液晶下面,結(jié)果初始化成功了顯示兩排方塊。暈了半天。調(diào)試半天還是沒用。后來捅了一下背面就好了……暈……!
             上代碼:
       

      #include <stc89c5x.h>//STC89C52
      
      //串行驅(qū)動1602,powered by 595
      #define LCD1602_BACKLIGHT        P1_3//背光
      #define LCD1602_SDA                        P1_0//數(shù)據(jù)輸入
      #define LCD1602_SCK                        P1_1//移位時鐘,SHCP,11pin
      #define LCD1602_SCL                        P1_2//鎖存時鐘,STCP,12pin
      
      /*
      * 硬件連接:
      * 74HC595 Q7 - 1602 RS
      * GND - 1602 RW(595沒有輸入功能,所以判定忙只能*延時,另外就是MCU的速度比較的慢。所以也可以直接去掉延時。但是在STC12系列上的表現(xiàn),相當?shù)牟诲e
      * 在傳統(tǒng)51上面。PWM占空比低于50%將會出現(xiàn)掃描線。12系列的,很高興的告訴大家。T0X12開了以后。不會有掃描線出現(xiàn)。但是如果一定要在傳統(tǒng)51上使用的話,請把10級調(diào)光改成4級。謝謝合作!
      * 74HC595 Q6 - 1602 EN
      * 74HC595 Q5~Q2 - 1602 D5~D7(這一次硬件設(shè)計不合理,才只能搞軟件修正了。不過好處就是直接就可以洞洞板上對著聯(lián),減少了燒壞595的概率。壞處就是CPU時間消耗的多了點。但是可以取消延時函數(shù)啦~
      * 1602 D1~D4 直接懸空
      * LCD_BACKLIGHT加一級PNP三極管射隨器加到液晶的A上,如果無需調(diào)光可以去掉這一部分電路和代碼
      * 至于595的連接,只要不弄反SCL和SCK,就沒有問題啦~
      */
      
      __sbit  __at  0xE0 A_0;//方便位操作,硬件設(shè)置真的是敗筆 - -
      __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();//輸出數(shù)據(jù)
              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)
      {
      //寫數(shù)據(jù)
              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); //顯示地址設(shè)為80H(即00H,)上排第一位
              for(i=0;i<16;i++)
              {
                      lcd_wdat(l1[i]);
              }
              lcd_wcmd(0x80+0x40); //重新設(shè)定顯示地址為0xc0,即下排第1位
              for(i=0;i<16;i++) 
              {
                      lcd_wdat(l2[i]);
              }
      }
      
      void lcd_cls()
      {
              lcd_wcmd(0x01); //清屏延時函數(shù)可以省略
      }
      //米有讀函數(shù),但是功能可以由上面的函數(shù)擴展哦~
      void lcd_init()
      {
          OutBuf=0xff;
          Send595();//復(fù)位VIO,這段代碼必須加。否則MCU忽然RESET會導(dǎo)致液晶亂碼
          lcd_wcmd(0x30);//復(fù)位1602,這段代碼必須加,同上
          lcd_en();//喚醒
              lcd_wcmd(0x20);
              lcd_en();//喚醒
              lcd_wcmd(0x28); //四位,5x7
              lcd_wcmd(0x0c); //開啟顯示屏,關(guān)光標,光標不閃爍
              lcd_wcmd(0x06); //顯示地址遞增,即寫一個數(shù)據(jù)后,顯示位置右移一位
              lcd_wcmd(0x01); //清屏        
              //調(diào)試的時候被設(shè)計失誤的對比度電位器坑死了:就是兩排小方塊死都不顯示
              //查了半天都不知道
              //最后捅了下電位器就正常了……
      }
      void lcd_print(unsigned char *str)
      {
          unsigned char addr=0x80,len=0;
          lcd_wcmd(addr); //顯示地址設(shè)為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++;
          }
      }//寫字符串函數(shù)
      void PWM() __interrupt 1 __using 1
      {
              ET0=0;
              TF0=0;//CLR
              TR0=0;
              EA=0;
              TH0=0xFC;TL0=0x00;//十級調(diào)光,頻率400Hz
              if(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()
      {//主函數(shù)
      
              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);
              }
      }
      

      下面上圖片:


      自己DIY的最小系統(tǒng),旁邊是串口轉(zhuǎn)接器。這個板子上有兩個晶振跳線選擇
      外加一個外界晶振,F(xiàn)在這個晶振跳在內(nèi)置的11.0592上。

      關(guān)閉窗口

      相關(guān)文章