发新帖我要提问
12
返回列表
打印
[其他ST产品]

基于DS3231时钟模块的stm32 程序,源码

[复制链接]
楼主: 610u
手机看帖
扫描二维码
随时随地手机跟帖
21
610u|  楼主 | 2023-12-23 15:54 | 只看该作者 回帖奖励 |倒序浏览
二、与stm32通信
模块通过stm32模拟I2C信号通道,接在串口3或者4,下面上源码(串口3为例)

使用特权

评论回复
22
610u|  楼主 | 2023-12-23 15:54 | 只看该作者
1、配置IO
/**
  ******************************************************************************
  * @file    bsp_i2c_ds3231.h  
  * @author  兲涳
  * @version V1.0
  * @date    2020-11-16
  * @brief   i2c RTC(DS3231)应用函数bsp
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */
       
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __I2C_DS3231_H
#define        __I2C_DS3231_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "bsp_usart.h"
#include "stdio.h"


/* Exported types ------------------------------------------------------------*/
typedef struct
{
        int hour;
        int min;
        int sec;                       
        u32 year;
        int month;
        int date;
        int week;
        int temperature;
}_calendar_obj;       
extern _calendar_obj calendar;        //日历结构体

/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/**************************I2C参数定义,I2C1或I2C2*****************************/
#define _I2C1    1
#define _I2C2    0

#if _I2C1
#define                    DS3231_I2Cx                                I2C1
#define             DS3231_I2C_APBxClock_FUN                   RCC_APB1PeriphClockCmd
#define             DS3231_I2C_CLK                             RCC_APB1Periph_I2C1
#define             DS3231_I2C_GPIO_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define             DS3231_I2C_GPIO_CLK                        RCC_APB2Periph_GPIOC     
#define             DS3231_I2C_SCL_PORT                        GPIOC   
#define             DS3231_I2C_SCL_PIN                         GPIO_Pin_10
#define             DS3231_I2C_SDA_PORT                        GPIOC
#define             DS3231_I2C_SDA_PIN                         GPIO_Pin_11

#elif _I2C2
#define             DS3231_I2Cx                                I2C2
#define             DS3231_I2C_APBxClock_FUN                   RCC_APB1PeriphClockCmd
#define             DS3231_I2C_CLK                             RCC_APB1Periph_I2C2
#define             DS3231_I2C_GPIO_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define             DS3231_I2C_GPIO_CLK                        RCC_APB2Periph_GPIOB     
#define             DS3231_I2C_SCL_PORT                        GPIOB   
#define             DS3231_I2C_SCL_PIN                         GPIO_Pin_10
#define             DS3231_I2C_SDA_PORT                        GPIOB
#define                                DS3231_I2C_SDA_PIN                                                   GPIO_Pin_11

#endif

/* STM32 I2C 快速模式 */
#define             I2C_Speed                                                                                              400000  
/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */
#define                                                 I2Cx_OWN_ADDRESS7                                                                                      0X0A   
/* DS3231 地址定义 */
#define DS3231_ADDRESS                                                                                                                                                                  0xD0   


/*等待超时时间*/
#define I2CT_FLAG_TIMEOUT         ((uint32_t)0x1000)
#define I2CT_LONG_TIMEOUT         ((uint32_t)(10 * I2CT_FLAG_TIMEOUT))


/*信息输出*/
#define DS3231_DEBUG_ON         0

#define DS3231_INFO(fmt,arg...)           printf("<<-DS3231-INFO->> "fmt"\n",##arg)
#define DS3231_ERROR(fmt,arg...)          printf("<<-DS3231-ERROR->> "fmt"\n",##arg)
#define DS3231_DEBUG(fmt,arg...)          do{\
                                          if(DS3231_DEBUG_ON)\
                                          printf("<<-DS3231-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\
                                          }while(0)

/* DS3231寄存器地址 */
                                                                                                                                                                       
#define                                                        DS3231_SECOND                                                                                                                         0x00    //秒
#define                                                 DS3231_MINUTE                                                                                                       0x01    //分
#define                                                 DS3231_HOUR                                                                                                         0x02    //时
#define                                                 DS3231_WEEK                                                                                                  0x03    //星期
#define                                                 DS3231_DAY                                                                                                   0x04    //日
#define                                                 DS3231_MONTH                                                                                          0x05    //月
#define                                     DS3231_YEAR                                                                                                  0x06    //年
/* 闹铃1 */         
#define                                     DS3231_SALARM1ECOND                        0x07    //秒
#define                                                 DS3231_ALARM1MINUTE                        0x08    //分
#define                                     DS3231_ALARM1HOUR                          0x09    //时
#define                                                 DS3231_ALARM1WEEK                                                                                                   0x0A    //星期/日
/* 闹铃2 */
#define                                                 DS3231_ALARM2MINUTE                                                                                          0x0b    //分
#define                                                 DS3231_ALARM2HOUR                          0x0c    //时
#define                                                 DS3231_ALARM2WEEK                          0x0d    //星期/日

#define                                                 DS3231_CONTROL                             0x0e    //控制寄存器
#define                                                 DS3231_STATUS                              0x0f    //状态寄存器
#define                                                 BSY                                                                                                          2       //忙
#define                                                 OSF                                                                                                                 7       //振荡器停止标志
#define                                                 DS3231_XTAL                                                                                                  0x10    //晶体老化寄存器
#define                                                 DS3231_TEMPERATUREH                                                                                          0x11    //温度寄存器高字节(8位)
#define                                                 DS3231_TEMPERATUREL                                                                                          0x12    //温度寄存器低字节(高2位)                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                               
/* Exported functions ------------------------------------------------------- */                                                                                                                                                               
void I2C_DS3231_Init(void);                                                                                                                                                                                                                                                                                                                                       
uint32_t I2C_DS3231_ByteWrite(u8 WriteAddr, u8 data);        
uint8_t I2C_DS3231_DataRead(u8 ReadAddr);
void I2C_WaitDs3231StandbyState(void);                                                                                                                                                                 
uint8_t BCD_DEC(u8 val);               
uint8_t DEC_BCD(u8 val);

void I2C_DS3231_SetTime(u8 yea,u8 mon,u8 da,u8 we,u8 hou,u8 min,u8 sec);
void Time_Regulate_Get(_calendar_obj *tm);

void I2C_DS3231_getTime(void);
void I2C_DS3231_getTemperature(void);

void GregorianDay(_calendar_obj * tm);

#endif /* __I2C_DS3231_H */

/*********************************************END OF FILE**********************/

使用特权

评论回复
23
610u|  楼主 | 2023-12-23 15:55 | 只看该作者
2、初始化与函数/**
  ******************************************************************************
  * @file    bsp_i2c_ds3231.c
  * @author  兲涳
  * @version V1.0
  * @date    2020-11-16
  * @brief   i2c RTC(DS3231)应用函数bsp
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */  

/* Includes ------------------------------------------------------------------*/
#include "bsp_i2c_ds3231.h"

/* Private typedef -----------------------------------------------------------*/
_calendar_obj calendar;
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint32_t  I2CTimeout = I2CT_LONG_TIMEOUT;
static uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode);

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
  * @brief  转换成BCD码
  * @param  无
  * @retval 无
  */
u16 B_BCD(u8 val)
{
  u8 i,j,k;
  i=val/10;
  j=val%10;
  k=j+(i<<4);
  return k;
}

/**
  * @brief  I2C I/O配置
  * @param  无
  * @retval 无
  */
static void I2C_GPIO_Config(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
       
        /* 使能与 I2C 有关的时钟 */
        DS3231_I2C_APBxClock_FUN ( DS3231_I2C_CLK, ENABLE );
        DS3231_I2C_GPIO_APBxClock_FUN ( DS3231_I2C_GPIO_CLK, ENABLE );
       
        /* I2C_SCL、I2C_SDA*/
  GPIO_InitStructure.GPIO_Pin = DS3231_I2C_SCL_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;               // 开漏复用输出
  GPIO_Init(DS3231_I2C_SCL_PORT, &GPIO_InitStructure);
       
  GPIO_InitStructure.GPIO_Pin = DS3231_I2C_SDA_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;               //  开漏复用输出
  GPIO_Init(DS3231_I2C_SDA_PORT, &GPIO_InitStructure);               
}

/**
  * @brief  I2C 工作模式配置
  * @param  无
  * @retval 无
  */
static void I2C_Mode_Configu(void)
{
        I2C_InitTypeDef I2C_InitStructure;
        /* 通信速率 */
        I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
        /* I2C 配置 */
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        /* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        /* 地址设置 */
        I2C_InitStructure.I2C_OwnAddress1 = I2Cx_OWN_ADDRESS7;
        /* 使能应答 */
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        /* I2C的寻址模式 */
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        /* I2C 初始化 */
        I2C_Init(DS3231_I2Cx, &I2C_InitStructure);
        /* 使能 I2C */
  I2C_Cmd(DS3231_I2Cx, ENABLE);        
}

