2024/10/29 V1.0:代码仅供参考,暂时没有上板验证,部分功能待完善,也有部分功能可以去除,比如硬件设定好采样率,不考虑省电模式。如有错误,还请指正,谢谢!
使用的是GD32F407芯片,使用SPI串行模式进行读取数据,对于并行操作,可以参考写的另外一篇,里面也对重要的管脚进行了简单说明,以官方手册为准。自己可以根据实际需求对其进行移植,主要是对Pin、GPIO、spi初始化进行更改。https://blog.youkuaiyun.com/magicssss/article/details/143205014https://blog.youkuaiyun.com/magicssss/article/details/143205014
使用SPI串行模式读取数据,该模式下AD7606_Pin6接逻辑高;DB[15:9] and DB[6:0]需要接地;DB7是1234通道数据先输出,DB8是5678通道数据先输出,通常只需要接一个输出口即可,如果接DB7,则输出数据依次为12345678通道,如果接DB8则输出顺序为56781234。对于AD7606,只有数据输出,没有数据输入,因此MCU的MOSI管脚不接。
SPI模式下的时序如下,SPI工作在模式3,空闲时刻SCLK为高电平,时钟上升沿采集数据线上的信号,下降沿将移位寄存器的数据放置到信号线上。
宏定义部分
为了方便更改,关键的控制pin尽量链接到同名的GPIO_Port,做不到就老实更改初始化的部分;注意开启自己使用的SPIx时钟源。
#include "gd32f4xx.h" // Device header
#include "systick.h"
uint16_t AD7606_Data[8];
//尽量将控制Pins和数据Pins分别接到同名GPIO口
#define AD7606_SPI SPI1
#define AD7606_CtrlPort GPIOD //其它的必要控制端口
#define AD7606_DataPort GPIOB //SPI相关端口以及输入信号
//GPIOB
#define AD7606_DoutA GPIO_PIN_14 //MISO
#define AD7606_SCLK GPIO_PIN_13 //SCLK
#define AD7606_BUSY GPIO_PIN_15 //转换状态信号;输入0:转换结束;1:正在转换
//GPIOD
#define AD7606_STBY GPIO_PIN_1 //下电模式选择;低电平有效;默认电平:1
#define AD7606_OS0 GPIO_PIN_2 //默认电平:0
#define AD7606_OS1 GPIO_PIN_3 //默认电平:0
#define AD7606_OS2 GPIO_PIN_4 //默认电平:0
#define AD7606_CS GPIO_PIN_5 //读取和片选控制信号;低电平有效;默认电平:1
#define AD7606_RESET GPIO_PIN_6 //复位信号;高电平有效;默认电平:0
#define AD7606_RANG GPIO_PIN_7 //输入电压范围选择;0:+-5V;1:+-10V
#define AD7606_CONVST_AB GPIO_PIN_8 //开始转换信号;高电平有效;默认电平:0
//用于设置over sampling率
#define AD7606_SetOS0() gpio_bit_set(AD7606_CtrlPort, AD7606_OS0)
#define AD7606_SetOS1() gpio_bit_set(AD7606_CtrlPort, AD7606_OS1)
#define AD7606_SetOS2() gpio_bit_set(AD7606_CtrlPort, AD7606_OS2)
#define AD7606_ResetOS0() gpio_bit_reset(AD7606_CtrlPort, AD7606_OS0)
#define AD7606_ResetOS1() gpio_bit_reset(AD7606_CtrlPort, AD7606_OS1)
#define AD7606_ResetOS2() gpio_bit_reset(AD7606_CtrlPort, AD7606_OS2)
初始化函数
/*!
\brief AD7606初始化配置
\param[in] 无
\param[out] 无
\retval 无
*/
void AD7606_Init(void)
{
//开启外设时钟,根据走线进行更改
rcu_periph_clock_enable(RCU_GPIOB | RCU_GPIOD);
rcu_periph_clock_enable(RCU_SPI1);
//反馈信号引脚配置
gpio_mode_set(AD7606_DataPort, GPIO_MODE_INPUT, GPIO_PUPD_NONE, AD7606_BUSY);
//SCLK和MISO(DoutA)配置
gpio_af_set(AD7606_DataPort, GPIO_AF_5, AD7606_DoutA | AD7606_SCLK);
gpio_mode_set(AD7606_DataPort, GPIO_MODE_AF, GPIO_PUPD_NONE, AD7606_DoutA | AD7606_SCLK);
gpio_output_options_set(AD7606_DataPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, AD7606_DoutA | AD7606_SCLK);
//输出控制信号:默认低电平的信号
gpio_mode_set(AD7606_CtrlPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, AD7606_RANG | AD7606_OS0 | AD7606_OS1 | AD7606_OS2 | AD7606_RESET | AD7606_CONVST_AB);
gpio_output_options_set(AD7606_CtrlPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, AD7606_RANG | AD7606_OS0 | AD7606_OS1 | AD7606_OS2 | AD7606_RESET | AD7606_CONVST_AB);
//输出控制信号:默认高电平的信号
gpio_mode_set(AD7606_CtrlPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, AD7606_STBY | AD7606_CS);
gpio_output_options_set(AD7606_CtrlPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, AD7606_STBY | AD7606_CS);
spi_parameter_struct spi_initstructure;
spi_initstructure.device_mode = SPI_MASTER;
spi_initstructure.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_initstructure.frame_size = SPI_FRAMESIZE_16BIT;
spi_initstructure.nss = SPI_NSS_SOFT;
spi_initstructure.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; //模式3
spi_initstructure.prescale = SPI_PSC_32;
spi_initstructure.endian = SPI_ENDIAN_MSB;
spi_init(AD7606_SPI, &spi_initstructure);
spi_enable(AD7606_SPI);
//上电复位AD7606芯片
gpio_bit_set(AD7606_CtrlPort, AD7606_RESET);
delay_1ms(1);
gpio_bit_reset(AD7606_CtrlPort, AD7606_RESET);
}
复位函数
/*!
\brief AD7606复位
\param[in] 无
\param[out] 无
\retval 无
*/
void AD7606_Reset(void)
{
gpio_bit_set(AD7606_CtrlPort, AD7606_RESET);
delay_1ms(1); //最小50 ns
gpio_bit_reset(AD7606_CtrlPort, AD7606_RESET);
}
采样率设置函数
/*!
\brief AD7606过采样选择
\param[in] OS: 过采样率选择
可选择参数:0、2、4、8、16、32、64
\param[out] 无
\retval 无
*/
void AD7606_SetOversampling(uint8_t OS)
{
switch(OS)
{
case 0: // 000
AD7606_ResetOS2();
AD7606_ResetOS1();
AD7606_ResetOS0();
break;
case 2: // 001
AD7606_ResetOS2();
AD7606_ResetOS1();
AD7606_SetOS0();
break;
case 4: // 010
AD7606_ResetOS2();
AD7606_SetOS1();
AD7606_ResetOS0();
break;
case 8: // 011
AD7606_ResetOS2();
AD7606_SetOS1();
AD7606_SetOS0();
break;
case 16: // 100
AD7606_SetOS2();
AD7606_ResetOS1();
AD7606_ResetOS0();
break;
case 32: // 101
AD7606_SetOS2();
AD7606_ResetOS1();
AD7606_SetOS0();
break;
case 64: // 110
AD7606_SetOS2();
AD7606_SetOS1();
AD7606_ResetOS0();
break;
default: // default case
AD7606_ResetOS2();
AD7606_ResetOS1();
AD7606_ResetOS0();
break;
}
}
启动与结束转换函数
/*!
\brief AD7606开始转换
\param[in] 无
\param[out] 无
\retval 无
*/
void AD7606_StartConv(void)
{
gpio_bit_set(AD7606_CtrlPort, AD7606_CONVST_AB);
}
/*!
\brief AD7606结束转换
\param[in] 无
\param[out] 无
\retval 无
*/
void AD7606_StopConv(void)
{
gpio_bit_reset(AD7606_CtrlPort, AD7606_CONVST_AB);
}
设置下电模式函数
/*!
\brief ADC省电模式选择
\param[in] Mode:
1:备用--->该模式下最大工作电流8 mA
STBY=0; RANG=1
0:下电--->该模式下最大工作电流6 μA,需要reset才能退出
STBY=0; RANG=1
\param[out] 无
\retval 无
*/
void AD7606_SwitchPowerDownMode(uint8_t Mode)
{
switch(Mode)
{
case 1 :
gpio_bit_reset(AD7606_CtrlPort, AD7606_STBY);
gpio_bit_set(AD7606_CtrlPort, AD7606_RANG);
break;
case 0 :
gpio_bit_reset(AD7606_CtrlPort, AD7606_STBY);
gpio_bit_reset(AD7606_CtrlPort, AD7606_RANG);
break;
default :
gpio_bit_reset(AD7606_CtrlPort, AD7606_STBY);
gpio_bit_set(AD7606_CtrlPort, AD7606_RANG);
break;
}
}
读取转换结果函数
该函数仅读取转换的结果,未进行转换!!!!!!!!
/*!
\brief AD7606读取数据
\param[in] 无
\param[out] 数组指针
\retval 并行模式下读取数据
*/
uint16_t* AD7606_ReadData(void)
{
//开始单次转换
AD7606_StartConv();
//等待转换结束
while(gpio_input_bit_get(AD7606_CtrlPort, AD7606_BUSY));
//结束转换准备读取数据寄存器中的数据
AD7606_StopConv();
//读取数据:SPI模式读取数据
for(uint8_t i = 0; i < 8; i ++)
{
gpio_bit_reset(AD7606_CtrlPort, AD7606_CS);
// 确保 SPI 发送缓冲区为空,可以发送数据
while (RESET == spi_i2s_flag_get(AD7606_SPI, SPI_FLAG_TBE));
// 向 SPI 发送 16 位数据以启动读取(通常为 dummy data,比如 0xFFFF)
spi_i2s_data_transmit(AD7606_SPI, 0xFFFF);
// 等待 SPI 接收缓冲区非空,表示已经接收到数据
while (RESET == spi_i2s_flag_get(AD7606_SPI, SPI_FLAG_RBNE));
// 读取 SPI 接收缓冲区中的 16 位数据
AD7606_Data[i] = spi_i2s_data_receive(AD7606_SPI);
delay_1ms(1);
gpio_bit_set(AD7606_CtrlPort, AD7606_CS);
}
return AD7606_Data;
}