STM32F429操作两片AD7689
项目需要用两片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相关推荐
- OpenNI2下简单操作两个体感设备(Xtion与Kinect for Xbox 360)
主要内容: 设备与驱动准备 代码演示 总结 一.设备与驱动准备 最近忙着写论文,已好长时间没瞎写了,这两天偶然看到一篇有关OpenNI2操作两个体感设备的文章,自己复制粘贴运行下看了效果挺好的,所以我 ...
- 华为系统里的计算机,一个屏幕操作两个系统 让你的手机装进华为MateBook 14电脑里...
2020春节一过全国掀起了一股在线办公.在线学习的热潮.笔者也由于特殊原因,无法回到工作室办公,只好用身边的华为MateBook 14 2020款居家远程办公. 也正是在这段日子,让笔者充分体会到华为 ...
- flutter 布局 Stack Positioned的混合操作 两个组件Container重叠 构建背景圆角操作 类似css的relative
flutter 布局 Stack Positioned的混合操作 两个组件Container重叠 构建背景圆角操作 首先看一下需求 需要在这里加一个背景圆角,涉及到两个组件Container的重叠 我 ...
- sql同时操作两列_SQL简单查询
1. 基本的查询语句 selece<列名1>,<列名2>,.... →select子句 from<表名>: →from子句 -- 在student表中查询出姓名.性 ...
- java json 去重_js操作两个json数组合并、去重,以及删除某一项元素
两个json数组合并去重,以及删除某一项元素 let ha = [ {id:'H',name:'3'}, {id:'A',name:'6'}, {id:'B',name:'14'}, {id:'C', ...
- MySQL可以同时修改两个表吗_(10)MySQL触发器(同时操作两张表)
什么是触发器 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合.触发器的这种特性可以协助应用在数据库端确保数据的完整性. 举个例子,比如你现在有两个表[用户表]和[日志 ...
- 同事操作两个数据源保持事务一致_「微服务架构」微服务架构中的数据一致性...
在微服务中,一个逻辑上原子操作可以经常跨越多个微服务.即使是单片系统也可能使用多个数据库或消息传递解决方案.使用多个独立的数据存储解决方案,如果其中一个分布式流程参与者出现故障,我们就会面临数据不一致 ...
- RT-Thread对GPIO操作两种方式的区别:1)通过设备操作接口2)直接通过通用GPIO设备驱动
在学习RT-Thread设备驱动框架时,看到潘多拉开发板的RT-Thread例程资料中的文档<AN0002-RT-Thread-通用 GPIO 设备应用笔记>有如下描述,因此产生使用文档中 ...
- 同事操作两个数据源保持事务一致_终于有人把分布式事务说清楚了
前言 这篇文章将给大家介绍一下对分布式事务的一些见解,并讲解分布式事务处理框架 TX-LCN 的执行原理,错误之处望各位不吝指正. 1. 什么情况下需要使用分布式事务? 使用的场景很多,先举一个常见的 ...
最新文章
- VTK:光标形状用法实战
- docker centos 环境 安装 python
- 2020年,中国AI创业公司将走向何方
- torch.bmm() 与 torch.matmul()==>张量的相乘运算
- Jenkins持续集成项目搭建与实践——基于Python Selenium自动化测试(自由风格)
- wordpress模板
- JPA-update方法使用踩坑记
- .md文件用什么软件打开
- js页面跳转并传值问题
- 富文本编辑器Froala Editor v3.x 使用
- 什么是网站前端框架?目前常用的网站前端框架都有哪些?
- fiddler连接代理手机无法上网问题解决办法
- 冬吃萝卜有讲究 名中医解疑惑
- 用代码写个烟花之基础版
- 用css实现朋友圈图片布局
- 循环世界模型(Recurrent World Models)——真实世界建模的强化学习利器
- gdpr隐私保护_微信公众平台已发布GDPR隐私保护条例的新措施
- Vue 项目对接接口数据
- 小西的快乐乘法表(想不到怎么做到同时输入两个数,并同时输出两张乘法表,求助)
- 美国计算机科学就业率,美国计算机就业率最高的30所大学