STM32标准库读写RX8025实时时钟芯片完整示例程序

STM32标准库读写RX8025实时时钟芯片完整示例程序

一、完整代码实现

1. 头文件 (rx8025.h)

#ifndef __RX8025_H
#define __RX8025_H

#include "stm32f10x.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "misc.h"

// RX8025 I2C地址定义
#define RX8025_I2C_ADDR_WRITE    0x64    // 写地址
#define RX8025_I2C_ADDR_READ     0x65    // 读地址

// RX8025寄存器地址定义
#define RX8025_REG_SECONDS       0x00    // 秒
#define RX8025_REG_MINUTES       0x01    // 分
#define RX8025_REG_HOURS         0x02    // 时
#define RX8025_REG_WEEK          0x03    // 星期
#define RX8025_REG_DAY           0x04    // 日
#define RX8025_REG_MONTH         0x05    // 月
#define RX8025_REG_YEAR          0x06    // 年
#define RX8025_REG_CONTROL1      0x07    // 控制寄存器1
#define RX8025_REG_CONTROL2      0x08    // 控制寄存器2
#define RX8025_REG_EXTENSION      0x0D    // 扩展寄存器
#define RX8025_REG_FLAG           0x0E    // 标志寄存器
#define RX8025_REG_TEMP           0x0F    // 温度寄存器

// 控制寄存器1位定义
#define RX8025_CTRL1_TEST        (1 << 7)  // 测试模式
#define RX8025_CTRL1_24H         (0 << 6)  // 24小时制
#define RX8025_CTRL1_12H         (1 << 6)  // 12小时制
#define RX8025_CTRL1_DAFG         (1 << 3)  // 日期闹钟标志
#define RX8025_CTRL1_WAFG         (1 << 4)  // 星期闹钟标志

// 控制寄存器2位定义
#define RX8025_CTRL2_RESET        (1 << 0)  // 复位
#define RX8025_CTRL2_CTFG         (1 << 1)  // 校准标志
#define RX8025_CTRL2_FSEL         (1 << 2)  // 频率选择
#define RX8025_CTRL2_TSEL         (1 << 3)  // 温度补偿选择
#define RX8025_CTRL2_USEL         (1 << 4)  // 更新选择
#define RX8025_CTRL2_WT           (1 << 5)  // 星期/日期选择
#define RX8025_CTRL2_HF           (1 << 6)  // 小时标志
#define RX8025_CTRL2_CT           (1 << 7)  // 校准使能

// 扩展寄存器位定义
#define RX8025_EXT_FSEL1         (1 << 2)  // 频率选择高位
#define RX8025_EXT_TSEL1         (1 << 3)  // 温度补偿选择高位

// 标志寄存器位定义
#define RX8025_FLAG_VDET         (1 << 0)  // 电压检测
#define RX8025_FLAG_XST          (1 << 1)  // 晶体振荡器停止
#define RX8025_FLAG_PON          (1 << 2)  // 电源开启
#define RX8025_FLAG_UTSF         (1 << 3)  // 更新结束标志
#define RX8025_FLAG_ALARM        (1 << 4)  // 闹钟标志
#define RX8025_FLAG_DAFG         (1 << 5)  // 日期闹钟标志
#define RX8025_FLAG_WAFG         (1 << 6)  // 星期闹钟标志
#define RX8025_FLAG_CTFG         (1 << 7)  // 校准标志

// 时间结构体定义
typedef struct {
    uint8_t seconds;     // 秒 (0-59)
    uint8_t minutes;     // 分 (0-59)
    uint8_t hours;       // 时 (0-23)
    uint8_t week;        // 星期 (0-6, 0=周日)
    uint8_t day;         // 日 (1-31)
    uint8_t month;       // 月 (1-12)
    uint8_t year;        // 年 (0-99)
} RX8025_TimeTypeDef;

// 温度结构体定义
typedef struct {
    int8_t integer;      // 整数部分
    uint8_t fraction;    // 小数部分 (0.25℃分辨率)
} RX8025_TempTypeDef;

// 闹钟结构体定义
typedef struct {
    uint8_t minute;      // 分钟 (0-59)
    uint8_t hour;        // 小时 (0-23)
    uint8_t day;         // 日 (1-31)
    uint8_t week;        // 星期 (0-6)
    uint8_t enable;      // 使能标志
} RX8025_AlarmTypeDef;

