新唐单片机模拟IIC读写INA220
*TPA626可做INA220的国产替代,一样可以用
#define SCL PA0
#define SDA PA1
#define NACK 1
#define ACK 0
#define INA220_CONFIG_REGISTER 0x00
#define INA220_SHUNT_VOLTAGE_REGISTER 0x01
#define INA220_BUS_VOLTAGE_REGISTER 0x02
#define INA220_POWER_REGISTER 0x03
#define INA220_CURRENT_REGISTER 0x04
#define INA220_CALIBRATION_REGISTER 0X05
//配置引脚
void anolog_iic_init(void)
{
GPIO_SetMode(PA, BIT0, GPIO_PMD_OUTPUT);
GPIO_SetMode(PA, BIT1, GPIO_PMD_QUASI);
}
//iic起始信号
void anolog_iic_start(void)
{
SCL = 1;
SDA = 1;
TIMER_Delay(TIMER3,4);
SDA = 0;
TIMER_Delay(TIMER3,4);
SCL = 0;
}
//iic停止信号
void anolog_iic_stop(void)
{
SCL = 0;
SDA = 0;
TIMER_Delay(TIMER3,4);
SCL = 1;
TIMER_Delay(TIMER3,4);
SDA = 1;
}
//等待应答
uint8_t anolog_iic_wait_ack(void)
{
uint8_t i = 0;
SDA = 1;
TIMER_Delay(TIMER3,4);
SCL = 1;
TIMER_Delay(TIMER3,4);
while(SDA){
i++;
DEBUG("wait %d ...\n",i);
if(i > 250){
anolog_iic_stop();
return NACK;
}
}
SCL = 0;
TIMER_Delay(TIMER3,4);
return ACK;
}
//主机发送NACK应答
void anolog_iic_send_nack(void)
{
SCL = 1;
SDA = 1;
TIMER_Delay(TIMER3,4);
SCL = 0;
SDA = 1; //更新:释放SDA,不然连续读可能出错
}
//主机发送ACK应答
void anolog_iic_send_ack(void)
{
SCL = 1;
SDA = 0;
TIMER_Delay(TIMER3,4);
SCL = 0;
SDA = 1; //更新:释放SDA,不然连续读可能出错
}
//iic往从机写一个字节
void anolog_iic_send_byte(uint8_t byte)
{
uint8_t i = 0;
DEBUG("iic send 0x%02x\n",byte);
for(i = 0; i<8; i++){
SCL = 0;
TIMER_Delay(TIMER3,4);
if(byte&(1<<(7-i)))
SDA = 1;
else
SDA = 0;
TIMER_Delay(TIMER3,4);
SCL = 1;
TIMER_Delay(TIMER3,4);
}
SCL = 0;
SDA = 1;
}
//iic从从机读一个字节
uint8_t anolog_iic_read_byte(uint8_t ack_flag)
{
uint8_t i = 0, data = 0;
SDA = 1;
SCL = 0;
TIMER_Delay(TIMER3,4);
for(i = 0; i<8; i++){
SCL = 1;
TIMER_Delay(TIMER3,4);
data <<=1;
data |= SDA;
TIMER_Delay(TIMER3,4);
SCL = 0;
TIMER_Delay(TIMER3,4);
}
if(ack_flag == ACK)
anolog_iic_send_ack();
else
anolog_iic_send_nack();
DEBUG("iic read 0x%02x\n",data);
return data;
}
//写
anolog_iic_start();
anolog_iic_send_byte(slave_addr<<1);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_send_byte(INA220_CONFIG_REGISTER);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_send_byte(ina220_config_data[0]);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_send_byte(ina220_config_data[1]);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_stop();
anolog_iic_start();
anolog_iic_send_byte(slave_addr<<1);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_send_byte(INA220_CALIBRATION_REGISTER);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_send_byte(ina220_calibration_data[0]);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_send_byte(ina220_calibration_data[1]);
if(ACK != anolog_iic_wait_ack())
return;
anolog_iic_stop();
//读
anolog_iic_start();
anolog_iic_send_byte(slave_addr<<1);
if(ACK != anolog_iic_wait_ack())
return -1;
anolog_iic_send_byte(reg_addr);
if(ACK != anolog_iic_wait_ack())
return -1;
anolog_iic_start();
anolog_iic_send_byte((slave_addr<<1)|0x01);
if(ACK != anolog_iic_wait_ack())
return -1;
val = anolog_iic_read_byte(ACK);
//if(ACK != anolog_iic_wait_ack())
// return -1;
val = (val<<8) + anolog_iic_read_byte(NACK);
更新1:
主机应答最后添加:SDA = 1; //释放SDA,不然连续读可能出错