项目需要用两片AD7689组成16通道工频数据采集,双通道同步采样,一次双通道采集耗时20us,一次单通道采集耗时14us,现把源码公开,希望大牛能将采样时间降到最低,减少CPU占用率。

/**
  ***********************************************************************************
  * 
  * @file    bsp_ad7689.c
  * @author  kwx618
  * @version V1.0.0
  * @date    09-May-2018
  * @Brief   AD7689 chip driver module
  * 
  ***********************************************************************************
  */
  
/* Includes ------------------------------------------------------------------*/
#include "bsp_ad7689.h"
#include "common.h"

/* Private typedef -----------------------------------------------------------*/
static GPIO_TypeDef* CVN_GPIO_PORT[AD7689n] = {AD7689x1_CS_PORT, AD7689x2_CS_PORT};

const uint16_t CVN_GPIO_PIN[AD7689n] = {AD7689x1_CS_PIN, AD7689x2_CS_PIN};

#ifdef AD7689_SOFT_SPI

static GPIO_TypeDef* AD7689_PORT[AD7689n] = {SPI2_GPIO_PORT, SPI3_GPIO_PORT};

const uint16_t AD7689_SCK_PIN[AD7689n]  = {SPI2_SCK,  SPI3_SCK};
const uint16_t AD7689_MISO_PIN[AD7689n] = {SPI2_MISO, SPI3_MISO};
const uint16_t AD7689_MOSI_PIN[AD7689n] = {SPI2_MOSI, SPI3_MOSI};

#else

const SPIx_EnumDef AD7689_SPI_COM[AD7689n] = {SPIx2, SPIx3};

#endif

/* Private define ------------------------------------------------------------*/
#define IN0             (0x3C79 << 2)
#define IN1             (0x3CF9 << 2)
#define IN2             (0x3D79 << 2)
#define IN3             (0x3DF9 << 2)
#define IN4             (0x3E79 << 2)
#define IN5             (0x3EF9 << 2)
#define IN6             (0x3F79 << 2)
#define IN7             (0x3FF9 << 2)
#define M               8                       // channel num

uint16_t AD7689_cfg[AD7689n][M] = { {IN7, IN6, IN5, IN4, IN3, IN2, IN5, IN0},
                                    {IN3, IN2, IN1, IN6, IN5, IN4, IN7, IN0} };  // CFG序列,与data错开2个序列

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void AD7689_CNV(AD7689x_EnumDef ADCx, uint8_t _level);
/* Private functions ---------------------------------------------------------*/

#ifdef AD7689_SOFT_SPI
/**
  * @brief  Set up SPI bus clock line for AD7689.
  * @param  _level: Specifies the SPI bus clock line level for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  0
  *     @arg  1
  * @retval None.
  * @notes  None.
  */
void AD7689_SCK(AD7689x_EnumDef ADCx, uint8_t _level)
{
    if (_level == Bit_RESET)
    {
        AD7689_PORT[ADCx]->BSRRH = AD7689_SCK_PIN[ADCx];
    }
    else
    {
        AD7689_PORT[ADCx]->BSRRL = AD7689_SCK_PIN[ADCx];
    }
}

/**
  * @brief  Set up SPI bus data line for AD7689.
  * @param  _level: Specifies the SPI bus data line level for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  0
  *     @arg  1
  * @retval None.
  * @notes  None.
  */
void AD7689_MOSI(AD7689x_EnumDef ADCx, uint8_t _level)
{
    if (_level == Bit_RESET)
    {
        AD7689_PORT[ADCx]->BSRRH = AD7689_MOSI_PIN[ADCx];
    }
    else
    {
        AD7689_PORT[ADCx]->BSRRL = AD7689_MOSI_PIN[ADCx];
    }
}

/**
  * @brief  Read SPI data line level for AD7689.
  * @param  None.
  * @retval Specifies the SPI bus data line level for AD7689.
  * @notes  None.
  */
