赞
踩
目录
工程压缩包:https://download.csdn.net/download/binocthrx/88222511?spm=1001.2014.3001.5503
模块名称:AD7606 多通道AD 数据采集模块
模块尺寸:50mm * 48mm
模块供电:5V
模块输入电压范围:±5V,±10V(由RANGE 引脚的逻辑电平决定,该引脚与逻辑高
电平连接时,所有通道模拟输入范围为±10V。该引脚与逻辑低
电平连接时,所有通道模拟输入范围为±5V。程序默认±5V)
输入阻抗:1MΩ
内部基准电压源:2.5V(可自行配置外部基准电压)
模拟输入箝位保护:±16.5V
模块采样率:200KSPS(所有8 个通道)
模块分辨率:16 bit
模块接口:SPI 接口或16 位并口(模块默认SPI 串口)
模拟输入滤波器带宽:23KHz(-3dB,±10V 范围)
15KHz(-3dB,±5V 范围)
信噪比:90dB(典型值,无过采样,±10V)
89dB(典型值,无过采样,±5V)
AD_CS-----PC12
AD_RESET-----PC10
AD_CONVST-----PC13 (板子上的CA/CB)
AD_RANGE------PC8
AD_OS0-----PC4
AD_OS1-----PC5
AD_OS2-----PC6
AD_BUSY-----PA5(不用可以不接)
SPI接线
具体为
SCK-----PB3 (板子上的RD口)
MISO----PB4 (板子上的D7口)
MOSI没用上不接
CONVST A和CONVST B连在一起,t5接近于0,此时为串行8路采样,CONVST A和CONVST B平时为高电平,转换时拉低至少50ns。转换时BUSY被拉高,转换结束被拉低,转换时间tconv在无过采样时典型值为4ns。
串行模式转换之后读取是,待BUSY被拉低后,可以将CS拉低控制SCLK时钟信号进行数据的读取,先读出的为高位。读出一个完整通道需要16位,读出8个通道依次16次读取循环8次即可,对于DA口,读取的顺序为通道1、2、3、4、5、6、7、8,对于DB口读取的顺序为通道5、6、7、8、1、2、3、4,两个端口同步输出。若只需一个通道,那么仅读取一次即可。根据DA\DB读取顺序的不同,我们可以两个端口同时读取,一次读取两个通道值,只需读4次即可读完8个通道值。
转换及读取代码如下
- uint16_t ADRED_AD7606(){
-
- uint16_t data;
- AD_CS_LOW();
-
- data=SPI1_ReadWriteByte(0xff);
-
- AD_CS_HIGH();
- ad7606_StartConv();
- return data;
- }
当BUSY为高电平,转换正在进行时,也可以从AD7606/AD7606-6/AD7606-4读取数据。这几乎不会影响转换器的性能,而且可以实现更快的吞吐速率。转换期间可以执行并行、并行字节或串行读取,可以使用或不用过采样。图3显示并行或串行模式下BUSY为高电平时读取操作的时序图。转换期间执行读取使得使用串行接口且VDRIVE高于4.75V时也可以达到最高吞吐速率。DRIVE在BUSY下降沿时,输出数据寄存器会被新转换数据更新,除外之外的任何时候都可以从AD7606读取数据。对于t6,最后CS上升沿与BUSY下降沿之间的最长时间为25ns。
此模块REF为2.5V,范围为10V时,对于正电压,输入电压VIN=CODE*10/32678。
对于负电压,可以看出输出的CODE为补码,负数补码的源码是符号位不变,其余位取反后加一,原码的首位仍为符号位,在此案例中获得其绝对值可以对其全部取反后加一即可,最后将转换的CODE手动加上负号。代码如下:
- sampdata=ADRED_AD7606();
- if(sampdata<32768){
- dataVol=((sampdata)*10.0 * 1000 ) / 32768;
- }
- else {
- sampdata = (~sampdata)+1;
- dataVol=((sampdata)*10.0 * -1000 ) / 32768;
- }
转换后的电压值负号为mV。
使用STM32F4自带的spi通信,参考正点原子的spi通信实验的代码,因为是146位ADC,我们直接配置16位的spi,配置如下:
- void SPI1_Init(void)
-
- {
-
- GPIO_InitTypeDef GPIO_InitStructure;
-
- SPI_InitTypeDef SPI_InitStructure;
-
-
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1时钟
-
-
-
- //GPIOFB3,4,5初始化设置
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//PB3~5复用功能输出
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
-
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
-
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
-
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
-
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
-
-
-
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3复用为 SPI1
-
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4复用为 SPI1
-
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5复用为 SPI1
-
-
-
- //这里只针对SPI口初始化
-
- RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//复位SPI1
-
- RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//停止复位SPI1
-
-
-
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
-
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
-
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //设置SPI的数据大小:SPI发送接收8位帧结构
-
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
-
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //串行同步时钟的第一个跳变沿(上升或下降)数据被采样
-
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
-
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; //定义波特率预分频的值:波特率预分频值为64
-
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
-
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
-
- SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
-
-
-
- SPI_Cmd(SPI1, ENABLE); //使能SPI外设
-
-
-
- SPI1_ReadWriteByte(0xff);//启动传输
-
- }

然后利用此函数进行数据通信:
- u16 SPI1_ReadWriteByte(u16 TxData)
-
- {
-
-
-
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空
-
-
-
- SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个byte 数据
-
-
-
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte
-
-
-
- return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
-
-
-
- }

最后这是利用信号发生器发出的1HZ正弦波交流信号采集后利用excel画出的波形
利用定时器,可控制采样率,此处利用TME3定时器,设置时长为0.5ms,也就是2K左右的采样率(2K实际值为2048),若设置为1ms那也就是大概1K
TIM3_Int_Init(500-1,84-1); //定时器时钟84M,分频系数84,所以84M/84=1000Khz的计数频率,计数500次为0.5ms
对于定时器初始化代码
- void TIM3_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3时钟
-
- TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
- TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
- TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
- TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
-
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
-
- TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
- TIM_Cmd(TIM3,ENABLE); //使能定时器3
-
- NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
- }

在中断函数中调用转换函数,注意此处不要有过多操作,仅读取即可,否则影响采样率精度,个人的操作方式是,采集够数据量时临时暂停一下定时器,在主函数中对数据操作完成后继续定时采集。
- //定时器3中断服务函数
- void TIM3_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
- {
- // LED1=!LED1;//DS1翻转
- ad_sampdata[ad_times++]=ADRED_AD7606();
- if(ad_times>=CA_SIZE){
- ad_times=0;
- AD_FULL=1;
- ad7606_StopRecord();
- }
- }
- TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。