//新时钟芯片搞定,读写都可以,在OLED屏和串口正常显示,温湿度参数和时间日期参数
制作出来的实物图如下:
电路原理图如下:
STC15W4K56S4单片机源程序如下:
- //** Descriptions:
- //------------------------------------------------------------------------------------
- #define MAIN_Fosc 11059200L //定义主时钟
- #include "15W4KxxS4.H"
- #include <intrins.h> // 加入此头文件后,可使用_nop_库函数
- #include <string.h> // 加入此头文件后,可使用strstr库函数
- #include "oled.h"
- #include "bmp.h"
- #include "AHT20.h"
- #include "stdio.h"
- #define uint8 unsigned char //0-256
- #define uint16 unsigned int //0-65535
- #define uint32 unsigned long //-100亿--+100亿
- #define BAUD 9600
- #define TM (65536 - (MAIN_Fosc/4/BAUD))
- #define Buf_Max 20 //串口7S1这里要设定到34,日期就可以正常显示了
- #define S2_S 0x01
- #define S2RI 0x01
- #define S2TI 0x02
- #define S3RI 0x01
- #define S3TI 0x02
- #define S4RI 0x01
- #define S4TI 0x02
- #define Write 0X64
- #define Read 0X65
- uint8 xdata Rec_Buf1[Buf_Max];//4个串口的接收缓存
- uint8 xdata Rec_Buf2[Buf_Max];
- uint8 xdata Rec_Buf3[Buf_Max];
- uint8 xdata Rec_Buf4[Buf_Max];
- uint8 i = 0; //串口3数组计数器
- uint8 j = 0; //串口4数组计数器
- #define ACK 0
- #define NOACK 1
- sbit RX8025SCL = P0^2;
- sbit RX8025SDA = P0^3;
- //extern u8 xdata RX8025TimeBuffH[];RX8025SDA
- u8 xdata RX8025YMD[]="2020-12-07"; //这里不设定参数,下面数组设
- u8 xdata RX8025HMS[]="12:34:56";
- u8 xdata RX8025TimeBuffH[]={11,24,9,4,8,12,23};//修改日期时钟,中间的是星期
- u8 xdata RX8025TImeBuffB[]={0X01,0X02,0X03,0X04,0X05,0X06,0X07};
- //----------------------------------------------------------------------------------------
- //-----------------------串口1初始化函数.注意该芯片有4个串口,1口中断优先级最高
- void Uart1_Init(void)
- {
- SCON = 0x50; //8位数据,可变波特率
- AUXR |= 0x40; //定时器时钟1T模式
- AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
- TMOD &= 0x0F; //设置定时器模式
- TL1 = 0xE0; //设置定时初始值
- TH1 = 0xFE; //设置定时初始值
- ET1 = 0; //禁止定时器中断
- TR1 = 1; //定时器
- }
- //---------------------------------- 串口1发送数据函数
- void SendDataByUart1(uint8 dat)
- {
- SBUF = dat; //写数据到UART数据寄存器
- while(TI == 0); //在停止位没有发送时,TI为0即一直等待
- TI = 0; //清除TI位(该位必须软件清零)
- }
- //------------------------===========串口1发送字符串函数
- void SendStringByUart1(uint8 *s)
- {
- while(*s)
- {
- SendDataByUart1(*s++);//将字符串中的字符一个一个发送
- }
- }
- //----------------------清除串口1缓存内容函数
- void CLR_Buf1(void)
- {
- uint8 k;
- for(k=0;k<Buf_Max;k++) //将串口1缓存数组的值都清为零
- {
- Rec_Buf1[k] = 0;
- }
- i = 0;
- }
- //-----------------------------------串口1握手判断函数
- bit Hand1(uint8 *a)
- {
- if(strstr(Rec_Buf1,a)!=NULL) //判断字符串a是否是字符串Rec_Buf1的子串
- return 1; //如果字符串a是字符串Rec_Buf1的子串
- else
- return 0; //如果字符串a不是字符串Rec_Buf1的子串
- }
- //------------------------------------下面串口1接收中断-----------------------
- void Uart1() interrupt UART1_VECTOR using 1
- {
- ES = 0; // 串口1中断关闭
- if (RI) //串行接收到停止位的中间时刻时,该位置1
- {
- RI = 0; //清除RI位 (该位必须软件清零)
- Rec_Buf1[i] = SBUF; //把串口1缓存SBUF寄存器数据依次存放到数组Rec_Buf1中
- i++;
- if(i>Buf_Max) //接收数大于定义接收数组最大个数时,覆盖接收数组之前值
- {
- i = 0;
- }
- }
- ES = 1; // 串口1中断打开
- }
- //================================================================================
- //----------------------------------------------------------------------------------------
- /*********BCD码转十六进制************/
- u8 BCDtoHEX(u8 BCD )
- {
- return ( ( (BCD/16)*10) +BCD%16 );
- }
- /**********十六进制转BCD码*************/
- u8 HEXtoBCD(u8 Hex)
- {
- return ( ((Hex/10)<<4) +Hex%10 );
- }
- /*********I2C延时***********/
- void I2CWait()
- {
- u8 i;
- for(i=0;i<10;i++)
- {
- _nop_();_nop_();_nop_();_nop_();
- }
- }
- bit I2C_Start2()
- {
- RX8025SDA = 1; //释放总线
- RX8025SCL = 1;
- I2CWait();
- if(!RX8025SDA) return 0; //总线忙退出
- RX8025SDA = 0;
- I2CWait();
- while(RX8025SDA) return 0; //总线为高电平则总线出错,退出
- RX8025SCL = 0;
- I2CWait();
- //return 1;
- }
- void I2C_Stop()
- {
- RX8025SCL = 0;
- RX8025SDA = 0;
- I2CWait();
- RX8025SCL = 1;
- I2CWait();
- RX8025SDA = 1;
- }
- /********主机向从机发送ACK****
- a=0,发送ACk a=1,发送NO ACK
- ******************************/
- void I2CSendACK(u8 a)
- {
- RX8025SDA = a;
- RX8025SCL = 0;
- I2CWait();
- RX8025SCL = 1;
- I2CWait();
- RX8025SCL = 0;
- }
- /*********主机读取从机ACK信号***/
- bit I2CReceivedACK()
- {
- u8 errtime=255;
- RX8025SCL = 0;
- RX8025SDA = 1; //释放总线
- I2CWait();
- RX8025SCL = 1;
- I2CWait();
- while(RX8025SDA) //读取 SDA上的电平,变为低电平,即有从机回复ACK信号
- {
- errtime--;
- if(!errtime) //超时退出
- {
- RX8025SCL=0;
- return 0;
- }
- }
- RX8025SCL=0;
- return 1;
- }
- /******************************************
- 主机向从机发送一字节数据-->dat
- order=0:先发送LSB,最后发送MSB
- order=1:先发送MSB;最后发送LSB
- 之所以设置order这个入口参数,是为了程序方便
- 移植,适应多个IIC芯片,只需设置order就能改变
- 数据传输方向,RX8025芯片 order 一直为 1
- ******************************************/
- void IIC_Send_Byte(u8 dat, bit order)
- {
- u8 i;
- if(order)
- {
- for(i=0;i<8;i++)
- {
- RX8025SDA = dat&0X80;
- RX8025SCL = 1;
- I2CWait();
- RX8025SCL = 0;
- dat<<=1;
- I2CWait();
- }
- }
- else
- {
- for(i=0;i<8;i++)
- {
- RX8025SDA = dat&0X01;
- RX8025SCL = 1;
- I2CWait();
- RX8025SCL = 0;
- dat>>=1;
- I2CWait();
- }
- }
- }
- /*********读取一字节数据*********
- order=0:先读取LSB,最后读取MSB
- order=1:先去读MSB,最后读取LSB
- ********************************/
- u8 IIC_Receive_Byte(bit order)
- {
- u8 i,j,Rdat;
- RX8025SDA = 1; //释放总线
- if(order) //MSB-->LSB
- {
- for(i=0;i<8;i++)
- {
- RX8025SCL = 0;
- I2CWait();
- Rdat =( Rdat<<1 )| RX8025SDA;
- RX8025SCL = 1;
- I2CWait();
- }
- }
- else //LSB-->MSB
- {
- for(i=0;i<8;i++)
- {
- RX8025SCL = 0;
- I2CWait();
- j=RX8025SDA;
- Rdat =( Rdat>>1 )| (j<<7);
- RX8025SCL = 1;
- I2CWait();
- }
- }
- RX8025SCL=0;
- return Rdat;
- }
- /******读取RX8025一个寄存器的数据*****/
- //u8 Read_RX8025_Byte(u8 add)
- //{
- // u8 Ridat;
- // I2C_Start2();
- // IIC_Send_Byte(Write,1);
- // if(!I2CReceivedACK()) //判断有无ACK信号
- // I2C_Stop();
- // IIC_Send_Byte(add,1);
- // if(!I2CReceivedACK()) //判断有无ACK信号
- // I2C_Stop();
- //
- // I2C_Start2();
- // IIC_Send_Byte(Read,1);
- // if(!I2CReceivedACK()) //判断有无ACK信号
- // I2C_Stop();
- // Ridat = IIC_Receive_Byte(1); //读取数据
- // I2CSendACK(1);
- // I2C_Stop();
- // return Ridat;
- //}
- //--单独向一个寄存器写数据
- void Write_RX8025_Byt(u8 add,u8 dat)
- {
- u8 Bdat;
- Bdat = dat;
- //Bdat = HEXtoBCD(dat); //将十六进制转换为BCD码
- //---开始写入数据
- I2C_Start2();
- IIC_Send_Byte(Write,1);
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- IIC_Send_Byte(add<<4,1); //--根据手册在写入时地址要右移4位
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- IIC_Send_Byte(Bdat,1);
- I2CReceivedACK();
- I2C_Stop();
- }
- //--连续读取时间、日历数据--
- //--add:读取的起始地址
- //--Num:读取数据的个数
- //--标准IIC连续读寄存器时序
- void Read_RX8025_Dat(u8 add, u8 Num)
- {
- u8 i;
- //---先写读寄存器地址
- I2C_Start2();
- IIC_Send_Byte(Write,1);
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- IIC_Send_Byte(add,1); //秒寄存器地址
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- //---连续读取数据
- I2C_Start2();
- IIC_Send_Byte(Read,1);
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- for(i=0;i<Num;i++)
- {
- RX8025TImeBuffB[i] = IIC_Receive_Byte(1); //读取数据
- if(i!=6)I2CSendACK(0);
- }
- I2CSendACK(1);
- I2C_Stop();
- for(i=0;i<Num;i++)
- {
- RX8025TimeBuffH[i] = BCDtoHEX(RX8025TImeBuffB[i]);
- }
- }
- /*****向RX8025连续写num个数据******/
- void Write_RX8025_Byte(u8 add,u8 *Buff)
- {
- u8 i;
- //---先写读寄存器地址
- I2C_Start2();
- IIC_Send_Byte(Write,1);
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- IIC_Send_Byte(add<<4,1);
- if(!I2CReceivedACK()) //判断有无ACK信号
- I2C_Stop();
- for(i=0;i<7;i++) //--连续写入7个时间日历数据
- {
- Buff[i] = HEXtoBCD(Buff[i]);
- IIC_Send_Byte(Buff[i],1);
- I2CReceivedACK();
- }
- I2C_Stop();
- }
- void RX8025_Init()
- {
- //--12/24小时寄存器地址为0X0E,
- Write_RX8025_Byt(0X0E,0X20); //RX8025-T 24小时制
- // Write_RX8025_Byt(0X0E,0X00); //RX8025-T 12小时制
- }
- void DisplayTime()
- {
- //--显示RX8025的时间
- Read_RX8025_Dat(0,7);
- RX8025YMD[2] = RX8025TimeBuffH[6]/10; //+0X30; 年
- RX8025YMD[3] = RX8025TimeBuffH[6]%10; //+0X30;
-
- RX8025YMD[5] = RX8025TimeBuffH[5]/10; //+0X30; 月
- RX8025YMD[6] = RX8025TimeBuffH[5]%10; //+0X30;
-
- RX8025YMD[8] = RX8025TimeBuffH[4]/10;// +0X30; 日
- RX8025YMD[9] = RX8025TimeBuffH[4]%10; //+0X30;
-
- RX8025HMS[0] = RX8025TimeBuffH[2]/10;// +0X30; 时
- RX8025HMS[1] = RX8025TimeBuffH[2]%10; //+0X30;
-
- RX8025HMS[3] = RX8025TimeBuffH[1]%100/10; //+0X30; 分
- RX8025HMS[4] = RX8025TimeBuffH[1]%10;// +0X30;
-
- RX8025HMS[6] = RX8025TimeBuffH[0]%100/10; //+0X30; 秒
- RX8025HMS[7] = RX8025TimeBuffH[0]%10; //+0X30;
- // Write_ASCII3X16_N(0,7,0,"T3:RX8025");
- // Write_ASCII3X16_N(0,8,0,RX8025YMD);
- // Write_ASCII3X16_N(2,9,0,RX8025HMS); Write_6x16Font_N(12,9,0,WeekD);
- }
- //==============================================================================
- int main()
- {
- uint32 CT_data[2];
- volatile float c1,t1;
- //
- P0M0=0x00,P0M1=0x00;//我自己加的代码 3
- P2M0=0x00,P2M1=0x00;//我自己加的代码 3
- P1M0=0x00,P1M1=0x00;//我自己加的代码 3
- P4M0=0x00,P4M1=0x00;//我自己加的代码 3
- P5M0=0x00,P5M1=0x00;//我自己加的代码
- Uart1_Init();
- delay_msT(500);//①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms
- WDT_CONTR = 0x35;//
- OLED_Init(); //注意OLED的数据线正好在15W4K56的P06,P07端口,先等这两个IO打开才能正常启动OLED
- RX8025_Init();
- Write_RX8025_Byte(0,RX8025TimeBuffH);//RX8025时钟芯片里写入日期时间参数,2020-5-1-12:00:00,
- if((AHT20_Read_Status()&0x18)!=0x18)//②上电第一次发0x71读取状态字,判断状态字是否为0x18,如果不是0x18,进行寄存器初始化
- {
- AHT20_Start_Init(); //重新初始化寄存器
- delay_msT(10);
- }
-
- while(1)//③根据客户自己需求发测量命令读取温湿度数据,当前while(1)循环发测量命令读取温湿度数据,仅供参考
- { WDT_CONTR = 0x35;//
- AHT20_Read_CTdata_crc(CT_data); //crc校验后,读取AHT20的温度和湿度数据
- c1 = ((float)CT_data[0]/1024/1024)*100; //计算得到湿度值c1放大10倍
- t1 = ((float)CT_data[1]/1024/1024)*200-50;//计算得到温度值t1放大10倍
-
- DisplayTime();
- OLED_ShowString(0,0,"T=",8);//
- OLED_ShowString(60,0,"H=",8);//
- OLED_ShowNum(16,0,t1,4,12);//温度
- OLED_ShowNum(76,0,c1,4,12);//湿度
-
-
- OLED_ShowNum(0,1,2,1,12);// 年 2
- OLED_ShowNum(8,1,0,1,12);// 年 0
- OLED_ShowNum(16,1,RX8025YMD[2],1,12);// 年 2
- OLED_ShowNum(24,1,RX8025YMD[3],1,12);// 年 3
-
- OLED_ShowNum(32,1,RX8025YMD[5],1,12);// 月
- OLED_ShowNum(40,1,RX8025YMD[6],1,12);// 月
- OLED_ShowNum(48,1,RX8025YMD[8],1,12);// 日 3
- OLED_ShowNum(56,1,RX8025YMD[9],1,12);// 日 3
- OLED_ShowString(64,1,"-",8);//
-
- OLED_ShowNum(76,1,RX8025HMS[0],1,12);// 时 十位 1
- OLED_ShowNum(84,1,RX8025HMS[1],1,12);// 时 个位 2
- OLED_ShowNum(92,1,RX8025HMS[3],1,12);// 分 十位 3
- OLED_ShowNum(100,1,RX8025HMS[4],1,12);//分 个位 4
- OLED_ShowNum(108,1,RX8025HMS[6],1,12);//秒 十位 5
- OLED_ShowNum(116,1,RX8025HMS[7],1,12);//秒 个位 6
-
- SendDataByUart1(0x32);
- SendDataByUart1(0x30);
- SendDataByUart1(RX8025YMD[2]+0x30);//串口发 年
- SendDataByUart1(RX8025YMD[3]+0x30);
- SendDataByUart1(0x20);//发空格
- SendDataByUart1(RX8025YMD[5]+0x30);//串口发 月
- SendDataByUart1(RX8025YMD[6]+0x30);
- SendDataByUart1(0x20);
- SendDataByUart1(RX8025YMD[8]+0x30);//串口发 日
- SendDataByUart1(RX8025YMD[9]+0x30);
- SendDataByUart1(0x20);
- SendDataByUart1(RX8025HMS[0]+0x30);//串口发 时
- SendDataByUart1(RX8025HMS[1]+0x30);//
- SendDataByUart1(0x3a);//发冒号
- SendDataByUart1(RX8025HMS[3]+0x30);//串口发 分
- SendDataByUart1(RX8025HMS[4]+0x30);//
- SendDataByUart1(0x3a);
- SendDataByUart1(RX8025HMS[6]+0x30);//串口发 秒
- SendDataByUart1(RX8025HMS[7]+0x30);//
-
-
- delay_msT(4000);
- delay_msT(4000);
- }
- }
复制代码 STC15W单片机同时驱动温湿度AHT20 时钟RX8025
原理图: 无
仿真: 无
代码:
程序.7z
(74.71 KB, 下载次数: 31)
|