双SPI总线操作AD7616
已有 238 次阅读2022-4-20 08:21
近期拿到一块EVAL-AD7616SDZ测试板。AD7616SDZ是16bit双通道同步采样的16通道ADC,相比AD7689单通道价格更便宜,速度更高,而且支持双通道同步,是替换AD7689的理想选择。
本来想用STM32MP157A板进行测试的,由于环境搭建以及调试上来说,选一块调试更方便的开发板进行测试,先行探探路。首选了STM32H743ZI_Nucleo板进行测试。
采用双SPI进行操作,那么这个双SPI需要同步时钟。STM32上的SPI2与SPI3同时钟源,SPI4与SPI5同时钟源,所以选择SPI4作为master,SPI5作为slave。
从网上搜到一篇ADI写的《操纵MCU SPI接口 以访问非标准SPI ADC》的文章,采用方案4:
这张图有一点问题,DOUTB应该接MOSI,而不是MISO。
AD7616支持4种操作方式:硬件并口,硬件串口,软件并口,软件串口。其中软件方式是可以配置寄存器的,能够使用AD7616的所有功能,现在选择软件串口方式,那么EVAL-AD7616SDZ测试板需要做以下接线配置:
AD7616的初始化顺序:
1> 初始化SPI接口;
2> 初始化CONVST启动转换端口、RESET复位端口、BUSY转换状态端口、CS片选端口;
3> 完全复位AD7616。AD7616有完全复位和部分复位,初始化需要完全复位,RESET低电平状态相当于AD7616断电。
4> 使master SPI的片选信号置低电平;
5> 写配置寄存器。发送0x8414,最高位置1表示写0x2寄存器,写入数据0x14表示32点过采样,此步测试配置;
6> 读取配置寄存器检测配置是否成功,读取的数据应该为0x14;
7> 使master SPI的片选信号置高电平;
8> 启动采样。CONVST产生上升沿启动采样,高电平要至少保持50ns。
9> 检测BUSY信号,出现下降沿表示可以读取采样数据;
10> 使master SPI的片选信号置低电平;
11> SPI4发送0,SPI4读取V0A通道数据;
12> SPI4发送0,SPI5读取V0B通道数据
13> 使master SPI的片选信号置高电平;
重复8~13步可以读取其他通道,当然是在配置了的情况下。默认配置时只能读取V0A和V0B。
最开始使用HAL库的发送与接收函数,发送用HAL_SPI_Transmit,接收用HAL_SPI_Receive。可以读取V0A和V0B通道的采样数据,而且采样数据经过折算后与施加的直流模拟信号一致,说明采样值读取的没问题。但是读取的配置寄存器值为0,通过单步仿真查看写入与读取情况,HAL_SPI_Transmit和HAL_SPI_Receive函数均返回HAL_OK,那么问题出现在哪里呢?此时用示波器观察SCK和MOSI波形,SCK和MISO波形,没有看出问题。后来查出来是HAL_SPI_Transmit函数发送uint16_t数据时将数据分开成两个字节发送,采用数组传入数据,由于ARM是小端,而SPI是MSB传输,数据错位。
调试一天,上面的问题没有找到,用STM32F429板子搭建了一个标准库程序,软件流程完全一样,只是SPI的收发函数用寄存器直接操作,能够正常读取和配置寄存器,正常读取通道采样值。下面把代码公布出来。
ad7616.c部分:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bsp.h"
#include "adc7616.h"
#define CONVST_Pin GPIO_Pin_3
#define CONVST_GPIO_Port GPIOE
#define CS_Pin GPIO_Pin_4
#define CS_GPIO_Port GPIOE
#define RESET_Pin GPIO_Pin_4
#define RESET_GPIO_Port GPIOA
#define BUSY_Pin GPIO_Pin_5
#define BUSY_GPIO_Port GPIOA
#define CLR_CNV() GPIO_ResetBits(CONVST_GPIO_Port, CONVST_Pin)
#define SET_CNV() GPIO_SetBits(CONVST_GPIO_Port, CONVST_Pin)
#define CLR_CS() GPIO_ResetBits(CS_GPIO_Port, CS_Pin)
#define SET_CS() GPIO_SetBits(CS_GPIO_Port, CS_Pin)
#define CLR_RST() GPIO_ResetBits(RESET_GPIO_Port, RESET_Pin)
#define SET_RST() GPIO_SetBits(RESET_GPIO_Port, RESET_Pin)
#define BUSY (FlagStatus)GPIO_ReadInputDataBit(BUSY_GPIO_Port, BUSY_Pin)
uint16_t ad7616_reg[20];
uint16_t samplearray[16];
uint16_t buffersize = 0;
uint8_t busyevent = 0;
static int32_t spi_init(ad7616_dev *dev);
static int32_t gpio_init(ad7616_dev *dev);
int8_t SPI4_SendByte(SPI_TypeDef* SPIx, uint16_t data)
{undefined
uint8_t res = 0;
int32_t retry = 20000;
/*!< Wait until the transmit buffer is empty */
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)
{undefined
retry--;
if(retry <= 0) return -2;
}
/*!< Send the data */
SPI_I2S_SendData(SPIx, data);
return res;
}
uint16_t SPI4_ExchangeData(SPI_TypeDef* SPIx, uint16_t data)
{undefined
int32_t retry = 200;
/*!< Wait until the transmit buffer is empty */
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)
{undefined
retry--;
if(retry <= 0) return 0;
}
/*!< Send the byte */
SPI_I2S_SendData(SPIx, data);
retry = 200;
/*!< Wait to receive a byte*/
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET)
{undefined
retry--;
if(retry <= 0) return 0;
}
/* return the byte */
return SPI_I2S_ReceiveData(SPIx);
}
/**
* Read from device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_read(ad7616_dev *dev, uint8_t reg_addr, uint16_t *reg_data)
{undefined
if (dev->interface == AD7616_SERIAL)
{undefined
return ad7616_spi_read(dev, reg_addr, reg_data);
}
else
{undefined
return ad7616_par_read(dev, reg_addr, reg_data);
}
}
/**
* Write to device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_write(ad7616_dev *dev, uint8_t reg_addr, uint16_t reg_data)
{undefined
if (dev->interface == AD7616_SERIAL)
{undefined
return ad7616_spi_write(dev, reg_addr, reg_data);
}
else
{undefined
return ad7616_par_write(dev, reg_addr, reg_data);
}
}
/**
* Read from device using a mask.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param mask - The mask.
* @param data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_read_mask(ad7616_dev *dev, uint8_t reg_addr, uint16_t mask, uint16_t *data)
{undefined
uint16_t reg_data;
int32_t ret;
if (dev->interface == AD7616_SERIAL)
{undefined
ret = ad7616_spi_read(dev, reg_addr, ®_data);
}
else
{undefined
ret = ad7616_par_read(dev, reg_addr, ®_data);
}
*data = (reg_data & mask);
return ret;
}
/**
* SPI write to device using a mask.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param mask - The mask.
* @param data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_write_mask(ad7616_dev *dev, uint8_t reg_addr, uint16_t mask, uint16_t data)
{undefined
uint16_t reg_data;
int32_t ret;
if (dev->interface == AD7616_SERIAL)
{undefined
ret = ad7616_spi_read(dev, reg_addr, ®_data);
}
else
{undefined
ret = ad7616_par_read(dev, reg_addr, ®_data);
}
reg_data &= ~mask;
reg_data |= data;
if (dev->interface == AD7616_SERIAL)
{undefined
ret |= ad7616_spi_write(dev, reg_addr, reg_data);
}
else
{undefined
ret |= ad7616_par_write(dev, reg_addr, reg_data);
}
return ret;
}
/**
* SPI read from device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_spi_read(ad7616_dev *dev, uint8_t reg_addr, uint16_t *reg_data)
{undefined
uint16_t regAddr;
int32_t ret = 0;
regAddr = 0x00 | ((reg_addr & 0x3F) << 1);
regAddr = (regAddr<<8) | 0x00;
ret = SPI4_ExchangeData(SPI4, regAddr);
regAddr = 0x00 | ((reg_addr & 0x3F) << 1);
regAddr = (regAddr<<8) | 0x00;
ret = SPI4_ExchangeData(SPI4, regAddr);
regAddr = (uint16_t)ret;
/* return the byte */
*reg_data = regAddr;
return ret;
}
/**
* SPI write to device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_spi_write(ad7616_dev *dev, uint8_t reg_addr, uint16_t reg_data)
{undefined
uint16_t regCfg;
int32_t ret=0;
regCfg = 0x80 | ((reg_addr & 0x3F) << 1) | ((reg_data & 0x100) >> 8);
regCfg = (regCfg<<8) | (reg_data & 0xFF);
ret = SPI4_SendByte(SPI4, regCfg);
return ret;
}
/**
* PAR read from device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_par_read(ad7616_dev *dev, uint8_t reg_addr, uint16_t *reg_data)
{undefined
return 0;
}
/**
* PAR write to device.
* @param dev - The device structure.
* @param reg_addr - The register address.
* @param reg_data - The register data.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_par_write(ad7616_dev *dev, uint8_t reg_addr, uint16_t reg_data)
{undefined
return 0;
}
void delay(uint32_t us)
{undefined
int i;
for(i=0; i<us; i++)
{undefined
}
}
/**
* Perform a full reset of the device.
* @param dev - The device structure.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_reset(ad7616_dev *dev)
{undefined
int32_t ret=0;
CLR_RST();
/* Low pulse width for a full reset should be at least 1200 ns */
delay_us(2000);
SET_RST();
/* 15 ms are required to completely reconfigure the device */
delay_us(20000);
return ret;
}
/**
* Set the analog input range for the selected analog input channel.
* @param dev - The device structure.
* @param ch - The channel number.
* Accepted values: AD7616_VA0
* AD7616_VA1
* AD7616_VA2
* AD7616_VA3
* AD7616_VA4
* AD7616_VA5
* AD7616_VA6
* AD7616_VA7
* AD7616_VB0
* AD7616_VB1
* AD7616_VB2
* AD7616_VB3
* AD7616_VB4
* AD7616_VB5
* AD7616_VB6
* AD7616_VB7
* @param range - The analog input range.
* Accepted values: AD7616_2V5
* AD7616_5V
* AD7616_10V
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_set_range(ad7616_dev *dev, ad7616_ch ch, ad7616_range range)
{undefined
uint8_t reg_addr;
uint8_t mask;
uint8_t data;
int32_t ret;
if (dev->mode == AD7616_SW)
{undefined
if (ch <= AD7616_VA7)
{undefined
dev->va[ch] = range;
if (ch <= AD7616_VA3)
{undefined
reg_addr = AD7616_REG_INPUT_RANGE_A1; //0x04
mask = AD7616_INPUT_RANGE(ch, AD7616_10V); //3H || 6H || CH || 18H
data = AD7616_INPUT_RANGE(ch, range); //3H || 6H || CH || 18H
}
else
{undefined
reg_addr = AD7616_REG_INPUT_RANGE_A2; //0x05
mask = AD7616_INPUT_RANGE(ch - AD7616_VA4, AD7616_10V);//3H || 6H || CH || 18H
data = AD7616_INPUT_RANGE(ch - AD7616_VA4, range);//3H || 6H || CH || 18H
}
}
else
{undefined
dev->vb[ch - AD7616_VB0] = range;
if (ch <= AD7616_VB3)
{undefined
reg_addr = AD7616_REG_INPUT_RANGE_B1; //0x06
mask = AD7616_INPUT_RANGE(ch - AD7616_VB0, AD7616_10V);
data = AD7616_INPUT_RANGE(ch - AD7616_VB0, range);
}
else
{undefined
reg_addr = AD7616_REG_INPUT_RANGE_B2; //0x07
mask = AD7616_INPUT_RANGE(ch - AD7616_VB4, AD7616_10V);
data = AD7616_INPUT_RANGE(ch - AD7616_VB4, range);
}
}
ret = ad7616_write_mask(dev, reg_addr, mask, data);
}
return ret;
}
/**
* Set the operation mode (software or hardware).
* @param dev - The device structure.
* @param mode - The operation mode.
* Accepted values: AD7616_SW
* AD7616_HW
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_set_mode(ad7616_dev *dev, ad7616_mode mode)
{undefined
uint8_t i;
int32_t ret = 0;
dev->mode = mode;
for (i = 0; i <= AD7616_VA7; i++)
{undefined
ret |= ad7616_set_range(dev, (ad7616_ch)i, dev->va[i]);
ret |= ad7616_set_range(dev, (ad7616_ch)(i + AD7616_VB0), dev->vb[i]);
}
return ret;
}
/**
* Set the oversampling ratio.
* @param dev - The device structure.
* @param osr - The oversampling ratio.
* Accepted values: AD7616_OSR_0
* AD7616_OSR_2
* AD7616_OSR_4
* AD7616_OSR_8
* AD7616_OSR_16
* AD7616_OSR_32
* AD7616_OSR_64
* AD7616_OSR_128
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_set_oversampling_ratio(ad7616_dev *dev, ad7616_osr osr)
{undefined
int32_t ret = 0;
if (dev->mode == AD7616_SW)
{undefined
ret = ad7616_write_mask(dev, AD7616_REG_CONFIG, AD7616_OS(0x7), AD7616_OS(osr));
}
return ret;
}
/**
* Start conversion.
* @param device - The device structure.
* @param init_param - The structure that contains the device initial
* parameters.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_startConvst(ad7616_dev *dev)
{undefined
SET_CNV();
delay_us(5);
CLR_CNV();
return 0;
}
/**
* Initialize the device.
* @param device - The device structure.
* @param init_param - The structure that contains the device initial
* parameters.
* @return 0 in case of success, negative error code otherwise.
*/
int32_t ad7616_setup(ad7616_dev *dev)
{undefined
uint8_t i;
int32_t ret = 0;
uint16_t databuffer = 0xFFFF;
dev->interface = AD7616_SERIAL;
dev->mode = AD7616_SW;
dev->osr = AD7616_OSR_32;
ret |= gpio_init(dev);
if (dev->interface == AD7616_SERIAL)
{undefined
ret |= spi_init(dev);
}
ad7616_reset(dev);
CLR_CS();
for (i = 0; i <= AD7616_VA7; i++)
{undefined
dev->va[i] = AD7616_10V;
dev->vb[i] = AD7616_10V;
}
ret |= ad7616_spi_read(dev, AD7616_REG_CONFIG, &ad7616_reg[0]);
// ret |= ad7616_set_mode(dev, dev->mode);
databuffer = 0x8414;
ret = SPI4_SendByte(SPI4, databuffer);
// ret |= ad7616_set_oversampling_ratio(dev, dev->osr);
ret |= ad7616_spi_read(dev, AD7616_REG_CONFIG, &ad7616_reg[2]);
ret |= ad7616_spi_read(dev, AD7616_REG_CHANNEL, &ad7616_reg[3]);
ret |= ad7616_spi_read(dev, AD7616_REG_INPUT_RANGE_A1, &ad7616_reg[4]);
ret |= ad7616_spi_read(dev, AD7616_REG_INPUT_RANGE_A2, &ad7616_reg[5]);
ret |= ad7616_spi_read(dev, AD7616_REG_INPUT_RANGE_B1, &ad7616_reg[6]);
ret |= ad7616_spi_read(dev, AD7616_REG_INPUT_RANGE_B2, &ad7616_reg[7]);
SET_CS();
return ret;
}
#define CHNL_NBR 2
#define CHNL_IDN 1
uint8_t bufIdx = 0;
extern __IO uint32_t uwTimingDelay;
uint32_t uwTimingHead;
uint32_t uwTimingSample;
/***************************************************************************//**
* @brief ad7616_capture_serial
*******************************************************************************/
int32_t ad7616_capture(ad7616_dev *dev)
{undefined
int32_t ret = 0;
/* wait for conversion finish, BUSY goes from high to low, Polling or interrupt mode */
if(busyevent == 1)
{undefined
busyevent = 0;
uwTimingDelay = 1000;
uwTimingHead = uwTimingDelay;
/* code number to read per conversion cycle */
while(buffersize < CHNL_NBR)
{undefined
CLR_CS();
/* Write in the DR register the data to be sent */
*(__IO uint8_t *)&SPI4->DR = 0;
/*!< Wait to receive a byte*/
while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
/* need half SCLK cycle delay for slow SCLK rate < 10MHz */
delay(20);
samplearray[bufIdx] = *(__IO uint16_t *)&SPI4->DR;
/* Write in the DR register the data to be sent */
*(__IO uint8_t *)&SPI4->DR = 0;
/*!< Wait to receive a byte*/
while(SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_RXNE) == RESET);
samplearray[bufIdx+CHNL_IDN] = *(__IO uint16_t *)&SPI5->DR;
SET_CS();
bufIdx++;
buffersize += 2;
}
bufIdx = 0;
buffersize = 2;
uwTimingSample = uwTimingHead - uwTimingDelay;
}
else if(buffersize == 0)
{undefined
ad7616_startConvst(dev);
delay(20);
}
else if(buffersize == 2)
{undefined
buffersize = 0;
LED_Toggle();
delay_us(200000); /* Use Systick to generate microsecond delay */
}
return ret;
}
/***************************************************************************//**
* @brief spi_init
*******************************************************************************/
static int32_t spi_init(ad7616_dev *dev)
{undefined
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* Enable SPI bus clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE);
/* Configure the GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
/* Configure the GPIO multiplexing function */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource2, GPIO_AF_SPI4);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_SPI4);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_SPI4);
/*!< SPI pins configuration */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
/* Configure SPI pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Configure the GPIO multiplexing function */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_SPI5);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource8, GPIO_AF_SPI5);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource7, GPIO_AF_SPI5);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_SPI5);
/* Configure SPI pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* Set SPI interface */
SPI_I2S_DeInit(SPI5);
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; /* 1Mbit/s */
SPI_InitStructure.SPI_CRCPolynomial = 0;
SPI_Init(SPI5, &SPI_InitStructure);
/* Fills each SPI_InitStruct member with its default value */
SPI_I2S_DeInit(SPI4);
/* Set SPI interface */
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; /* 1Mbit/s */
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI4, &SPI_InitStructure);
SPI_Cmd(SPI4, ENABLE);
SPI_Cmd(SPI5, ENABLE);
return 0;
}
/***************************************************************************//**
* @brief gpio_init
*******************************************************************************/
static int32_t gpio_init(ad7616_dev *dev)
{undefined
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/* Configure the GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/*Configure GPIO pin : CS_Pin */
GPIO_InitStruct.GPIO_Pin = CS_Pin;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CS_GPIO_Port, &GPIO_InitStruct);
GPIO_SetBits(CS_GPIO_Port, CS_Pin);
/*Configure GPIO pin : CONVST_Pin */
GPIO_InitStruct.GPIO_Pin = CONVST_Pin;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CONVST_GPIO_Port, &GPIO_InitStruct);
GPIO_ResetBits(CONVST_GPIO_Port, CONVST_Pin);
/*Configure GPIO pin : RESET_Pin */
GPIO_InitStruct.GPIO_Pin = RESET_Pin;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(RESET_GPIO_Port, &GPIO_InitStruct);
GPIO_ResetBits(RESET_GPIO_Port, RESET_Pin);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*Configure GPIO pin : BUSY_Pin */
GPIO_InitStruct.GPIO_Pin = BUSY_Pin;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BUSY_GPIO_Port, &GPIO_InitStruct);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource5);
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
return 0;
}
/***************************************************************************//**
* @brief gpio_init
*******************************************************************************/
void EXTI9_5_IRQHandler(void)
{undefined
if(EXTI_GetITStatus(EXTI_Line5) != RESET)
{undefined
EXTI_ClearITPendingBit(EXTI_Line5);
busyevent = 1;
}
}
初始化调用ad7616_setup函数,在主函数中调用ad7616_capture函数,不需要加延时。后面应用到项目中可以建个定时器,定时启动采样。经测试,同步的两个通道采样时间,在SPI时钟8分频时一对通道采样读取2微秒,16分频时3微秒,32分频时6微秒,还是很快的,SPI采用2分频是不行的。所以需要更高采样的,需要使用并口操作,如FMC。
下面把头文件贴上。
ad7616.h部分与官方库一致。
#ifndef AD7616_H_
#define AD7616_H_
#include "stm32f4xx_conf.h"
/******************************************************************************/
/********************** Macros and Constants Definitions **********************/
/******************************************************************************/
#define AD7616_REG_CONFIG 0x02
#define AD7616_REG_CHANNEL 0x03
#define AD7616_REG_INPUT_RANGE_A1 0x04
#define AD7616_REG_INPUT_RANGE_A2 0x05
#define AD7616_REG_INPUT_RANGE_B1 0x06
#define AD7616_REG_INPUT_RANGE_B2 0x07
#define AD7616_REG_SEQUENCER_STACK(x) (0x20 + (x))
/* AD7616_REG_CONFIG */
#define AD7616_SDEF (1 << 7)
#define AD7616_BURSTEN (1 << 6)
#define AD7616_SEQEN (1 << 5)
#define AD7616_OS(x) (((x) & 0x7) << 2)
#define AD7616_STATUSEN (1 << 1)
#define AD7616_CRCEN (1 << 0)
/* AD7616_REG_INPUT_RANGE */
#define AD7616_INPUT_RANGE(ch, x) (((x) & 0x3) << (((ch) & 0x3) * 2))
/* AD7616_REG_SEQUENCER_STACK(x) */
#define AD7616_ADDR(x) (((x) & 0x7F) << 9)
#define AD7616_SSREN (1 << 8)
#define AD7616_BSEL(x) (((x) & 0xF) << 4)
#define AD7616_ASEL(x) (((x) & 0xF) << 0)
/* AD7616_REG_STATUS */
#define AD7616_STATUS_A(x) (((x) & 0xF) << 12)
#define AD7616_STATUS_B(x) (((x) & 0xF) << 8)
#define AD7616_STATUS_CRC(x) (((x) & 0xFF) << 0)
/******************************************************************************/
/*************************** Types Declarations *******************************/
/******************************************************************************/
typedef enum {undefined
AD7616_SW, /* 软件模式 */
AD7616_HW, /* 硬件模式 */
} ad7616_mode;
typedef enum {undefined
AD7616_SERIAL, /* 串行接口 */
AD7616_PARALLEL, /* 并行接口 */
} ad7616_interface;
typedef enum {undefined
AD7616_VA0,
AD7616_VA1,
AD7616_VA2,
AD7616_VA3,
AD7616_VA4,
AD7616_VA5,
AD7616_VA6,
AD7616_VA7,
AD7616_VB0,
AD7616_VB1,
AD7616_VB2,
AD7616_VB3,
AD7616_VB4,
AD7616_VB5,
AD7616_VB6,
AD7616_VB7,
} ad7616_ch;
typedef enum {undefined
AD7616_2V5 = 1, /* 采样范围 */
AD7616_5V = 2,
AD7616_10V = 3,
} ad7616_range;
typedef enum {undefined
AD7616_OSR_0, /* 过采样点数 */
AD7616_OSR_2,
AD7616_OSR_4,
AD7616_OSR_8,
AD7616_OSR_16,
AD7616_OSR_32,
AD7616_OSR_64,
AD7616_OSR_128,
} ad7616_osr;
typedef struct {undefined
/* Device Settings */
ad7616_interface interface;
ad7616_mode mode;
ad7616_range va[8];
ad7616_range vb[8];
ad7616_osr osr;
} ad7616_dev;
/******************************************************************************/
/************************ Functions Declarations ******************************/
/******************************************************************************/
/* SPI read from device. */
int32_t ad7616_read(ad7616_dev *dev, uint8_t reg_addr, uint16_t *reg_data);
/* SPI write to device. */
int32_t ad7616_write(ad7616_dev *dev, uint8_t reg_addr, uint16_t reg_data);
/* SPI read from device using a mask. */
int32_t ad7616_read_mask(ad7616_dev *dev, uint8_t reg_addr, uint16_t mask, uint16_t *data);
/* SPI write to device using a mask. */
int32_t ad7616_write_mask(ad7616_dev *dev, uint8_t reg_addr, uint16_t mask, uint16_t data);
/* SPI read from device. */
int32_t ad7616_spi_read(ad7616_dev *dev, uint8_t reg_addr, uint16_t *reg_data);
/* SPI write to device. */
int32_t ad7616_spi_write(ad7616_dev *dev, uint8_t reg_addr, uint16_t reg_data);
/* PAR read from device. */
int32_t ad7616_par_read(ad7616_dev *dev, uint8_t reg_addr, uint16_t *reg_data);
/* PAR write to device. */
int32_t ad7616_par_write(ad7616_dev *dev, uint8_t reg_addr, uint16_t reg_data);
/* Perform a full reset of the device. */
int32_t ad7616_reset(ad7616_dev *dev);
/* Set the analog input range for the selected analog input channel. */
int32_t ad7616_set_range(ad7616_dev *dev, ad7616_ch ch, ad7616_range range);
/* Set the operation mode (software or hardware). */
int32_t ad7616_set_mode(ad7616_dev *dev, ad7616_mode mode);
/* Set the oversampling ratio. */
int32_t ad7616_set_oversampling_ratio(ad7616_dev *dev, ad7616_osr osr);
/* Initialize the device. */
int32_t ad7616_setup(ad7616_dev *dev);
int32_t ad7616_capture(ad7616_dev *dev);
————————————————
版权声明:本文为CSDN博主「信阳茶农」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:[url]https://blog.csdn.net/kwx618/article/details/107643572[/url]