// 函数声明
void RX8025_I2C_Init(void);
uint8_t RX8025_WriteReg(uint8_t reg_addr, uint8_t data);
uint8_t RX8025_ReadReg(uint8_t reg_addr, uint8_t *data);
uint8_t RX8025_WriteMultiReg(uint8_t reg_addr, uint8_t *data, uint8_t len);
uint8_t RX8025_ReadMultiReg(uint8_t reg_addr, uint8_t *data, uint8_t len);
uint8_t RX8025_SetTime(RX8025_TimeTypeDef *time);
uint8_t RX8025_GetTime(RX8025_TimeTypeDef *time);
uint8_t RX8025_GetTemperature(RX8025_TempTypeDef *temp);
uint8_t RX8025_SetAlarm(RX8025_AlarmTypeDef *alarm);
uint8_t RX8025_GetAlarm(RX8025_AlarmTypeDef *alarm);
uint8_t RX8025_ClearFlags(uint8_t flags);
uint8_t RX8025_Init(void);
uint8_t BCD2DEC(uint8_t bcd);
uint8_t DEC2BCD(uint8_t dec);
void RX8025_Delay(uint32_t ms);
void RX8025_ErrorHandler(void);

#endif /* __RX8025_H */

2. 源文件 (rx8025.c)

#include "rx8025.h"
#include <stdio.h>

// I2C超时时间
#define I2C_TIMEOUT     10000

// 全局变量
static I2C_TypeDef* RX8025_I2C = I2C1;
static uint32_t I2C_ClockSpeed = 400000; // 400kHz

// I2C初始化
void RX8025_I2C_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;
    
    // 使能GPIOB和I2C1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    
    // 配置PB6(SCL)和PB7(SDA)为复用开漏输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;  // 复用开漏
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    // 复位I2C
    I2C_DeInit(RX8025_I2C);
    
    // I2C配置
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;  // 从机地址,主机模式可设为0
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = I2C_ClockSpeed;
    
    I2C_Init(RX8025_I2C, &I2C_InitStructure);
    I2C_Cmd(RX8025_I2C, ENABLE);
}

// 写单个寄存器
uint8_t RX8025_WriteReg(uint8_t reg_addr, uint8_t data) {
    uint32_t timeout = I2C_TIMEOUT;
    
    // 等待I2C总线空闲
    while(I2C_GetFlagStatus(RX8025_I2C, I2C_FLAG_BUSY)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送起始条件
    I2C_GenerateSTART(RX8025_I2C, ENABLE);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_MODE_SELECT)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送设备地址(写)
    I2C_Send7bitAddress(RX8025_I2C, RX8025_I2C_ADDR_WRITE, I2C_Direction_Transmitter);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送寄存器地址
    I2C_SendData(RX8025_I2C, reg_addr);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送数据
    I2C_SendData(RX8025_I2C, data);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送停止条件
    I2C_GenerateSTOP(RX8025_I2C, ENABLE);
    
    return 0;
}

// 读单个寄存器
uint8_t RX8025_ReadReg(uint8_t reg_addr, uint8_t *data) {
    uint32_t timeout = I2C_TIMEOUT;
    
    // 等待I2C总线空闲
    while(I2C_GetFlagStatus(RX8025_I2C, I2C_FLAG_BUSY)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送起始条件(写模式)
    I2C_GenerateSTART(RX8025_I2C, ENABLE);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_MODE_SELECT)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送设备地址(写)
    I2C_Send7bitAddress(RX8025_I2C, RX8025_I2C_ADDR_WRITE, I2C_Direction_Transmitter);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送寄存器地址
    I2C_SendData(RX8025_I2C, reg_addr);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 重新发送起始条件(读模式)
    I2C_GenerateSTART(RX8025_I2C, ENABLE);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_MODE_SELECT)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送设备地址(读)
    I2C_Send7bitAddress(RX8025_I2C, RX8025_I2C_ADDR_READ, I2C_Direction_Receiver);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 禁用应答(读取最后一个字节)
    I2C_AcknowledgeConfig(RX8025_I2C, DISABLE);
    
    // 等待数据接收完成
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 读取数据
    *data = I2C_ReceiveData(RX8025_I2C);
    
    // 发送停止条件
    I2C_GenerateSTOP(RX8025_I2C, ENABLE);
    
    // 重新使能应答
    I2C_AcknowledgeConfig(RX8025_I2C, ENABLE);
    
    return 0;
}