uint8_t AD7689_MISO(AD7689x_EnumDef ADCx)
{
    uint8_t bitstatus = Bit_RESET;
    
    if ((AD7689_PORT[ADCx]->IDR & AD7689_MISO_PIN[ADCx]) != (uint32_t)Bit_RESET)
    {
        bitstatus = (uint8_t)Bit_SET;
    }
    else
    {
        bitstatus = (uint8_t)Bit_RESET;
    }
    return bitstatus;    
}

#else

/**
  * @brief  SPI bus interface initialization for AD7689 operation.
  * @param  SPIx: Specifies the SPI to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  SPIx1
  *     @arg  SPIx2
  * @retval None
  */
void AD7689_SpiInit(SPIx_EnumDef SPIx)
{
    SPI_InitTypeDef  SPI_InitStructure;
  
    /* SPI bus IO port initialization */
    SPIx_GpioInit(SPIx);  
    
    /* Enable SPI bus clock */
    SPIx_CLK_ENABLE(SPIx);
    
    /* 先禁止SPI  */
    SPI_Cmd(HardSPIx[SPIx], DISABLE);    
    
    /* Fills each SPI_InitStruct member with its default value */
    SPI_StructInit(&SPI_InitStructure);
    
    /* Set SPI interface */
    SPI_InitStructure.SPI_CPOL              = SPI_CPOL_Low;                     /* Choose the steady state of serial clock for low*/
    SPI_InitStructure.SPI_CPHA              = SPI_CPHA_1Edge;                   /* Set bit to capture the active edge of the clock at 2 */
    SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;                     /* The NSS signal is specified by the hardware (NSS) or the software (using the SSI bit).*/   
    SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;  /* Set up the SPI - way or two-way data mode*/
    SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;                  /* Set up SPI work mode */
    SPI_InitStructure.SPI_DataSize          = SPI_DataSize_16b;                 /* Set up the SPI data size*/
    SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;                 /* Specify data transfer from MSB or LSB to start*/    
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;         /* Defining the value of baud rate prescaling:2~256 */     
    SPI_InitStructure.SPI_CRCPolynomial     = 7;                                /* A polynomial defined for CRC values*/

SPI_Init(HardSPIx[SPIx], &SPI_InitStructure);
    
    /* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
    HardSPIx[SPIx]->I2SCFGR &= SPI_Mode_Select;        /* 选择SPI模式,不是I2S模式 */

SPI_Cmd(HardSPIx[SPIx], ENABLE);                /* 使能SPI  */        
}

#endif

/**
  * @brief  AD7689 initialize.
  * @param  ADCx: Specifies the Model ADC sampling chip for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  AD7689x1
  *     @arg  AD7689x2
  * @retval None.
  * @notes  The function called by BSP_Init()
  */
void AD7689_Init(AD7689x_EnumDef ADCx)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    
    /* SPI interface initialization. */
#ifdef AD7689_SOFT_SPI

/* Enable the chip operate bus clock of AD7689 port  */
    AD7689_CLK_ENABLE(ADCx);
    
    /* The configuration for the push-pull output mode chip line */
    GPIO_InitStruct.GPIO_Pin   = AD7689_SCK_PIN[ADCx] | AD7689_MOSI_PIN[ADCx];
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(AD7689_PORT[ADCx], &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin   = AD7689_MISO_PIN[ADCx];
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_Init(AD7689_PORT[ADCx], &GPIO_InitStruct);

AD7689_SCK(ADCx, 1);
    AD7689_MOSI(ADCx, 1);     
    
#else

AD7689_SpiInit(AD7689_SPI_COM[ADCx]);

#endif
    
    /* Enable the chip select clock of AD7689 port  */
    AD7689_CS_CLK_ENABLE(ADCx);
    
    /* The configuration for the push-pull output mode chip select line */
    GPIO_InitStruct.GPIO_Pin   = CVN_GPIO_PIN[ADCx];
    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(CVN_GPIO_PORT[ADCx], &GPIO_InitStruct);

/* The chip select high, not selected */
    AD7689_CNV(ADCx, 1);
}

