stm32 hal i2c 库读写sd3088时钟

来源:互联网 发布:php的mvc模式 编辑:程序博客网 时间:2024/05/18 03:18


前一版本的修正。

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"#endifextern 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;}





1 0