初始化毕业设计项目
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user