/**
  * @brief  I2C 外设(DS3231)初始化
  * @param  无
  * @retval 无
  */
void I2C_DS3231_Init(void)
{
  I2C_GPIO_Config();

  I2C_Mode_Configu();
}

/**
  * @brief        写一个字节到I2C DS3231中
  * @param   
  *                @ARG data:要写入的字节
  *                @arg WriteAddr:写地址
        * @retval 返回1,表示写入成功.
  */
uint32_t I2C_DS3231_ByteWrite(u8 WriteAddr, u8 data)
{
        /* 产生 I2C 起始信号 */
        I2C_GenerateSTART(DS3231_I2Cx, ENABLE);
        /* 设置超时等待时间 */
        I2CTimeout = I2CT_FLAG_TIMEOUT;  
        /* 检测 EV5 事件并清除标志*/
        while (!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
        {
                if ((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(0);
        }
       
        I2CTimeout = I2CT_FLAG_TIMEOUT;
        /* 发送 DS3231 设备地址 */
        I2C_Send7bitAddress(DS3231_I2Cx, DS3231_ADDRESS, I2C_Direction_Transmitter);
        /* 检测 EV6 事件并清除标志 */
  while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(1);
  }
       
  /* 发送要写入的 DS3231 内部地址(即 DS3231 内部存储器的地址) */
  I2C_SendData(DS3231_I2Cx, WriteAddr);
        I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* 检测 EV8 事件并清除标志 */
  while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(2);
  }
       
        /* 发送一字节要写入的数据 */
  I2C_SendData(DS3231_I2Cx, data);
        I2CTimeout = I2CT_FLAG_TIMEOUT;  
  /* 检测 EV8 事件并清除标志 */
  while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
  }
       
  /* 发送停止信号 */
  I2C_GenerateSTOP(DS3231_I2Cx, ENABLE);
       
        return 1;
}

/**
  * @brief        从DS3231里面读取一个字节数据
  * @param   
  *                @arg data:存放从DS3231读取的数据
  *                @arg ReadAddr:读取数据的DS3231的地址
        * @retval data:返回数据.
  */
uint8_t I2C_DS3231_DataRead(u8 ReadAddr)
{
        uint8_t data;
  I2CTimeout = I2CT_LONG_TIMEOUT;
  /* 等待空闲 */
  while(I2C_GetFlagStatus(DS3231_I2Cx, I2C_FLAG_BUSY))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(9);
  }
       
        /* 产生 I2C 起始信号 */
  I2C_GenerateSTART(DS3231_I2Cx, ENABLE);
        /* 设置超时等待时间 */
  I2CTimeout = I2CT_FLAG_TIMEOUT;
        /* 检测 EV5 事件并清除标志*/
        while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(10);
  }
       
        /* 发送 DS3231 设备地址,写 */
  I2C_Send7bitAddress(DS3231_I2Cx, DS3231_ADDRESS, I2C_Direction_Transmitter);
        /* 设置超时等待时间 */
  I2CTimeout = I2CT_FLAG_TIMEOUT;
        /* 检测 EV6 事件并清除标志 */
  while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(11);
  }
       
        /* 通过重新设置 PE 位清除 EV6 事件  */
  I2C_Cmd(DS3231_I2Cx, ENABLE);
       
  /* 发送要读取的 DS3231 内部地址(即 DS3231 内部存储器的地址) */
  I2C_SendData(DS3231_I2Cx, ReadAddr);
  /* 设置超时等待时间 */  
  I2CTimeout = I2CT_FLAG_TIMEOUT;
  /* 检测 EV8 事件并清除标志 */
  while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(12);
  }
       
        /* 产生第二次 I2C 起始信号 */  
  I2C_GenerateSTART(DS3231_I2Cx, ENABLE);
        /* 设置超时等待时间 */
  I2CTimeout = I2CT_FLAG_TIMEOUT;
        /* 检测 EV5 事件并清除标志*/
        while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(13);
  }
       
        /* 发送 DS3231 设备地址,读 */
        I2C_Send7bitAddress(DS3231_I2Cx, DS3231_ADDRESS, I2C_Direction_Receiver);
        /* 设置超时等待时间 */
  I2CTimeout = I2CT_FLAG_TIMEOUT;
        /* 检测 EV6 事件并清除标志 */
  while(!I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(14);
  }

        /* 发送非应答信号 */
        I2C_AcknowledgeConfig(DS3231_I2Cx, DISABLE);
       
        /* 发送停止信号 */
        I2C_GenerateSTOP(DS3231_I2Cx, ENABLE);

        /* 检测 EV7 事件并清除标志 */   
        I2CTimeout = I2CT_LONG_TIMEOUT;
       
        while(I2C_CheckEvent(DS3231_I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)  
        {
                if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
        }
         
        /* 通过 I2C,从设备中读取一个字节的数据 */
        data = I2C_ReceiveData(DS3231_I2Cx);     
       
        /* 使能应答,方便下一次 I2C 传输 */
        I2C_AcknowledgeConfig(DS3231_I2Cx, ENABLE);
       
        return data;
}