/**
  * @brief  Chip select signal of AD7689 chip.
  * @param  ADCx: Specifies the Model ADC sampling chip for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  AD7689x1
  *     @arg  AD7689x2
  * @retval None.
  * @notes  None.
  */
static void DelayUs(uint32_t us)
{
    uint32_t i = 0;
    
    while(i<us)
    {
        i++;
    }
}

/**
  * @brief  Chip select signal of AD7689 chip.
  * @param  ADCx: Specifies the Model ADC sampling chip for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  AD7689x1
  *     @arg  AD7689x2
  * @retval None.
  * @notes  None.
  */
static void AD7689_CNV(AD7689x_EnumDef ADCx, uint8_t _level)
{
    if (_level == Bit_RESET)
    {
        CVN_GPIO_PORT[ADCx]->BSRRH = CVN_GPIO_PIN[ADCx];
    }
    else
    {
        CVN_GPIO_PORT[ADCx]->BSRRL = CVN_GPIO_PIN[ADCx];
    }
}

/**
  * @brief  Read a channel sampling data for AD7689.
  * @param  ADCx: Specifies the Model ADC sampling chip for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  AD7689x1
  *     @arg  AD7689x2
  * @param  chn: Specifies the Model ADC channel for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  0、1、2、3、4、5、6、7
  * @retval None.
  * @notes  It takes 16 microseconds to read a channel using IO port to simulate SPI bus, 
  *         232 microseconds to sample 16 channels data of two AD7689s by cross-cyclic sampling;
  *         12 microseconds to read a channel by hardware SPI bus and 
  *         187 microseconds to sample 16 channels data of two AD7689s by cross-cyclic sampling.
  */
uint16_t AD7689_ReadReg(AD7689x_EnumDef ADCx, uint8_t chn)
{
    uint16_t data = 0;

#ifdef AD7689_SOFT_SPI
    
    uint8_t i;
    uint16_t cfg = AD7689_cfg[ADCx][chn];
    
    AD7689_CNV(ADCx, 0u);
    AD7689_SCK(ADCx, 0u);

for(i=16; i>0; i--)
    {
        if(cfg & 0x8000)
        {
            AD7689_MOSI(ADCx, 1u);
        }
        else
        {
            AD7689_MOSI(ADCx, 0u);
        }           
        
        cfg <<= 1;

AD7689_SCK(ADCx, 1u);
        DelayUs(2u);
        
        data <<= 1;
        
        if(AD7689_MISO(ADCx) == 1)
        {
            data |= 0x0001;
        }

AD7689_SCK(ADCx, 0u);
    }
    
    AD7689_CNV(ADCx, 1u);
    DelayUs(2u);       
          
#else
    
    AD7689_CNV(ADCx, 1u);
    DelayUs(120u);  //80-MIN
   
    AD7689_CNV(ADCx, 0u); //RAC with a busy indicator
    DelayUs(1u); 
    
    data = SPIx_ExchangeData(AD7689_SPI_COM[ADCx], AD7689_cfg[ADCx][chn]);
    
#endif 
    
    return data;
}

/**
  * @brief  Read dual channel sampling data for each AD7689.
  * @param  ADCx: Specifies the Model ADC sampling chip for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  AD7689x1
  *     @arg  AD7689x2
  * @param  chn: Specifies the Model ADC channel for AD7689 to be configured.
  *   This parameter can be one of following parameters:
  *     @arg  0、1、2、3、4、5、6、7
  * @retval None.
  * @notes  It takes 16 microseconds to read a channel using IO port to simulate SPI bus, 
  *         232 microseconds to sample 16 channels data of two AD7689s by cross-cyclic sampling;
  *         12 microseconds to read a channel by hardware SPI bus and 
  *         187 microseconds to sample 16 channels data of two AD7689s by cross-cyclic sampling.
  */
