You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
8.5 KiB
294 lines
8.5 KiB
#include "bsp_i2c_soft.h"
|
|
#include "elog.h"
|
|
// #include "delay.h"
|
|
|
|
void IIC_Init(const IIC_SOFT_TypeDef *pSoftIIC )
|
|
{
|
|
GPIO_InitTypeDef GPIO_Initure;
|
|
|
|
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
|
|
|
|
//PB6 SCL PB7初始化设置
|
|
GPIO_Initure.Pin = pSoftIIC->scl_pin ;
|
|
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
|
|
GPIO_Initure.Pull = GPIO_PULLUP; // 上拉
|
|
GPIO_Initure.Speed = GPIO_SPEED_FAST; // 快速
|
|
HAL_GPIO_Init( pSoftIIC->scl_port, &GPIO_Initure );
|
|
|
|
// SDA PB7 初始化设置
|
|
GPIO_Initure.Pin = pSoftIIC->sda_pin;
|
|
HAL_GPIO_Init( pSoftIIC->sda_port, &GPIO_Initure );
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
}
|
|
|
|
|
|
int IIC_READ_SDA_Pin(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
return HAL_GPIO_ReadPin(pSoftIIC->sda_port,pSoftIIC->sda_pin);
|
|
}
|
|
|
|
int IIC_SDA_Mode_In(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
// 取针脚号 pin6 的值为 2^6
|
|
// GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);
|
|
pSoftIIC->sda_port->MODER&=~(3<<(pSoftIIC->sda_pin_num*2));
|
|
pSoftIIC->sda_port->MODER|=0<<pSoftIIC->sda_pin_num*2;
|
|
}
|
|
int IIC_SDA_Mode_Out(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
// GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);
|
|
pSoftIIC->sda_port->MODER&=~(3<<(pSoftIIC->sda_pin_num*2));
|
|
pSoftIIC->sda_port->MODER|=1<<pSoftIIC->sda_pin_num*2;
|
|
}
|
|
//产生IIC起始信号
|
|
void IIC_Start(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
// SDA_OUT();//sda线输出
|
|
IIC_SDA_Mode_Out( pSoftIIC); //sda线输出
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
delay_us(4);
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 0); //START:when CLK is high,DATA change form high to low
|
|
delay_us(4);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);//钳住I2C总线,准备发送或接收数据
|
|
}
|
|
|
|
//产生IIC停止信号
|
|
void IIC_Stop(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
// SDA_OUT();//sda线输出
|
|
IIC_SDA_Mode_Out( pSoftIIC); //sda线输出
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 0);//STOP:when CLK is high DATA change form low to high
|
|
delay_us(4);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);//发送I2C总线结束信号
|
|
delay_us(4);
|
|
}
|
|
//等待应答信号到来
|
|
//返回值:1,接收应答失败
|
|
// 0,接收应答成功
|
|
int IIC_Wait_Ack(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
uint8_t ucErrTime=0;
|
|
// SDA_IN(); //SDA设置为输入
|
|
IIC_SDA_Mode_In( pSoftIIC); //SDA设置为输入
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);delay_us(1);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);delay_us(1);
|
|
while(IIC_READ_SDA_Pin(pSoftIIC))
|
|
// while( READ_SDA() )
|
|
{
|
|
ucErrTime++;
|
|
if(ucErrTime>250)
|
|
{
|
|
IIC_Stop(pSoftIIC);
|
|
return 1;
|
|
}
|
|
}
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);//时钟输出0
|
|
return 0;
|
|
}
|
|
//产生ACK应答
|
|
void IIC_Ack(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
|
|
// SDA_OUT();//sda线输出
|
|
IIC_SDA_Mode_Out( pSoftIIC); //sda线输出
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 0);
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
}
|
|
//不产生ACK应答
|
|
void IIC_NAck(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
|
|
// SDA_OUT();//sda线输出
|
|
IIC_SDA_Mode_Out( pSoftIIC); //sda线输出
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, 1);
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
}
|
|
//IIC发送一个字节
|
|
//返回从机有无应答
|
|
//1,有应答
|
|
//0,无应答
|
|
int IIC_Send_Byte(const IIC_SOFT_TypeDef *pSoftIIC, uint8_t txd)
|
|
{
|
|
uint8_t t;
|
|
// SDA_OUT();//sda线输出
|
|
IIC_SDA_Mode_Out( pSoftIIC); //sda线输出
|
|
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);//拉低时钟开始数据传输
|
|
for(t=0;t<8;t++)
|
|
{
|
|
// IIC_SDA=(txd&0x80)>>7;
|
|
// IIC_SDA( (txd&0x80)>>7);
|
|
GPIO_WRITE_PIN(pSoftIIC->sda_port, pSoftIIC->sda_pin, (txd&0x80)>>7 );
|
|
txd<<=1;
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
delay_us(2);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int IIC_Read_Byte( const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
unsigned char i,receive=0;
|
|
|
|
// SDA_IN(); //SDA设置为输入
|
|
IIC_SDA_Mode_In( pSoftIIC); //SDA设置为输入
|
|
|
|
for(i=0;i<8;i++ )
|
|
{
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 0);
|
|
delay_us(2);
|
|
GPIO_WRITE_PIN(pSoftIIC->scl_port, pSoftIIC->scl_pin, 1);
|
|
receive<<=1;
|
|
if(IIC_READ_SDA_Pin(pSoftIIC))receive++;
|
|
// if( READ_SDA() )receive++;
|
|
|
|
delay_us(1);
|
|
}
|
|
|
|
return receive;
|
|
}
|
|
|
|
// 发送Slave_Addr 带应答, 兼容7bit 10bit
|
|
int IIC_Send_Slave_Addr(const IIC_SOFT_TypeDef *pSoftIIC,uint8_t r_w)
|
|
{
|
|
if( pSoftIIC->slave_address_width == I2C_SW_Slave_Address_7Bit )
|
|
{
|
|
log_i("salve adrr %02X %02X",pSoftIIC->addr, (pSoftIIC->addr << 1)|r_w);
|
|
IIC_Send_Byte(pSoftIIC, (pSoftIIC->addr << 1) | r_w);
|
|
if(IIC_Wait_Ack(pSoftIIC)) { IIC_Stop(pSoftIIC); return -1;};
|
|
}
|
|
else if( pSoftIIC->slave_address_width == I2C_SW_Slave_Address_10Bit )
|
|
{
|
|
uint8_t h_addr = 0x0F00 | ((pSoftIIC->addr >> 8 & 0x03) << 2) | r_w;
|
|
IIC_Send_Byte(pSoftIIC, h_addr);
|
|
if(IIC_Wait_Ack(pSoftIIC)) { IIC_Stop(pSoftIIC); return -1;};
|
|
|
|
uint8_t l_addr = pSoftIIC->addr & 0xff;
|
|
IIC_Send_Byte(pSoftIIC, l_addr);
|
|
if(IIC_Wait_Ack(pSoftIIC)) { IIC_Stop(pSoftIIC); return -1;};
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// 发送reg_addr 带应答, 兼容8bit 16bit 32bit
|
|
int IIC_Send_Reg_Addr( const IIC_SOFT_TypeDef *pSoftIIC, uint32_t reg_addr )
|
|
{
|
|
for(int j = 0; j < pSoftIIC->slave_reg_addr_width; j++)
|
|
{
|
|
uint8_t offset = (pSoftIIC->slave_reg_addr_width - 1 - j) * 8;
|
|
uint8_t temp_reg_addr = (reg_addr >> offset) & 0xff;
|
|
|
|
IIC_Send_Byte(pSoftIIC, temp_reg_addr);
|
|
if(IIC_Wait_Ack(pSoftIIC)) { IIC_Stop(pSoftIIC); return -1;};
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int IIC_Send_One_Reg_Value( const IIC_SOFT_TypeDef *pSoftIIC, uint32_t reg_val )
|
|
{
|
|
for(int k = 0; k < pSoftIIC->slave_reg_value_width; k++)
|
|
{
|
|
uint8_t offset = (pSoftIIC->slave_reg_value_width - 1 - k) * 8;
|
|
|
|
i2c_send_byte(pSoftIIC, (reg_val >> offset) & 0xff);
|
|
if(!i2c_wait_ack(pSoftIIC))
|
|
return false;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int IIC_Send_Receive_One_Reg_Value( const IIC_SOFT_TypeDef *pSoftIIC, uint32_t* reg_val, uint8_t ack )
|
|
{
|
|
for(int k = 0; k < pSoftIIC->slave_reg_value_width; k++)
|
|
{
|
|
uint8_t offset = (pSoftIIC->slave_reg_value_width - 1 - k) * 8;
|
|
*reg_val |= (IIC_Read_Byte(pSoftIIC) << offset);
|
|
|
|
if(ack)
|
|
i2c_ack(pSoftIIC);
|
|
else
|
|
i2c_no_ack(pSoftIIC);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int IIC_Write_Buf(const IIC_SOFT_TypeDef *pSoftIIC , uint32_t reg_addr, uint8_t *buf, uint8_t len)
|
|
{
|
|
IIC_Start(pSoftIIC);
|
|
|
|
IIC_Send_Slave_Addr( pSoftIIC,I2C_WRITE );
|
|
IIC_Send_Reg_Addr( pSoftIIC, reg_addr );
|
|
|
|
for (size_t i = 0; i < len; i++)
|
|
{
|
|
IIC_Send_Byte(pSoftIIC,*buf);
|
|
if(IIC_Wait_Ack(pSoftIIC)) { IIC_Stop(pSoftIIC); return -1;};
|
|
}
|
|
|
|
IIC_Stop(pSoftIIC);//产生一个停止条件
|
|
// HAL_Delay( 200 );
|
|
// delay_us(6000);
|
|
return 0;
|
|
}
|
|
|
|
// 寄存器地址 8位置
|
|
int IIC_Read_Buf(const IIC_SOFT_TypeDef *pSoftIIC, uint32_t reg_addr, uint8_t *buf, uint8_t len)
|
|
{
|
|
uint8_t temp=0;
|
|
|
|
IIC_Start(pSoftIIC);
|
|
IIC_Send_Slave_Addr( pSoftIIC,I2C_WRITE );
|
|
IIC_Send_Reg_Addr( pSoftIIC, reg_addr );
|
|
|
|
IIC_Start(pSoftIIC);
|
|
IIC_Send_Slave_Addr( pSoftIIC,I2C_READ );
|
|
for(int i=0; i<len-1; i++)
|
|
{
|
|
*buf=IIC_Read_Byte(pSoftIIC);
|
|
IIC_Ack(pSoftIIC); // 应答
|
|
buf++;
|
|
}
|
|
*buf = IIC_Read_Byte(pSoftIIC);// 读非应答
|
|
IIC_NAck(pSoftIIC);
|
|
// if(IIC_Wait_Ack()) { IIC_Stop(); return -1;};
|
|
|
|
IIC_Stop(pSoftIIC);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int IIC_Device_Check(const IIC_SOFT_TypeDef *pSoftIIC)
|
|
{
|
|
uint8_t ret = 0;
|
|
IIC_Start(pSoftIIC);
|
|
|
|
ret = IIC_Send_Slave_Addr( pSoftIIC,I2C_WRITE );
|
|
|
|
IIC_Stop(pSoftIIC);
|
|
|
|
return ret;
|
|
} |