/**
  * @brief  等待 DS3231 到准备状态
  * @param  无
  * @retval 无
  */
void I2C_WaitDs3231StandbyState(void)      
{
  vu16 SR1_Tmp = 0;

  do
  {
    /* 发送起始信号 */
    I2C_GenerateSTART(DS3231_I2Cx, ENABLE);
    /* 读 I2C1 SR1 寄存器 */
    SR1_Tmp = I2C_ReadRegister(DS3231_I2Cx, I2C_Register_SR1);
    /* 发送 DS3231 地址 + 方向 */
    I2C_Send7bitAddress(DS3231_I2Cx, DS3231_ADDRESS, I2C_Direction_Transmitter);
  }while(!(I2C_ReadRegister(DS3231_I2Cx, I2C_Register_SR1) & 0x0002));
  
  /* 清除 AF 位 */
  I2C_ClearFlag(DS3231_I2Cx, I2C_FLAG_AF);
        /* 发送停止信号 */   
        I2C_GenerateSTOP(DS3231_I2Cx, ENABLE);
}

/**
  * @brief        BCD(8421)转DEC.
  * @param  val:BCD码.
  * @retval i:DEC码.
  */
uint8_t BCD_DEC(u8 val)
{
        u8 i;
        i= val&0x0f;
        val >>= 4;
        val &= 0x0f;
        val *= 10;
        i += val;   
        return i;
}

/**
  * @brief        BCD(8421)转DEC.
  * @param  val:DEC码.
  * @retval k:BCD码.
  */
uint8_t DEC_BCD(u8 val)
{
  u8 i,j,k;
  i=val/10;
  j=val%10;
  k=j+(i<<4);
  return k;
}

/**
  * @brief        超时报警处理.
  * @param  errorCode:错误代码,可以用来定位是哪个环节出错.
  * @retval 返回0,表示IIC读取失败.
  */
static  uint32_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{
  /* 使用串口 printf 输出错误信息,方便调试 */
  DS3231_ERROR("I2C 等待超时!errorCode = %d",errorCode);   
       
  return 0;
}

/**
  * @brief        时间设置
  * @param   
  *                @arg         分别输入 年 月 日 星期 时 分 秒
  * @retval 无
  */
void I2C_DS3231_SetTime(u8 yea,u8 mon,u8 da,u8 we,u8 hou,u8 min,u8 sec)
{
  u8 temp=0;
  
  temp=DEC_BCD(yea);
  I2C_DS3231_ByteWrite(0x06,temp);
  
  temp=DEC_BCD(mon);
  I2C_DS3231_ByteWrite(0x05,temp);
   
  temp=DEC_BCD(da);
  I2C_DS3231_ByteWrite(0x04,temp);
  
//        temp=DEC_BCD(we);
//  I2C_DS3231_ByteWrite(0x03,temp);
       
  temp=DEC_BCD(hou);
  I2C_DS3231_ByteWrite(0x02,temp);
  
  temp=DEC_BCD(min);
  I2C_DS3231_ByteWrite(0x01,temp);
  
  temp=DEC_BCD(sec);
  I2C_DS3231_ByteWrite(0x00,temp);
}       

/**
  * @brief        获取时间
  * @param   
  *                @arg pBuffer:存放从DS3231读取的数据的缓冲区指针
  *                @arg ReadAddr:读取数据的DS3231的地址
  *   @arg NumByteToWrite:要从DS3231读取的字节数
  * @retval 返回1,表示读取成功.
  */
