美信的RTC芯片看起来不错,但是贵。
威帆的SD3088这个不错,而且还可以给电池充电,便宜很多,淘宝上价格6元一片。我这项目对时间要求严格,就不使用1元多的芯片了。
网传STM32F1的I2C有Bug,模拟通信最为保险。
威帆网站上的例子是模拟的,看起来也蛮简单。官方说0.5秒内读值就行,要求不高。
我这里是使用HAL库,先前使用I2C读过PCF8563,看起来也正常。
环境:
IAR7.40
STM32CUBEMX 4.10.0
STM32F1 V1.20
1、STM32CUBEMX配置I2C
按默认值。
不启用中断。
不使用DMA。
Pin配置
2、启用Freertos
3、sd3088.h
/*
*文件 sd3088.h
*/
#ifndef SD3088_H
#define SD3088_H
#include "i2c.h"
#define DEBUG
#ifdef DEBUG
#include "stdio.h"
#endif
#define RTC_Addr 0x64 //RTC器件地址
#define IDcode 0x72 //8字节ID号起始地址
#define Bat_High_Addr 0x1A //电量最高位寄存器地址
#define Bat_Low_Addr 0x1B //电量低八位寄存器地址
#define BCD2DEC(x) (((x) >> 4) * 10 + ((x) & 0x0f))
typedef struct
{
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t week;
uint8_t day;
uint8_t month;
uint8_t year;
uint8_t quantity; // 电量
}Time;
extern Time Time_sd3088; //初始化时间结构体变量(设置时间:2014年11月12日 14:59:55 星期一)
void read_rtc(void);
#endif
4、sd3088.c
/*
*SD3088时钟芯片 读写
*文件 sd3088.h
*作者 于
*麦知 www.mazclub.com
*版本 v1.0
*/
#include "sd3088.h"
extern I2C_HandleTypeDef hi2c1;
Time Time_sd3088 = {0x55, 0x59, 0x14, 0x01, 0x12, 0x11, 0x14}; //初始化时间结构体变量(设置时间:2014年11月12日 14:59:55 星期一)
uint8_t rtc_data[8]; //通用数据缓存器
uint8_t sram[8]; //通用数据缓存器
uint8_t pdata;
void read_rtc(void)
{
// 读取时间
pdata = 0;
if(HAL_I2C_Master_Transmit(&hi2c1, 0x64, &pdata, 1, 1) == HAL_OK)
if(HAL_I2C_Master_Receive(&hi2c1, 0x65, &rtc_data[0], 7, 1) == HAL_OK) {
Time_sd3088.second = BCD2DEC(rtc_data[0] & 0x7f);
Time_sd3088.minute = BCD2DEC(rtc_data[1] & 0x7f);
Time_sd3088.hour = BCD2DEC(rtc_data[2] & 0x1f);
Time_sd3088.week = BCD2DEC(rtc_data[3] & 0x07);
Time_sd3088.day = BCD2DEC(rtc_data[4] & 0x3f);
Time_sd3088.month = BCD2DEC(rtc_data[5] & 0x1f);
Time_sd3088.year = BCD2DEC(rtc_data[6]);
}
// 电量
pdata = 0x1b;
if(HAL_I2C_Master_Transmit(&hi2c1, 0x64, &pdata, 1, 1) == HAL_OK)
if(HAL_I2C_Master_Receive(&hi2c1, 0x65, &rtc_data[7], 1, 1) == HAL_OK) {
Time_sd3088.quantity = BCD2DEC(rtc_data[7]);
}
#ifdef DEBUG
printf("%d-%d-%d,week %d, %d:%d:%d, qualit:%d\r\n",Time_sd3088.year,Time_sd3088.month,Time_sd3088.day, \
Time_sd3088.week,Time_sd3088.hour,Time_sd3088.minute,Time_sd3088.second, Time_sd3088.quantity);
#endif
}
存在的错误,读取 星期和电量不对。
另,
在串口窗口看打印信息,这里照着老外抄了个简单的:
我是在生成的usart.c中
1)添加 变量定义,FILE已经定义,这里只需引用
/* USER CODE BEGIN 0 */
FILE __stdout;
/* USER CODE END 0 */
2)添加 函数
在需要打印的位置使用printf函数即可, 头文件要保含 stdio.h。
IAR的工程配置为默认。
/* USER CODE BEGIN 1 */
int fputc(int ch, FILE *f)
{
/* Send your custom byte */
/* Send byte to USART */
uint8_t ch_t[1] = {ch};
HAL_UART_Transmit(&huart1, ch_t, 1, 1);
/* If everything is OK, you have to return character written */
return ch;
/* If character is not correct, you can return EOF (-1) to stop writing */
//return -1;
}
/* USER CODE END 1 */
PC端使用Tera Term, 波特率是38400bps 。