基于AD5791的高精度恒流源设计

提示:本设计基于GD32F407系列芯片设计,电路和代码仅供参考,项目上使用,这是我自己根据一些参考资料摸索的,代码部分没有上板验证,提供参考,后期可能会修改。

一、参考电路

        这里仅提供参考电路,参考韦子辉,张要发,杨泽,等.高稳定度可调恒流源的设计与实现[J].中国测试,2020,46(03):77-83.文献设计。

二、参考代码

1. 定义一些常量

        这部分内容在移植到STM平台时,需要更改端口名和GPIO相关的函数,正常情况下Keil会提示报错,请更改。其次,最下面定义了输入电压参考范围,这个根据自己电路需求自己更改,本人电路的输入范围是0-5V。

#include "gd32f4xx.h"                   // Device header
#include "systick.h"

/************8888
SPI0
MCU PA6  -- Pin31-> MISO<---->  AD5791-Pin11(SDO)
MCU PA7  -- Pin32-> MOSI<---->  AD5791-Pin12(SDIN)
MCU PA5  -- Pin30-> SCLK<---->  AD5791-Pin13(SCLK)
other pin: 低电平有效
MCU PA1  -- Pin24<---->  AD5791-Pin6(RESET_N)
MCU PA2  -- Pin25<---->  AD5791-Pin7(CLR_N)
MCU PA3  -- Pin26<---->  AD5791-Pin8(LDAC_N)
MCU PA4  -- Pin29<---->  AD5791-Pin14(SYNC_N)
****************/

#define		AD5791_Port				GPIOA					
#define		AD5791_SPIx				SPI0					//选的什么用什么,注意开启RCU_SPIx时钟
#define		AD5791_SCLK				GPIO_PIN_5
#define		AD5791_SDIN				GPIO_PIN_7
#define		AD5791_SDO				GPIO_PIN_6

#define		AD5791_SYNC_N			GPIO_PIN_1
#define		AD5791_RESET_N			GPIO_PIN_2
#define		AD5791_CLR_N			GPIO_PIN_3
#define		AD5791_LDAC_N			GPIO_PIN_4

#define		AD5791_Set_SYNC()		gpio_bit_set(AD5791_Port, AD5791_SYNC_N)
#define		AD5791_Reset_SYNC()		gpio_bit_reset(AD5791_Port, AD5791_SYNC_N)
#define		AD5791_Set_RESET()		gpio_bit_set(AD5791_Port, AD5791_RESET_N)
#define		AD5791_Reset_RESET()	gpio_bit_reset(AD5791_Port, AD5791_RESET_N)
#define		AD5791_Set_CLR()		gpio_bit_set(AD5791_Port, AD5791_CLR_N)
#define		AD5791_Reset_CLR()		gpio_bit_reset(AD5791_Port, AD5791_CLR_N)
#define		AD5791_Set_LDAC()		gpio_bit_set(AD5791_Port, AD5791_LDAC_N)
#define		AD5791_Reset_LDAC()		gpio_bit_reset(AD5791_Port, AD5791_LDAC_N)

#define		AD5791_DefultMode		0x20003E
#define		AD5791_NormalMode		0x200032

#define		VREFP					5
#define		VREFN					0

2. GPIO初始化

        在移植到STM32平台时,需要更改这部分内容。

/*!
    \brief        DAC初始化配置
    \param[in]    无
    \param[out]   无
    \retval       无
*/
void AD5791_GPIOInit(void)
{
	//开启外设时钟,根据走线更改
	rcu_periph_clock_enable(RCU_GPIOA);	
	rcu_periph_clock_enable(RCU_SPI0);
	
	//初始化SPI相关的GPIO端口
	gpio_af_set(AD5791_Port, GPIO_AF_5, AD5791_SDIN | AD5791_SCLK | AD5791_SDO);
	gpio_mode_set(AD5791_Port, GPIO_MODE_AF, GPIO_PUPD_NONE, AD5791_SDIN | AD5791_SCLK);
	gpio_mode_set(AD5791_Port, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, AD5791_SDO);	
	gpio_output_options_set(AD5791_Port, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, AD5791_SDIN | AD5791_SCLK);
	
	//控制引脚设置为上拉输出,默认为高电平。
	gpio_mode_set(AD5791_Port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, AD5791_SYNC_N | AD5791_RESET_N | AD5791_CLR_N | AD5791_LDAC_N);
	
	//初始化SPI工作模式
	spi_parameter_struct spi_initstructure;
	spi_initstructure.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
	spi_initstructure.device_mode = SPI_MASTER;
	spi_initstructure.endian = SPI_ENDIAN_MSB;							//高位先行
	spi_initstructure.frame_size = SPI_FRAMESIZE_8BIT;					//数据位 8bits
	spi_initstructure.nss = SPI_NSS_SOFT;								//软件片选
	spi_initstructure.prescale = SPI_PSC_128;
	spi_initstructure.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
	spi_init(AD5791_SPIx, &spi_initstructure);
	
	//启用SPI
	spi_enable(AD5791_SPIx);
}

