您的位置:首页 > 其它

stm32 hal i2c 库读写sd3088时钟

2016-03-06 19:57 453 查看
前一版本的修正。

sd3008在每次通信开始0.5s做一次总线复位,不必考虑stm32的i2c Bug问题。

而且HAL库,是不是也应考虑到软件上补充这个Bug?

使用HAL_I2C_Mem_Read/Write,使得代码非常好看。模拟I2C方式,一字长蛇阵模样。

使用Freertos,读取时间、保存数据到用户SRAM,需要考虑Mutex对RTC时钟资源进行保护。

* SD3088时钟芯片 读写
* 文件 sd3088.h
* http://git.oschina.net/maizhi/small-pellet-sove-control-system *作者 于
*版本 v1.1
*/
#include "sd3088.h"

#if DEBUG
#include "stdio.h"
#endif

extern I2C_HandleTypeDef hi2c1;

RTC_Time Time_sd3088 = {0x55, 0x59, 0x14, 0x01, 0x12, 0x11, 0x14};	//初始化时间结构体变量(设置时间:2014年11月12日 14:59:55  星期一)
uint8_t  rtc_data[7];  		//通用数据缓存器

/* 读取时间 */
uint8_t read_rtc(void)
{
uint8_t battery[2];

if(HAL_I2C_Mem_Read(&hi2c1, RTC_ADDR_READ, 0x0, 1, &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]);

}

// 电量 0x1a 0x1b
if(HAL_I2C_Mem_Read(&hi2c1, RTC_ADDR_READ, 0x1a, 1, battery, 2, 1) == HAL_OK) {
Time_sd3088.quantity = (battery[0] >> 7) * 255 + battery[1];
printf("quality:%x\r\n",Time_sd3088.quantity);

}

return 0;

}

/* 允许写 */
bool enable_write(void)
{
bool result = false;
uint8_t wcr = 0x80;

// 写 0x10
if(HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, 0x10, 1, &wcr, 1, 1) == HAL_OK) {
//  写 0x0f
wcr = 0xff;
if(HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, 0x0f, 1, &wcr, 1, 1) == HAL_OK)
result = true;

}

return result;

}

/* 禁止写 */
bool disable_write(void)
{
bool result = false;
uint8_t wcr = 0x7b;

// 写 0x0f
if(HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, 0x0f, 1, &wcr, 1, 1) == HAL_OK) {

//  写 0x10
wcr = 0x0;
if(HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, 0x10, 1, &wcr, 1, 1) == HAL_OK)
result = true;

}

return result;

}

/* 保存时间 */
void write_rtc(RTC_Time *t)
{
// 计算星期
uint8_t y, m , d;
y = t->year + 2000;
m = t->month;
d = t->day;

if (m ==1 || m ==2) {

m += 12;  //把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算
y--;
}

// 使用基姆拉尔森公式计算星期
uint8_t week = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;

uint8_t data[7];
data[0] = 0;
data[1] = DEC2BCD(t->minute);
data[2] = DEC2BCD(t->hour);
data[3] = week;
data[4] = DEC2BCD(t->day);
data[5] = DEC2BCD(t->month);
data[6] = DEC2BCD(t->year);

if (enable_write()) {

// 写时间数据
if(HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, 0x0, 1, &data[0], 7, 1) == HAL_OK) {
printf("saved time successful.\r\n");
}
else
printf("saved time failure.\r\n");

disable_write();
}

}

/* 保存数据到RTC */
bool save_to_rtc(uint16_t address, uint8_t *data, uint16_t len)
{
bool result = false;

if (address < 0x2c || address > 0x71 || len > 70)
return false;

if (enable_write()) {
if (HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, address, 1, data, len, 1) == HAL_OK) {
result = true;
}
disable_write();
}

// 读回做检验?

return result;

}

/* 读取数据从RTC */
bool read_from_rtc(uint16_t address, uint8_t *data, uint16_t len)
{
bool result = false;

if (address < 0x2c || address > 0x71 || len > 70)
return false;
// 读回
if(HAL_I2C_Mem_Write(&hi2c1, RTC_ADDR_WRITE, address, 1, data, len, 1) == HAL_OK) {

}

return result;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: