【嵌入式硬件芯片开发笔记】4-20mA DAC芯片AD5421配置流程
 16位、串行输入、环路供电、4 mA至20 mA DAC
 可用于HART协议相关电路 同AD5700配合使用

 
 
 AD5421的SPI和普通的不一样
 回读时要发两段 CS中间拉高一次
数据在SCLK上升沿逐个输出,而且在 SCLK下降沿有效
 固CPOL为低电平,CPHA为2 edge
 可选择开启CRC校验

 一般接的是4-20mA
在加载DAC、强制报警电流、复位、启动VLOOP/温度测量 或无操作命令字节后写入的16 Bits数据字为无关位
 上电后寄存器复位,看门狗开启,默认值1s,在1s内没有收到SPI信号,则FAULT置高。
开始运行
- 发送RESET命令,延时50us
- 读写寄存器操作
- 最后开启功能
初始化
- 环路电流为4-20mA,通过读写DAC控制器可以输出环路电流大小,输出20mA就是写入0xFFFF
  
- 写入控制寄存器,使其为0xFC00,禁用看门狗,不进行写入故障回读,检测到SPI故障时不将环路电流驱动至报警值,其他默认
 D8、D7可配置ADC测量功能
  
- 故障寄存器只读,可以读取故障,同时FAULT引脚置高时为故障,读故障寄存器后,自动复位
- 失调、增益调整寄存器,用于配置偏移
- 发送加载DAC命令,输出电流
- 开启ADC,控制寄存器D7置1,,发送ADC读取命令,在故障寄存器内读ADC状态
代码例程
/*!
 * @brief       	操作AD5421
 *
 * @param 	[in]	hspi: AD5421对应的SPI
 *					[in]	add: 寄存器地址
 *					[in]	data: 数据(读数据可以不管)
 *					[in]	WriteNotRead: true为写,false为读
 *
 * @return				dat_16: 返回数据
 */
uint16_t Ctrl_AD5421(SPI_HandleTypeDef *hspi,uint8_t add,uint16_t data,bool WriteNotRead)
{
	uint16_t dat_16=0;
	uint8_t dat_buf[3];
	memset(dat_buf,0,sizeof(dat_buf));
	
	if(WriteNotRead)
	{
		dat_buf[0]=add&0x7F;
		dat_buf[1]=data>>8;
		dat_buf[2]=data&0x00FF;
		SPI_Send_x_Read_y(&hspi2,dat_buf,3,0,30,true);
	}
	else
	{
		dat_buf[0]=add|0x80;
		dat_buf[1]=0;
		dat_buf[2]=0;
		SPI_Send_x_Read_y(&hspi2,dat_buf,3,0,30,true);
		dat_buf[0]=AD5421_NOP;
		dat_16=SPI_Send_x_Read_y(&hspi2,dat_buf,1,2,30,false)&0x0000FFFF;
	}
	
	return dat_16;
}
/*!
 * @brief       	操作AD5421的DAC
 *
 * @param 	[in]	current_v: 要输入的电流值
 *					[in]	WriteNotRead: true为写入并加载DAC,false为读DAC并返回电流值
 *
 * @return				current: 返回的DAC寄存器中对应的电流值
 */
float Ctrl_AD5421_DAC(float current_v,bool WriteNotRead)
{
	float current=0.0f;
	current=current_v;
	uint16_t dat_16=0;
	if(WriteNotRead)
	{		
		if(current>19.9998f)
		{
			dat_16=0xFFFF;
		}
		else if(current<4.0f)
		{
			dat_16=0;
		}
		else
		{
			dat_16=(current-4.0f)*0x10000/16.0f;
		}
		Ctrl_AD5421(&hspi2,AD5421_DAC,dat_16,true);	
		Ctrl_AD5421(&hspi2,AD5421_Load_DAC,0,true);
	}
	else
	{
		dat_16=Ctrl_AD5421(&hspi2,AD5421_DAC,0,false);
		current=16.0f*dat_16/0x10000+4.0f;
		Ctrl_AD5421(&hspi2,AD5421_Load_DAC,0,true);
	}
	return current;
}
/*!
 * @brief       	操作AD5421的ADC
 *
 * @param 	[in]	adc_flag: 0 测量VLOOP,1 测量芯片温度
 *					[in]	EnableNotDisable: true为写入并加载DAC,false为读DAC并返回电流值
 *
 * @return				dat_float: ADC测量值
 */
float Ctrl_AD5421_ADC(uint8_t adc_flag,bool EnableNotDisable)
{
	float dat_float=0.0f;
	uint16_t dat_16=0;	
	if(EnableNotDisable)
	{
		dat_16=Ctrl_AD5421(&hspi2,AD5421_Control,0,false);
		Ctrl_AD5421(&hspi2,AD5421_Control,dat_16|(1<<7),true);
	}
	else
	{
		Ctrl_AD5421(&hspi2,AD5421_Control,dat_16&(~(1<<7)),true);
		return dat_float;
	}
	
	Ctrl_AD5421(&hspi2,AD5421_Load_ADC,0,true);
	delay_us(50);
	
	if(adc_flag)
	{
		dat_16=Ctrl_AD5421(&hspi2,AD5421_Control,0,false);
		Ctrl_AD5421(&hspi2,AD5421_Control,dat_16|(1<<8),true);
		dat_16=Ctrl_AD5421(&hspi2,AD5421_Fault,0,false);	
		dat_float= (-1.559)*(dat_16&0x00FF)+312;
		printf("[INFO] AD5421_TEMP: %0.4f\n",dat_float);
	}
	else
	{
		dat_16=Ctrl_AD5421(&hspi2,AD5421_Control,0,false);
		Ctrl_AD5421(&hspi2,AD5421_Control,dat_16&(~(1<<8)),true);
		dat_16=Ctrl_AD5421(&hspi2,AD5421_Fault,0,false);
		dat_float=2.5f/256.0f*(dat_16&0x00FF);
		printf("[INFO] AD5421_VLOOP: %0.4f\n",dat_float);
	}
	return dat_float;
}
/*!
 * @brief       	初始化AD5421
 *
 * @param 				None
 *
 * @return				None
 */
void Init_AD5421(void)
{	
	Ctrl_AD5421(&hspi2,AD5421_RESET,0,true);
	delay_us(50);
	
	Ctrl_AD5421(&hspi2,AD5421_Control,0xFC00,true);	
	
	Ctrl_AD5421_DAC(20,true);
	
	Ctrl_AD5421_ADC(0,true);
}



