// 写多个寄存器
uint8_t RX8025_WriteMultiReg(uint8_t reg_addr, uint8_t *data, uint8_t len) {
    uint32_t timeout = I2C_TIMEOUT;
    uint8_t i;
    
    // 等待I2C总线空闲
    while(I2C_GetFlagStatus(RX8025_I2C, I2C_FLAG_BUSY)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送起始条件
    I2C_GenerateSTART(RX8025_I2C, ENABLE);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_MODE_SELECT)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送设备地址(写)
    I2C_Send7bitAddress(RX8025_I2C, RX8025_I2C_ADDR_WRITE, I2C_Direction_Transmitter);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送寄存器地址
    I2C_SendData(RX8025_I2C, reg_addr);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送多个数据
    for(i = 0; i < len; i++) {
        I2C_SendData(RX8025_I2C, data[i]);
        timeout = I2C_TIMEOUT;
        while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
            if((timeout--) == 0) {
                RX8025_ErrorHandler();
                return 1;
            }
        }
    }
    
    // 发送停止条件
    I2C_GenerateSTOP(RX8025_I2C, ENABLE);
    
    return 0;
}

// 读多个寄存器
uint8_t RX8025_ReadMultiReg(uint8_t reg_addr, uint8_t *data, uint8_t len) {
    uint32_t timeout = I2C_TIMEOUT;
    uint8_t i;
    
    // 等待I2C总线空闲
    while(I2C_GetFlagStatus(RX8025_I2C, I2C_FLAG_BUSY)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送起始条件(写模式)
    I2C_GenerateSTART(RX8025_I2C, ENABLE);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_MODE_SELECT)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送设备地址(写)
    I2C_Send7bitAddress(RX8025_I2C, RX8025_I2C_ADDR_WRITE, I2C_Direction_Transmitter);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送寄存器地址
    I2C_SendData(RX8025_I2C, reg_addr);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 重新发送起始条件(读模式)
    I2C_GenerateSTART(RX8025_I2C, ENABLE);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_MODE_SELECT)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 发送设备地址(读)
    I2C_Send7bitAddress(RX8025_I2C, RX8025_I2C_ADDR_READ, I2C_Direction_Receiver);
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
        if((timeout--) == 0) {
            RX8025_ErrorHandler();
            return 1;
        }
    }
    
    // 读取多个数据
    for(i = 0; i < len; i++) {
        if(i == len - 1) {
            // 最后一个字节,禁用应答
            I2C_AcknowledgeConfig(RX8025_I2C, DISABLE);
        }
        
        // 等待数据接收完成
        timeout = I2C_TIMEOUT;
        while(!I2C_CheckEvent(RX8025_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
            if((timeout--) == 0) {
                RX8025_ErrorHandler();
                return 1;
            }
        }
        
        // 读取数据
        data[i] = I2C_ReceiveData(RX8025_I2C);
    }
    
    // 发送停止条件
    I2C_GenerateSTOP(RX8025_I2C, ENABLE);
    
    // 重新使能应答
    I2C_AcknowledgeConfig(RX8025_I2C, ENABLE);
    
    return 0;
}

// BCD码转十进制
uint8_t BCD2DEC(uint8_t bcd) {
    return ((bcd >> 4) * 10) + (bcd & 0x0F);
}

// 十进制转BCD码
uint8_t DEC2BCD(uint8_t dec) {
    return ((dec / 10) << 4) | (dec % 10);
}

// 设置时间
uint8_t RX8025_SetTime(RX8025_TimeTypeDef *time) {
    uint8_t data[7];
    
    // 转换为BCD码
    data[0] = DEC2BCD(time->seconds) & 0x7F;  // 秒,最高位为0
    data[1] = DEC2BCD(time->minutes) & 0x7F;  // 分,最高位为0
    data[2] = DEC2BCD(time->hours) & 0x3F;    // 时,24小时制
    data[3] = time->week & 0x07;              // 星期,0-6
    data[4] = DEC2BCD(time->day) & 0x3F;      // 日
    data[5] = DEC2BCD(time->month) & 0x1F;    // 月
    data[6] = DEC2BCD(time->year);            // 年
    
    // 写入时间寄存器
    return RX8025_WriteMultiReg(RX8025_REG_SECONDS, data, 7);
}

