参考链接:
DS3231应用程序之温度读出与变换函数
文档说明:
这里将ds3231这3个寄存器的初值读出:
可以看到温度高8位初始值为0x15,低8位为0xff。
控制寄存器(0x0E)初始值为1c (00011100),这是上电默认的值.
温度转换说明:
控制器启动温度转换,新的温度值存储到11h、12h这两个寄存器中,温度的编码为补码形式,正数的数据与补码相同,要求负数的原数据的话将补码还原成原码,方法是除最高位不变,其余的求反加一,最高位1表示的是该值是负值。本人买的模块里面的芯片是ds3231SN,温度范围在-40~85。芯片的温度的分辨率为0.25。参考上面给出的文档,高8位数据是整数部分,低8位的bit7、bit6为小数部分,将bit7、bit6这两位数据乘以分辨率0.25再加上整数部分就是他的温度值。
转换温度CONV位为一时将温度送到11h、12h寄存器中。里面的BSY位按我的理解是如果CONV位置1是,将温度送到11h、12h寄存器中,顺便检查BSY位,如果BSY为1的话,就不执行TCXO,否则就执行TCXO.
代码部分:
- i2c_master.h
#ifndef __I2C_MASTER_H__
#define __I2C_MASTER_H__
#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_MTCK_U
#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_MTDI_U
#define I2C_MASTER_SDA_GPIO 13
#define I2C_MASTER_SCL_GPIO 12
#define I2C_MASTER_SDA_FUNC FUNC_GPIO13
#define I2C_MASTER_SCL_FUNC FUNC_GPIO12
//#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO2_U
//#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_GPIO0_U
//#define I2C_MASTER_SDA_GPIO 2
//#define I2C_MASTER_SCL_GPIO 0
//#define I2C_MASTER_SDA_FUNC FUNC_GPIO2
//#define I2C_MASTER_SCL_FUNC FUNC_GPIO0
#if 0
#define I2C_MASTER_GPIO_SET(pin) \
gpio_output_set(1<<pin,0,1<<pin,0)
#define I2C_MASTER_GPIO_CLR(pin) \
gpio_output_set(0,1<<pin,1<<pin,0)
#define I2C_MASTER_GPIO_OUT(pin,val) \
if(val) I2C_MASTER_GPIO_SET(pin);\
else I2C_MASTER_GPIO_CLR(pin)
#endif
#define I2C_MASTER_SDA_HIGH_SCL_HIGH() \
gpio_output_set(1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0)
#define I2C_MASTER_SDA_HIGH_SCL_LOW() \
gpio_output_set(1<<I2C_MASTER_SDA_GPIO, 1<<I2C_MASTER_SCL_GPIO, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0)
#define I2C_MASTER_SDA_LOW_SCL_HIGH() \
gpio_output_set(1<<I2C_MASTER_SCL_GPIO, 1<<I2C_MASTER_SDA_GPIO, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0)
#define I2C_MASTER_SDA_LOW_SCL_LOW() \
gpio_output_set(0, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0)
void i2c_master_gpio_init(void);
void i2c_master_init(void);
#define i2c_master_wait os_delay_us
void i2c_master_stop(void);
void i2c_master_start(void);
void i2c_master_setAck(uint8 level);
uint8 i2c_master_getAck(void);
uint8 i2c_master_readByte(void);
void i2c_master_writeByte(uint8 wrdata);
bool i2c_master_checkAck(void);
void i2c_master_send_ack(void);
void i2c_master_send_nack(void);
#endif
- i2c_master.c
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "driver/i2c_master.h"
/******************************************************************************
* FunctionName : i2c_master_setDC
* Description : Internal used function -
* set i2c SDA and SCL bit value for half clk cycle
* Parameters : uint8 SDA
* uint8 SCL
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
i2c_master_setDC(uint8 SDA, uint8 SCL)
{
SDA &= 0x01;
SCL &= 0x01;
if ((0 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_LOW();
} else if ((0 == SDA) && (1 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_HIGH();
} else if ((1 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_HIGH_SCL_LOW();
} else {
I2C_MASTER_SDA_HIGH_SCL_HIGH();
}
}
/******************************************************************************
* FunctionName : i2c_master_getDC
* Description : Internal used function -
* get i2c SDA bit value
* Parameters : NONE
* Returns : uint8 - SDA bit value
*******************************************************************************/
LOCAL uint8 ICACHE_FLASH_ATTR
i2c_master_getDC(void)
{
uint8 sda_out;
sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
return sda_out;
}
/******************************************************************************
* FunctionName : i2c_master_init
* Description : initilize I2C bus to enable i2c operations
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_init(void) //复位i2c从机状态
{
while(!i2c_master_getDC()){//检测i2c从机是否挂死,fSCL约等于333.3kHz
system_soft_wdt_feed();//喂软件看门狗
i2c_master_setDC(1, 0);
i2c_master_wait(2); // sda 1, scl 0
i2c_master_setDC(1, 1);
i2c_master_wait(1); // sda 1, scl 1
}
// reset all
i2c_master_stop();
return;
}
/******************************************************************************
* FunctionName : i2c_master_gpio_init
* Description : config SDA and SCL gpio to open-drain output mode,
* mux and gpio num defined in i2c_master.h
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_gpio_init(void)
{
ETS_GPIO_INTR_DISABLE() ;
// ETS_INTR_LOCK();
PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC);
PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC);
/*设置SDA_GPIO口为输入模式
gpio_output_set(0, 0, 0, GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));*/
//设置SDA_GPIO口为开漏模式
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SDA_GPIO));
//设置CLK_GPIO口为开漏模式
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SCL_GPIO));
I2C_MASTER_SDA_HIGH_SCL_HIGH();
ETS_GPIO_INTR_ENABLE() ;
// ETS_INTR_UNLOCK();
i2c_master_init();
}
/******************************************************************************
* FunctionName : i2c_master_start
* Description : set i2c to send state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_start(void)
{
i2c_master_setDC(1, 0);
i2c_master_wait(1);
i2c_master_setDC(1, 1);
i2c_master_wait(1); // 一个重复起始信号的建立时间0.6us
i2c_master_setDC(0, 1);
i2c_master_wait(1); // 起始信号的保持时间0.6us,在这段时间过后可产生第一个时钟脉冲
i2c_master_setDC(0, 0);
i2c_master_wait(1); // 起始信号的保持时间0.6us,在这段时间过后可产生第一个时钟脉冲
}
/******************************************************************************
* FunctionName : i2c_master_writeByte
* Description : write wrdata value(one byte) into i2c
* Parameters : uint8 wrdata - write value
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(uint8 wrdata)//向i2c写数据
{
uint8 dat;
sint8 i;
for (i = 7; i >= 0; i--) {
dat = wrdata >> i;
i2c_master_setDC(dat, 0);
i2c_master_wait(1);//数据建立时间100ns
i2c_master_setDC(dat, 1);
i2c_master_wait(1);//SCL时钟高电平周期0.6us
i2c_master_setDC(dat, 0);
i2c_master_wait(1);//SCL时钟低电平周期1.3us+数据保持时间max0.9us
}
}
/******************************************************************************
* FunctionName : i2c_master_checkAck
* Description : get dev response
* Parameters : NONE
* Returns : true : get ack ; false : get nack
*******************************************************************************/
bool ICACHE_FLASH_ATTR
i2c_master_checkAck(void)//检查从机应答状态
{
if(i2c_master_getAck()){
return FALSE;
}else{
return TRUE;
}
}
/******************************************************************************
* FunctionName : i2c_master_getAck
* Description : confirm if peer send ack
* Parameters : NONE
* Returns : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)//第九个时钟获取应答状态
{
uint8 retVal;
i2c_master_setDC(0, 0);
i2c_master_wait(1);
i2c_master_setDC(1, 1);
i2c_master_wait(1);
retVal = i2c_master_getDC();
i2c_master_setDC(0, 0);
i2c_master_wait(1);
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_stop
* Description : set i2c to stop sending state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_start(void)
{
i2c_master_setDC(1, 0);
i2c_master_wait(1);
i2c_master_setDC(1, 1);
i2c_master_wait(1); // 一个重复起始信号的建立时间0.6us
i2c_master_setDC(0, 1);
i2c_master_wait(1); // 起始信号的保持时间0.6us,在这段时间过后可产生第一个时钟脉冲
i2c_master_setDC(0, 0);
i2c_master_wait(1); // 起始信号的保持时间0.6us,在这段时间过后可产生第一个时钟脉冲
}
/******************************************************************************
* FunctionName : i2c_master_writeByte
* Description : write wrdata value(one byte) into i2c
* Parameters : uint8 wrdata - write value
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(uint8 wrdata)//向i2c写数据
{
uint8 dat;
sint8 i;
for (i = 7; i >= 0; i--) {
dat = wrdata >> i;
i2c_master_setDC(dat, 0);
i2c_master_wait(1);//数据建立时间100ns
i2c_master_setDC(dat, 1);
i2c_master_wait(1);//SCL时钟高电平周期0.6us
i2c_master_setDC(dat, 0);
i2c_master_wait(1);//SCL时钟低电平周期1.3us+数据保持时间max0.9us
}
}
/******************************************************************************
* FunctionName : i2c_master_checkAck
* Description : get dev response
* Parameters : NONE
* Returns : true : get ack ; false : get nack
*******************************************************************************/
bool ICACHE_FLASH_ATTR
i2c_master_checkAck(void)//检查从机应答状态
{
if(i2c_master_getAck()){
return FALSE;
}else{
return TRUE;
}
}
/******************************************************************************
* FunctionName : i2c_master_getAck
* Description : confirm if peer send ack
* Parameters : NONE
* Returns : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)//第九个时钟获取应答状态
{
uint8 retVal;
i2c_master_setDC(0, 0);
i2c_master_wait(1);
i2c_master_setDC(1, 1);
i2c_master_wait(1);
retVal = i2c_master_getDC();
i2c_master_setDC(0, 0);
i2c_master_wait(1);
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_stop
* Description : set i2c to stop sending state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_stop(void)
{
i2c_master_setDC(0, 0);
i2c_master_wait(1);
i2c_master_setDC(0, 1);
i2c_master_wait(1); // 终止信号的建立时间0.6us
i2c_master_setDC(1, 1);
i2c_master_wait(1); // 在一个终止信号和起始信号之间总线必须空闲的时间1.6us
}
/******************************************************************************
* FunctionName : i2c_master_setAck
* Description : set ack to i2c bus as level value
* Parameters : uint8 level - 0 or 1
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(uint8 level)//设置主机应答方式
{
i2c_master_setDC(level, 0);
i2c_master_wait(1); // 数据建立时间100ns
i2c_master_setDC(level, 1);
i2c_master_wait(1); //SCL时钟信号高电平周期
i2c_master_setDC(level, 0);
i2c_master_wait(1); //数据保持时间max0.9us
i2c_master_setDC(1, 0);
}
/******************************************************************************
* FunctionName : i2c_master_send_ack
* Description : response ack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_ack(void)//i2c主机应答
{
i2c_master_setAck(0x0);
}
/******************************************************************************
* FunctionName : i2c_master_send_nack
* Description : response nack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_nack(void)//i2c主机非应答
{
i2c_master_setAck(0x1);
}
/******************************************************************************
* FunctionName : i2c_master_readByte
* Description : read Byte from i2c bus
* Parameters : NONE
* Returns : uint8 - readed value
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_readByte(void)//向i2c总线读数据
{
uint8 retVal = 0;
uint8 k, i;
for (i = 0; i < 8; i++) {
i2c_master_setDC(1, 1);
i2c_master_wait(1); //SCL时钟信号高电平周期
k = i2c_master_getDC();
i2c_master_setDC(1, 0);
i2c_master_wait(1); //SCL时钟信号低电平周期
k <<= (7 - i);
retVal |= k;
}
return retVal;
}
- i2c_ds3231.h
/*
* i2c_ds3231.h
*
* Created on: 2018年12月14日
* Author: 王杰龙
*/
#ifndef APP_INCLUDE_DRIVER_I2C_DS3231_H_
#define APP_INCLUDE_DRIVER_I2C_DS3231_H_
#define address 0xd0 //ds3231地址
void ds3231_write(unsigned char Command , unsigned char Data);
unsigned char ds3231_read(unsigned char Command);//读寄存器数据
unsigned int ds3231_read_temperature(void);//读温度
void ds3231_init(unsigned char year,unsigned char month,unsigned char date,unsigned char hour,unsigned char minute,unsigned char second,unsigned char day);
#endif /* APP_INCLUDE_DRIVER_I2C_DS3231_H_ */
- i2c_ds3231.c
* i2c_ds3231.c
*
* Created on: 2018年12月14日
* Author: 王杰龙
*/
#include "driver/i2c_ds3231.h"
#include "c_types.h"
void ICACHE_FLASH_ATTR
ds3231_write(uint8 Command , uint8 Data){
i2c_master_start();
i2c_master_writeByte(address&0xfe);//写
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(Command);//写寄存器地址
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(Data);//写寄存器地址
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_stop();
}
/*
* 功能:读计时寄存器的时间数据
* 参数:Command,寄存器的地址
* 返回:时间数据
*/
uint8 ICACHE_FLASH_ATTR
ds3231_read(uint8 Command){
uint8 temp;
i2c_master_start();
i2c_master_writeByte(address&0xfe);//写
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
}
i2c_master_writeByte(Command);//写寄存器地址
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
}
i2c_master_start();
i2c_master_writeByte(address|0x01);//读寄存器数据
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
}
temp=i2c_master_readByte();
i2c_master_send_nack();
i2c_master_stop();
return temp;
}
uint32 ICACHE_FLASH_ATTR
ds3231_read_temperature(void){//读温度
uint32 temp;
ds3231_write(0x0e,(ds3231_read(0x0e)|0x20));//开启温度转换
temp=ds3231_read(0x11);//读温度高8位
temp<<=8;
temp|=(ds3231_read(0x12)>>6);//读温度低8位并将最高两位数据移到低两位
return temp;
}
void ICACHE_FLASH_ATTR
ds3231_init(unsigned char year,unsigned char month,unsigned char date,unsigned char hour,unsigned char minute,unsigned char second,unsigned char day){
i2c_master_start();
i2c_master_writeByte(address&0xfe);//写
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(0x00);//写寄存器地址
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(second);//写秒
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(minute);//写分
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(hour);//写时
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(day);//写星期
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(date);//写日
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(month);//写月
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_writeByte(year);//写年
if(!i2c_master_checkAck()) {
i2c_master_stop();//如果从设备未应答,将设备停止
return ;
}
i2c_master_stop();
}
- user_main.c
#include "osapi.h"
#include "user_interface.h"
#include "driver/i2c_master.h"
uint32 priv_param_start_sec;
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
priv_param_start_sec = 0x3C;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
priv_param_start_sec = 0x7C;
break;
case FLASH_SIZE_16M_MAP_512_512:
rf_cal_sec = 512 - 5;
priv_param_start_sec = 0x7C;
break;
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
priv_param_start_sec = 0xFC;
break;
case FLASH_SIZE_32M_MAP_512_512:
rf_cal_sec = 1024 - 5;
priv_param_start_sec = 0x7C;
break;
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
priv_param_start_sec = 0xFC;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
priv_param_start_sec = 0xFC;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
priv_param_start_sec = 0xFC;
break;
default:
rf_cal_sec = 0;
priv_param_start_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
LOCAL os_timer_t timer;
void ICACHE_FLASH_ATTR
timer_cb(void){
uint32 temp=ds3231_read_temperature();
unsigned int high = 0 ;
unsigned int low = 0 ;
high = ((temp >> 8 )& 0xff);
low = (temp&0xff) ;
os_printf("temperature_HEX:0x%x\n",temp);
os_printf("temperature:%d.%d\n",high,low*25);
}
void ICACHE_FLASH_ATTR
user_init(void)
{
i2c_master_gpio_init();
os_delay_us(60000);
os_delay_us(60000);
ds3231_init(0x18,0x12,0x16,0x01,0x13,0x00,0x07);
os_timer_disarm (&timer);
os_timer_setfn(&timer,(os_timer_func_t *)timer_cb,NULL);
os_timer_arm(&timer,1000,1);
}
串口输出温度值: