STC单片机C51程序读时钟芯片RX8025T,发串口显示

  
//STC15W4K56S4单片机读写时钟芯片RX8025T,可以在OLED屏和串口显示参数,单片机用内部11.0592晶震,串口9600,N.8.1. 直接复制代码就能跑起来,很方便,代码都在main函数里,方便大家学习和移植到其他IDE,这个电路板也是我设计的,上面还有个温湿度传感器,AHT20.需要图纸和驱动可联系我,赵科17717361475/2023.12.8
//** Descriptions:                       
//------------------------------------------------------------------------------------
#define MAIN_Fosc        11059200L    //定义主时钟
#include    "15W4KxxS4.H"
#include <intrins.h>         // 加入此头文件后,可使用_nop_库函数
#include <string.h>           // 加入此头文件后,可使用strstr库函数
#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);

}   

//========================================================================

void delay_msT(uint16 i)    //延时 i ms,不是十分精准,当i大于58时误差会超过1ms
{
    for(;i>0;i--)
    {    
        delay_1ms();
        WDT_CONTR = 0x35;//
    
    }
}

//----------------------------------------------------------------------------------------------------
int main()
{
    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();
  
     RX8025_Init();
     Write_RX8025_Byte(0,RX8025TimeBuffH);//RX8025时钟芯片里写入日期时间参数,2020-5-1-12:00:00,

         while(1)
    {      WDT_CONTR = 0x35;//喂狗

         
           DisplayTime();

        
      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);
    
    
     }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值