眩しさだけは、忘れなかった。|

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---

本文作者:漫舞八月(Mount256)

本文链接:https://www.cnblogs.com/Mount256/p/15955934.html

版权声明:本作品采用CC 4.0 BY-SA许可协议进行许可。

posted @   漫舞八月(Mount256)  阅读(274)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开
  1. 1 Main Menu Theme Syd Matters
  2. 2 Luminous Memory (Acyanxi Remix) Acyanxi
  3. 3 夏影 麻枝准
  4. 4 潮騒の香り 水月陵
  5. 5 stand still 井口裕香 (いぐち ゆか)
  6. 6 流星雨 麻枝准
  7. 7 Summer Fantasy 傅许
  8. 8 失う 米白
  9. 9 epilogue 霜月はるか
  10. 10 夏に君を待ちながら 小原好美
  11. 11 桜のような恋でした 鹿乃 (かの)
  12. 12 風は微かに、熱を残し… 水月陵
  13. 13 夏凪ぎ 麻枝准/やなぎなぎ
  14. 14 空に光る 戸越まごめ
  15. 15 木漏れ日 riya
  16. 16 Songbirds Homecomings (ホームカミングス)
  17. 17 宝物になった日 麻枝准/やなぎなぎ
  18. 18 夏影~あの飛行機雲を超えた、その先へ~ 雪桜草 (雪樱草)
  19. 19 快晴 Orangestar (蜜柑星P),初音未来 (初音ミク)
  20. 20 永遠 霜月はるか
  21. 21 Sion 天門
  22. 22 遙かな年月-piano- 麻枝准
  23. 23 夏恋慕 kobasolo/春茶
  24. 24 夏凪ぎ-piano ver.- MANYO/麻枝准
  25. 25 Goodbye Seven Seas -piano ver.- MANYO/麻枝准
  26. 26 Light Years 麻枝准/やなぎなぎ
  27. 27 優しさの記憶 鹿乃 (かの)
Luminous Memory (Acyanxi Remix) - Acyanxi
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.