G
N
I
D
A
O
L

STM8驱动RTC芯片DS1302

使用软件:IAR FOR STM8

编程方式:固件库

硬件配套:STM8S105C6T6实验板

1. DS1302.h

  • 引脚定义
  • 函数封装
  • 时间数据结构体定义
  • 数据缓冲区定义
#ifndef __DS1302_H
#define __DS1302_H

/****************************驱动 RTC 芯片 DS1302******************************/

/* Includes ------------------------------------------------------------------*/

#include "stm8s.h"

/* Defines -------------------------------------------------------------------*/

#define RTC_RESET_TIME_EN       0u

#define RTC_SCK_PORT            (GPIOD)         
#define RTC_SCK_PIN             (GPIO_PIN_2)            // PD2
#define RTC_SCK_HIGH()          GPIO_WriteHigh(RTC_SCK_PORT, RTC_SCK_PIN)
#define RTC_SCK_LOW()           GPIO_WriteLow (RTC_SCK_PORT, RTC_SCK_PIN)

#define RTC_IO_PORT             (GPIOD)
#define RTC_IO_PIN              (GPIO_PIN_3)            // PD3

#define RTC_IO_IN()             GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_IN_PU_NO_IT)
#define RTC_IO_STATUS()         GPIO_ReadInputPin(RTC_IO_PORT, RTC_IO_PIN)

#define RTC_IO_OUT()            GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW) 
#define RTC_IO_HIGH()           GPIO_WriteHigh(RTC_IO_PORT, RTC_IO_PIN)
#define RTC_IO_LOW()            GPIO_WriteLow (RTC_IO_PORT, RTC_IO_PIN)

#define RTC_RST_PORT            (GPIOD)
#define RTC_RST_PIN             (GPIO_PIN_7)            // PD7
#define RTC_RST_HIGH()          GPIO_WriteHigh(RTC_RST_PORT, RTC_RST_PIN)
#define RTC_RST_LOW()           GPIO_WriteLow (RTC_RST_PORT, RTC_RST_PIN)

/* Values --------------------------------------------------------------------*/

typedef struct Time
{
  uint8_t year;         // year       0-99 
  uint8_t month;        // month      01-12
  uint8_t day;          // day        01-28,29,30,31
  uint8_t week;         // week       01-07
  uint8_t hour;         // hour       01-12 or 00-23
  uint8_t minute;       // minute     00-59
  uint8_t second;       // second     00-59
}TimeTypeDef;

static TimeTypeDef TimeBuffer;   // 数据缓冲区(8421-BCD码)

/* Functions -----------------------------------------------------------------*/

void DS1302_Init (void);

static void    DS1302_WriteByte (uint8_t byte);
static uint8_t DS1302_ReadByte  (void);
static void    DS1302_WriteData (uint8_t addr, uint8_t data);
static uint8_t DS1302_ReadData  (uint8_t addr);

TimeTypeDef DS1302_ReadTime  (void);
void        DS1302_WriteTime (TimeTypeDef *TimeDisplay);

static uint8_t DectoBCD (uint8_t num);
static uint8_t BCDtoDec (uint8_t num);

static void DS1302_DLY_ms(uint16_t nCount);
static void DS1302_DLY_us(uint16_t nCount);

#endif /* __DS1302_H */

2. DS1302.c

  • 引脚初始化
  • 数据传输协议实现
  • BCD 码和十进制数互相转换
  • 数据处理
#include "ds1302.h"

/*************************************************************************
                                初始化
--------------------------------------------------------------------------
无参数
--------------------------------------------------------------------------
无返回值
*************************************************************************/
void DS1302_Init (void)
{
  GPIO_Init(RTC_SCK_PORT, RTC_SCK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW);
  GPIO_Init(RTC_RST_PORT, RTC_RST_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW);
  GPIO_Init(RTC_IO_PORT,  RTC_IO_PIN,  GPIO_MODE_OUT_PP_HIGH_SLOW);
  
  RTC_SCK_LOW();
  RTC_IO_LOW();
  RTC_RST_LOW();
}

