標(biāo)題: 單片機(jī)加個(gè)PCF8574模塊,實(shí)現(xiàn)IIC方式驅(qū)動(dòng)LCD1602 [打印本頁(yè)]

作者: lmn2005    時(shí)間: 2019-3-4 18:51
標(biāo)題: 單片機(jī)加個(gè)PCF8574模塊,實(shí)現(xiàn)IIC方式驅(qū)動(dòng)LCD1602
PCF8574模塊使實(shí)現(xiàn)IIC驅(qū)動(dòng)LCD1602成為現(xiàn)實(shí)。

下圖是PCF8574模塊與1602的連接電路圖:

實(shí)物接法如下:
想要使用PCF8574模塊來(lái)實(shí)現(xiàn)IIC驅(qū)動(dòng)LCD1602,首先非常必要弄清楚IIC的時(shí)序、PCF8574設(shè)備地址、四線控制LCD1602方法。
下面是兩個(gè)重要的h文件。通過(guò)修改這兩個(gè)h文件中的部分代碼(接線有所不同)即可移植到你的程序中去。

單片機(jī)源程序如下:
  1. void delay1(uchar x)
  2. {
  3.         uchar a,b;
  4.         for(a=x;a>0;a--)
  5.          for(b=200;b>0;b--);
  6. }

  7. void write_com(uchar com)                //寫命令函數(shù)
  8. {        uchar com1,com2;
  9.         com1=com|0x0f;
  10.         write_add(com1&0xfc);
  11.         delay1(2);
  12.     write_add(com1&0xf8);
  13.         com2=com<<4;
  14.         com2=com2|0x0f;
  15.         write_add(com2&0xfc);
  16.         delay1(2);
  17.     write_add(com2&0xf8);
  18.        
  19. }

  20. void write_date(uchar date)                //寫數(shù)據(jù)函數(shù)
  21. {
  22.         uchar date1,date2;
  23.         date1=date|0x0f;
  24.         write_add(date1&0xfd);
  25.         delay1(2);
  26.         write_add(date1&0xf9);
  27.         date2=date<<4;
  28.         date2=date2|0x0f;
  29.         write_add(date2&0xfd);
  30.         delay1(2);
  31.         write_add(date2&0xf9);
  32.                
  33. }

  34. void init_lcd()                                        //初始化函數(shù)
  35. {                                                                                                 
  36.         write_com(0x33); //顯示模式設(shè)置
  37.         delayms(6);
  38.         write_com(0x32); //顯示模式設(shè)置
  39.         delayms(6);
  40.         write_com(0x28); //4位總線,雙行顯示,顯示5×7的點(diǎn)陣字符
  41.         delayms(6);
  42.         write_com(0x01); //清屏
  43.         delayms(6);
  44.         write_com(0x06); //字符進(jìn)入模式:屏幕不動(dòng),字符后移
  45.         delayms(6);
  46.         write_com(0x0c); //顯示開(kāi),關(guān)光標(biāo)
  47.         //write_LCD_Command(0x0f); //顯示開(kāi),開(kāi)光標(biāo),光標(biāo)閃爍
  48.         delayms(6);
  49. }

  50. //顯示字符串:第x行第y列顯示什么內(nèi)容
  51. void ShowString(unsigned char x,unsigned char y,unsigned char *str)
  52. {
  53.        
  54.         if(x == 1)
  55.         {
  56.                 write_com(0x80 | y-1);
  57.         }
  58.         if(x == 2)
  59.         {
  60.                 write_com(0xc0 | y-1);
  61.         }
  62.         //輸出字符串
  63.        
  64.         while(*str!='\0')
  65.         {
  66.                 write_date(*str);
  67.                 str++;
  68.         }

  69. }
復(fù)制代碼

所有資料51hei提供下載:
PCF8574 LCD1602_4.rar (685 Bytes, 下載次數(shù): 658)
PCF8574.rar (536 Bytes, 下載次數(shù): 444)

作者: lmn2005    時(shí)間: 2019-3-5 10:28
補(bǔ)個(gè)實(shí)物連接圖:

作者: w402333815    時(shí)間: 2019-4-19 17:26
看到里面的內(nèi)容了,一個(gè)函數(shù)一個(gè)壓縮包
作者: at366    時(shí)間: 2019-6-23 17:09
謝謝分享,不好一點(diǎn)就是分成兩包
作者: bhjyqjs    時(shí)間: 2019-6-24 08:17
謝謝樓主分享,但實(shí)際中毫無(wú)意義。淘寶上IIC方式驅(qū)動(dòng)的LCD1602屏就8元多,比這個(gè)模塊貴不了多少。好用多了!
作者: ldshen00    時(shí)間: 2019-7-9 22:05
void delay1(uchar x)
{
        uchar a,b;
        for(a=x;a>0;a--)
         for(b=200;b>0;b--);
}