// 读取时间
uint8_t RX8025_GetTime(RX8025_TimeTypeDef *time) {
    uint8_t data[7];
    
    // 读取时间寄存器
    if(RX8025_ReadMultiReg(RX8025_REG_SECONDS, data, 7)) {
        return 1;
    }
    
    // 转换为十进制
    time->seconds = BCD2DEC(data[0] & 0x7F);
    time->minutes = BCD2DEC(data[1] & 0x7F);
    time->hours = BCD2DEC(data[2] & 0x3F);
    time->week = data[3] & 0x07;
    time->day = BCD2DEC(data[4] & 0x3F);
    time->month = BCD2DEC(data[5] & 0x1F);
    time->year = BCD2DEC(data[6]);
    
    return 0;
}

// 读取温度
uint8_t RX8025_GetTemperature(RX8025_TempTypeDef *temp) {
    uint8_t data;
    
    // 读取温度寄存器
    if(RX8025_ReadReg(RX8025_REG_TEMP, &data)) {
        return 1;
    }
    
    // 解析温度数据
    temp->integer = (int8_t)(data & 0x7F);  // 整数部分
    if(data & 0x80) {
        temp->integer = -temp->integer;     // 负数
    }
    
    // 小数部分 (0.25℃分辨率)
    temp->fraction = 0;  // RX8025温度寄存器只包含整数部分
    
    return 0;
}

// 设置闹钟
uint8_t RX8025_SetAlarm(RX8025_AlarmTypeDef *alarm) {
    uint8_t data[4];
    
    // 设置闹钟时间
    data[0] = DEC2BCD(alarm->minute) & 0x7F;  // 分钟
    data[1] = DEC2BCD(alarm->hour) & 0x3F;    // 小时
    data[2] = DEC2BCD(alarm->day) & 0x3F;      // 日
    data[3] = alarm->week & 0x7F;              // 星期
    
    // 写入闹钟寄存器
    if(RX8025_WriteMultiReg(0x09, data, 4)) {
        return 1;
    }
    
    // 设置闹钟使能
    uint8_t ctrl2;
    if(RX8025_ReadReg(RX8025_REG_CONTROL2, &ctrl2)) {
        return 1;
    }
    
    if(alarm->enable) {
        ctrl2 |= RX8025_CTRL2_WT;  // 选择日期模式
        if(alarm->day) {
            ctrl2 &= ~RX8025_CTRL2_DAFG;  // 使能日期闹钟
        } else {
            ctrl2 &= ~RX8025_CTRL2_WAFG;  // 使能星期闹钟
        }
    } else {
        ctrl2 &= ~(RX8025_CTRL2_DAFG | RX8025_CTRL2_WAFG);  // 禁用闹钟
    }
    
    return RX8025_WriteReg(RX8025_REG_CONTROL2, ctrl2);
}

// 读取闹钟
uint8_t RX8025_GetAlarm(RX8025_AlarmTypeDef *alarm) {
    uint8_t data[4];
    
    // 读取闹钟寄存器
    if(RX8025_ReadMultiReg(0x09, data, 4)) {
        return 1;
    }
    
    // 转换为十进制
    alarm->minute = BCD2DEC(data[0] & 0x7F);
    alarm->hour = BCD2DEC(data[1] & 0x3F);
    alarm->day = BCD2DEC(data[2] & 0x3F);
    alarm->week = data[3] & 0x7F;
    
    // 读取控制寄存器2获取使能状态
    uint8_t ctrl2;
    if(RX8025_ReadReg(RX8025_REG_CONTROL2, &ctrl2)) {
        return 1;
    }
    
    alarm->enable = (ctrl2 & (RX8025_CTRL2_DAFG | RX8025_CTRL2_WAFG)) ? 1 : 0;
    
    return 0;
}

