立即注册 登录
逆天PCB论坛 返回首页

brilliance的个人空间 https://bbs.ntpcb.com/?35973 [收藏] [复制] [RSS]

日志

双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]

路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

平平安安
TOP
返回顶部