void write_com(uchar com)                //寫命令函數(shù)
{        uchar com1,com2;
        com1=com|0x0f;
        write_add(com1&0xfc);
        delay1(2);
    write_add(com1&0xf8);
        com2=com<<4;
        com2=com2|0x0f;
        write_add(com2&0xfc);
        delay1(2);
    write_add(com2&0xf8);
       
}

void write_date(uchar date)                //寫數(shù)據(jù)函數(shù)
{
        uchar date1,date2;
        date1=date|0x0f;
        write_add(date1&0xfd);
        delay1(2);
        write_add(date1&0xf9);
        date2=date<<4;
        date2=date2|0x0f;
        write_add(date2&0xfd);
        delay1(2);
        write_add(date2&0xf9);
               
}

void init_lcd()                                        //初始化函數(shù)
{                                                                                                 
        write_com(0x33); //顯示模式設(shè)置
        delayms(6);
        write_com(0x32); //顯示模式設(shè)置
        delayms(6);
        write_com(0x28); //4位總線,雙行顯示,顯示5×7的點(diǎn)陣字符
        delayms(6);
        write_com(0x01); //清屏
        delayms(6);
        write_com(0x06); //字符進(jìn)入模式:屏幕不動(dòng),字符后移
        delayms(6);
        write_com(0x0c); //顯示開(kāi),關(guān)光標(biāo)
        //write_LCD_Command(0x0f); //顯示開(kāi),開(kāi)光標(biāo),光標(biāo)閃爍
        delayms(6);
}

//顯示字符串:第x行第y列顯示什么內(nèi)容
void ShowString(unsigned char x,unsigned char y,unsigned char *str)
{
       
        if(x == 1)
        {
                write_com(0x80 | y-1);
        }
        if(x == 2)
        {
                write_com(0xc0 | y-1);
        }
        //輸出字符串
       
        while(*str!='\0')
        {
                write_date(*str);
                str++;
        }

}
這就是 高級(jí)貨
作者: ampere53060083    時(shí)間: 2019-7-10 03:12
厲害 高手
作者: 鵬博士PBs    時(shí)間: 2019-7-10 09:18
I2C通訊啊
作者: zxy2266    時(shí)間: 2019-7-30 11:40
正要做這個(gè),軟件很好
作者: jiajuntao    時(shí)間: 2019-10-20 21:41
能驅(qū)動(dòng)就好,麻煩能告訴下,哪句是PCF8574地址句。
作者: xlmttkl    時(shí)間: 2019-12-1 19:25
write_add函數(shù)沒(méi)有啊
作者: 哇哦恩    時(shí)間: 2019-12-12 21:10
淘寶店家給的例程是arduino的,直接調(diào)用現(xiàn)成的庫(kù),也是醉了,到論壇里來(lái)看看有沒(méi)有能用的程序
作者: ytzmoonunit    時(shí)間: 2019-12-26 17:34
這段代碼可行嗎,有人成功嗎?
里面的 write_byte 有疑問(wèn)
作者: ytzmoonunit    時(shí)間: 2019-12-26 17:51
我測(cè)試成功了,感謝樓主!
分享下經(jīng)驗(yàn):如果是8574 寫入的地址是0X27<<1 ,如果是8574A,寫入的地址是0X3F<<1
(write_add 里面指代的是8574A)
iic的sart,stop,ack 。。。 都是通用的

作者: LEI365    時(shí)間: 2020-1-10 13:16
先看看,正在用這個(gè)模塊。
作者: LEI365    時(shí)間: 2020-1-20 09:34
有現(xiàn)成的,懶得自己寫協(xié)議轉(zhuǎn)換程序了。
作者: lyl44    時(shí)間: 2020-2-28 14:53
bhjyqjs 發(fā)表于 2019-6-24 08:17
謝謝樓主分享,但實(shí)際中毫無(wú)意義。淘寶上IIC方式驅(qū)動(dòng)的LCD1602屏就8元多,比這個(gè)模塊貴不了多少。好用多了 ...

那個(gè)寶上買的就是這個(gè)東西的成品。
作者: minjunshuyi    時(shí)間: 2020-3-5 21:32
2個(gè)文件都需要?
作者: lmn2005    時(shí)間: 2020-3-25 08:11
jiajuntao 發(fā)表于 2019-10-20 21:41
能驅(qū)動(dòng)就好,麻煩能告訴下,哪句是PCF8574地址句。

