找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机+DS1302+DHT11+LCD1602做的万年历源程序

  [复制链接]
跳转到指定楼层
楼主
闲来无事,做的万年历。时间设定、闹钟定时功能版本的万年历后面再发。

电路原理图如下:


单片机源程序如下:
  1. #include "reg52.h"
  2. #include "intrins.h"
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit Dat=P2^0;
  6. sbit RS=P2^6;
  7. sbit RW=P2^5;
  8. sbit EN=P2^7;
  9. sbit CE=P3^5;
  10. sbit DSIO=P3^4;
  11. sbit SCL=P3^6;
  12. uchar code talble[]="0123456789";
  13. uchar  read[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};                //存放秒、分、小时、日期、月份、周、年的读寄存器命令字
  14. uchar  time[]={0x21,0x53,0x15,0x18,0x09,0x05,0x20};                //放置初始的秒、分、小时、日期、月份、周、年的BCD码
  15. uchar num0=0,num1=0,num2=0;
  16. void delayms(uint z)        //12MHz时,z=1约为1ms
  17. {
  18.         uint x,y;
  19.         for(x=z;x>0;x--)
  20.                 for(y=122;y>0;y--);
  21. }
  22. void delayus(uchar z)                //12MHz时,z=1约为17us
  23. {
  24.         while(z--);
  25. }
  26. /************************************按键*************************************/
  27. //待写
  28. /******************************DHT11温湿度传感器********************************/
  29. uchar Read_Byte()
  30. {
  31.         uchar m,n,sum;
  32.         for(m=0;m<8;m++)
  33.         {
  34.                 while(!Dat);        //每个数据前面会有一个50us的低电平,等待50us结束
  35.                 delayus(3);                //延时50us后检测电平
  36.                 sum<<=1;                //循环左移,左移放在判断数据是0或者1的前面,数据读出正确
  37.                 n=Dat;                //读数据
  38.                 if(n==1)
  39.                 {
  40.                         sum=sum|0x01;
  41.                         while(!Dat);        //等待高电平结束
  42.                 }
  43.                 else
  44.                 {
  45.                         sum=sum|0x00;
  46.                 }
  47.                 delayus(3);
  48.         }
  49.         return (sum);
  50. }
  51. void dht11()
  52. {
  53.         uchar m0,m1,m2,m3,m4;
  54.         Dat=1;
  55.         delayms(1);
  56.         Dat=0;                                //拉低单总线
  57.         delayms(20);                //至少保持18ms
  58.         Dat=1;                        //拉高总线,等待接收DHT11应答信号
  59.         delayus(3);                //主机发送开始信号后,等待20~40u后,检测DHT11应答信号
  60.         if(Dat==0)                //检测DHT11是否有应答信号,当DHT11检测到信号后,首先将总线拉低约80us,然后再拉高80us作为应答信号
  61.         {
  62.                 while(!Dat);                //检测到应答信号,等待应答信号结束
  63.                 while(Dat);                        //发送响应信号后,再把总线拉高约80us,准备发送数据,这里是等待开始
  64.                 m0=Read_Byte();                //读取湿度整数数据
  65.                 m1=Read_Byte();                //读取湿度小数数据
  66.                 m2=Read_Byte();                //读取温度整数数据
  67.                 m3=Read_Byte();                //读取温度小数数据
  68.                 m4=Read_Byte();                //读取校验和
  69.         }
  70.         if(m4==(m0+m1+m2+m3))                //校验数据,正确的话更新数据,错误的话保持数据不变
  71.         {
  72.                 num0=m0;
  73.                 num1=m2;
  74.         }
  75.         else
  76.         {
  77.                 num0=num0;
  78.                 num1=num1;
  79.         }
  80. }
  81. /************************************DS1302*************************************/
  82. void Ds1302_Write_Byte(uchar addr,uchar dat)                        //向某个地址写入一个字节数据
  83. {
  84.         uchar i;
  85.         CE=0;                                        //CE引脚为低,数据传送中指
  86.         SCL=0;                                //清零时钟总线
  87.         CE=1;                                        //CE为高,逻辑控制有效
  88.         for(i=0;i<8;i++)        //发送地址,循环8次移位
  89.         {
  90.                 DSIO=addr&0x01;        //每次传输低位字节
  91.                 addr>>=1;                                        //数据位右移1位
  92.                 SCL=1;                //上升沿将数据送入DS1302
  93.                 _nop_();
  94.                 SCL=0;
  95.                 _nop_();
  96.         }
  97.         for(i=0;i<8;i++)        //发送数据位
  98.         {
  99.                 DSIO=dat&0x01;
  100.                 dat>>=1;
  101.                 SCL=1;
  102.                 _nop_();
  103.                 SCL=0;
  104.                 _nop_();
  105.         }
  106.         CE=0;
  107. }
  108. uchar Ds1302_Read_Byte(uchar addr)                        //读取某个地址的数据
  109. {
  110.         uchar i,dat0,dat1;
  111.         CE=0;                                        //CE置低电平,初始化
  112.         SCL=0;                                //SCL置低电平,初始化
  113.         CE=1;                                        //启动DS1302总线,CE拉高
  114.         for(i=0;i<8;i++)
  115.         {
  116.                 DSIO=addr&0x01;                //按位与运算,取出addr的最低位,并将其赋给DSIO
  117.                 addr>>=1;                                //将地址右移一位,低位抛弃,高位补0
  118.                 SCL=1;                                        //开始SCL为低电平,现在置高,产生一个上升沿,数据被写入DS1302,数据要先写入,然后再发送
  119.                 _nop_();
  120.                 SCL=0;                                        //将SCL置低,为下次写入数据做准备
  121.                 _nop_();
  122.         }
  123.         for(i=0;i<8;i++)
  124.         {
  125.                 dat0=DSIO;
  126.                 dat1=(dat1>>1)|(dat0<<7);
  127.                 SCL=1;
  128.                 _nop_();
  129.                 SCL=0;
  130.                 _nop_();
  131.         }
  132.         CE=0;
  133.         SCL=1;
  134.         DSIO=0;
  135.         DSIO=1;
  136.         return dat1;
  137. }
  138. void DS1302_Init()
  139. {
  140.         Ds1302_Write_Byte(0x8e,0x00);                //关闭写保护寄存器
  141.         Ds1302_Write_Byte(0x80,0x21);                //秒位初始化
  142.         Ds1302_Write_Byte(0x82,0x53);                //分钟初始化
  143.         Ds1302_Write_Byte(0x84,0x15);                //小时初始化
  144.         Ds1302_Write_Byte(0x86,0x18);                //日期初始化
  145.         Ds1302_Write_Byte(0x88,0x09);                //月份初始化
  146.         Ds1302_Write_Byte(0x8a,0x05);                //周初始化
  147.         Ds1302_Write_Byte(0x8c,0x20);                //年初始化
  148.         Ds1302_Write_Byte(0x8e,0x80);                //允许写保护        
  149. }
  150. void Read_time()
  151. {
  152.         uchar i;
  153.         for(i=0;i<7;i++)
  154.         {
  155.                 time[i]=Ds1302_Read_Byte(read[i]);
  156.         }
  157. }
  158. /************************************闹钟*************************************/
  159. //待写
  160. /**********************************1602液晶*************************************/
  161. bit Busy()
  162. {
  163.         bit bsy;
  164.         RS=0;
  165.         RW=1;
  166.         EN=1;
  167.         _nop_();
  168.         _nop_();
  169.         _nop_();
  170.         _nop_();
  171.         bsy=(bit)(P0&0x80);
  172.         EN=0;
  173.         return (bsy);
  174. }
  175. void Wr_com(uchar com)
  176. {
  177.         while(Busy());
  178.         RS=0;
  179.         RW=0;
  180.         P0=com;
  181.         delayus(1);
  182.         EN=1;
  183.         EN=0;
  184. }
  185. void Wr_dat(uchar dat)
  186. {
  187.         while(Busy());
  188.         RS=1;
  189.         RW=0;
  190.         P0=dat;
  191.         delayus(1);
  192.         EN=1;
  193.         EN=0;
  194. }
  195. void LCD_Init()
  196. {
  197.         Wr_com(0x38);
  198.         Wr_com(0x0C);
  199.         Wr_com(0x06);
  200.         Wr_com(0x01);
  201. }
  202. void display()
  203. {
  204.         Wr_com(0x80);
  205.         Wr_dat('2');
  206.         Wr_dat('0');
  207.         Wr_dat('0'+time[6]/16);                                //年
  208.         Wr_dat('0'+(time[6]&0x0f));
  209.         Wr_dat('-');                                                        //-
  210.         Wr_dat('0'+time[4]/16);                                //月
  211.         Wr_dat('0'+(time[4]&0x0f));        
  212.         Wr_dat(0xb0);                                                        //-
  213.         Wr_dat('0'+time[3]/16);                                //日
  214.         Wr_dat('0'+(time[3]&0x0f));

  215.         Wr_com(0x80+0x0b);
  216.         Wr_dat('0'+(time[5]&0x0f));                //星期

  217.         Wr_com(0x80+0x0d);                                                        
  218.         Wr_dat(talble[num0/10]);                        //湿度
  219.         Wr_dat(talble[num0%10]);
  220.         Wr_dat(0x25);                                                        //%

  221.         Wr_com(0xC0);
  222.         Wr_dat('0'+time[2]/16);                                //时
  223.         Wr_dat('0'+(time[2]&0x0f));        
  224.         Wr_dat(0x3a);                                                        //:
  225.         Wr_dat('0'+time[1]/16);                                //分
  226.         Wr_dat('0'+(time[1]&0x0f));
  227.         Wr_dat(0x3a);                                                        //:
  228.         Wr_dat('0'+time[0]/16);                                //秒
  229.         Wr_dat('0'+(time[0]&0x0f));
  230.         
  231.         Wr_com(0xC0+0x0a);
  232.         Wr_dat(talble[num1/10]);                        //温度
  233.         Wr_dat(talble[num1%10]);
  234.         Wr_dat(0x2e);                                                        //.
  235.         Wr_dat(talble[0]);
  236.         Wr_dat(0xdf);                                                        //
  237.         Wr_dat(0x43);                                                        //C        
  238. }
  239. void main()
  240. {
  241.         uint a;
  242.         LCD_Init();
  243.         DS1302_Init();
  244.         while(1)
  245.         {
  246.                 a++;
  247.                 if(a==20)
  248.                 {
  249.                       a=0;
  250.                       dht11();
  251.                  }
  252.                 Read_time();
  253.                 display();
  254.         }

  255. }
复制代码


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:1017804 发表于 2022-4-12 15:30 | 只看该作者
有没有电路图啊
回复

使用道具 举报

板凳
ID:1013894 发表于 2022-12-5 22:09 | 只看该作者
大神想看看闹钟版本的
回复

使用道具 举报

地板
ID:1013894 发表于 2022-12-5 22:41 | 只看该作者
为啥我仿真的情况是这样子的。。

捕获.PNG (70.26 KB, 下载次数: 20)

捕获.PNG
回复

使用道具 举报

5#
ID:1013894 发表于 2022-12-6 12:52 | 只看该作者
vjack 发表于 2022-12-5 22:41
为啥我仿真的情况是这样子的。。

调完电压后,LCD1602没有显示
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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