提示:本设计基于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); //默认状态
}