uint32_t AD7689_ReadDualReg(uint8_t chn)
{
    LONG_T data;

#ifdef AD7689_SOFT_SPI
    
    uint8_t i;
    uint16_t cfg0 = AD7689_cfg[AD7689x1][chn];
    uint16_t cfg1 = AD7689_cfg[AD7689x2][chn];
    
    AD7689_CNV(AD7689x1, 0u);
    AD7689_SCK(AD7689x1, 0u);
    
    AD7689_CNV(AD7689x2, 0u);
    AD7689_SCK(AD7689x2, 0u);
    
    for(i=16; i>0; i--)
    {
        if(cfg0 & 0x8000)
        {
            AD7689_MOSI(AD7689x1, 1u);
        }
        else
        {
            AD7689_MOSI(AD7689x1, 0u);
        }
        if(cfg1 & 0x8000)
        {
            AD7689_MOSI(AD7689x2, 1u);
        }
        else
        {
            AD7689_MOSI(AD7689x2, 0u);
        }        
        
        cfg0 <<= 1;
        cfg1 <<= 1;

AD7689_SCK(AD7689x1, 1u);
        AD7689_SCK(AD7689x2, 1u);
        DelayUs(1u);
        
        data.dbyte.l <<= 1;
        data.dbyte.h <<= 1;
        
        if(AD7689_MISO(AD7689x1) == 1)
        {
            data.dbyte.l |= 0x0001;
        }
        if(AD7689_MISO(AD7689x2) == 1)
        {
            data.dbyte.h |= 0x0001;
        }

AD7689_SCK(AD7689x1, 0u);
        AD7689_SCK(AD7689x2, 0u);
    }
    
    
    AD7689_CNV(AD7689x1, 1u);
    AD7689_CNV(AD7689x2, 1u);
    DelayUs(2u);       
          
#else
    
    AD7689_CNV(AD7689x1, 1u);
    AD7689_CNV(AD7689x2, 1u);
    DelayUs(120u);  //80-MIN
   
    AD7689_CNV(AD7689x1, 0u); //RAC with a busy indicator
    AD7689_CNV(AD7689x2, 0u);
    DelayUs(1u); 
    
    data.dbyte.l = SPIx_ExchangeData(AD7689_SPI_COM[AD7689x1], AD7689_cfg[AD7689x1][chn]);
    data.dbyte.h = SPIx_ExchangeData(AD7689_SPI_COM[AD7689x2], AD7689_cfg[AD7689x2][chn]);
    
#endif 
    
    return data.word;
}

/**
  * @brief  Control Chip Stop Conversion
  * @param  None.
  * @retval None.
  * @notes  None.
  */
void AD7689_StopConvert(void)
{
    AD7689_CNV(AD7689x1, 0u);
    AD7689_CNV(AD7689x2, 0u);
}

/**
  * @brief  Control Chip Start Conversion
  * @param  None.
  * @retval None.
  * @notes  None.
  */
void AD7689_StartConvert(void)
{
    AD7689_CNV(AD7689x1, 1u);
    AD7689_CNV(AD7689x2, 1u);
}

尝试了两种方法,一种是通过IO口模拟SPI操作,一种是通过SPI总线控制器操作,最想通过SPI总线控制器配合DMA,这种方式是最优解,只是一直失败,请教大牛!!!

