【问题解决记录】国产GP8211S问题解决记录

项目场景:

最近在使用国产DAC芯片GP8211S,使用STM32F030通过IIC与之连接,发现设置输出寄存器内容成0x7FFF后,最大输出达到12V,超过了手册中说明的10V;


问题描述

这个是我GP8211S初始化函数和发送,设置0x77是想得到最大10V的电压输出;

void Gp8211s_Init(void)
{	
	//Range 0 to 5V
	Gp8211s_IIC_Start();
	Gp8211s_IIC_SendByte(0xB0);
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_SendByte(0x01);
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_SendByte(0x77);  
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_Stop(); 
}

// data_hex max: 0x7FFF
void gp8211s_send_cmd(uint16_t data_hex )
{	
	uint8_t data8_tmp = 0;

	//Set Reg value
	Gp8211s_IIC_Start();
	Gp8211s_IIC_SendByte(0xB0);
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_SendByte(0x02);
	Gp8211s_IIC_WaitAck();
	data8_tmp = data_hex & 0xFF;
	Gp8211s_IIC_SendByte(data8_tmp);//DATA Low
	//Gp8211s_IIC_WaitAck();   //!!! add this, not OK;
	data8_tmp = (data_hex & 0x7F00 )>> 8;
	Gp8211s_IIC_SendByte(data8_tmp);//DATA High
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_Stop(); 
}

GP8211S 配置手册描述:
GP8211S 配置手册描述
我的电路图如下,这个电路是12V供电,代码里设置0x7FFF,输出12V;
在这里插入图片描述
实物

原因分析:

通过实际测试发现:
1)好像1byte设置为0x55以下的数值,得到的最大输出范围就是5V的;
2)设置数值大于0x55的,就会得到超过10V的输出;
3)而等于0x55,最大输出就是10V;

还有,时序图中的DATA Low和DATA High之间的ACK,程序要“不检查ACK”,才能设置数据成功!
在这里插入图片描述


c代码:

提示:这里填写该问题的具体解决方案:

#include "gp8211s.h"
#include "main.h"
#include "delay.h"

uint8_t Gp8211s_Channel_Sel;

void Gp8211s_Choose_Channel(uint8_t ch)
{
	if( !ch ) 
		Gp8211s_Channel_Sel = 0;
	else
		Gp8211s_Channel_Sel = 1;
}

void Gp8211s_SCL_Clr()
{
	if( !Gp8211s_Channel_Sel )
		HAL_GPIO_WritePin(GP1_SCLK_GPIO_Port, GP1_SCLK_Pin, GPIO_PIN_RESET);
	else	
		HAL_GPIO_WritePin(GP2_SCLK_GPIO_Port, GP2_SCLK_Pin, GPIO_PIN_RESET);
}
void Gp8211s_SCL_Set()
{
	if( !Gp8211s_Channel_Sel )
		HAL_GPIO_WritePin(GP1_SCLK_GPIO_Port, GP1_SCLK_Pin, GPIO_PIN_SET);
	else	
		HAL_GPIO_WritePin(GP2_SCLK_GPIO_Port, GP2_SCLK_Pin, GPIO_PIN_SET);
}
void Gp8211s_SDA_Clr()
{
	if( !Gp8211s_Channel_Sel )
		HAL_GPIO_WritePin(GP1_SDA_GPIO_Port, GP1_SDA_Pin, GPIO_PIN_RESET);
	else	
		HAL_GPIO_WritePin(GP2_SDA_GPIO_Port, GP2_SDA_Pin, GPIO_PIN_RESET);
}
void Gp8211s_SDA_Set()
{
	if( !Gp8211s_Channel_Sel )
		HAL_GPIO_WritePin(GP1_SDA_GPIO_Port, GP1_SDA_Pin, GPIO_PIN_SET);
	else	
		HAL_GPIO_WritePin(GP2_SDA_GPIO_Port, GP2_SDA_Pin, GPIO_PIN_SET);
}


void Gp8211s_IIC_SdaOut()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	if( !Gp8211s_Channel_Sel )
	{
		GPIO_InitStruct.Pin = GP1_SDA_Pin;
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		HAL_GPIO_Init( GP1_SDA_GPIO_Port, &GPIO_InitStruct );
	}
	else
	{
		GPIO_InitStruct.Pin = GP2_SDA_Pin;
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		HAL_GPIO_Init( GP2_SDA_GPIO_Port, &GPIO_InitStruct );
	}
}

void Gp8211s_IIC_SdaIn()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	//return;

	if( !Gp8211s_Channel_Sel )
	{
		GPIO_InitStruct.Pin = GP1_SDA_Pin;
		GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		HAL_GPIO_Init( GP1_SDA_GPIO_Port, &GPIO_InitStruct );
	}
	else
	{
		GPIO_InitStruct.Pin = GP2_SDA_Pin;
		GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		HAL_GPIO_Init( GP2_SDA_GPIO_Port, &GPIO_InitStruct );
	}
}