/*************************************************************************
                              写一字节数据
--------------------------------------------------------------------------
byte:一字节数据
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_WriteByte (uint8_t byte)
{
  uint8_t i;
  BitStatus bit;
  
  RTC_IO_OUT();         // IO 配置为输出模式
  
  for (i = 0; i < 8; i++)
  {
    RTC_SCK_LOW();
    
    bit = (BitStatus)(byte & 0x01);
    if (bit != RESET)
      RTC_IO_HIGH();
    else
      RTC_IO_LOW();
    
    RTC_SCK_HIGH();
    byte >>= 1;
    
    //DS1302_DLY_ms(1);
  }
}

/*************************************************************************
                              读一字节数据
--------------------------------------------------------------------------
addr:地址
--------------------------------------------------------------------------
返回值:一字节数据
*************************************************************************/
static uint8_t DS1302_ReadByte (void)
{
  uint8_t i;
  uint8_t data = 0;
  BitStatus bit;
  
  RTC_IO_IN();          // IO 配置为输入模式
  
  for (i = 0; i < 8; i++)
  {
    data >>= 1;
    RTC_SCK_LOW();
    
    bit = RTC_IO_STATUS();
    if (bit != RESET)
      data |= 0x80;
    else
      data &= 0x7F;
    
    RTC_SCK_HIGH();
    
    //DS1302_DLY_ms(1);
  }
  
  return data;
}

/*************************************************************************
                      往指定寄存器写入一字节数据
--------------------------------------------------------------------------
addr:地址  data:一字节数据
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_WriteData (uint8_t addr, uint8_t data)
{
  // 数据传输开始
  RTC_RST_LOW();
  RTC_SCK_LOW();
  RTC_RST_HIGH();
  
  DS1302_WriteByte (addr);      // 写入的地址
  DS1302_WriteByte (data);      // 写入的数据
  
  // 数据传输结束
  RTC_RST_LOW();
}

/*************************************************************************
                      在指定寄存器读出一字节数据
--------------------------------------------------------------------------
addr:地址
--------------------------------------------------------------------------
返回值:一字节数据
*************************************************************************/
static uint8_t DS1302_ReadData (uint8_t addr)
{
  uint8_t data;
  
  // 数据传输开始
  RTC_RST_LOW();
  RTC_SCK_LOW();
  RTC_RST_HIGH();
  
  DS1302_WriteByte (addr);      // 要读的地址
  data = DS1302_ReadByte();     // 要读的数据
  
  // 数据传输结束
  RTC_RST_LOW();
  
  return data;
}

/*************************************************************************
                                读时间
--------------------------------------------------------------------------
无参数
--------------------------------------------------------------------------
返回值:时间数据
*************************************************************************/
TimeTypeDef DS1302_ReadTime (void)
{
  TimeTypeDef TimeDisplay;
  
  // 读出来的数据是 BCD 码
  TimeBuffer.year   = DS1302_ReadData (0x8D);  
  TimeBuffer.month  = DS1302_ReadData (0x89);  
  TimeBuffer.day    = DS1302_ReadData (0x87);  
  TimeBuffer.week   = DS1302_ReadData (0x8B);  
  TimeBuffer.hour   = DS1302_ReadData (0x85);  
  TimeBuffer.minute = DS1302_ReadData (0x83);  
  TimeBuffer.second = DS1302_ReadData (0x81);  // bit7 定义为时钟暂停标志(CH)
  
  // BCD 码转换为十进制
  TimeDisplay.year   = BCDtoDec (TimeBuffer.year);
  TimeDisplay.month  = BCDtoDec (TimeBuffer.month);
  TimeDisplay.day    = BCDtoDec (TimeBuffer.day);
  TimeDisplay.week   = BCDtoDec (TimeBuffer.week);
  TimeDisplay.hour   = BCDtoDec (TimeBuffer.hour);
  TimeDisplay.minute = BCDtoDec (TimeBuffer.minute);
  TimeDisplay.second = BCDtoDec (TimeBuffer.second);
  
  return TimeDisplay;
}

