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