void write_iic(uchar date1)//寫入數(shù)據(jù)到IO    中的
      write_byte(0x7e); //8574A地址,寫數(shù)據(jù)

uchar read_iic()//向IO讀取數(shù)據(jù)  中的
      write_byte(0x7f); //8574A地址,寫數(shù)據(jù)
作者: a461624201    時(shí)間: 2020-4-1 00:51
確實(shí)不錯(cuò),void write_add(uchar date1)//寫入數(shù)據(jù)到IO
{
        start();
//        write_byte(0x7e); 0X3F<<1   0x7e 8574A芯片
        write_byte(0x4e); //bin(0x27<<1) 0x4e 8574 芯片
        respons();
        write_byte(date1);
        respons();
        stop();
}
作者: 1233423asd    時(shí)間: 2020-4-6 10:55
真好用感謝感謝
作者: 羅程峰8200    時(shí)間: 2020-4-20 21:14
真好,要啥來(lái)啥,我都懷疑我被監(jiān)控了,謝謝
作者: yy1956029281    時(shí)間: 2020-5-10 14:27
這個(gè)是只需要該pcf8574的地址然后直接運(yùn)行就可以了嗎
作者: hunterfox    時(shí)間: 2020-5-14 16:34
STC12C5A60S2 打死也調(diào)試不出來(lái)。瘋了
作者: rsbook    時(shí)間: 2020-5-22 14:46
剛買子這個(gè)模塊測(cè)試下
作者: bresya    時(shí)間: 2020-6-4 20:09
ytzmoonunit 發(fā)表于 2019-12-26 17:51
我測(cè)試成功了,感謝樓主!
分享下經(jīng)驗(yàn):如果是8574 寫入的地址是0X27

還好你提醒,要不然我怎么都調(diào)試不通。
作者: 欣語(yǔ)寶貝    時(shí)間: 2020-7-30 19:40
1602  老是搞不定   不知道哪里問(wèn)題
作者: JasonW    時(shí)間: 2020-8-19 17:01
感謝樓主分享,現(xiàn)在就試一下
作者: ag26259    時(shí)間: 2021-1-16 21:21
感謝樓主分享,剛?cè)肓诉@轉(zhuǎn)接板,現(xiàn)在就試一下
作者: cx301    時(shí)間: 2021-2-16 22:09
借用樓主程序,用STC15W408單片機(jī)測(cè)試了一下,現(xiàn)把完整的測(cè)試工程文件分享一下

PCF8574+1602.rar

28.43 KB, 下載次數(shù): 80, 下載積分: 黑幣 -5


作者: wwh2382    時(shí)間: 2021-2-17 16:03
請(qǐng)問(wèn)pcf8574+1602可以用proteus仿真嗎?
作者: tomsmiss123    時(shí)間: 2021-4-28 12:21
正在看這個(gè),但是沒(méi)有點(diǎn)亮,在找找看是啥原因

作者: 天下倒數(shù)第一    時(shí)間: 2021-4-28 12:29
謝謝,51hei真好用
作者: Capta1nY    時(shí)間: 2021-6-30 16:42
hunterfox 發(fā)表于 2020-5-14 16:34
STC12C5A60S2 打死也調(diào)試不出來(lái)。瘋了

老哥,我也用的60s2,同樣調(diào)不出來(lái),你知道什么問(wèn)題了嗎
作者: Capta1nY    時(shí)間: 2021-6-30 16:43
tomsmiss123 發(fā)表于 2021-4-28 12:21
正在看這個(gè),但是沒(méi)有點(diǎn)亮,在找找看是啥原因

找到原因了么,我也是沒(méi)有輸出顯示
作者: Capta1nY    時(shí)間: 2021-6-30 16:46
請(qǐng)教一下,我也用的這個(gè)模塊,單片機(jī)用的stc12C5A60S2, lcd是1602A,用您的程序調(diào)試,沒(méi)用結(jié)果,地址我改的0x27,不過(guò)換了其他的也沒(méi)用
作者: zmc419    時(shí)間: 2021-7-2 23:23
謝謝樓主,有用
作者: 828    時(shí)間: 2021-12-20 14:12
不是SCL對(duì)應(yīng)15,SDA對(duì)應(yīng)14嗎
作者: kmsj    時(shí)間: 2022-9-5 13:03
非常感謝樓主的無(wú)私奉獻(xiàn)!按照樓主的程序,稍加修改,立即成功!
之前用一片CD4094成功驅(qū)動(dòng)LCD1602,這次我只要把8574驅(qū)動(dòng)I/O口的試驗(yàn)做成功就可以了。