STM32F429操作两片AD7689相关推荐

  1. OpenNI2下简单操作两个体感设备(Xtion与Kinect for Xbox 360)

    主要内容: 设备与驱动准备 代码演示 总结 一.设备与驱动准备 最近忙着写论文,已好长时间没瞎写了,这两天偶然看到一篇有关OpenNI2操作两个体感设备的文章,自己复制粘贴运行下看了效果挺好的,所以我 ...

  2. 华为系统里的计算机,一个屏幕操作两个系统 让你的手机装进华为MateBook 14电脑里...

    2020春节一过全国掀起了一股在线办公.在线学习的热潮.笔者也由于特殊原因,无法回到工作室办公,只好用身边的华为MateBook 14 2020款居家远程办公. 也正是在这段日子,让笔者充分体会到华为 ...

  3. flutter 布局 Stack Positioned的混合操作 两个组件Container重叠 构建背景圆角操作 类似css的relative

    flutter 布局 Stack Positioned的混合操作 两个组件Container重叠 构建背景圆角操作 首先看一下需求 需要在这里加一个背景圆角,涉及到两个组件Container的重叠 我 ...

  4. sql同时操作两列_SQL简单查询

    1. 基本的查询语句 selece<列名1>,<列名2>,.... →select子句 from<表名>: →from子句 -- 在student表中查询出姓名.性 ...

  5. java json 去重_js操作两个json数组合并、去重,以及删除某一项元素

    两个json数组合并去重,以及删除某一项元素 let ha = [ {id:'H',name:'3'}, {id:'A',name:'6'}, {id:'B',name:'14'}, {id:'C', ...

  6. MySQL可以同时修改两个表吗_(10)MySQL触发器(同时操作两张表)

    什么是触发器 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合.触发器的这种特性可以协助应用在数据库端确保数据的完整性. 举个例子,比如你现在有两个表[用户表]和[日志 ...

  7. 同事操作两个数据源保持事务一致_「微服务架构」微服务架构中的数据一致性...

    在微服务中,一个逻辑上原子操作可以经常跨越多个微服务.即使是单片系统也可能使用多个数据库或消息传递解决方案.使用多个独立的数据存储解决方案,如果其中一个分布式流程参与者出现故障,我们就会面临数据不一致 ...

  8. RT-Thread对GPIO操作两种方式的区别:1)通过设备操作接口2)直接通过通用GPIO设备驱动

    在学习RT-Thread设备驱动框架时,看到潘多拉开发板的RT-Thread例程资料中的文档<AN0002-RT-Thread-通用 GPIO 设备应用笔记>有如下描述,因此产生使用文档中 ...

  9. 同事操作两个数据源保持事务一致_终于有人把分布式事务说清楚了

    前言 这篇文章将给大家介绍一下对分布式事务的一些见解,并讲解分布式事务处理框架 TX-LCN 的执行原理,错误之处望各位不吝指正. 1. 什么情况下需要使用分布式事务? 使用的场景很多,先举一个常见的 ...

最新文章

  1. VTK:光标形状用法实战
  2. docker centos 环境 安装 python
  3. 2020年,中国AI创业公司将走向何方
  4. torch.bmm() 与 torch.matmul()==>张量的相乘运算
  5. Jenkins持续集成项目搭建与实践——基于Python Selenium自动化测试(自由风格)
  6. wordpress模板
  7. JPA-update方法使用踩坑记
  8. .md文件用什么软件打开
  9. js页面跳转并传值问题
  10. 富文本编辑器Froala Editor v3.x 使用
  11. 什么是网站前端框架?目前常用的网站前端框架都有哪些?
  12. fiddler连接代理手机无法上网问题解决办法
  13. 冬吃萝卜有讲究 名中医解疑惑
  14. 用代码写个烟花之基础版
  15. 用css实现朋友圈图片布局
  16. 循环世界模型(Recurrent World Models)——真实世界建模的强化学习利器
  17. gdpr隐私保护_微信公众平台已发布GDPR隐私保护条例的新措施
  18. Vue 项目对接接口数据
  19. 小西的快乐乘法表(想不到怎么做到同时输入两个数,并同时输出两张乘法表,求助)
  20. 美国计算机科学就业率,美国计算机就业率最高的30所大学

热门文章

  1. 大众汽车发动机引擎列表及历史
  2. Catia 零件 曲面 装配 工程图 仿真运动 参数和知识工程视频教程
  3. linux第三方软件安装目录
  4. python里感叹号什么意思_感叹号!代表什么意思,标点符号的用法之感叹号
  5. 为什么坚持用iPod?没有比它更好的赏乐方式了
  6. Js获取当前时间的月初月末
  7. 使用阿里云身份证扫描识别接口案例——CSDN博客
  8. 接打电话的蓝牙耳机哪个牌子好?接听电话蓝牙耳机推荐
  9. 手机H5网站 支付宝、微信支付遇到的问题和注意事项
  10. 什么是XFP光模块以极和SFP+模块的区别