新唐单片机模拟IIC

新唐单片机模拟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,不然连续读可能出错

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值