【嵌入式硬件芯片开发笔记】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);
}