STM32与测温芯片ADT7410通过模拟IIC通信

举报
kobesdu 发表于 2022/01/29 13:24:18 2022/01/29
【摘要】 ADT7410是一款基于SOIC封装的高精度数字温度传感器。它内部具有带隙温度参考源以及13位ADC,可以提高0.0625摄氏度的温度精度。 他的通信接口是IIC总线。I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。两根线是SDA(串行数据线)和SCL(串行时钟线) 根据数据手册,iic通信时序如下 按照他的通信时序...

ADT7410是一款基于SOIC封装的高精度数字温度传感器。它内部具有带隙温度参考源以及13位ADC,可以提高0.0625摄氏度的温度精度。 他的通信接口是IIC总线。I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。两根线是SDA(串行数据线)和SCL(串行时钟线) 根据数据手册,iic通信时序如下

1632892334(1).png

按照他的通信时序,实现iic通信如下

#include "stm32f10x_gpio.h"
 #define GPIO_PORT_I2C GPIOC/* GPIO端口 / 
#define RCC_I2C_PORT RCC_APB2Periph_GPIOC/ GPIO端口时钟
 / #define I2C_SCL_PIN GPIO_Pin_0 / 连接到SCL时钟线的GPIO 
/ #define I2C_SDA_PIN GPIO_Pin_13 / 连接到SDA数据线的GPIO */

#define I2C_SCL_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SCL_PIN)/* SCL = 1 
/ #define I2C_SCL_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SCL_PIN)/ SCL = 0 */

#define I2C_SDA_1() GPIO_SetBits(GPIO_PORT_I2C, I2C_SDA_PIN)/* SDA = 1 /
 #define I2C_SDA_0() GPIO_ResetBits(GPIO_PORT_I2C, I2C_SDA_PIN)/ SDA = 0 */

#define I2C_SDA_READ() GPIO_ReadInputDataBit(GPIO_PORT_I2C, I2C_SDA_PIN)/* 读SDA口线状态 */

extern void delay(unsigned int num);

typedef struct 
{ 
char (*init) (void); float (*read_temperature)(void);

}IIC_SIMULATION_T;

extern IIC_SIMULATION_T *IIC_Simulation;

#include "DeviceSimulationIICDriver.h"

/*

函 数 名: i2c_Delay
功能说明: I2C总线位延迟,最快400KHz
形 参:无
返 回 值: 无

*/ static void i2c_Delay(void) { uint8_t i;

/*  下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。 CPU主频72MHz时,在内部Flash运行, MDK工程不优化 循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us

IAR工程编译效率高,不能设置为7 */ for (i = 0; i < 10; i++); }

/*

函 数 名: i2c_Start
功能说明: CPU发起I2C总线启动信号
形 参:无
返 回 值: 无

/ void i2c_Start(void)
 { / 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
 I2C_SCL_1(); I2C_SDA_1(); 
i2c_Delay(); I2C_SDA_0(); 
// i2c_Delay(); 
// I2C_SCL_0(); 
// i2c_Delay(); }

/*

函 数 名: i2c_Start
功能说明: CPU发起I2C总线停止信号
形 参:无
返 回 值: 无

/ void i2c_Stop(void) 
{ / 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
 I2C_SCL_1(); 
I2C_SDA_0(); 
i2c_Delay(); 
I2C_SDA_1(); 
}

/*

函 数 名: i2c_SendByte
功能说明: CPU向I2C总线设备发送8bit数据
形 参:_ucByte : 等待发送的字节
返 回 值: 无

*/ void i2c_SendByte(uint8_t _ucByte) 
{ uint8_t i;

/* 先发送字节的高位bit7 / for (i = 0; i < 8; i++) { I2C_SCL_0(); i2c_Delay(); if (_ucByte & 0x80) { I2C_SDA_1(); } else { I2C_SDA_0(); } i2c_Delay(); I2C_SCL_1(); i2c_Delay(); I2C_SCL_0(); if (i == 7) { I2C_SDA_1(); // 释放总线 } _ucByte <<= 1; / 左移一个bit */ i2c_Delay(); } }

/*

函 数 名: i2c_ReadByte
功能说明: CPU从I2C总线设备读取8bit数据
形 参:无
返 回 值: 读到的数据

*/ uint8_t i2c_ReadByte(void) { uint8_t i; uint8_t value;

/* 读到第1个bit为数据的bit7 */ 
value = 0; 
I2C_SCL_1();
 i2c_Delay(); 
for
 (i = 0; i < 8; i++)
 { 
value <<= 1; 
I2C_SCL_1();
 i2c_Delay(); 
if (I2C_SDA_READ())
 { value++; } 
I2C_SCL_0();
 i2c_Delay(); 
} return value; 
}