void Gp8211s_IIC_Init()
{
	Gp8211s_IIC_SdaOut();
	Gp8211s_SDA_Set();
	Gp8211s_SCL_Set();
	delay_us(10);
}

void Gp8211s_IIC_Start(void)
{
	Gp8211s_IIC_SdaOut();
	Gp8211s_SDA_Set();
	Gp8211s_SCL_Set();
	delay_us(10);
	Gp8211s_SDA_Clr();
	delay_us(10);
}

void Gp8211s_IIC_Stop(void)
{
	Gp8211s_IIC_SdaOut();
	Gp8211s_SDA_Clr();
	Gp8211s_SCL_Set();
	delay_us(10);
	Gp8211s_SDA_Set();
	delay_us(10);
}

void Gp8211s_IIC_SendByte(uint8_t txd)
{
	uint8_t t;  
	uint8_t tdata = txd;	
	
	Gp8211s_IIC_SdaOut();
    Gp8211s_SCL_Clr();
	delay_us(10);
    for(t=0; t<8; t++)
    {              
        if( tdata & 0x80 )
			Gp8211s_SDA_Set();
		else
			Gp8211s_SDA_Clr();
        tdata <<= 1; 	  
		delay_us(10);
		Gp8211s_SCL_Set();
		delay_us(10);
		Gp8211s_SCL_Clr();
		delay_us(10);
    }	 
}



uint8_t Gp8211s_IIC_SdaState()
{
	uint8_t ret;
	
	if( !Gp8211s_Channel_Sel )
		ret = HAL_GPIO_ReadPin(GP1_SDA_GPIO_Port, GP1_SDA_Pin);
	else
		ret = HAL_GPIO_ReadPin(GP2_SDA_GPIO_Port, GP2_SDA_Pin);
	return ret;
}

uint8_t Gp8211s_IIC_ReadByte(void)
{
	uint8_t t;  
	uint8_t rdata=0;	
	
	Gp8211s_IIC_SdaIn();
    for(t=0; t<8; t++)
    {      
		Gp8211s_SCL_Set();
		delay_us(10);
		rdata <<= 1; 
		
        if( Gp8211s_IIC_SdaState() )
			rdata|=0x01;
		Gp8211s_SCL_Clr();
		delay_us(10);
    }	 
	return rdata;
}

uint8_t Gp8211s_IIC_WaitAck(void)
{
	uint32_t ucErrTime = 0;
	GPIO_PinState sda_state;
	uint8_t RetValue = 0;
	
	Gp8211s_SCL_Set();
	delay_us(20);
		
	#if 0	
	Gp8211s_IIC_SdaIn();
	while(ucErrTime++ < 10000)
	{
		delay_us(20);
		sda_state = Gp8211s_IIC_SdaState();
		if( sda_state == GPIO_PIN_RESET )
		{
			RetValue = 1;
			break;
		}
	}
	
	if( ucErrTime >= 10000 )
	{
		printf("Gp8211s_IIC_WaitAck timeout\n");
		Gp8211s_IIC_Stop();
	}
	#endif
	
	return RetValue;
}

void Gp8211s_Init(void)
{	
	//Range 0 to 5V
	Gp8211s_IIC_Start();
	Gp8211s_IIC_SendByte(0xB0);
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_SendByte(0x01);
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_SendByte(0x55);   //0x44, 5V; 0x55: 10V; 0x77:12V;
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_Stop(); 
}

// data_hex max: 0x7FFF
void gp8211s_send_cmd(uint16_t data_hex )
{	
	uint8_t data8_tmp = 0;

	//Set Reg value
	Gp8211s_IIC_Start();
	Gp8211s_IIC_SendByte(0xB0);
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_SendByte(0x02);
	Gp8211s_IIC_WaitAck();
	data8_tmp = data_hex & 0xFF;
	Gp8211s_IIC_SendByte(data8_tmp);//DATA Low
	//Gp8211s_IIC_WaitAck();   //!!! add this, not OK;
	data8_tmp = (data_hex & 0x7F00 )>> 8;
	Gp8211s_IIC_SendByte(data8_tmp);//DATA High
	Gp8211s_IIC_WaitAck();
	Gp8211s_IIC_Stop(); 
}

void gp8211s_OutPutVolt(uint16_t volt_in_mv )
{	
	uint32_t VoltRange = 10*1000; //10V
	uint16_t  RegVal = 0;
	
	if( volt_in_mv > VoltRange )
		volt_in_mv = VoltRange;
	
	RegVal = volt_in_mv * 0x7FFF / VoltRange;
	RegVal &= 0x7FFF;
	//printf("volt_in_mv: %d, RegVal: %X  \n ", volt_in_mv, RegVal);
	
	gp8211s_send_cmd(RegVal);
//		gp8211s_send_cmd(0x4000);
	//printf("volt_in_mv: %d, RegVal: %X  \n ", volt_in_mv, RegVal);
}

更多技术讨论: 添加请微信: automan_111 tel:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值