// 清除标志
uint8_t RX8025_ClearFlags(uint8_t flags) {
    return RX8025_WriteReg(RX8025_REG_FLAG, flags);
}

// 初始化RX8025
uint8_t RX8025_Init(void) {
    uint8_t data;
    
    // 初始化I2C
    RX8025_I2C_Init();
    
    // 延时等待芯片稳定
    RX8025_Delay(10);
    
    // 读取控制寄存器1,检查芯片是否正常
    if(RX8025_ReadReg(RX8025_REG_CONTROL1, &data)) {
        return 1;
    }
    
    // 设置24小时制,禁用测试模式
    data &= ~RX8025_CTRL1_TEST;  // 清除测试位
    data &= ~RX8025_CTRL1_12H;   // 设置为24小时制
    
    if(RX8025_WriteReg(RX8025_REG_CONTROL1, data)) {
        return 1;
    }
    
    // 设置控制寄存器2
    data = 0x00;
    data &= ~RX8025_CTRL2_RESET;  // 不清除复位
    data &= ~RX8025_CTRL2_CT;     // 禁用校准
    data &= ~RX8025_CTRL2_WT;     // 选择日期模式
    
    if(RX8025_WriteReg(RX8025_REG_CONTROL2, data)) {
        return 1;
    }
    
    // 清除所有标志
    if(RX8025_ClearFlags(0xFF)) {
        return 1;
    }
    
    return 0;
}

// 简单延时函数
void RX8025_Delay(uint32_t ms) {
    uint32_t i, j;
    for(i = 0; i < ms; i++) {
        for(j = 0; j < 7200; j++);  // 72MHz下大约1ms
    }
}

// 错误处理函数
__weak void RX8025_ErrorHandler(void) {
    // 默认错误处理 - 可以在此添加LED闪烁等指示
    while(1) {
        // 错误处理代码
    }
}

3. 主程序示例 (main.c)

#include "stm32f10x.h"
#include "rx8025.h"
#include "stdio.h"
#include "string.h"

// 串口重定向
#ifdef __GNUC__
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE {
    USART_SendData(USART1, (uint8_t)ch);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    return ch;
}

// 串口初始化
void USART1_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
    
    // 配置PA9为USART1_TX
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置PA10为USART1_RX
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // USART配置
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}

// 系统时钟初始化
void RCC_Configuration(void) {
    // 设置系统时钟为72MHz
    SystemInit();
    
    // 使能外设时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
}

// 简单菜单显示
void ShowMenu(void) {
    printf("\r\n===== RX8025 RTC 测试程序 =====\r\n");
    printf("1. 读取当前时间\r\n");
    printf("2. 设置新时间\r\n");
    printf("3. 读取温度\r\n");
    printf("4. 设置闹钟\r\n");
    printf("5. 读取闹钟设置\r\n");
    printf("6. 清除所有标志\r\n");
    printf("7. 退出\r\n");
    printf("请选择操作: ");
}

// 设置时间函数
void SetNewTime(void) {
    RX8025_TimeTypeDef new_time;
    char input[20];
    
    printf("\r\n请输入新时间 (格式: YYYY-MM-DD HH:MM:SS): ");
    fflush(stdout);
    
    // 简化实现 - 实际中应使用串口接收
    printf("2024-05-20 14:30:00\r\n");
    strcpy(input, "2024-05-20 14:30:00");
    
    // 解析输入
    sscanf(input, "%d-%d-%d %d:%d:%d", 
           (int*)&new_time.year, 
           (int*)&new_time.month, 
           (int*)&new_time.day,
           (int*)&new_time.hours,
           (int*)&new_time.minutes,
           (int*)&new_time.seconds);
    
    // 设置星期 (简化 - 实际中需要计算)
    new_time.week = 1; // 周一
    
    if(RX8025_SetTime(&new_time) == 0) {
        printf("时间设置成功!\r\n");
    } else {
        printf("时间设置失败!\r\n");
    }
}