拆掉洞洞板之前做試驗(yàn)的兩片74HC595,留下LED和電阻,加上8574,我用的是雙列直插PCF8574P,經(jīng)過(guò)試驗(yàn)發(fā)現(xiàn),PCF8574P的I/O口驅(qū)動(dòng)能力較弱,通過(guò)1K電阻驅(qū)動(dòng)LED,亮度只有一點(diǎn)點(diǎn),遠(yuǎn)遠(yuǎn)達(dá)不到CD4094和74HC595的驅(qū)動(dòng)能力,估計(jì)驅(qū)動(dòng)LCD1602問(wèn)題不大,畢竟PCF8574P的I/O口是雙向I/O口。之所以用PCF8574P,是因?yàn)镻CF8574P才一塊多錢一片,需要注意的是,PCF8574P 13腳INT不能直接接VCC,必須通過(guò)電阻才能接VCC,否則芯片發(fā)燙。!
單片機(jī)用的是STC8H1K08,PCF8574P雙列直插的寫地址是0x40,STC8H1K08用的IRC是1.2M,注釋掉所有的delay( ),程序運(yùn)行照樣正常,經(jīng)過(guò)試驗(yàn),IRC為5M,程序正常,IRC為6M,程序不正常, delay( )替換成一個(gè)_nop_ ( ) 應(yīng)該就可以了,那么IRC為12M,估計(jì)要替換兩個(gè)到三個(gè)nop,程序才能正常。另外,應(yīng)答部分的程序代碼沒(méi)有完全看懂,等以后用到的時(shí)候再慢慢研究和改進(jìn)了。


作者: puqiong233    時(shí)間: 2022-10-28 01:19
hunterfox 發(fā)表于 2020-5-14 16:34
STC12C5A60S2 打死也調(diào)試不出來(lái)。瘋了

我也是,請(qǐng)問(wèn)調(diào)試出來(lái)了么
作者: jokerking    時(shí)間: 2023-3-21 15:32
沒(méi)有人試STC89C51的嗎
孩子pcf8574為什么地址設(shè)置的0x27也不行
#include <reg52.h>
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int

//#define                        L1                0x80            // 第一行寫入地址
//#define                        L2                0xc0            // 第二行寫入地址
        
sbit SCL = P2^1;
sbit SDA = P2^0;

uchar woder[]={"wangzijie"};

//char ADDR = 0x4E;    // PCF8574  T  模塊的地址碼
//char ADDR = 0x7e;    // PCF8574   AT  模塊的地址碼
char ADDR = 0x27;    // PCF8574   AT  模塊的地址碼


//***************************** 延時(shí) y  ms ***********************************************


void delay1(int y)   //
{
         ;
        while(y--)
        {
        unsigned char a,b,c;
        for(c=1;c>0;c--)
        for(b=142;b>0;b--)
        for(a=2;a>0;a--);
        }
}






//******************************** IIC 串口開(kāi)始 ********************************************


void IIC_start(void)
{
        SDA=1;
        _nop_();
        SCL=1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SDA=0;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SCL=0;
}




//********************************** IIC 串口寫1個(gè)字節(jié) ******************************************


void IIC_writeByte(char temp)
{
        char i;
        for(i=0;i<8;i++)
        {
                SDA=(bit)(temp & 0x80) ;   // 根據(jù)規(guī)定1602的數(shù)據(jù)最高位必須為  1  
                temp <<=1;
                _nop_();
                _nop_();
                SCL=1;
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                SCL=0;
        }
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SDA=1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SCL=1;
        _nop_();
        _nop_();
        _nop_();
        while(SDA);
        _nop_();
        SCL=0;
}




//******************************** 1602寫命令 ********************************************


void LCD_write_command(char comm)
{
        char tmp;
        IIC_start();          // 串口開(kāi)始
        IIC_writeByte(ADDR);  // 先選PCF 8574T 的地址  (應(yīng)該是相當(dāng)于選中的意思吧)
        
        tmp = comm & 0xF0;    // 與0xf0 應(yīng)該是取第四位的意思吧
        tmp |= 0x0C;         //保留高4位為指令的高四位,低四位為   RS = 0, RW = 0, EN = 1  
        IIC_writeByte(tmp);  //從串口送出
        delay1(20);
        tmp &= 0xFB;        //Make EN = 0
        IIC_writeByte(tmp);
        
        tmp = (comm & 0x0F) << 4 ;  //將指令的低四位 送到高位置保存
        tmp |= 0x0C;        //RS = 0, RW = 0, EN = 1
        IIC_writeByte(tmp);
        delay1(20);
        tmp &= 0xFB; // Make EN = 0
        IIC_writeByte(tmp);
        
}
//******************************** 1602寫數(shù)據(jù) ********************************************


