|

楼主 |
发表于 2025-1-24 10:10:58
|
显示全部楼层
/*
*********************************************************************************************************
*
* 模块名称 : AD7606数据采集模块
* 文件名称 : bsp_fsmc_ad7606.c
* 版 本 : V1.0
* 说 明 : AD7606挂在STM32的FMC总线上,本例子使用了TIM8作为硬件定时器,定时启动ADC转换。
* AD7606的FMC驱动做了两种采集方式:
* (1)软件查询方式,适合低速查询获取。
* (2)FIFO工作模式,适合8路实时采集,支持最高采样率200Ksps。
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2020-05-01 armfly 正式发布
*
* Copyright (C), 2020-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "bsp.h"
/*
STM32-V6开发板 + AD7606模块, 控制采集的IO:
GND ---> AD7606_OS0 无过采样
GND ---> AD7606_OS1
GND ---> AD7606_OS2
GND ---> AD7606_RAGE 输入模拟电压量程,正负5V
PF0 ---> AD7606_RESET 复位
PA6 ---> AD7606_BUSY 忙信号 (未使用)
PB6/PB7 ---> AD7606_CONVSTA/CONVSTB 启动ADC转换
*/
/* CONVST 启动ADC转换的GPIO = PH12 */
#define CONVST_RCC_GPIO_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
#define CONVST_TIM8_CLK_DISABLE __HAL_RCC_TIM4_CLK_DISABLE
#define CONVST_GPIO GPIOB
#define CONVST_PIN GPIO_PIN_6
#define CONVST_TIMX TIM4
#define CONVST_TIMCH 1
#define CONVST_GPIO2 GPIOB
#define CONVST_PIN2 GPIO_PIN_7
#define CONVST_TIMX2 TIM4
#define CONVST_TIMCH2 2
/* 启动AD转换 */
#define CONVST_1() CONVST_GPIO->BSRR = CONVST_PIN; CONVST_GPIO2->BSRR = CONVST_PIN2
#define CONVST_0() CONVST_GPIO->BSRR = ((uint32_t)CONVST_PIN << 16U); CONVST_GPIO2->BSRR = ((uint32_t)CONVST_PIN2 << 16U)
/* BUSY 转换完毕信号 = PI6 */
#define BUSY_RCC_GPIO_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
#define BUSY_GPIO GPIOA
#define BUSY_PIN GPIO_PIN_6
#define BUSY_IRQn EXTI9_5_IRQn
#define BUSY_IRQHandler EXTI9_5_IRQHandler
/* AD7606复位口线 : PF0 */
#define RESET_RCC_GPIO_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE
#define RESET_GPIO GPIOF
#define RESET_PIN GPIO_PIN_0
#define RESET_1() RESET_GPIO->BSRR = RESET_PIN
#define RESET_0() RESET_GPIO->BSRR = ((uint32_t)RESET_PIN << 16U)
/* AD7606 FSMC总线地址,只能读,无需写 */
#define AD7606_RESULT() *(__IO uint16_t *)0x6C000000
AD7606_VAR_T g_tAD7606; /* 定义1个全局变量,保存一些参数 */
AD7606_FIFO_T g_tAdcFifo; /* 定义FIFO结构体变量 */
static void AD7606_CtrlLinesConfig(void);
static void AD7606_FSMCConfig(void);
/*
*********************************************************************************************************
* 函 数 名: bsp_InitAD7606
* 功能说明: 配置连接外部SRAM的GPIO和FSMC
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitAD7606(void)
{
AD7606_CtrlLinesConfig();
AD7606_FSMCConfig();
// AD7606_SetOS(AD_OS_NO); /* 无过采样 */
AD7606_SetInputRange(0); /* 0表示输入量程为正负5V, 1表示正负10V */
AD7606_Reset(); /* 复位 */
CONVST_1(); /* 启动转换的GPIO,平时设置为高 */
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_CtrlLinesConfig
* 功能说明: 配置GPIO口线,FMC管脚设置为复用功能
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
/*
安富莱STM32-V5开发板接线方法:
PG12/FSMC_NE4 --- 主片选(TFT, OLED 和 AD7606)
PD4/FSMC_NOE --- 读控制信号,OE = Output Enable , N 表示低有效
PD14/FSMC_D0
PD15/FSMC_D1
PD0 /FSMC_D2
PD1 /FSMC_D3
PE7 /FSMC_D4
PE8 /FSMC_D5
PE9 /FSMC_D6
PE10/FSMC_D7
PE11/FSMC_D8
PE12/FSMC_D9
PE13/FSMC_D10
PE14/FSMC_D11
PE15/FSMC_D12
PD8 /FSMC_D13
PD9 /FSMC_D14
PD10/FSMC_D15
其他的控制IO:
PB6/PB7 ---> AD7606_CONVSTA/CONVSTB 启动ADC转换
PF0 ---> AD7606_RESET 复位
PA6 ---> AD7606_BUSY 忙信号 (未使用)
*/
static void AD7606_CtrlLinesConfig(void)
{
GPIO_InitTypeDef gpio_init_structure;
/* 使能 GPIO时钟 */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/* 使能FMC时钟 */
__HAL_RCC_FSMC_CLK_ENABLE();
/* 设置 GPIOD 相关的IO为复用推挽输出 */
gpio_init_structure.Mode = GPIO_MODE_AF_PP;
gpio_init_structure.Pull = GPIO_PULLUP;
gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
/* 配置GPIOD */
gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 |
GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 |
GPIO_PIN_15;
HAL_GPIO_Init(GPIOD, &gpio_init_structure);
/* 配置GPIOE */
gpio_init_structure.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 |
GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
HAL_GPIO_Init(GPIOE, &gpio_init_structure);
/* 配置GPIOG */
gpio_init_structure.Pin = GPIO_PIN_12;
HAL_GPIO_Init(GPIOG, &gpio_init_structure);
/* 配置几个控制用的GPIO
PH12/DCMI_D3/AD7606_CONVST ---> AD7606_CONVST 启动ADC转换
PI4/DCMI_D5/AD7606_RESET ---> AD7606_RESET 复位
*/
/* 其它IO */
{
GPIO_InitTypeDef GPIO_InitStructure;
RESET_RCC_GPIO_CLK_ENABLE();
CONVST_RCC_GPIO_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; /* 设置推挽输出 */
GPIO_InitStructure.Pull = GPIO_PULLUP; /* 上下拉电阻不使能 */
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; /* GPIO速度等级 */
GPIO_InitStructure.Pin = CONVST_PIN;
HAL_GPIO_Init(CONVST_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = CONVST_PIN2;
HAL_GPIO_Init(CONVST_GPIO2, &GPIO_InitStructure);
GPIO_InitStructure.Pin = RESET_PIN;
HAL_GPIO_Init(RESET_GPIO, &GPIO_InitStructure);
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_FSMCConfig
* 功能说明: 配置FSMC并口访问时序
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void AD7606_FSMCConfig(void)
{
/*
TFT-LCD,OLED和AD7606公用一个FMC配置,如果都开启,请以FMC速度最慢的为准。
从而保证所有外设都可以正常工作。
*/
SRAM_HandleTypeDef hsram = {0};
FSMC_NORSRAM_TimingTypeDef SRAM_Timing = {0};
/*
AD7606规格书要求(3.3V时,通信电平Vdriver):RD读信号低电平脉冲宽度最短21ns,对应FMC的DataSetupTime
CS片选和RD读信号独立方式的高电平脉冲最短宽度15ns。
CS片选和RD读信号并联方式的高电平脉冲最短宽度22ns。
这里将22ns作为最小值更合理些,对应FMC的AddressSetupTime
2-x-3-x-x-x : RD高持续27.8ns,低电平持续41.7ns. 读取8路样本数据到内存差不多就是556ns。
*/
hsram.Instance = FSMC_NORSRAM_DEVICE;
hsram.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
/* FMC使用的HCLK,主频72MHz,1个FMC时钟周期就是13.9ns */
SRAM_Timing.AddressSetupTime = 2; /* 2*13.9ns=27.8ns,地址建立时间,范围0 -15个FMC时钟周期个数 */
SRAM_Timing.AddressHoldTime = 0; /* 地址保持时间,配置为模式A时,用不到此参数 范围1 -15个时钟周期个数 */
SRAM_Timing.DataSetupTime = 3; /* 3*13.9ns=41.7ns,数据保持时间,范围1 -255个时钟周期个数 */
SRAM_Timing.BusTurnAroundDuration = 0; /* 此配置用不到这个参数 */
SRAM_Timing.CLKDivision = 0; /* 此配置用不到这个参数 */
SRAM_Timing.DataLatency = 0; /* 此配置用不到这个参数 */
SRAM_Timing.AccessMode = FSMC_ACCESS_MODE_A; /* 配置为模式A */
hsram.Init.NSBank = FSMC_NORSRAM_BANK4; /* 使用的BANK4,即使用的片选FSMC_NE4 */
hsram.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; /* 禁止地址数据复用 */
hsram.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM; /* 存储器类型SRAM */
hsram.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; /* 16位总线宽度 */
hsram.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; /* 关闭突发模式 */
hsram.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; /* 用于设置等待信号的极性,关闭突发模式,此参数无效 */
hsram.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; /* 关闭突发模式,此参数无效 */
hsram.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; /* 用于使能或者禁止写保护 */
hsram.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE; /* 关闭突发模式,此参数无效 */
hsram.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE; /* 禁止扩展模式 */
hsram.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; /* 用于异步传输期间,使能或者禁止等待信号,这里选择关闭 */
hsram.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; /* 禁止写突发 */
// hsram.Init.ContinuousClock = FSMC_CONTINUOUS_CLOCK_SYNC_ONLY; /* 仅同步模式才做时钟输出 */
// hsram.Init.WriteFifo = FSMC_WRITE_FIFO_ENABLE; /* 使能写FIFO */
/* 初始化SRAM控制器 */
if (HAL_SRAM_Init(&hsram, &SRAM_Timing, &SRAM_Timing) != HAL_OK)
{
/* 初始化错误 */
Error_Handler(__FILE__, __LINE__);
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_SetInputRange
* 功能说明: 配置AD7606模拟信号输入量程。
* 形 参: _ucRange : 0 表示正负5V 1表示正负10V
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_SetInputRange(uint8_t _ucRange)
{
if (_ucRange == 0)
{
g_tAD7606.ucRange = 0;
// RANGE_0(); /* 设置为正负5V */
}
else
{
g_tAD7606.ucRange = 1;
// RANGE_1(); /* 设置为正负10V */
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_Reset
* 功能说明: 硬件复位AD7606,复位之后恢复到正常工作状态。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_Reset(void)
{
RESET_0(); /* 退出复位状态 */
RESET_1(); /* 进入复位状态 */
RESET_1(); /* 仅用于延迟。 RESET复位高电平脉冲宽度最小50ns。 */
RESET_1();
RESET_1();
RESET_0(); /* 退出复位状态 */
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_StartConvst
* 功能说明: 启动1次ADC转换
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_StartConvst(void)
{
/* page 7: CONVST 高电平脉冲宽度和低电平脉冲宽度最短 25ns */
/* CONVST平时为高 */
CONVST_0();
CONVST_0();
CONVST_0();
CONVST_1();
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_ReadNowAdc
* 功能说明: 读取8路采样结果。结果存储在全局变量 g_tAD7606
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
/* 弱定义,方便用户将采集的结果实时输出 */
__weak void AD7606_SEGGER_RTTOUT(void)
{
}
void AD7606_ReadNowAdc(void)
{
g_tAD7606.sNowAdc[0] = AD7606_RESULT(); /* 读第1路样本 */
g_tAD7606.sNowAdc[1] = AD7606_RESULT(); /* 读第2路样本 */
g_tAD7606.sNowAdc[2] = AD7606_RESULT(); /* 读第3路样本 */
g_tAD7606.sNowAdc[3] = AD7606_RESULT(); /* 读第4路样本 */
g_tAD7606.sNowAdc[4] = AD7606_RESULT(); /* 读第5路样本 */
g_tAD7606.sNowAdc[5] = AD7606_RESULT(); /* 读第6路样本 */
g_tAD7606.sNowAdc[6] = AD7606_RESULT(); /* 读第7路样本 */
g_tAD7606.sNowAdc[7] = AD7606_RESULT(); /* 读第8路样本 */
AD7606_SEGGER_RTTOUT();
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
/*
*********************************************************************************************************
*
* 模块名称 : AD7606测试
* 文件名称 : demo_fmc_ad7606.c
* 版 本 : V1.0
* 说 明 : AD7606测试。
* AD7606的FMC驱动做了两种采集方式
* (1)软件查询方式,适合低速查询获取。
* (2)FIFO工作模式,适合8路实时采集,支持最高采样率200Ksps。
* 数据展示方式:
* (1)软件查询方式,数据通过串口打印输出。
* (2)FIFO工作模式,数据通过J-Scope实时输出。
*
* 修改记录 :
* 版本号 日期 作者 说明
* V1.0 2020-05-01 armfly 正式发布
*
* Copyright (C), 2020-2030, 安富莱电子 www.armfly.com
*
*********************************************************************************************************
*/
#include "bsp.h"
#include "demo_fsmc_ad7606.h"
/* 仅允许本文件内调用的函数声明 */
static void sfDispMenu(void);
static void AD7606_Mak(void);
static void AD7606_Disp(void);
static int16_t s_volt[8];
/*
*********************************************************************************************************
* 函 数 名: DemoFmcAD7606
* 功能说明: AD7606测试
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void DemoFmcAD7606(void)
{
uint8_t ucKeyCode;
uint8_t ucRefresh = 0;
uint8_t ucFifoMode;
ucFifoMode = 0; /* AD7606进入普通工作模式 */
ucRefresh = 0; /* 数据在串口刷新的标志 */
// AD7606_SetOS(AD_OS_NO); /* 无过采样 */
AD7606_SetInputRange(0); /* 0表示输入量程为正负5V, 1表示正负10V */
AD7606_StartConvst(); /* 启动1次转换 */
bsp_StartAutoTimer(0, 50); /* 启动1个500ms的自动重装的定时器 */
bsp_StartAutoTimer(3, 2000); /* 启动1个200ms的自动重装的定时器 */
while(1)
{
bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
/* 判断定时器超时时间 */
if (bsp_CheckTimer(3))
{
/* 每隔100ms 进来一次 */
bsp_LedToggle(2);
}
if (ucRefresh == 1)
{
ucRefresh = 0;
/* 处理数据 */
AD7606_Mak();
/* 打印ADC采样结果 */
AD7606_Disp();
}
// if (ucFifoMode == 0) /* AD7606 普通工作模式 */
{
if (bsp_CheckTimer(0))
{
/* 每隔500ms 进来一次. 由软件启动转换 */
AD7606_ReadNowAdc(); /* 读取采样结果 */
AD7606_StartConvst(); /* 启动下次转换 */
ucRefresh = 1; /* 刷新显示 */
}
}
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_Mak
* 功能说明: 处理采样后的数据
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_Mak(void)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
/*
32767 = 5V , 这是理论值,实际可以根据5V基准的实际值进行公式矫正
volt = ((int16_t)dat * 5000) / 32767; 计算实际电压值(近似估算的),如需准确,请进行校准
volt = dat * 0.3051850947599719
*/
if (g_tAD7606.ucRange == 0)
{
s_volt = (g_tAD7606.sNowAdc * 5000) / 32767;
}
else
{
s_volt = (g_tAD7606.sNowAdc * 10000) / 32767;
}
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_Disp
* 功能说明: 显示采样后的数据
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_Disp(void)
{
int16_t i;
int16_t iTemp;
/* 打印采集数据 */
PRINT(plotter, "%d,%d,%d", s_volt[0], s_volt[1], s_volt[2]);
}
/*
*********************************************************************************************************
* 函 数 名: sfDispMenu
* 功能说明: 显示操作提示菜单
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void sfDispMenu(void)
{
printf("Menu:\r\n");
printf("1. AutoTimer LED2\r\n");
// printf("2. K1 : 切换量程(5V或10V)\r\n");
// printf("3. K2 : 进入FIFO工作模式\r\n");
}
/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|
-
|