找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机驱动温湿度芯片AHT20和RX8025时钟芯片

[复制链接]
跳转到指定楼层
楼主
//新时钟芯片搞定,读写都可以,在OLED屏和串口正常显示,温湿度参数和时间日期参数

制作出来的实物图如下:



电路原理图如下:


STC15W4K56S4单片机源程序如下:
  1. //** Descriptions:                       
  2. //------------------------------------------------------------------------------------
  3. #define MAIN_Fosc        11059200L    //定义主时钟
  4. #include    "15W4KxxS4.H"
  5. #include <intrins.h>         // 加入此头文件后,可使用_nop_库函数
  6. #include <string.h>           // 加入此头文件后,可使用strstr库函数
  7. #include "oled.h"
  8. #include "bmp.h"
  9. #include "AHT20.h"
  10. #include "stdio.h"
  11. #define  uint8 unsigned char  //0-256
  12. #define  uint16  unsigned int //0-65535
  13. #define  uint32  unsigned long  //-100亿--+100亿


  14. #define BAUD 9600               
  15. #define TM (65536 - (MAIN_Fosc/4/BAUD))   
  16. #define Buf_Max 20    //串口7S1这里要设定到34,日期就可以正常显示了
  17. #define S2_S  0x01   

  18. #define S2RI 0x01
  19. #define S2TI 0x02

  20. #define S3RI 0x01
  21. #define S3TI 0x02

  22. #define S4RI 0x01
  23. #define S4TI 0x02

  24. #define Write 0X64
  25. #define Read  0X65

  26. uint8 xdata Rec_Buf1[Buf_Max];//4个串口的接收缓存     
  27. uint8 xdata Rec_Buf2[Buf_Max];     
  28. uint8 xdata Rec_Buf3[Buf_Max];      
  29. uint8 xdata Rec_Buf4[Buf_Max];

  30. uint8 i = 0; //串口3数组计数器            
  31. uint8 j = 0; //串口4数组计数器

  32. #define ACK 0
  33. #define NOACK 1
  34. sbit RX8025SCL = P0^2;
  35. sbit RX8025SDA = P0^3;

  36. //extern u8 xdata RX8025TimeBuffH[];RX8025SDA        

  37. u8 xdata RX8025YMD[]="2020-12-07"; //这里不设定参数,下面数组设
  38. u8 xdata RX8025HMS[]="12:34:56";

  39. u8 xdata RX8025TimeBuffH[]={11,24,9,4,8,12,23};//修改日期时钟,中间的是星期
  40. u8 xdata RX8025TImeBuffB[]={0X01,0X02,0X03,0X04,0X05,0X06,0X07};

  41. //----------------------------------------------------------------------------------------
  42. //-----------------------串口1初始化函数.注意该芯片有4个串口,1口中断优先级最高
  43. void Uart1_Init(void)
  44. {   
  45.            SCON = 0x50;                //8位数据,可变波特率
  46.         AUXR |= 0x40;                //定时器时钟1T模式
  47.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  48.         TMOD &= 0x0F;                //设置定时器模式
  49.         TL1 = 0xE0;                        //设置定时初始值
  50.         TH1 = 0xFE;                        //设置定时初始值
  51.         ET1 = 0;                        //禁止定时器中断
  52.         TR1 = 1;                        //定时器
  53. }
  54. //---------------------------------- 串口1发送数据函数
  55. void SendDataByUart1(uint8 dat)
  56. {
  57.     SBUF = dat;                 //写数据到UART数据寄存器
  58.         while(TI == 0);             //在停止位没有发送时,TI为0即一直等待
  59.         TI = 0;                     //清除TI位(该位必须软件清零)
  60. }
  61. //------------------------===========串口1发送字符串函数

  62. void SendStringByUart1(uint8 *s)
  63. {
  64.     while(*s)
  65.     {
  66.         SendDataByUart1(*s++);//将字符串中的字符一个一个发送
  67.     }
  68. }
  69. //----------------------清除串口1缓存内容函数

  70. void CLR_Buf1(void)
  71. {
  72.     uint8 k;
  73.     for(k=0;k<Buf_Max;k++)      //将串口1缓存数组的值都清为零
  74.         {
  75.                Rec_Buf1[k] = 0;
  76.           }
  77.     i = 0;                    
  78. }
  79. //-----------------------------------串口1握手判断函数
  80. bit Hand1(uint8 *a)
  81. {
  82.     if(strstr(Rec_Buf1,a)!=NULL)     //判断字符串a是否是字符串Rec_Buf1的子串
  83.         return 1;                      //如果字符串a是字符串Rec_Buf1的子串
  84.       else
  85.           return 0;                      //如果字符串a不是字符串Rec_Buf1的子串
  86. }

  87. //------------------------------------下面串口1接收中断-----------------------

  88. void Uart1() interrupt UART1_VECTOR using 1
  89. {
  90.     ES = 0;                       // 串口1中断关闭
  91.     if (RI)                       //串行接收到停止位的中间时刻时,该位置1
  92.   {
  93.       RI = 0;                     //清除RI位 (该位必须软件清零)
  94.             Rec_Buf1[i] = SBUF;       //把串口1缓存SBUF寄存器数据依次存放到数组Rec_Buf1中
  95.             i++;                     
  96.         if(i>Buf_Max)             //接收数大于定义接收数组最大个数时,覆盖接收数组之前值
  97.                 {   

  98.                     i = 0;                 
  99.                 }           
  100.    }

  101.      ES =  1;                   // 串口1中断打开
  102. }
  103. //================================================================================
  104. //----------------------------------------------------------------------------------------
  105. /*********BCD码转十六进制************/
  106. u8 BCDtoHEX(u8 BCD )
  107. {
  108.         return ( ( (BCD/16)*10) +BCD%16 );
  109. }

  110. /**********十六进制转BCD码*************/
  111. u8  HEXtoBCD(u8 Hex)
  112. {
  113.         return  ( ((Hex/10)<<4) +Hex%10 );
  114. }

  115. /*********I2C延时***********/
  116. void I2CWait()
  117. {        
  118.         u8 i;
  119.         for(i=0;i<10;i++)
  120.         {
  121.                 _nop_();_nop_();_nop_();_nop_();
  122.         }
  123. }

  124. bit I2C_Start2()
  125. {
  126.         RX8025SDA = 1;        //释放总线
  127.         RX8025SCL = 1;
  128.         I2CWait();
  129.         if(!RX8025SDA)        return 0;        //总线忙退出
  130.         RX8025SDA = 0;
  131.         I2CWait();
  132.         while(RX8025SDA) return 0;        //总线为高电平则总线出错,退出
  133.         RX8025SCL = 0;
  134.         I2CWait();
  135.         //return 1;
  136. }

  137. void I2C_Stop()
  138. {
  139.         RX8025SCL = 0;
  140.         RX8025SDA = 0;
  141.         I2CWait();
  142.         RX8025SCL = 1;
  143.         I2CWait();
  144.         RX8025SDA = 1;        
  145. }

  146. /********主机向从机发送ACK****
  147. a=0,发送ACk        a=1,发送NO ACK
  148. ******************************/
  149. void I2CSendACK(u8 a)
  150. {
  151.         RX8025SDA = a;
  152.         RX8025SCL = 0;
  153.         I2CWait();
  154.         RX8025SCL = 1;
  155.         I2CWait();
  156.         RX8025SCL = 0;
  157. }

  158. /*********主机读取从机ACK信号***/
  159. bit I2CReceivedACK()
  160. {
  161.         u8 errtime=255;
  162.         RX8025SCL = 0;
  163.         RX8025SDA = 1;        //释放总线
  164.         I2CWait();
  165.         RX8025SCL = 1;
  166.         I2CWait();
  167.         while(RX8025SDA)        //读取 SDA上的电平,变为低电平,即有从机回复ACK信号
  168.         {
  169.                 errtime--;
  170.                 if(!errtime)        //超时退出
  171.                 {
  172.                         RX8025SCL=0;
  173.                         return 0;
  174.                 }
  175.         }
  176.         RX8025SCL=0;
  177.         return 1;
  178. }

  179. /******************************************
  180. 主机向从机发送一字节数据-->dat
  181. order=0:先发送LSB,最后发送MSB
  182. order=1:先发送MSB;最后发送LSB
  183. 之所以设置order这个入口参数,是为了程序方便
  184. 移植,适应多个IIC芯片,只需设置order就能改变
  185. 数据传输方向,RX8025芯片 order 一直为 1
  186. ******************************************/
  187. void IIC_Send_Byte(u8 dat, bit order)
  188. {
  189.         u8 i;
  190.         if(order)
  191.         {
  192.                 for(i=0;i<8;i++)
  193.                 {
  194.                         RX8025SDA = dat&0X80;
  195.                         RX8025SCL = 1;
  196.                         I2CWait();
  197.                         RX8025SCL = 0;
  198.                         dat<<=1;
  199.                         I2CWait();
  200.                 }
  201.         }
  202.         else
  203.         {
  204.                 for(i=0;i<8;i++)
  205.                 {
  206.                         RX8025SDA = dat&0X01;
  207.                         RX8025SCL = 1;
  208.                         I2CWait();
  209.                         RX8025SCL = 0;
  210.                         dat>>=1;
  211.                         I2CWait();
  212.                 }
  213.         }
  214. }

  215. /*********读取一字节数据*********
  216. order=0:先读取LSB,最后读取MSB
  217. order=1:先去读MSB,最后读取LSB
  218. ********************************/
  219. u8 IIC_Receive_Byte(bit order)
  220. {
  221.         u8 i,j,Rdat;
  222.         RX8025SDA = 1;        //释放总线
  223.         if(order)        //MSB-->LSB
  224.         {
  225.                 for(i=0;i<8;i++)
  226.                 {
  227.                         RX8025SCL = 0;
  228.                         I2CWait();
  229.                         Rdat =( Rdat<<1 )| RX8025SDA;
  230.                         RX8025SCL = 1;
  231.                         I2CWait();
  232.                 }
  233.         }
  234.         else        //LSB-->MSB
  235.         {
  236.                 for(i=0;i<8;i++)
  237.                 {
  238.                         RX8025SCL = 0;
  239.                         I2CWait();
  240.                         j=RX8025SDA;
  241.                         Rdat =( Rdat>>1 )| (j<<7);
  242.                         RX8025SCL = 1;
  243.                         I2CWait();
  244.                 }
  245.         }
  246.         RX8025SCL=0;
  247.         return Rdat;
  248. }

  249. /******读取RX8025一个寄存器的数据*****/
  250. //u8 Read_RX8025_Byte(u8 add)
  251. //{
  252. //        u8 Ridat;
  253. //        I2C_Start2();
  254. //        IIC_Send_Byte(Write,1);
  255. //        if(!I2CReceivedACK())        //判断有无ACK信号
  256. //                I2C_Stop();
  257. //        IIC_Send_Byte(add,1);
  258. //        if(!I2CReceivedACK())        //判断有无ACK信号
  259. //                I2C_Stop();
  260. //        
  261. //        I2C_Start2();
  262. //        IIC_Send_Byte(Read,1);
  263. //        if(!I2CReceivedACK())        //判断有无ACK信号
  264. //                I2C_Stop();
  265. //        Ridat = IIC_Receive_Byte(1);        //读取数据
  266. //        I2CSendACK(1);
  267. //        I2C_Stop();
  268. //        return Ridat;
  269. //}

  270. //--单独向一个寄存器写数据
  271. void Write_RX8025_Byt(u8 add,u8 dat)
  272. {
  273.         u8 Bdat;
  274.         Bdat = dat;
  275.         //Bdat = HEXtoBCD(dat);        //将十六进制转换为BCD码
  276. //---开始写入数据               
  277.         I2C_Start2();
  278.         IIC_Send_Byte(Write,1);
  279.         if(!I2CReceivedACK())        //判断有无ACK信号
  280.                 I2C_Stop();
  281.         IIC_Send_Byte(add<<4,1);        //--根据手册在写入时地址要右移4位
  282.         if(!I2CReceivedACK())        //判断有无ACK信号
  283.                 I2C_Stop();
  284.         IIC_Send_Byte(Bdat,1);
  285.         I2CReceivedACK();
  286.         I2C_Stop();
  287. }

  288. //--连续读取时间、日历数据--
  289. //--add:读取的起始地址
  290. //--Num:读取数据的个数
  291. //--标准IIC连续读寄存器时序
  292. void Read_RX8025_Dat(u8 add, u8 Num)
  293. {
  294.         u8 i;
  295. //---先写读寄存器地址
  296.         I2C_Start2();
  297.         IIC_Send_Byte(Write,1);
  298.         if(!I2CReceivedACK())        //判断有无ACK信号
  299.                 I2C_Stop();
  300.         IIC_Send_Byte(add,1);        //秒寄存器地址
  301.         if(!I2CReceivedACK())        //判断有无ACK信号
  302.                 I2C_Stop();
  303. //---连续读取数据        
  304.         I2C_Start2();
  305.         IIC_Send_Byte(Read,1);
  306.         if(!I2CReceivedACK())        //判断有无ACK信号
  307.                 I2C_Stop();
  308.         for(i=0;i<Num;i++)
  309.         {
  310.                 RX8025TImeBuffB[i] = IIC_Receive_Byte(1);        //读取数据
  311.                 if(i!=6)I2CSendACK(0);
  312.         }
  313.         I2CSendACK(1);
  314.         I2C_Stop();
  315.         for(i=0;i<Num;i++)
  316.         {
  317.                 RX8025TimeBuffH[i] = BCDtoHEX(RX8025TImeBuffB[i]);
  318.         }
  319. }

  320. /*****向RX8025连续写num个数据******/
  321. void Write_RX8025_Byte(u8 add,u8 *Buff)
  322. {
  323.         u8 i;
  324. //---先写读寄存器地址
  325.         I2C_Start2();
  326.         IIC_Send_Byte(Write,1);
  327.         if(!I2CReceivedACK())        //判断有无ACK信号
  328.                 I2C_Stop();
  329.         IIC_Send_Byte(add<<4,1);
  330.         if(!I2CReceivedACK())        //判断有无ACK信号
  331.                 I2C_Stop();
  332.         for(i=0;i<7;i++)        //--连续写入7个时间日历数据
  333.         {
  334.                 Buff[i] = HEXtoBCD(Buff[i]);
  335.                 IIC_Send_Byte(Buff[i],1);
  336.                 I2CReceivedACK();
  337.         }
  338.         I2C_Stop();
  339. }

  340. void RX8025_Init()
  341. {
  342. //--12/24小时寄存器地址为0X0E,
  343.         Write_RX8025_Byt(0X0E,0X20);                //RX8025-T                24小时制
  344. //        Write_RX8025_Byt(0X0E,0X00);                //RX8025-T                12小时制
  345. }

  346. void DisplayTime()
  347. {

  348. //--显示RX8025的时间
  349.         Read_RX8025_Dat(0,7);        

  350.         RX8025YMD[2] = RX8025TimeBuffH[6]/10; //+0X30; 年
  351.         RX8025YMD[3] = RX8025TimeBuffH[6]%10; //+0X30;
  352.         
  353.         RX8025YMD[5] = RX8025TimeBuffH[5]/10; //+0X30;         月
  354.         RX8025YMD[6] = RX8025TimeBuffH[5]%10; //+0X30;
  355.         
  356.         RX8025YMD[8] = RX8025TimeBuffH[4]/10;// +0X30; 日
  357.         RX8025YMD[9] = RX8025TimeBuffH[4]%10; //+0X30;
  358.         
  359.         RX8025HMS[0] = RX8025TimeBuffH[2]/10;// +0X30;         时
  360.         RX8025HMS[1] = RX8025TimeBuffH[2]%10; //+0X30;
  361.         
  362.         RX8025HMS[3] = RX8025TimeBuffH[1]%100/10; //+0X30; 分
  363.         RX8025HMS[4] = RX8025TimeBuffH[1]%10;// +0X30;
  364.         
  365.         RX8025HMS[6] = RX8025TimeBuffH[0]%100/10; //+0X30; 秒
  366.         RX8025HMS[7] = RX8025TimeBuffH[0]%10; //+0X30;        

  367. //        Write_ASCII3X16_N(0,7,0,"T3:RX8025");
  368. //        Write_ASCII3X16_N(0,8,0,RX8025YMD);        
  369. //        Write_ASCII3X16_N(2,9,0,RX8025HMS);        Write_6x16Font_N(12,9,0,WeekD);

  370. }   

  371. //==============================================================================
  372. int main()
  373. {
  374.   uint32 CT_data[2];
  375.         volatile float  c1,t1;
  376.         //
  377.         P0M0=0x00,P0M1=0x00;//我自己加的代码 3
  378.         P2M0=0x00,P2M1=0x00;//我自己加的代码 3
  379.         P1M0=0x00,P1M1=0x00;//我自己加的代码 3
  380.         P4M0=0x00,P4M1=0x00;//我自己加的代码 3
  381.         P5M0=0x00,P5M1=0x00;//我自己加的代码

  382.         Uart1_Init();
  383.         delay_msT(500);//①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms
  384.          WDT_CONTR = 0x35;//        
  385.          OLED_Init(); //注意OLED的数据线正好在15W4K56的P06,P07端口,先等这两个IO打开才能正常启动OLED   
  386.      RX8025_Init();
  387.          Write_RX8025_Byte(0,RX8025TimeBuffH);//RX8025时钟芯片里写入日期时间参数,2020-5-1-12:00:00,

  388.         if((AHT20_Read_Status()&0x18)!=0x18)//②上电第一次发0x71读取状态字,判断状态字是否为0x18,如果不是0x18,进行寄存器初始化
  389.         {
  390.         AHT20_Start_Init(); //重新初始化寄存器
  391.         delay_msT(10);
  392.         }
  393.         

  394.         while(1)//③根据客户自己需求发测量命令读取温湿度数据,当前while(1)循环发测量命令读取温湿度数据,仅供参考
  395.         {          WDT_CONTR = 0x35;//

  396.       AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据
  397.           c1 = ((float)CT_data[0]/1024/1024)*100;  //计算得到湿度值c1放大10倍
  398.       t1 = ((float)CT_data[1]/1024/1024)*200-50;//计算得到温度值t1放大10倍
  399.            
  400.                DisplayTime();

  401.           OLED_ShowString(0,0,"T=",8);//
  402.       OLED_ShowString(60,0,"H=",8);//
  403.             OLED_ShowNum(16,0,t1,4,12);//温度        
  404.           OLED_ShowNum(76,0,c1,4,12);//湿度        
  405.         
  406.          
  407.           OLED_ShowNum(0,1,2,1,12);// 年 2
  408.       OLED_ShowNum(8,1,0,1,12);// 年 0
  409.           OLED_ShowNum(16,1,RX8025YMD[2],1,12);// 年 2
  410.           OLED_ShowNum(24,1,RX8025YMD[3],1,12);// 年 3
  411.          
  412.       OLED_ShowNum(32,1,RX8025YMD[5],1,12);// 月
  413.           OLED_ShowNum(40,1,RX8025YMD[6],1,12);// 月

  414.           OLED_ShowNum(48,1,RX8025YMD[8],1,12);// 日 3         
  415.       OLED_ShowNum(56,1,RX8025YMD[9],1,12);// 日 3
  416.             OLED_ShowString(64,1,"-",8);//
  417.          
  418.           OLED_ShowNum(76,1,RX8025HMS[0],1,12);// 时 十位 1         
  419.           OLED_ShowNum(84,1,RX8025HMS[1],1,12);// 时 个位 2
  420.           OLED_ShowNum(92,1,RX8025HMS[3],1,12);// 分 十位 3         
  421.           OLED_ShowNum(100,1,RX8025HMS[4],1,12);//分 个位 4
  422.           OLED_ShowNum(108,1,RX8025HMS[6],1,12);//秒 十位 5         
  423.           OLED_ShowNum(116,1,RX8025HMS[7],1,12);//秒 个位 6
  424.          
  425.           SendDataByUart1(0x32);
  426.           SendDataByUart1(0x30);
  427.           SendDataByUart1(RX8025YMD[2]+0x30);//串口发 年        
  428.           SendDataByUart1(RX8025YMD[3]+0x30);
  429.                 SendDataByUart1(0x20);//发空格
  430.       SendDataByUart1(RX8025YMD[5]+0x30);//串口发 月        
  431.           SendDataByUart1(RX8025YMD[6]+0x30);
  432.                   SendDataByUart1(0x20);
  433.           SendDataByUart1(RX8025YMD[8]+0x30);//串口发 日        
  434.           SendDataByUart1(RX8025YMD[9]+0x30);
  435.                 SendDataByUart1(0x20);

  436.           SendDataByUart1(RX8025HMS[0]+0x30);//串口发 时
  437.           SendDataByUart1(RX8025HMS[1]+0x30);//
  438.                  SendDataByUart1(0x3a);//发冒号
  439.           SendDataByUart1(RX8025HMS[3]+0x30);//串口发 分
  440.           SendDataByUart1(RX8025HMS[4]+0x30);//
  441.                  SendDataByUart1(0x3a);
  442.           SendDataByUart1(RX8025HMS[6]+0x30);//串口发 秒
  443.           SendDataByUart1(RX8025HMS[7]+0x30);//
  444.                                  
  445.                
  446.                 delay_msT(4000);
  447.                  delay_msT(4000);
  448.          }

  449. }
复制代码
STC15W单片机同时驱动温湿度AHT20 时钟RX8025
原理图: 无
仿真: 无
代码: 程序.7z (74.71 KB, 下载次数: 31)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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