有哪位朋友做过STM32的IO口模拟I2C读取BQ34Z100电量计数据吗,在下老读到数据时0xffff
#include "config.h"
extern unsigned char TxData[BUFFERSIZE];
extern unsigned char RxData[BUFFERSIZE];
void BQ34Z100_I2C_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
I2C_SCL_H;
I2C_SDA_H;
}
/**********************************************************
I2C_SDA_OUT初始化函数
**************************************************************/
void BQ34Z100_I2C_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/**********************************************************
I2C_SDA_IN初始化函数
**************************************************************/
void BQ34Z100_I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
//void MSP430_SWI2CMST_delay(void)
//{
// __delay_cycles(GPIODELAYCYCLES); // Quick delay
//}
void BQ34Z100_I2C_start(void)
{
BQ34Z100_I2C_SDA_OUT();
I2C_SDA_H;
I2C_SCL_H;
delay_us(4);
I2C_SDA_L;
delay_us(4);
I2C_SCL_L;
delay_us(4);
}
void BQ34Z100_I2C_stop(void)
{
BQ34Z100_I2C_SDA_OUT();
I2C_SDA_L;
delay_us(4);
I2C_SCL_H;
delay_us(4);
I2C_SDA_H;
delay_us(4);
}
unsigned char BQ34Z100_I2C_txByte(unsigned char data)
{
unsigned char bits, temp, ack;
I2C_SCL_L;
temp = data; // Initialize temp variable
bits = 0x08;
BQ34Z100_I2C_SDA_OUT(); // Load I2C bit counter
while (bits != 0x00) // Loop until all bits are shifted
{
if (temp & 0x80) // Test data bit
I2C_SDA_H; // SDA = 1
else
I2C_SDA_L; // SDA = 0
delay_us(4); // Quick delay
I2C_SCL_H; // SCL = 1
// while (I2C_SCL_READ() == 0); //111去掉 Wait for any SCL clock stretching change1
delay_us(4); // Quick delay
temp = (temp << 1); // Shift bits 1 place to the left
I2C_SCL_L; // SCL = 0
bits = (bits - 1); // Loop until 8 bits are sent
}
delay_us(4);// I2CDELAY;
I2C_SDA_H; // SDA = 1
I2C_SCL_H;
// while (I2C_SCL_READ() == 0); // Wait for any SCL clock stretchingchange2
delay_us(4); // Quick delay
ack=I2C_SDA_READ(); // Read ACK state from Slave
I2C_SCL_L; // SCL = 0
if (ack) // Return ACK state to calling app
return (1);
else
return (0);
}
unsigned char BQ34Z100_I2C_rxByte(char ack)
{
unsigned char bits, data = 0;
BQ34Z100_I2C_SDA_IN();
I2C_SDA_H; // SDA = 1
bits = 0x08; // Load I2C bit counter
while (bits > 0) // Loop until all bits are read
{
I2C_SCL_H; // SCL = 1
// while (I2C_SCL_READ() == 0); // while ((PxIN & SCL) == 0); 111去掉 // Wait for any SCL clock stretchingchange3
delay_us(4); // Quick delay
data = (data << 1); // Shift bits 1 place to the left
if(I2C_SDA_READ()==1) // Check digital input
data = (data + 1); // If input is high, store a '1'
I2C_SCL_L; // SCL = 0
delay_us(4); // Quick delay
bits = (bits - 1); // Decrement I2C bit counter
}
if (ack) // Need to send ACK to Slave?
I2C_SDA_L;/ // Yes, so pull SDA low
else
I2C_SDA_H; // No, so keep SDA high
I2C_SCL_H; // SCL = 1
delay_us(4); // Equivalent to sending N(ACK)
I2C_SCL_L; // SCL = 0
I2C_SDA_H; // SDA = 1
return (data); // Return 8-bit data byte
}
void BQ34Z100_I2C_writeBlock(unsigned char SlaveAddress,
unsigned int numBytes, unsigned char multi,
void* TxData)
{
unsigned int i;
unsigned char *temp;
temp = (unsigned char *)TxData; // Initialize array pointer
BQ34Z100_I2C_start(); // Send Start condition
BQ34Z100_I2C_txByte(SlaveAddress); // [ADDR] + R/W bit = 0
for (i = 0; i < numBytes; i++)
{
BQ34Z100_I2C_txByte(*(temp)); // Send data and ack
temp++; // Increment pointer to next element
}
if (multi == 0) // Need STOP condition?
{
BQ34Z100_I2C_stop(); // Yes, send STOP condition
}
delay_us(4);// I2CDELAY; // Quick delay
}
void BQ34Z100_I2C_readBlock(unsigned char SlaveAddress,
unsigned int numBytes, void* RxData)
{
unsigned int i;
unsigned char* temp;
temp = (unsigned char *)RxData; // Initialize array pointer
BQ34Z100_I2C_start(); // Send Start condition
BQ34Z100_I2C_txByte(SlaveAddress+0x01); // [ADDR] + R/W bit = 1
for (i = 0; i < numBytes; i++)
{
if (i == (numBytes - 1))
*(temp) = BQ34Z100_I2C_rxByte(0);// Read last 8-bit data with no ACK
else
*(temp) = BQ34Z100_I2C_rxByte(1);// Read 8-bit data & then send ACK
temp++; // Increment pointer to next element
}
BQ34Z100_I2C_stop(); // Send Stop condition
}
unsigned int transBytes2UnsignedInt(unsigned char msb, unsigned char lsb)
{
unsigned int tmp;
tmp = ((msb << 8) & 0xFF00);
return ((unsigned int)(tmp + lsb) & 0x0000FFFF);
}
void BQ34Z100_read(unsigned char cmd, unsigned int bytes)
{
unsigned char tx[1];
tx[0] = cmd;
BQ34Z100_I2C_writeBlock(I2CSLAVEADDR, 1, 1, tx);
BQ34Z100_I2C_readBlock(I2CSLAVEADDR, bytes, RxData);
}
主函数里:
BQ34Z100_read(0x0C, 2);//读取温度
vale= transBytes2UnsignedInt(RxData[1], RxData[0]);
我做过430 模拟 stm8 IIC 但是开发的不是这款片子 根据我之前遇到的问题 1 SMBbus 通信首先速率 大于10K?记不清了 小于100K 2 地址0x16 3类似IIC 从机有时会拉低时钟线 请求主机等待 这一点大多数人没留意 4 通信有时配置为有校验 我当时用EV2300通信示波器捕捉 拍照片比对 你就仿照波形去写代码 挺有效的 也是搞了好久成功 祝你成功
用STM32单片机模拟I2C,发送地址0xAA,BQ34Z100的SDA没有回复ACK
地址不对吧 对了就会有应答啊