PCF8563/85063 高精度时钟IIC芯片 ESP驱动程序

/* i2c - Simple example
   Simple I2C example that shows how to initialize I2C
   as well as reading and writing from and to registers for a sensor connected over I2C.
   The sensor used in this example is a PCF85063 inertial measurement unit.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"


static const char *TAG = "i2c-pcf85063";


#define I2C_MASTER_SDA_IO           36   //CONFIG_I2C_MASTER_SDA      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_SCL_IO           35   //CONFIG_I2C_MASTER_SCL      /*!< GPIO number used for I2C master clock */

#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          400000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000


#define PCF85063_SENSOR_ADDR            0x51       /*!< Slave address of the PCF85063 sensor */
//注意:PCF85063秒寄存器0x04 ,PCF8563秒寄存器地址是0x02 
#define PCF85063_SEC_REG_ADDR           0x04       /*!< Register addresses of the timer_second register */
//PCF85063_REG: sec=4,min=5,hour=6,day=7,week=8,month=9,year=10

typedef struct 
{
   int nYear;
   int nMonth;
   int nWeek;
   int nDay;
   int nHour;
   int nMin;
   int nSec;
} CTime;

//12=>0x12
uint8_t PCD85063TP_decToBcd(uint8_t val)
{
  return ( (val/10*16) + (val%10) );
}

//0x12=>12
uint8_t PCD85063TP_bcdToDec(uint8_t val)
{
  return ( (val/16*10) + (val%16) );
}



/**
 * @brief Read a sequence of bytes from a PCF85063 sensor registers
 */
static esp_err_t PCF85063_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{
    return i2c_master_write_read_device(I2C_MASTER_NUM, PCF85063_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
}

/**
 * @brief Write N byte to a PCF85063 sensor register
 */
static esp_err_t PCF85063_register_write(uint8_t reg_addr, uint8_t *data,int len)
{
    int ret = 0;
    uint8_t *wr_dat = (uint8_t*) malloc(len+1);

    if(wr_dat==NULL)
      return -1;

    wr_dat[0] = reg_addr;

    for(int i=0;i<len;i++)
    {
        wr_dat[i+1] = data[i];
    }
    ret = i2c_master_write_to_device(I2C_MASTER_NUM, PCF85063_SENSOR_ADDR, wr_dat, len+1, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
    
    free(wr_dat);

    return ret;
}

int PCF85063_get_Week(int y,int m,int d)
{
  int week = 0;
  if(m==1 || m == 2)
  {
    m += 12;
    y--;
  }
  week=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
  //ret=0   星期天
  //ret=N   星期N
  return (week+1)%7;
}

//设置时间结构体,isAutoCalcWeek自动计算星期几
void PCF85063_setTime(CTime tm,int isAutoCalcWeek)
{
  uint8_t data[7] = {0};
  if (isAutoCalcWeek)
  {
    tm.nWeek = pcf8563_get_Week(tm.nYear, tm.nMonth, tm.nDay);
  }
  bool flag_19xx = true;
  uint16_t yr = tm.nYear;
  if (tm.nYear >= 2000)
  {
    flag_19xx = false;
    yr -= 2000;
  }
  else
  {
    yr -= 1900;
  }

  data[0] = pcf8563_decToBcd(tm.nSec);
  data[1] = pcf8563_decToBcd(tm.nMin);
  data[2] = pcf8563_decToBcd(tm.nHour);
  data[3] = pcf8563_decToBcd(tm.nDay);
  data[4] = pcf8563_decToBcd(tm.nWeek);
  data[5] = pcf8563_decToBcd(tm.nMonth);
  data[6] = pcf8563_decToBcd(yr);

  if (flag_19xx)
  {
    data[5] |= 0x80;
  }

  ESP_ERROR_CHECK(pcf8563_register_write(PCF8563_SEC_REG_ADDR, data, 7));

}

//获取年月日时分秒
bool PCF85063_getTime(CTime *tm)
{
    uint8_t data[7] = {0};
    ESP_ERROR_CHECK(PCF85063_register_read(PCF85063_SEC_REG_ADDR, data,7));
    
    bool flag_19xx = (data[5] >> 7) & 0x01; // Year:19XX_Flag
    bool flag_vl = (data[0] >> 7) & 0x01;   //(Voltage Low)VL=1:初始数据不可靠
    
    tm->nSec   = PCD85063TP_bcdToDec( data[0]&0x7f );
    tm->nMin   = PCD85063TP_bcdToDec( data[1]&0x7f );
    tm->nHour  = PCD85063TP_bcdToDec( data[2]&0x3f );
    tm->nDay   = PCD85063TP_bcdToDec( data[3]&0x3f );
    tm->nWeek  = PCD85063TP_bcdToDec( data[4] );
    tm->nMonth = PCD85063TP_bcdToDec( data[5]&0x1f );
    tm->nYear  = PCD85063TP_bcdToDec( data[6] ); //0~99
    
    if (flag_19xx)
    {
     tm->nYear += 1900;
    }
    else
   {
    tm->nYear += 2000;
   }
    return flag_vl;
}

//格式1: 20xx/xx/xx xx:xx:xx
//格式0: xx:xx:xx
char *PCF85063_getTmString(int isYMD)
{
   char tmStr[25]={0};
   CTime tm;
   PCF85063_getTime(&tm);
    if( isYMD )
        sprintf(tmStr,"20%02d/%02d/%02d %02d:%02d:%02d", tm.nYear,tm.nMonth,tm.nDay,tm.nHour,tm.nMin,tm.nSec );    
    else
        sprintf(tmStr,"%02d:%02d:%02d", tm.nHour,tm.nMin,tm.nSec );    
   return tmStr;
}





/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

void test_loop_task()
{
    
    int cnt = 0;
    //日期初始化为: 22年10月(周1)24日,09:58:50
    CTime tm={22,10,1,24,9,58,50};
  
   PCF85063_setTime( tm ,1 );

   while(1)
   {
    uint8_t data[10]={0};
    ESP_ERROR_CHECK(PCF85063_register_read(PCF85063_SEC_REG_ADDR, data,7));
    ESP_LOGI(TAG, "20%02X/%02X/%02X %02X:%02X:%02X_%X.", data[6],data[5],data[3],data[2],data[1]&0x7F,data[0]&0x7F,data[4] );    
   
    printf("cnt[%d].time=> %s \n ",cnt++,PCF85063_getTmString(1) );
    vTaskDelay(100);//x10ms
   }

}


void app_main(void)
{
    uint8_t data[2];//M+S
    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGI(TAG, "I2C initialized successfully,BUILD:[%s %s]",__DATE__,__TIME__);

    /* Read the PCF85063 initial second+minute register */
    ESP_ERROR_CHECK( PCF85063_register_read(PCF85063_SEC_REG_ADDR, data, 2) );
    ESP_LOGI(TAG, "Initial read ,Sec= %02X ,Min = %02X", data[0]&0x7F,data[1]&0x7F );
    
    vTaskDelay(150);
    xTaskCreate(test_loop_task, "test_loop_task", 1024*10, NULL, 10, NULL);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值