STM32F407库函数通过软件模拟IO口的IIC通信如何读取INA260寄存器内的数据的具体代码
时间: 2023-07-16 19:15:00 浏览: 117
STM32F407 软件模拟IIC通信程序
以下是一个使用STM32F407库函数通过软件模拟IO口的I2C通信读取INA260寄存器数据的示例代码:
```c
#include "stm32f4xx.h"
#define INA260_I2C_ADDR (0x40 << 1)
void delay_us(uint32_t us)
{
uint32_t count = 0;
const uint32_t ticks = SystemCoreClock / 1000000;
while (count++ < (ticks*us));
}
void I2C_Start(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_6);
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_6);
delay_us(10);
}
void I2C_Stop(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_SetBits(GPIOB, GPIO_Pin_6);
delay_us(10);
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
}
void I2C_Ack(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
}
void I2C_NAck(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_7);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
}
uint8_t I2C_WaitAck(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5))
{
I2C_Stop();
return 1;
}
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
return 0;
}
void I2C_SendByte(uint8_t byte)
{
for (uint8_t i = 0; i < 8; i++)
{
if (byte & 0x80)
{
GPIO_SetBits(GPIOB, GPIO_Pin_6);
}
else
{
GPIO_ResetBits(GPIOB, GPIO_Pin_6);
}
delay_us(10);
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
byte <<= 1;
}
}
uint8_t I2C_ReadByte(void)
{
uint8_t byte = 0;
GPIO_ResetBits(GPIOB, GPIO_Pin_6);
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
for (uint8_t i = 0; i < 8; i++)
{
byte <<= 1;
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5))
{
byte |= 0x01;
}
GPIO_SetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
delay_us(10);
}
return byte;
}
void I2C_WriteReg(uint8_t reg, uint16_t value)
{
I2C_Start();
I2C_SendByte(INA260_I2C_ADDR);
if (I2C_WaitAck())
{
return;
}
I2C_SendByte(reg);
I2C_WaitAck();
I2C_SendByte(value >> 8);
I2C_WaitAck();
I2C_SendByte(value & 0xFF);
I2C_WaitAck();
I2C_Stop();
}
uint16_t I2C_ReadReg(uint8_t reg)
{
uint16_t value = 0;
I2C_Start();
I2C_SendByte(INA260_I2C_ADDR);
if (I2C_WaitAck())
{
return 0;
}
I2C_SendByte(reg);
I2C_WaitAck();
I2C_Start();
I2C_SendByte(INA260_I2C_ADDR | 0x01);
I2C_WaitAck();
value |= (uint16_t)(I2C_ReadByte() << 8);
I2C_Ack();
value |= I2C_ReadByte();
I2C_NAck();
I2C_Stop();
return value;
}
int main(void)
{
// 初始化GPIO
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// INA260复位
I2C_WriteReg(0x00, 0x8000);
// 设置INA260配置寄存器
I2C_WriteReg(0x05, 0x0000); // Average 1, Conversion time 140us, Continuous mode
I2C_WriteReg(0x06, 0x0C00); // Shunt and bus ADC resolution 18 bits
// 读取INA260电流值
uint16_t current = I2C_ReadReg(0x01);
while (1);
}
```
以上代码使用GPIO模拟I2C总线,并通过软件实现I2C通信协议。由于STM32F407的GPIO输出电平范围为0V和3.3V,因此需要使用开漏输出模式,并且通过外部上拉电阻将总线拉高。在代码中,使用`GPIO_Pin_5`模拟I2C总线的SDA信号,使用`GPIO_Pin_6`模拟I2C总线的SCL信号。
在`main`函数中,首先对INA260进行复位操作,然后设置INA260的配置寄存器以选择采样精度和采样时间。最后,通过读取INA260的电流寄存器来获取电流值。
阅读全文