stm32f767 实现模拟SMBUS驱动bq4050


#define SDA_IN() {GPIOB->MODER&=~(3<<(7*2));GPIOB->MODER|=0<<7*2;} //PB7输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(7*2));GPIOB->MODER|=1<<7*2;} //PB7输出模式
//IO操作
#define IIC_SCL(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET)) //SCL
#define IIC_SDA(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET)) //SDA
#define READ_SDA HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)    //输入SDA

//IIC初始化
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;

__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOH时钟

GPIO_Initure.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull = GPIO_PULLUP; //上拉
GPIO_Initure.Speed = GPIO_SPEED_HIGH; //快速
HAL_GPIO_Init(GPIOB, &GPIO_Initure);

IIC_SDA(1);
IIC_SCL(1);
}

//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SCL(0);
hrt_delay_us(2);
IIC_SDA(1);
hrt_delay_us(1);
IIC_SCL(1);
hrt_delay_us(9);
IIC_SDA(0);
hrt_delay_us(9);
IIC_SCL(0);//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT(); //sda线输出
IIC_SCL(0);
hrt_delay_us(1);
IIC_SDA(0); //STOP:when CLK is high DATA change form low to high
hrt_delay_us(9);
IIC_SCL(1);
hrt_delay_us(9);
IIC_SDA(1);//发送I2C总线结束信号
hrt_delay_us(9);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
uint8 IIC_Wait_Ack(void)
{
uint16 uErrTime=0;

SDA_IN(); //SDA设置为输入
IIC_SDA(1);
hrt_delay_us(9);
IIC_SCL(1);
hrt_delay_us(9);
while(READ_SDA)
{
uErrTime++;
if(uErrTime > 250)
{
IIC_Stop();
return 1;
}
//hrt_delay_us(1);
}
IIC_SCL(0); //时钟输出0
hrt_delay_us(2);

return 0;
}


//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(0);
hrt_delay_us(9);
IIC_SCL(1);
hrt_delay_us(9);
IIC_SCL(0);
}


//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(1);
hrt_delay_us(9);
IIC_SCL(1);
hrt_delay_us(9);
IIC_SCL(0);
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(uint8 txd)
{
uint8 t=0;

SDA_OUT();
IIC_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA((txd&0x80)>>7);
txd <<= 1;
hrt_delay_us(8);
IIC_SCL(1);
hrt_delay_us(8);
IIC_SCL(0);
hrt_delay_us(8);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK

uint8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i;
unsigned char recv=0;

SDA_IN(); //SDA设置为输入
for(i=0; i<8; i++)
{
IIC_SCL(0);
hrt_delay_us(12);
IIC_SCL(1);
recv <<= 1;
if(READ_SDA)
{
recv++;
}
hrt_delay_us(9);
}

return recv;
}void IIC_Write(unsigned char dat)

{
unsigned char t;
 
for(t=0; t<8; t++)
{
if(dat & 0x80)
{
       IIC_SDA(1);
    }
else
{
IIC_SDA(0);
}
delay_us(10);
IIC_SCL(1);
delay_us(10);
IIC_SCL(0);
delay_us(10);
dat <<= 1;
}
}

uint8 getBatteryInfo(uint8 slaveAddr, uint8 Comcode,uint8 *data, uint8 size)
{
uint8 ackFlag=0;
uint8_t buff[2];

IIC_Start();
IIC_Send_Byte(slaveAddr);//发送地址
IIC_Wait_Ack();
IIC_Send_Byte(Comcode);
IIC_Wait_Ack();
rt_thread_delay(1);
IIC_Start();
IIC_Send_Byte(slaveAddr+1);//发送地址
IIC_Wait_Ack();
rt_thread_delay(1);
while(size-1)
{
*data = IIC_Read_Byte(1);
IIC_Ack();
hrt_delay_us(10);
data++;
size--;
}
rt_thread_delay(1);
*data++ = IIC_Read_Byte(0);
IIC_Stop();
rt_thread_delay(5);
}

 

注意: 在SDA输入输出切换时,最好使用寄存器操作!!!


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM