找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6769|回复: 13
打印 上一主题 下一主题
收起左侧

pcf8574扩展出来的i2c驱动1602液晶定时开关单片机源程序与实物制作

  [复制链接]
跳转到指定楼层
楼主
主要元件
89c52单片机
ds1302实时时钟程序
24c02
18b20
pcf8574
lcd1602
不知道为什么使用i2c光标不清晰

下面制作出来的实物图:


单片机源程序如下:
  1. #include"mcu.h"
  2. #include"ds1302.c"
  3. #include"pcf8574lcd.h"
  4. #include"24c02.h"
  5. sbit a0 = ACC^0;
  6. sbit a1 = ACC^1;
  7. sbit a2 = ACC^2;
  8. sbit a3 = ACC^3;
  9. sbit a4 = ACC^4;
  10. sbit a5 = ACC^5;
  11. sbit a6 = ACC^6;
  12. sbit a7 = ACC^7;

  13. sbit SCLK = P1^2;              //时钟        
  14. sbit IO = P1^3;                      //数据
  15. sbit RST = P1^4;                //复位

  16. sbit DQ = P0^0 ; //18B20接口
  17. sbit sp = P3^4 ; //蜂鸣器

  18. sbit sb = P0^6 ;   //继电器电源
  19. //输出
  20. sbit sb0 = P2^0 ;        
  21. sbit sb1 = P2^1 ;
  22. sbit sb2 = P2^2 ;        
  23. sbit sb3 = P2^3 ;
  24. //按键
  25. sbit MODE = P2^7 ;        //模式键
  26. sbit INC = P2^6 ;        //增加键
  27. sbit DEC = P2^5 ;        //减少键
  28. sbit OK = P2^4 ;        //OK键        定时开关键
  29.          
  30. volatile uint8 data timedata[7] ;        //时间值
  31. volatile uint8 data display_buffer1[16];        //显示缓冲区1
  32. volatile uint8 data display_buffer2[16];        //显示缓冲区2
  33. volatile uint8 data temdata[5] ;        //存放温度值
  34. volatile uint16 data tdat ;        //温度值变量
  35. volatile uint8 data tflag ;        //温度正负值标志
  36. volatile int self_pos = 0 ;//菜单箭头标志变量
  37. volatile int OK_VALUE = 0 ; //OK键键值变量
  38. volatile bit bdata DIS_ON = 1 ; //显示开关 1 == on 0 == off
  39. volatile bit bdata SCAN_ON = 0 ; //按键扫描开关位,由定时器每20MS刷新
  40. volatile data MODE_ON = 0 ; //模式键按下后显示菜单
  41. volatile data INC_VALUE = 0 ;
  42. volatile data DEC_VALUE = 0 ;
  43. volatile bit bdata ALARM_VALUE = 0 ;//闹钟标志位
  44. volatile bit bdata ALARM_ON = 1 ; //闹钟响时关闭标志位
  45. volatile int data read_1 = 1,read_2 = 1,read_3 = 1,read_4 = 1;
  46.                                                          

  47. /****************************************************************
  48. 延时函数
  49. *****************************************************************/
  50. void delay_ms(uint16 count)        // 延时时间count*1ms
  51. {        uint16 i;
  52.         for(;count>0;count--)
  53.         {
  54.                 for(i=0;i<110;i++)
  55.                 {
  56.                         nop;
  57.                 }
  58.         }
  59. }
  60. /**********************************************************
  61. 蜂鸣器
  62. ************************************************************/
  63. void speakers(uint8 speak_count)
  64. {
  65.         for(;speak_count>0;speak_count--)
  66.                 {
  67.                         sp = 0 ;
  68.                         delay_ms(15) ;
  69.                         sp = 1 ;
  70.                         
  71.                 }
  72. }


  73. //底层驱动函数(输入)
  74. void DS1302_input(uint8 inputdata)
  75. {
  76.         ACC = inputdata ;
  77.         IO = a0 ; SCLK = 1 ; SCLK = 0 ;
  78.         IO = a1 ; SCLK = 1 ; SCLK = 0 ;
  79.         IO = a2 ; SCLK = 1 ; SCLK = 0 ;
  80.         IO = a3 ; SCLK = 1 ; SCLK = 0 ;
  81.         IO = a4 ; SCLK = 1 ; SCLK = 0 ;
  82.         IO = a5 ; SCLK = 1 ; SCLK = 0 ;
  83.         IO = a6 ; SCLK = 1 ; SCLK = 0 ;
  84.         IO = a7 ; SCLK = 1 ; SCLK = 0 ;
  85. }

  86. //底层驱动函数(输出)控制位的第七位必须为1
  87. uint8 DS1302_output(void)
  88. {
  89.         IO = 1 ;
  90.         a0 = IO ;
  91.         SCLK = 1 ; SCLK =0 ; a1 = IO ;
  92.         SCLK = 1 ; SCLK =0 ; a2 = IO ;
  93.          SCLK = 1 ; SCLK =0 ; a3 = IO ;
  94.     SCLK = 1 ; SCLK =0 ; a4 = IO ;
  95.     SCLK = 1 ; SCLK =0 ; a5 = IO ;
  96.     SCLK = 1 ; SCLK =0 ; a6 = IO ;
  97.     SCLK = 1 ; SCLK =0 ; a7 = IO ;
  98.         return(ACC);
  99. }
  100. //底层驱动函数(指定地址写一个字节的数据)
  101. void DS1302_write_byte(uint8 cmd , uint8 dat)
  102. {
  103.         SCLK = 0 ;
  104.         RST = 0 ;
  105.         RST = 1 ;
  106.         DS1302_input(cmd) ;
  107.         DS1302_input(dat) ;
  108.         RST = 0 ;
  109.         SCLK = 1 ;
  110. }
  111. //底层驱动函数(指定地址读取一字节的数据)
  112. uint8 DS1302_read_byte(int cmd)
  113. {
  114.         uint8 receivedata = 0 ;
  115.     SCLK = 0 ;
  116.         RST = 0 ;
  117.         RST = 1 ;
  118.         DS1302_input(cmd) ;
  119.         receivedata = DS1302_output() ;
  120.         RST = 0 ;
  121.         SCLK = 1 ;
  122.         return(receivedata) ;
  123. }

  124. //1302的初始数据
  125. void DS1302_init()
  126. {        
  127.                 if(DS1302_read_byte(0xef) != 0xf0) //检测初始化标志数据不为f0则初始化1302
  128.                 {                                                                                                                 
  129.                         DS1302_write_byte(0x8e,0x00) ;//允许写操作
  130.                         DS1302_write_byte(0xee,0xf0) ; //初始化标志
  131.                         DS1302_write_byte(0x8c,0x18) ;//年
  132.                         DS1302_write_byte(0x8a,0x01) ;//星期
  133.                         DS1302_write_byte(0x88,0x01) ;//月
  134.                         DS1302_write_byte(0x86,0x01) ;//日
  135.                         DS1302_write_byte(0x84,0x12) ;//时
  136.                         DS1302_write_byte(0x82,0x00) ;//分
  137.                         DS1302_write_byte(0x80,0x00) ;//秒
  138.                         DS1302_write_byte(0x90,0xa5) ;//充电

  139.                         DS1302_write_byte(0x8e,0x80) ;//禁止写操作         
  140.                 }
  141. }
  142. /********************************************************
  143. 读取时间数据并放在timedata[]中
  144. *********************************************************/
  145. void DS1302_read_time()
  146. {
  147.         timedata[0] = DS1302_read_byte(0x8d) ;        //年
  148.         timedata[1] = DS1302_read_byte(0x89) ;        //月
  149.         timedata[2] = DS1302_read_byte(0x87) ;        //日

  150.         timedata[3] = DS1302_read_byte(0x85) ;        //时
  151.         timedata[4] = DS1302_read_byte(0x83) ;        //分
  152.         timedata[5] = DS1302_read_byte(0x81) ;        //秒

  153.         timedata[6] = DS1302_read_byte(0x8b) ;        //星期
  154. }


  155. /***********************************************************
  156. DS18B20函数
  157. *************************************************************/
  158. void delay_18b20(int16 sum) //短暂延时
  159. {
  160.         while(sum--);
  161. }

  162. void rst_18b20()                 //18B20复位
  163. {        //uchar flag;
  164.         DQ=1;
  165.         delay_18b20(8);
  166.         DQ=0;
  167.         delay_18b20(80);
  168.         DQ=1;
  169.         delay_18b20(13);
  170.         //flag=DQ;
  171.         //return(flag);
  172. //        delay_18b20(20);
  173. }        


  174. void wr_18b20(int dat)        //写一个字节的数据
  175. {
  176.         uint8 i=8;
  177.         for(;i>0;i--)
  178.         {
  179.                 DQ=0;
  180.                 DQ=dat&0x01;
  181.                 delay_18b20(5);
  182.                 DQ=1;
  183.                 dat>>=1;
  184.         }        
  185. }

  186. uint8 rd_18b20()                //读一个字节的内容
  187. {
  188.         uint8 dat=0,i=8;
  189.         for(;i>0;i--)
  190.         {
  191.                 DQ=0;
  192.                 dat>>=1;
  193.                 DQ=1;
  194.                 if(DQ)
  195.                 dat|=0x80;
  196.                 delay_18b20(4);
  197.         }
  198.         return(dat);
  199. }
  200. uint16 rd_temperature()                //读取温度值
  201. {        
  202.         uint8 a=0,b=0;
  203.         uint16 t=0;
  204.         float tt=0;
  205.         rst_18b20();                //复位
  206.         wr_18b20(0xcc);                //跳过ROM
  207.         wr_18b20(0x44);                //启动温度转换
  208.         rst_18b20();                //再次对18B20操作时,需要重新复位一次
  209.         wr_18b20(0xcc);                //跳过ROM
  210.         wr_18b20(0xbe);                //读取内部RAM的内容
  211.         a=rd_18b20();                //读温度值低位(内部RAM的第0个字节)
  212.         b=rd_18b20();                //读温度值高位(内部RAM的第1个字节)
  213.         t=b;
  214.         t<<=8;                                //温度值的高8位放在t的高8位
  215.         t=t|a;                                //温度值的低8位放在t的低8位
  216.         if(t<0x0fff)                //判断温度值得正负值
  217.                    tflag=0;                //tflag=0温度值为正
  218.     else
  219.    {
  220.                 t=~t+1;                        //温度值为负,负值以补码形式存放,这里要将其还原成原码
  221.                 tflag=1;                //tflag=1温度值为负
  222.    }
  223.         tt=t*0.0625;
  224.         t = tt*100 ;                        
  225.         return(t);
  226.         
  227. }

  228. //***********************************************//



  229. void tem_conv()                        //温度转换
  230.                         {               
  231.                                 uint8 flagdat ;//定义温度值符号
  232.                                 if(tflag==0)
  233.                                 temdata[4]=flagdat=0x20;//温度为正不显示负号
  234.                                    else
  235.                                  temdata[4]=flagdat=0x2d;//负温度显示负号
  236.                                  temdata[0]=tdat/1000+0x30;//温度十位
  237.                              temdata[1]=tdat%1000/100+0x30;//温度个位
  238.                              temdata[2]=tdat%100/10+0x30;//小数十位
  239.                              temdata[3]=tdat%10+0x30;//小数百位
  240.                                 /*if(temdata[0]==0x30)
  241.                                     {temdata[0]=0x20;//?????0,???
  242.                                                    if(temdata[1]==0x30)
  243.                                             {
  244.                                                         temdata[1]=0x20;//?????0,???0????
  245.                                             }
  246.                                            }*/
  247.                                 
  248.                           }
  249.                         
  250. /**************************************************************
  251. 更新显示缓冲区
  252. ***************************************************************/
  253. void updata_buffer(void)
  254. {

  255. //显示日期
  256.         display_buffer1[0] = '2' ;
  257.         display_buffer1[1] = '0' ;
  258.         display_buffer1[2] = timedata[0]/16+0x30 ;                //年
  259.         display_buffer1[3] = timedata[0]%16+0x30 ;
  260.         display_buffer1[4] = 0 ;
  261.         display_buffer1[5] = timedata[1]/16+0x30 ;                //月
  262.         display_buffer1[6] = timedata[1]%16+0x30 ;
  263.         display_buffer1[7] = 0 ;
  264.         display_buffer1[8] = timedata[2]/16+0x30 ;                 //日
  265.         display_buffer1[9] = timedata[2]%16+0x30 ;
  266.         display_buffer1[10] = ' ' ;
  267.         display_buffer1[11] = ' ' ;
  268.         display_buffer1[12] = ' ' ;
  269.         switch(timedata[6]%16)                            //显示星期
  270.                 {        case 1 : {display_buffer1[13] = '1' ;
  271.                                         }break ;
  272.                         case 2 : {display_buffer1[13] = '2' ;
  273.                                         }break ;
  274.                         case 3 : {display_buffer1[13] = '3' ;
  275.                                         }break ;
  276.                         case 4 : {display_buffer1[13] = '4' ;
  277.                                         }break ;
  278.                         case 5 : {display_buffer1[13] = '5' ;
  279.                                         }break ;
  280.                         case 6 : {display_buffer1[13] = '6' ;
  281.                                         }break ;
  282.                         case 7 : {display_buffer1[13] = '7' ;
  283.                                         }break ;
  284.                         default : break;        }
  285.         display_buffer1[14] = ' ' ;
  286.         if(ALARM_VALUE == 1)
  287.                 display_buffer1[15] = 1 ;          //按下ok键显示定时标志
  288.         else
  289.     if(ALARM_VALUE == 0)
  290.                 display_buffer1[15] = 3 ;
  291.                                 
  292.                 //当前时间值
  293.         display_buffer2[0] = timedata[3]/16+0x30;                //时
  294.         display_buffer2[1] = timedata[3]%16+0x30;
  295.         display_buffer2[2] = ':' ;
  296.         display_buffer2[3] = timedata[4]/16+0x30 ;           //分
  297.         display_buffer2[4] = timedata[4]%16+0x30 ;
  298.         display_buffer2[5] = ':' ;
  299.         display_buffer2[6] = timedata[5]/16+0x30 ;           //秒
  300.         display_buffer2[7] = timedata[5]%16+0x30 ;
  301.                         
  302.                         //温度值
  303.         display_buffer2[8] = ' ' ;
  304.         display_buffer2[9] = temdata[4] ;                //负号
  305.         display_buffer2[10] = temdata[0] ;                //温度十位
  306.         display_buffer2[11] = temdata[1] ;                //温度个位
  307.         display_buffer2[12] = '.' ;
  308.         display_buffer2[13] = temdata[2] ;                //小数十位
  309.         display_buffer2[14] = temdata[3] ;           //小数百位
  310.         display_buffer2[15] = 'C' ;
  311. }

  312. /******************************************************************
  313. 显示缓冲区内容
  314. *******************************************************************/
  315. void display_buffer(void)
  316. {
  317.         uint8 i ;
  318.         send_command(0x80) ;        //显示第一行
  319.         for(i=0;i<16;i++)
  320.         send_data(display_buffer1[i]);
  321.         send_command(0xc0) ;   //显示第二行
  322.         for(i=0;i<16;i++)
  323.         send_data(display_buffer2[i]);
  324. }
  325. /*****************************************************************
  326. 按键扫描函数
  327. ******************************************************************/

  328. void key_scan(void)
  329. {
  330.         if(MODE == 0)
  331.                 {
  332.                         delay_ms(10) ;
  333.                         while(!MODE) ;
  334.                         speakers(5) ;
  335.                         DIS_ON = 0 ;
  336.                         MODE_ON ++ ;
  337.                         if(MODE_ON == 1 && OK_VALUE == 0)
  338.                         send_command(0x01);
  339.                         if(MODE_ON == 2 && OK_VALUE == 0)
  340.                                 {
  341.                                         MODE_ON = 0 ;
  342.                                         DIS_ON = 1 ;
  343.                                         self_pos = 0 ;
  344.                                 }
  345.                 }
  346.         
  347.         if(INC == 0 && MODE_ON == 1 && OK_VALUE == 0)
  348.                 {
  349.                         delay_ms(10) ;
  350.                         while(!INC) ;
  351.                         speakers(5) ;
  352.                         send_command(0x01) ;
  353.                         self_pos++ ;
  354.                         if(self_pos > 4)
  355.                         self_pos = 0 ;
  356.                 }
  357.         if(DEC == 0 && MODE_ON == 1 && OK_VALUE == 0)
  358.                 {
  359.                         delay_ms(10) ;
  360.                         while(!DEC) ;
  361.                         speakers(5) ;
  362.                         send_command(0x01) ;
  363.                         self_pos++ ;
  364.                         if(self_pos > 4)
  365.                         self_pos = 0 ;
  366.                 }
  367.         if(DEC == 0 )
  368.                 {
  369.                         delay_ms(10) ;
  370.                         while(!DEC) ;
  371.                         speakers(5) ;
  372.                         DEC_VALUE++;
  373.                 }
  374.         if(INC == 0)
  375.                 {
  376.                         delay_ms(10) ;
  377.                         while(!INC) ;
  378.                         speakers(5) ;
  379.                         INC_VALUE++;
  380.                 }
  381.         if(OK == 0 && MODE_ON != 0)
  382.                 {
  383.                         delay_ms(10) ;
  384.                         while(!OK) ;
  385.                         speakers(5) ;
  386.                         send_command(0x01) ;
  387.                         OK_VALUE++;
  388.                         INC_VALUE = 0 ;
  389.                         DEC_VALUE = 0 ;
  390.                 }
  391.         if(OK == 0 && MODE_ON == 0)
  392.                 {
  393.                         delay_ms(10) ;
  394.                         while(!OK) ;
  395.                         speakers(5) ;
  396.                         ALARM_ON = 1 ;
  397.                         if(ALARM_VALUE == 1)
  398.                                 ALARM_VALUE = 0 ;
  399.                         else
  400.                                 ALARM_VALUE = 1 ;
  401.                 }        
  402. }
  403. /*******************************************************************
  404. 按键菜单人机交互函数(第一级)
  405. ********************************************************************/
  406. void menu_display_1()
  407. {
  408.         if(MODE_ON == 1 && OK_VALUE == 0)
  409.                 {
  410.                         switch(self_pos)
  411.                                 {        
  412.                                         case 0 :  {
  413.                                                                 LCD1602_write_string(1,1,"Time  ") ;
  414.                                                                 LCD1602_write_string(1,0," Timing1 ") ;
  415.                                                           }break ;
  416.                                         case 1 :  {
  417.                                                                 LCD1602_write_string(1,1," Time  ") ;
  418.                                                                  LCD1602_write_string(1,0,"Timing1 ") ;
  419.                                                           }break ;
  420.                                         case 2 :  {
  421.                                                                 LCD1602_write_string(1,1," Timing1  ") ;
  422.                                                                 LCD1602_write_string(1,0,"Timing2") ;
  423.                                                           }break ;
  424.                                         case 3 :  {
  425.                                                                 LCD1602_write_string(1,1," Timing2  ") ;
  426.                                                                 LCD1602_write_string(1,0,"Timing3") ;
  427.                                                           }break ;
  428.                                         case 4 :  {
  429.                                                                 LCD1602_write_string(1,1," Timing3  ") ;
  430.                                                                 LCD1602_write_string(1,0,"Timing4") ;
  431.                                                           }break ;
  432.                                         default :  break ;
  433.                                 }        
  434.                 }
  435. }

  436. /*******************************************************************
  437. 按键菜单人机交互函数(第二级)
  438. ********************************************************************/
  439. void menu_display_2(void)
  440. {
  441.         uint8 i ,j;
  442.         if(MODE_ON != 0 && OK_VALUE != 0)
  443.                 {
  444.                         send_command(0x0f) ;
  445.                         if(self_pos == 0 )
  446.                                 {
  447.                                        
  448.                                         send_command(0x81) ;
  449.                                         for(i=0;i<15;i++)
  450.                                                 
  451. ……………………

  452. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


所有资料51hei提供下载:
8574and1602ti.rar (92.21 KB, 下载次数: 96)



评分

参与人数 2黑币 +55 收起 理由
lamyauhoi + 5
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:261837 发表于 2018-3-2 17:51 | 只看该作者
更新的源码!!!!

8574and1602ti.rar

95.54 KB, 下载次数: 76, 下载积分: 黑币 -5

回复

使用道具 举报

板凳
ID:228939 发表于 2018-6-23 00:27 | 只看该作者
感谢楼主,收藏了
回复

使用道具 举报

地板
ID:44889 发表于 2019-1-19 23:41 | 只看该作者
正在研究I2C接口的LCD1602程序怎么写,谢谢
回复

使用道具 举报

5#
ID:472104 发表于 2019-1-23 15:24 | 只看该作者
PCF8574LCD模块链接1602单片机51例程
回复

使用道具 举报

6#
ID:261837 发表于 2019-4-22 15:01 | 只看该作者
somexu 发表于 2019-1-19 23:41
正在研究I2C接口的LCD1602程序怎么写,谢谢

发送相应的数据就可以了;1602使用4线模式 占4位 es/rw/e 占3位 还有一位是背光的 参考电路就知道了。
回复

使用道具 举报

7#
ID:261837 发表于 2019-4-22 15:03 | 只看该作者
8574模块的电路

pcf8574模块电路.jpg (39.53 KB, 下载次数: 19)

pcf8574模块电路.jpg
回复

使用道具 举报

8#
ID:115740 发表于 2019-5-22 22:01 | 只看该作者
谢谢分享
回复

使用道具 举报

9#
ID:465596 发表于 2019-6-20 14:52 | 只看该作者
一下子就省了5个IO口   赞
谢谢分享
回复

使用道具 举报

10#
ID:465596 发表于 2019-6-23 20:22 | 只看该作者
要注意 pcf8574T 跟pcf8574AT的地址不一样。
回复

使用道具 举报

11#
ID:357396 发表于 2019-9-14 22:12 | 只看该作者
楼主,下载了你的程序后我的什么也没显示,是啥原因??地址我改了,背光也调过。[img]C:\Users\Administrator\Desktop[/img]
回复

使用道具 举报

12#
ID:677678 发表于 2020-1-2 21:59 | 只看该作者
somexu 发表于 2019-1-19 23:41
正在研究I2C接口的LCD1602程序怎么写,谢谢

我也在研究
回复

使用道具 举报

13#
ID:677678 发表于 2020-1-2 22:33 | 只看该作者
头文件??
回复

使用道具 举报

14#
ID:709013 发表于 2020-3-15 19:35 | 只看该作者
编译到倒数第二行出错是什么问题?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表