void I2C_DS3231_getTime(void)
{
        calendar.year=I2C_DS3231_DataRead(0x06);  
        calendar.year=BCD_DEC(calendar.year);

        calendar.month=I2C_DS3231_DataRead(0x05);
        calendar.month=BCD_DEC(calendar.month);

        calendar.date=I2C_DS3231_DataRead(0x04);  
        calendar.date=BCD_DEC(calendar.date);

        calendar.week=I2C_DS3231_DataRead(0x03);  
        calendar.week=BCD_DEC(calendar.week);

        calendar.hour=I2C_DS3231_DataRead(0x02);
        calendar.hour&=0x3f;                  
        calendar.hour=BCD_DEC(calendar.hour);

        calendar.min=I2C_DS3231_DataRead(0x01);
        calendar.min=BCD_DEC(calendar.min);


        calendar.sec=I2C_DS3231_DataRead(0x00);
        calendar.sec=BCD_DEC(calendar.sec);
}

/**
  * @brief 保存用户使用串口设置的时间
  * @param   
  *                @arg tm:用于设置RTC时间的结构体指针
  * @retval
  */
void Time_Regulate_Get(_calendar_obj *tm)
{
          uint32_t temp_num = 0;
                uint8_t day_max=0 ;

          printf("\r\n=========================设置时间==================");
               
          do
          {
                        printf("\r\n  请输入年份(Please Set Years),范围[2000~2255],输入字符后请加回车:");
                        scanf("%d",&temp_num);
                        if(temp_num <2000 || temp_num >65535)
                        {
                                printf("\r\n 您输入的数字是:%d,不符合要求",temp_num);
                                          
                        }
                        else
                        {          
                                printf("\n\r  年份被设置为: %d\n\r", temp_num);
                        temp_num-=2000;
                                DEC_BCD(temp_num);
                                printf("\n\r  年份被设置为11: %d\n\r", temp_num);
                                tm->year = temp_num;
                                printf("year = %d  %d\n",calendar.year,temp_num);
                                break;
                        }
          }while(1);


         do
          {
                        printf("\r\n  请输入月份(Please Set Months):范围[1~12],输入字符后请加回车:");
                        scanf("%d",&temp_num);
                        if(temp_num <1 || temp_num >12)
                        {
                                printf("\r\n 您输入的数字是:%d,不符合要求",temp_num);
                                          
                        }
                        else
                        {          
                                printf("\n\r  月份被设置为: %d\n\r", temp_num);
        DEC_BCD(temp_num);
                                tm->month = temp_num;
                                break;
                        }
          }while(1);
               
                /*根据月份计算最大日期*/
                switch(tm->month)
                        {
                                case 1:
                                case 3:
                                case 5:
                                case 7:
                                case 8:
                                case 10:
                                case 12:                                       
                                                day_max = 31;
                                        break;
                               
                                case 4:
                                case 6:
                                case 9:
                                case 11:
                                                day_max = 30;
                                        break;
                               
                                case 2:                                       
                                     /*计算闰年*/
                                                if(((tm->year+2000)%4==0) &&
                                                         (((tm->year+2000)%100!=0) || ((tm->year+2000)%400==0)))
                                                                {
                                                                        day_max = 29;
                                                                } else
                                                                {
                                                                        day_max = 28;
                                                                }
                                        break;                       
                        }

                do
          {                               
                        printf("\r\n  请输入日期(Please Set Months),范围[1~%d],输入字符后请加回车:",day_max);
                        scanf("%d",&temp_num);
                       
                        if(temp_num <1 || temp_num >day_max)
                        {
                                printf("\r\n 您输入的数字是:%d,不符合要求",temp_num);
                        }
                        else
                        {
                                printf("\n\r  日期被设置为: %d\n\r", temp_num);
        DEC_BCD(temp_num);
                                tm->date = temp_num;
                                break;
                        }
          }while(1);
               
                GregorianDay( tm );
               
                do
          {                               
                        printf("\r\n  请输入时钟(Please Set Hours),范围[0~23],输入字符后请加回车:");
                        scanf("%d",&temp_num);
                       
                        if( temp_num >23)
                        {
                                printf("\r\n 您输入的数字是:%d,不符合要求",temp_num);
                        }
                        else
                        {
                                printf("\n\r  时钟被设置为: %d\n\r", temp_num);
        DEC_BCD(temp_num);
                                tm->hour = temp_num;
                                break;
                        }
          }while(1);

                do
          {                               
                        printf("\r\n  请输入分钟(Please Set Minutes),范围[0~59],输入字符后请加回车:");
                        scanf("%d",&temp_num);
                       
                        if( temp_num >59)
                        {
                                printf("\r\n 您输入的数字是:%d,不符合要求",temp_num);
                        }
                        else
                        {
                                printf("\n\r  分钟被设置为: %d\n\r", temp_num);
        DEC_BCD(temp_num);
                                tm->min = temp_num;
                                break;
                        }
          }while(1);

                do
          {                               
                        printf("\r\n  请输入秒钟(Please Set Seconds),范围[0~59],输入字符后请加回车:");
                        scanf("%d",&temp_num);
                       
                        if( temp_num >59)
                        {
                                printf("\r\n 您输入的数字是:%d,不符合要求",temp_num);
                        }
                        else
                        {
                                printf("\n\r  秒钟被设置为: %d\n\r", temp_num);
        DEC_BCD(temp_num);
                                tm->sec = temp_num;
                                break;
                        }
          }while(1);
                USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
}


/**
  * @brief        获取温度
  * @param  无
  * @retval 无
  */
void I2C_DS3231_getTemperature(void)
{
        I2C_DS3231_ByteWrite(DS3231_CONTROL, 0x20|0x05);
        calendar.temperature=I2C_DS3231_DataRead(DS3231_TEMPERATUREH);
}

/*计算公历天数得出星期*/
void GregorianDay(_calendar_obj * tm)
{
        int leapsToDate;
        int lastYear;
        int day;
        int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };

        lastYear=tm->year-1;

        /*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
        leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;      

     /*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/
        if((tm->year%4==0) &&
           ((tm->year%100!=0) || (tm->year%400==0)) &&
           (tm->month>2)) {
                /*
                 * We are past Feb. 29 in a leap year
                 */
                day=1;
        } else {
                day=0;
        }

        day += lastYear*365 + leapsToDate + MonthOffset[tm->month-1] + tm->date; /*计算从公元元年元旦到计数日期一共有多少天*/

        tm->week=day%7; //算出星期
}

/*********************************************END OF FILE**********************/

使用特权

评论回复
24
610u|  楼主 | 2023-12-23 15:55 | 只看该作者
3、主函数调用/**
  ******************************************************************************
  * @file    main.c
  * @author  兲涳
  * @version V1.0
  * @date    2020-11-16
  * @brief   
  ******************************************************************************
  * @attention
  * I2C_2 RTC(DS3231)测试,测试信息通过USART1打印在电脑调试助手上,通过串口设置时间
        * !!!串口输入  t  回车 ,进行设置时间。
  ******************************************************************************
  */  
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "bsp_usart.h"
#include "bsp_i2c_ds3231.h"
#include <string.h>

/* Private typedef -----------------------------------------------------------*/
uint8_t i=0;
extern _calendar_obj calendar;        //日历结构体

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define SOFT_DELAY                Delay(0x4FFFFF);

/* Private variables ---------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void Delay(__IO u32 nCount);

/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */
int main(void)
{
        /* 初始化USART 配置模式为 115200 8-N-1 */
  USART_Config();
  printf("\nDS3231   RTC时钟\n");
        /* I2C 外设初(DS3231)始化 */
        I2C_DS3231_Init();
//  I2C_DS3231_SetTime(20,8,24,1,13,43,20);
  while(1)
        {
                SOFT_DELAY;
                if(i==1)
                {
                        Time_Regulate_Get( &calendar );
                        I2C_DS3231_SetTime(calendar.year, calendar.month, calendar.date, calendar.week, calendar.hour, calendar.min, calendar.sec);
                        i=0;
                }
                I2C_DS3231_getTime();                //获取时间
                I2C_DS3231_getTemperature();                //获取温度
                printf("%d年%d月%d日%d时%d分%d秒 星期%d 温度%d\n",calendar.year+2000,calendar.month,calendar.date,\
                                                calendar.hour,calendar.min,calendar.sec,calendar.week,calendar.temperature);//打印到串口屏不能有printf("\n");换行!!!       
        }
}       

/**
  * @brief  延时函数
  * @param  无  
  * @retval 无
  */
void Delay(__IO uint32_t nCount)         //简单的延时函数
{
        for(; nCount != 0; nCount--);
}
/*********************************************END OF FILE**********************/

使用特权

评论回复
25
610u|  楼主 | 2023-12-23 15:55 | 只看该作者
4、使用
在串口工具上,输入t,即可进入设置时钟。该程序自动在串口上打印时间及温度

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则