3. 软件SPI交换字节时序

        在移植到STM32平台时,该函数需要更改。

/**
  * 函    数:SPI交换传输一个字节,使用SPI模式0
  * 参    数:ByteSend 要发送的一个字节
  * 返 回 值:接收的一个字节
  */
uint8_t MySPI0_SwapByte(uint8_t ByteSend)
{
	while (spi_i2s_flag_get(AD5791_SPIx, SPI_FLAG_TBE) != SET);	//等待发送数据寄存器空
	
	spi_i2s_data_transmit(AD5791_SPIx, ByteSend);				//写入数据到发送数据寄存器,开始产生时序
	
	while (spi_i2s_flag_get(AD5791_SPIx, SPI_FLAG_RBNE) != SET);//等待接收数据寄存器非空
	
	return spi_i2s_data_receive(AD5791_SPIx);					//读取接收到的数据并返回
}

4. 起始与结束信号

/*!
    \brief        拉低SYNC,开始数据交换
    \param[in]    无
    \param[out]   无
    \retval       无
*/
void AD5791_StartSync(void)
{
	AD5791_Reset_SYNC();
}

/*!
    \brief        拉高SYNC,结束数据交换
    \param[in]    无
    \param[out]   无
    \retval       无
*/
void AD5791_StopSync(void)
{
	AD5791_Set_SYNC();
	
	AD5791_Reset_LDAC();
	
	delay_1ms(1);			//最小14 ns,系统的延时函数,1 ms时间有点长了
	
	AD5791_Set_LDAC();
}

5. 设置DAC输出值(非电压值)

/*!
    \brief        设置DAC值
    \param[in]    DAC:待设置的DAC数值
    \param[out]   无
    \retval       无
	\高位先行
	\	bit24	bit22	bit21	bit20	bit19-bit0	
	\	R=1/W=0	|	 寄存器地址 	|	寄存器数据
	\	  -		  0 	  0		  0						无操作,用于回读
	\	  0		  0       0       1						写入DAC寄存器
	\	  0		  0       1       0						写入控制寄存器			
	\	  0		  0       1       1						写入清零代码寄存器	
	\	  0		  1       0       0						写入软件控制寄存器(控制reset/loda/clr,不建议使用)
    \	  1		  0       0       1						读DAC寄存器			
    \	  1		  0       1       0						读控制寄存器
	\	  1		  0       1       1						读清零代码寄存器
*/  
void AD5791_SetDAC(uint32_t DAC)
{
	uint32_t temp = 0x100000;
	temp |= DAC;
	AD5791_StartSync();
	
	MySPI0_SwapByte(temp > 16);
    MySPI0_SwapByte((temp > 8) & 0xff);	
	MySPI0_SwapByte(temp & 0xff);

	AD5791_StopSync();
}

6. 设置输出电压值

/*!
    \brief        设置Voltage值
    \param[in]    Voltage:输出电压值
    \param[out]   无
    \retval       无
*/  
void AD5791_OutputVoltage(float Voltage)
{
	uint32_t DAC;
	DAC = (uint32_t)1048576*(Voltage - VREFN) / (VREFP - VREFN);
	
	AD5791_SetDAC(Voltage);
}

7. 设置DAC的工作模式等

/*!
    \brief        设置DAC的模式等
    \param[in]    CMD:24 bits控制命令
    \param[out]   无
    \retval       无
*/
void AD5791_CtrlDAC(uint32_t CMD)
{	
	uint32_t temp = 0x200000;
	temp = temp | CMD;
	
	AD5791_StartSync();
	
	MySPI0_SwapByte(CMD > 16);
    MySPI0_SwapByte((CMD > 8) & 0xff);	
	MySPI0_SwapByte(CMD & 0xff);
	
	AD5791_StopSync();
}

8. 读取DAC寄存器数值

/*!
    \brief        读取寄存器值
	\param[in]    Addr:0x9/0xA/0xB
    \param[out]   寄存器值
    \retval       无
    \	  1		  0       0       1						读DAC寄存器			
    \	  1		  0       1       0						读控制寄存器
	\	  1		  0       1       1						读清零代码寄存器
*/

uint32_t AD5791_ReadReg(uint8_t Addr)
{
	uint32_t temp, RegData = 0;
	temp |= Addr < 20;
	
	AD5791_StartSync();

	MySPI0_SwapByte(temp > 16);
	MySPI0_SwapByte((temp > 8) & 0xff);
	MySPI0_SwapByte(temp & 0xff);
	
	AD5791_Set_SYNC();
	
	delay_1ms(1);
	
	AD5791_StartSync();
	
	RegData  = MySPI0_SwapByte(0xff);
	RegData += MySPI0_SwapByte(0xff);
	RegData += MySPI0_SwapByte(0xff);
	
	AD5791_Set_SYNC();
	
	return RegData;
}

9. AD5791初始化

/*!
    \brief        读取寄存器值
	\param[in]    无
    \param[out]   无
    \retval       无
*/
void AD5791_Init(void)
{
	AD5791_GPIOInit();
	AD5791_CtrlDAC(AD5791_DefultMode);			//默认状态
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值