void LCD_write_data(char data1)
{
        char tmp;
        IIC_start();
        IIC_writeByte(ADDR);   // 先選PCF8574T 的地址  (應(yīng)該是相當(dāng)于選中的意思吧)
        
        tmp = data1 & 0xF0;
        tmp |= 0x0D; //RS = 0, RW = 0, EN = 1
        IIC_writeByte(tmp);
        delay1(20);
        tmp &= 0xFB; //Make EN = 0
        IIC_writeByte(tmp);
        
        tmp = (data1 & 0x0F) << 4 ;
        tmp |= 0x0D; //RS = 0, RW = 0, EN = 1
        IIC_writeByte(tmp);
        delay1(20);
        tmp &= 0xFB ; // Make EN = 0
        IIC_writeByte(tmp);
}


//******************************** 1602初始化 ********************************************


void Init_Lcd(void)
{
        LCD_write_command(0x33); //將8位總線轉(zhuǎn)為4位總線
        delay1(50) ;
        LCD_write_command(0x32); //
        delay1(50) ;
        LCD_write_command(0x28); // 4位數(shù)據(jù)線0x28,顯示2行,5*7點(diǎn)陣字符  !如果是0x38  則為8位數(shù)據(jù)線,顯示2行,5*7點(diǎn)陣字符
        delay1(50) ;
        LCD_write_command(0x0C); // 開(kāi)顯示,關(guān)閉光標(biāo),不閃爍
        delay1(50) ;  
        LCD_write_command(0x06); // 設(shè)定輸入方式,增量不位移
        delay1(50) ;
        LCD_write_command(0x01); // 清屏
        delay1(50) ;
//                LCD_write_command(0x80);  //設(shè)置數(shù)據(jù)指針起點(diǎn)
//                delay1(50) ;
}








//*************************************** 在指定位置顯示字符串 *************************************


void Write_LCD(int x, int y, char *str)
{
        char addr;
        if( x < 0)
        {
                x = 0;
        }
        if(x > 15)
        {
                x = 15;
        }
        if(y<0)
        {
                y = 0;
        }
        if(y > 1)
        {
                y = 1;
        }
        
        addr = 0x80 + 0x40 * y + x;   // Move cursor  移動(dòng)光標(biāo)
        LCD_write_command(addr);
        while (*str)
        {
                LCD_write_data(*str++);
        }
}


//-------------------------------------------- 顯示字符串的函數(shù) ----------------------------------------------------


void LCD_write_word(unsigned char *s)                  //顯示字符串的函數(shù)
{
        while(*s>0)
        {
                LCD_write_data(*s);
                s++;
        }
}

void main()
{               
        uchar i;
        Init_Lcd();
//        for(i=0;i<9;i++)
//        {
        Write_LCD(0,0,(uchar *)woder[i]);
        LCD_write_word((uchar *)woder[i]);
//        }
        while(1);                               
}


//********************************* 指定位置顯示一個(gè)字符*******************************************


/*
void Print_Char (unsigned char line,unsigned char num,unsigned char date)
{
                LCD_write_command(line+num);
                LCD_write_data(date);
}


*/




//按指定位置顯示一個(gè)字符(針對(duì)1602液晶)-用在溫度顯示


//void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
//{
//Y &= 0x1;
//X &= 0xF;                 //限制X不能大于15,Y不能大于1
//if (Y) X |= 0x40;        //當(dāng)要顯示第二行時(shí)地址碼+0x40;
//X |= 0x80;               // 算出指令碼
//LCD_write_command(X);    //這里不檢測(cè)忙信號(hào),發(fā)送地址碼
//LCD_write_data(DData);
//}

看看代碼嗚嗚嗚@
作者: 15031773670    時(shí)間: 2023-4-8 11:21
cx301 發(fā)表于 2021-2-16 22:09
借用樓主程序,用STC15W408單片機(jī)測(cè)試了一下,現(xiàn)把完整的測(cè)試工程文件分享一下

等我有分了來(lái)下載一下。終于看到了。謝謝分享希望好用。
作者: 15031773670    時(shí)間: 2023-4-8 17:37
lmn2005 發(fā)表于 2019-3-5 10:28
補(bǔ)個(gè)實(shí)物連接圖:

我用的和這個(gè)是一樣的。您的代碼看不懂。用的204S用下面的408AS的也是不行。程序改了。端口也改了。希望得到回復(fù)
作者: su27smk    時(shí)間: 2023-7-30 10:58
試了一下,可以用




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1