/*

函 数 名: i2c_WaitAck
功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
形 参:无
返 回 值: 返回0表示正确应答,1表示无器件响应

*/ uint8_t i2c_WaitAck(void) { uint8_t re;

I2C_SDA_1(); /* CPU释放SDA总线 
/ i2c_Delay(); I2C_SCL_1(); / CPU驱动SCL = 1, 此时器件会返回ACK应答 / i2c_Delay(); if (I2C_SDA_READ()) / CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } I2C_SCL_0(); i2c_Delay(); return re; }

/*

函 数 名: i2c_Ack
功能说明: CPU产生一个ACK信号
形 参:无
返 回 值: 无

/ void i2c_Ack(void)
 { I2C_SDA_0(); / CPU驱动SDA = 0 / i2c_Delay(); I2C_SCL_1(); / CPU产生1个时钟 / i2c_Delay(); I2C_SCL_0(); i2c_Delay(); I2C_SDA_1(); / CPU释放SDA总线 */ }

/*

函 数 名: i2c_NAck
功能说明: CPU产生1个NACK信号
形 参:无
返 回 值: 无

/ void i2c_NAck(void)
 { I2C_SDA_1(); / CPU驱动SDA = 1 /
 i2c_Delay(); 
I2C_SCL_1(); / CPU产生1个时钟 */ 
i2c_Delay(); 
I2C_SCL_0(); 
i2c_Delay(); }

/*

函 数 名: i2c_CfgGpio
功能说明: 配置I2C总线的GPIO,采用模拟IO的方式实现
形 参:无
返 回 值: 无

*/ void iic_init(void) 
{ GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE); /* 打开GPIO时钟 */

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; 
/* 开漏输出 */ 
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);

/* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */ i2c_Stop(); }

/*

函 数 名: i2c_CheckDevice
功能说明: 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在
形 参:_Address:设备的I2C总线地址
返 回 值: 返回值 0 表示正确, 返回1表示未探测到

*/ uint8_t i2c_CheckDevice(uint8_t _Address) { uint8_t ucAck;

// i2c_CfgGpio();/* 配置GPIO */

i2c_Start(); /* 发送启动信号 */

/* 发送设备地址+读写控制bit(0 = w, 1 = r) bit7 先传 / i2c_SendByte(_Address | 0); ucAck = i2c_WaitAck(); / 检测设备的ACK应答 */

i2c_Stop(); /* 发送停止信号 */

return ucAck; }

static float read_temperature() 
{
 float num,read_h,read_l; 
i2c_Start(); 
i2c_SendByte((0x48<<1));
 if (i2c_WaitAck() != 0)
 { return 0; } i
2c_SendByte(0x00); 
if (i2c_WaitAck() != 0) { return 0; }
 // i2c_Stop(); i2c_Start();
 i2c_SendByte((0x48<<1)|1); 
if (i2c_WaitAck() != 0)
 { return 0; } read_h=i2c_ReadByte();
 i2c_Stop(); 
// if (i2c_WaitAck() != 0) 
// { // return 0; // } 
i2c_Start();
 i2c_SendByte((0x48<<1));
 if (i2c_WaitAck() != 0) 
{ return 0; } 
i2c_SendByte(0x01);
 if (i2c_WaitAck() != 0) 
{ return 0; }

// i2c_Stop(); 
i2c_Start();
 i2c_SendByte((0x48<<1)|1);
 if (i2c_WaitAck() != 0) { return 0; } r
ead_l=i2c_ReadByte(); i2c_Stop(); 
num=read_h*256+read_l;
 if(num<32768) {
num=num/128; } 
else {
num=(num-65536)/128;
} delay_ms(10); 
// delay(999); 
// delay(999); 
return num;

}

static char adt7410_init() {

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);

// GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
// GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure); // // GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);

i2c_Stop();

i2c_Start(); i2c_SendByte(0x48<<1); if (i2c_WaitAck() != 0) { return 1; }

i2c_SendByte(0x03); if (i2c_WaitAck() != 0) { return 1; } i2c_SendByte(0xc0); if (i2c_WaitAck() != 0) { return 1; } i2c_Stop(); return 0;

}

IIC_SIMULATION_T IIC_init = { .init = adt7410_init, .read_temperature = read_temperature, };

IIC_SIMULATION_T *IIC_Simulation=&IIC_init;
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。