/*************************************************************************
                                修改时间
--------------------------------------------------------------------------
*TimeDisplay:要显示的时间(十进制)
--------------------------------------------------------------------------
无返回值
*************************************************************************/
void DS1302_WriteTime (TimeTypeDef *TimeDisplay)
{ 
  // 十进制转换为 BCD 码
  TimeBuffer.year   = DectoBCD (TimeDisplay->year);
  TimeBuffer.month  = DectoBCD (TimeDisplay->month);
  TimeBuffer.day    = DectoBCD (TimeDisplay->day);
  TimeBuffer.week   = DectoBCD (TimeDisplay->week);
  TimeBuffer.hour   = DectoBCD (TimeDisplay->hour);
  TimeBuffer.minute = DectoBCD (TimeDisplay->minute);
  TimeBuffer.second = DectoBCD (TimeDisplay->second);
  
  // 关闭写保护(控制寄存器:8FH、8EH  bit7:保护位)
  DS1302_WriteData (0x8E, 0x00);        
  
  // 写入的数据是 BCD 码
  DS1302_WriteData (0x8C, TimeBuffer.year);   
  DS1302_WriteData (0x88, TimeBuffer.month); 
  DS1302_WriteData (0x86, TimeBuffer.day); 
  DS1302_WriteData (0x8A, TimeBuffer.week); 
  DS1302_WriteData (0x84, TimeBuffer.hour); 
  DS1302_WriteData (0x82, TimeBuffer.minute); 
  DS1302_WriteData (0x80, TimeBuffer.second); // bit7 定义为时钟暂停标志(CH)
  
  // 开启写保护(控制寄存器:8FH、8EH  bit7:保护位)
  DS1302_WriteData (0x8E, 0x80);        
}

/*************************************************************************
                             十进制转BCD码
--------------------------------------------------------------------------
num:十进制数
--------------------------------------------------------------------------
返回值:BCD码
*************************************************************************/
static uint8_t DectoBCD (uint8_t num)
{
  uint8_t result;
  uint8_t temp1, temp2;

  temp1  = (num / 10) << 4;          // 十位 / 10 * 16
  temp2  =  num % 10;                // 个位 % 10
  result = temp1 + temp2;
  
  return result;
}

/*************************************************************************
                             BCD码转十进制
--------------------------------------------------------------------------
num:BCD码
--------------------------------------------------------------------------
返回值:十进制
*************************************************************************/
static uint8_t BCDtoDec (uint8_t num)
{
  uint8_t result;
  uint8_t temp1, temp2;
  
  temp1 = (num >> 4) * 10;         // 十位 / 16 * 10
  temp2 =  num & 0x0F;             // 个位 % 16
  result = temp1 + temp2;
  
  return result;
}

/*************************************************************************
                             软件延时(ms级别)
--------------------------------------------------------------------------
nCount:延时长度
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_DLY_ms(uint16_t nCount)
{
  while(nCount--)
  {
    DS1302_DLY_us(1000);
  }
}

/*************************************************************************
                             软件延时(us级别)
--------------------------------------------------------------------------
nCount:延时长度
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_DLY_us(uint16_t nCount)
{
  nCount *= 2;
  while(--nCount);
}

3. main.c

#include "stm8s.h"
#include "ds1302.h"
#include "uart.h"

void SystemInit_CLK(void);

void main(void)
{
  // 数据显示区(十进制)
  // 初始值:2022.02.25 Fri. 01:59:50
  TimeTypeDef TimeDisplay = {22, 02, 25, 5, 01, 59, 50};  
  uint8_t TimeSecPre;
  
  SystemInit_CLK();
  UART2_Config();
  DS1302_Init();
  
  printf("Init Success!\r\n");
  
#if RTC_RESET_TIME_EN > 0u
  DS1302_WriteTime(&TimeDisplay);
#endif
  
  while (1)
  {
    TimeDisplay = DS1302_ReadTime();
    if (TimeSecPre != TimeDisplay.second)
    {
      TimeSecPre = TimeDisplay.second;
      printf("20%d年%d月%d日 星期%d\r\n", TimeDisplay.year, TimeDisplay.month, TimeDisplay.day, 
             TimeDisplay.week);
      printf("%d时%d分%d秒\r\n", TimeDisplay.hour, TimeDisplay.minute, TimeDisplay.second);
      printf("\r\n");
    }
  }
}

void SystemInit_CLK(void)
{
  CLK_DeInit();
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 16MHz
  CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
  CLK_HSICmd(ENABLE);
}


#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

在串口打印时间:

image

---EOF---
posted @ 2022-03-02 16:52  漫舞八月(Mount256)  阅读(268)  评论(0编辑  收藏  举报