初始化

This commit is contained in:
2026-05-01 11:13:45 +08:00
commit bb1d10615e
99 changed files with 48378 additions and 0 deletions
+246
View File
@@ -0,0 +1,246 @@
#include "DS1302.h"
#include "Delay.h"
// 根据连接图.md: DS1302引脚配置
// CLK: PA4, DAT: PA5, RST: PA6
#define DS1302_SCLK_PIN GPIO_Pin_4 // CLK
#define DS1302_IO_PIN GPIO_Pin_5 // DAT (双向)
#define DS1302_CE_PIN GPIO_Pin_6 // RST/CE
#define DS1302_GPIO GPIOA
// GPIO控制宏
#define SCLK_H GPIO_SetBits(DS1302_GPIO, DS1302_SCLK_PIN)
#define SCLK_L GPIO_ResetBits(DS1302_GPIO, DS1302_SCLK_PIN)
#define DATA_H GPIO_SetBits(DS1302_GPIO, DS1302_IO_PIN)
#define DATA_L GPIO_ResetBits(DS1302_GPIO, DS1302_IO_PIN)
#define CE_H GPIO_SetBits(DS1302_GPIO, DS1302_CE_PIN)
#define CE_L GPIO_ResetBits(DS1302_GPIO, DS1302_CE_PIN)
#define DATA_READ GPIO_ReadInputDataBit(DS1302_GPIO, DS1302_IO_PIN)
// DS1302寄存器地址(写地址)
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
// BCD码转换
#define BCD_TO_DEC(bcd) (((bcd) >> 4) * 10 + ((bcd) & 0x0F))
#define DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10))
// 微秒延时
static void delay_us(uint32_t us)
{
volatile uint32_t i;
while (us--) {
for (i = 0; i < 12; i++); // 72MHz下约1us
}
}
/**
* @brief 配置IO口为输出
*/
static void DS1302_DATAOUT_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
}
/**
* @brief 配置IO口为输入
*/
static void DS1302_DATAINPUT_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS1302_IO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
}
/**
* @brief DS1302初始化
*/
void DS1302_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置SCLK和CE为推挽输出
GPIO_InitStructure.GPIO_Pin = DS1302_SCLK_PIN | DS1302_CE_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS1302_GPIO, &GPIO_InitStructure);
// 配置IO为输出(初始状态)
DS1302_DATAOUT_init();
// 初始化引脚状态
SCLK_L;
CE_L;
}
/**
* @brief 向DS1302发送一字节数据(根据demo代码)
* @param data 要发送的数据
*/
static void DS1302_write_onebyte(uint8_t data)
{
uint8_t count = 0;
DS1302_DATAOUT_init(); // 配置为输出
SCLK_L;
for (count = 0; count < 8; count++)
{
SCLK_L;
// 先准备好数据再发送
if (data & 0x01)
DATA_H;
else
DATA_L;
SCLK_H; // 拉高时钟线,发送数据
data >>= 1;
}
}
/**
* @brief 向指定寄存器地址发送数据(根据demo代码)
* @param address 寄存器地址
* @param data 数据
*/
void DS1302_WriteByte(uint8_t address, uint8_t data)
{
CE_L;
SCLK_L;
delay_us(1);
CE_H;
delay_us(2);
DS1302_write_onebyte(address);
DS1302_write_onebyte(data);
CE_L;
SCLK_L;
delay_us(2);
}
/**
* @brief 从指定地址读取一字节数据(根据demo代码)
* @param address 寄存器地址
* @retval 读取到的数据
*/
uint8_t DS1302_ReadByte(uint8_t address)
{
uint8_t count = 0;
uint8_t return_data = 0x00;
CE_L;
SCLK_L;
delay_us(3);
CE_H;
delay_us(3);
DS1302_write_onebyte(address);
DS1302_DATAINPUT_init(); // 配置I/O口为输入
delay_us(2);
for (count = 0; count < 8; count++)
{
delay_us(2); // 使电平持续一段时间
return_data >>= 1;
SCLK_H;
delay_us(4); // 使高电平持续一段时间
SCLK_L;
delay_us(14); // ⭐ 关键延时:延时14us后再去读取电压,更加准确
if (DATA_READ)
return_data = return_data | 0x80;
}
delay_us(2);
CE_L;
DATA_L;
return return_data;
}
/**
* @brief 设置DS1302时间
* @param time 时间结构体指针
*/
void DS1302_SetTime(DS1302_Time* time)
{
// 关闭写保护
DS1302_WriteByte(DS1302_WP, 0x00);
// 写入时间数据(BCD码格式)
DS1302_WriteByte(DS1302_SECOND, DEC_TO_BCD(time->second));
DS1302_WriteByte(DS1302_MINUTE, DEC_TO_BCD(time->minute));
DS1302_WriteByte(DS1302_HOUR, DEC_TO_BCD(time->hour));
DS1302_WriteByte(DS1302_DATE, DEC_TO_BCD(time->day));
DS1302_WriteByte(DS1302_MONTH, DEC_TO_BCD(time->month));
DS1302_WriteByte(DS1302_DAY, DEC_TO_BCD(time->week));
DS1302_WriteByte(DS1302_YEAR, DEC_TO_BCD(time->year % 100));
// 开启写保护
DS1302_WriteByte(DS1302_WP, 0x80);
}
/**
* @brief 读取DS1302时间
* @param time 时间结构体指针
*/
void DS1302_GetTime(DS1302_Time* time)
{
uint8_t read_time[7];
uint8_t hour_reg;
// 读取时间数据(BCD码)
read_time[0] = DS1302_ReadByte(0x81); // 读秒
read_time[1] = DS1302_ReadByte(0x83); // 读分
read_time[2] = DS1302_ReadByte(0x85); // 读时
read_time[3] = DS1302_ReadByte(0x87); // 读日
read_time[4] = DS1302_ReadByte(0x89); // 读月
read_time[5] = DS1302_ReadByte(0x8B); // 读星期
read_time[6] = DS1302_ReadByte(0x8D); // 读年
// BCD码转换为10进制(先屏蔽控制位,再转换)
time->second = BCD_TO_DEC(read_time[0] & 0x7F); // bit7=CH
time->minute = BCD_TO_DEC(read_time[1] & 0x7F);
hour_reg = read_time[2];
if (hour_reg & 0x80) {
// 12小时制:bit5=PM, bit4~0=小时(1~12)
uint8_t hour12 = BCD_TO_DEC(hour_reg & 0x1F);
uint8_t is_pm = (hour_reg & 0x20) ? 1 : 0;
if (hour12 == 12) {
time->hour = is_pm ? 12 : 0;
} else {
time->hour = is_pm ? (hour12 + 12) : hour12;
}
} else {
// 24小时制:bit5~0=小时(0~23)
time->hour = BCD_TO_DEC(hour_reg & 0x3F);
}
time->day = BCD_TO_DEC(read_time[3] & 0x3F);
time->month = BCD_TO_DEC(read_time[4] & 0x1F);
time->week = read_time[5] & 0x07;
time->year = BCD_TO_DEC(read_time[6]) + 2000;
}