// 设置闹钟函数
void SetAlarm(void) {
    RX8025_AlarmTypeDef alarm;
    char input[20];
    
    printf("\r\n请输入闹钟时间 (格式: HH:MM): ");
    fflush(stdout);
    
    // 简化实现
    printf("08:00\r\n");
    strcpy(input, "08:00");
    
    // 解析输入
    sscanf(input, "%d:%d", (int*)&alarm.hour, (int*)&alarm.minute);
    
    alarm.second = 0;
    alarm.day = 0;
    alarm.week = 0;
    alarm.enable = 1;
    
    if(RX8025_SetAlarm(&alarm) == 0) {
        printf("闹钟设置成功!\r\n");
    } else {
        printf("闹钟设置失败!\r\n");
    }
}

int main(void) {
    RX8025_TimeTypeDef current_time;
    RX8025_TempTypeDef temperature;
    RX8025_AlarmTypeDef alarm;
    uint8_t choice;
    char input[10];
    
    // 系统初始化
    RCC_Configuration();
    USART1_Init();
    
    printf("\r\n系统启动中...\r\n");
    
    // 初始化RX8025
    if(RX8025_Init() == 0) {
        printf("RX8025 初始化成功!\r\n");
    } else {
        printf("RX8025 初始化失败!\r\n");
        while(1);
    }
    
    while(1) {
        ShowMenu();
        
        // 简化实现 - 实际中应使用串口接收
        printf("1\r\n");
        choice = 1;
        
        switch(choice) {
            case 1: // 读取当前时间
                if(RX8025_GetTime(&current_time) == 0) {
                    printf("\r\n当前时间: 20%02d-%02d-%02d %02d:%02d:%02d 星期%d\r\n",
                           current_time.year, current_time.month, current_time.day,
                           current_time.hours, current_time.minutes, current_time.seconds,
                           current_time.week);
                } else {
                    printf("读取时间失败!\r\n");
                }
                break;
                
            case 2: // 设置新时间
                SetNewTime();
                break;
                
            case 3: // 读取温度
                if(RX8025_GetTemperature(&temperature) == 0) {
                    printf("\r\n当前温度: %d.%d °C\r\n", 
                           temperature.integer, temperature.fraction);
                } else {
                    printf("读取温度失败!\r\n");
                }
                break;
                
            case 4: // 设置闹钟
                SetAlarm();
                break;
                
            case 5: // 读取闹钟设置
                if(RX8025_GetAlarm(&alarm) == 0) {
                    printf("\r\n闹钟设置: %02d:%02d 日:%d 星期:%d 状态:%s\r\n",
                           alarm.hour, alarm.minute, alarm.day, alarm.week,
                           alarm.enable ? "使能" : "禁用");
                } else {
                    printf("读取闹钟设置失败!\r\n");
                }
                break;
                
            case 6: // 清除所有标志
                if(RX8025_ClearFlags(0xFF) == 0) {
                    printf("所有标志已清除!\r\n");
                } else {
                    printf("清除标志失败!\r\n");
                }
                break;
                
            case 7: // 退出
                printf("程序退出\r\n");
                return 0;
                
            default:
                printf("无效选择!\r\n");
        }
        
        RX8025_Delay(2000); // 延时2秒
    }
}

二、关键功能说明

1. I2C通信实现

2. 时间管理功能

3. 温度监测

4. 闹钟功能

5. 标志管理

三、硬件连接指南

1. 引脚连接

RX8025模块 STM32F103 说明
VCC 3.3V 电源正极
GND GND 电源地
SDA PB7 I2C数据线
SCL PB6 I2C时钟线
INT PA0 中断输出(可选)

2. 电路设计要点

  1. 上拉电阻:SDA和SCL线需要4.7kΩ上拉电阻到3.3V
  2. 电源滤波:VCC引脚附近加0.1μF去耦电容
  3. 晶振:RX8025内置32.768kHz晶振,无需外部晶振
  4. 备用电池:VBAT引脚可接3V纽扣电池(CR2032)
  5. ESD保护:建议在I2C线路上添加ESD保护器件

四、使用说明

1. 初始化流程

  1. 调用RCC_Configuration()配置系统时钟
  2. 调用USART1_Init()初始化调试串口
  3. 调用RX8025_Init()初始化RTC芯片
  4. 使用各功能函数进行读写操作

2. 主要功能调用

// 设置时间
RX8025_TimeTypeDef time;
time.year = 24;   // 2024年
time.month = 5;   // 5月
time.day = 20;    // 20日
time.hours = 14;  // 14时
time.minutes = 30;// 30分
time.seconds = 0; // 0秒
time.week = 1;    // 周一
RX8025_SetTime(&time);

// 读取时间
RX8025_TimeTypeDef current_time;
RX8025_GetTime(&current_time);

// 设置闹钟
RX8025_AlarmTypeDef alarm;
alarm.hour = 8;
alarm.minute = 0;
alarm.enable = 1;
RX8025_SetAlarm(&alarm);

// 读取温度
RX8025_TempTypeDef temp;
RX8025_GetTemperature(&temp);

参考代码 STM32标准库读写RX8025的示例程序 www.youwenfan.com/contentcnt/183295.html

五、常见问题解决

1. I2C通信失败

2. 时间读取错误

3. 温度读取异常

4. 闹钟不触发

六、扩展功能建议

1. 低功耗设计

// 进入低功耗模式
void Enter_LowPower_Mode(void) {
    // 关闭外设时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, DISABLE);
    
    // 配置唤醒源
    PWR_WakeUpPinCmd(ENABLE);
    
    // 进入待机模式
    PWR_EnterSTANDBYMode();
}

2. 数据记录器

// 记录时间戳
void Log_Event(const char* event) {
    RX8025_TimeTypeDef time;
    RX8025_GetTime(&time);
    
    printf("[%02d:%02d:%02d] %s\n", 
           time.hours, time.minutes, time.seconds, event);
}

3. 网络时间同步

// 通过NTP同步时间
void Sync_With_NTP(void) {
    // 实现NTP协议获取网络时间
    // 然后调用RX8025_SetTime()设置RTC
}

七、性能优化建议

  1. I2C速率优化

    • 在400kHz模式下,确保PCB布线符合规范
    • 使用短而直的走线
    • 避免与高频信号线平行走线
  2. 代码优化

    • 使用DMA传输I2C数据
    • 将频繁访问的数据放入RAM
    • 使用查表法优化BCD转换
  3. 电源管理

    • 在电池供电时降低I2C速率
    • 关闭未使用的外设
    • 使用低功耗模式

八、项目应用示例

1. 数据记录器

// 数据记录结构
typedef struct {
    RX8025_TimeTypeDef timestamp;
    float sensor_value;
} DataPoint;

// 记录数据
void Record_Data(float value) {
    static DataPoint data[1000];
    static uint16_t index = 0;
    
    // 获取时间戳
    RX8025_GetTime(&data[index].timestamp);
    
    // 记录传感器值
    data[index].sensor_value = value;
    
    // 保存到Flash或SD卡
    // ...
    
    index = (index + 1) % 1000;
}

2. 定时控制

// 定时控制函数
void Check_Schedule(void) {
    RX8025_TimeTypeDef time;
    RX8025_GetTime(&time);
    
    // 早上8点打开设备
    if(time.hours == 8 && time.minutes == 0 && time.seconds == 0) {
        Turn_On_Device();
    }
    
    // 晚上10点关闭设备
    if(time.hours == 22 && time.minutes == 0 && time.seconds == 0) {
        Turn_Off_Device();
    }
}

3. 事件提醒

// 检查闹钟
void Check_Alarms(void) {
    uint8_t flag;
    RX8025_ReadReg(RX8025_REG_FLAG, &flag);
    
    if(flag & RX8025_FLAG_ALARM) {
        // 闹钟触发
        Trigger_Alarm();
        
        // 清除标志
        RX8025_ClearFlags(RX8025_FLAG_ALARM);
    }
}

九、总结

本程序提供了完整的STM32标准库读写RX8025实时时钟芯片的实现,包括:

  1. 核心功能

    • I2C通信协议实现
    • 时间读写与管理
    • 温度监测
    • 闹钟功能
    • 标志管理
  2. 完整代码

    • 头文件(rx8025.h)包含所有定义
    • 源文件(rx8025.c)实现所有功能
    • 主程序(main.c)提供使用示例
  3. 实用功能

    • 详细的错误处理机制
    • 完善的注释说明
    • 多种应用场景示例
    • 常见问题解决方案
  4. 扩展能力

    • 低功耗设计支持
    • 数据记录器实现
    • 网络时间同步接口
    • 定时控制功能

 

专注于matlab/simulink,电子电路,编程