|
楼主 |
发表于 2021-7-15 14:37:28
|
显示全部楼层
因为公司电脑加密了,我就直接复制粘贴代码了哈
.c文件如下
/*
*********************************************************************************************************
*
* 模块名称 : AD7606数据采集模块
* 文件名称 : bsp_ad7606.c
* 版 本 : V1.0
* 说 明 : AD7606挂在STM32的FMC总线上,本例子使用了TIM8作为硬件定时器,定时启动ADC转换。
* AD7606的FMC驱动做了两种采集方式:
* (1)软件查询方式,适合低速查询获取。
* (2)FIFO工作模式,适合8路实时采集,支持最高采样率200Ksps。
*
*********************************************************************************************************
*/
#include "bsp.h"
AD7606_VAR_T g_tAD7606; /* 定义1个全局变量,保存一些参数 */
AD7606_FIFO_T g_tAdcFifo; /* 定义FIFO结构体变量 */
/*
*********************************************************************************************************
* 函 数 名: AD7606_CtrlLinesConfig
* 功能说明: 配置GPIO口线,FMC管脚设置为复用功能
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
/*
接线配置:
PC6/AD7606_BUSY
PC7/AD7606_RESET
PC8/AD7606_CONVST
PD0/FMC_D2
PD1/FMC_D3
PD4/FMC_NOE
PD7/FMC_NE1
PD8/FMC_D13
PD9/FMC_D14
PD10/FMC_D15
PD14/FMC_D0
PD15/FMC_D1
PE7/FMC_D4
PE8/FMC_D5
PE9/FMC_D6
PE10/FMC_D7
PE11/FMC_D8
PE12/FMC_D9
PE13/FMC_D10
PE14/FMC_D11
PE15/FMC_D12
*/
/*
控制AD7606参数的其他IO:硬件实现
AD7606_OS0
AD7606_OS1
AD7606_OS2
AD7606_RAGE
*/
static void AD7606_CtrlLinesConfig(void)
{
/* bsp_fm_io 已配置fmc,bsp_InitExtIO();
此处可以不必重复配置FMC,其它的要配置。
*/
GPIO_InitTypeDef gpio_init_structure;
/* 使能 GPIO时钟 */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
/* 使能FMC时钟 */
__HAL_RCC_FMC_CLK_ENABLE();
/* 设置 GPIO 相关的IO为复用推挽输出 */
gpio_init_structure.Mode = GPIO_MODE_AF_PP;
gpio_init_structure.Pull = GPIO_PULLUP;
gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
gpio_init_structure.Alternate = GPIO_AF12_FMC;
/* 配置GPIOD */
gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_7 |
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_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);
/* 配置BUSY引脚(PC6),默认是普通IO状态 */
{
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_SYSCFG_CLK_ENABLE();
BUSY_RCC_GPIO_CLK_ENABLE(); /* 打开GPIO时钟 */
/* BUSY信号,使用的PC6,用于转换完毕检测 */
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; /* 设置推挽输出 */
GPIO_InitStructure.Pull = GPIO_NOPULL; /* 无上拉下拉 */
GPIO_InitStructure.Pin = BUSY_PIN;
HAL_GPIO_Init(BUSY_GPIO, &GPIO_InitStructure);
}
/* RESET 复位ADC的GPIO = PC7 */
/* CONVST 启动ADC转换的GPIO = PC8 */
{
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_NOPULL; /* 上下拉电阻不使能 */
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; /* GPIO速度等级 */
GPIO_InitStructure.Pin = RESET_PIN;
HAL_GPIO_Init(RESET_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = CONVST_PIN;
HAL_GPIO_Init(CONVST_GPIO, &GPIO_InitStructure);
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_FSMCConfig
* 功能说明: 配置FSMC并口访问时序
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void AD7606_FSMCConfig(void)
{
SRAM_HandleTypeDef hsram = {0};
FMC_NORSRAM_TimingTypeDef SRAM_Timing = {0};
/*
AD7606规格书要求(3.3V时,通信电平Vdriver):RD读信号低电平脉冲宽度最短21ns,对应FMC的DataSetupTime
CS片选和RD读信号独立方式的高电平脉冲最短宽度15ns。
CS片选和RD读信号并联方式的高电平脉冲最短宽度22ns。
这里将22ns作为最小值更合理些,对应FMC的AddressSetupTime
4-x-6-x-x-x : RD高持续35.7ns,低电平持续23.8ns. 读取8路样本数据到内存差不多就是476ns。
*/
hsram.Instance = FMC_NORSRAM_DEVICE;
hsram.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/* FMC使用的HCLK,主频168MHz,1个FMC时钟周期就是5.95ns */
SRAM_Timing.AddressSetupTime = 4; /* 4*5.95ns=23.8ns,地址建立时间,范围0 -15个FMC时钟周期个数 */
SRAM_Timing.AddressHoldTime = 0; /* 地址保持时间,配置为模式A时,用不到此参数 范围1 -15个时钟周期个数 */
SRAM_Timing.DataSetupTime = 6; /* 6*5.95ns=35.7ns,数据保持时间,范围1 -255个时钟周期个数 */
SRAM_Timing.BusTurnAroundDuration = 0; /* 此配置用不到这个参数 */
SRAM_Timing.CLKDivision = 0; /* 此配置用不到这个参数 */
SRAM_Timing.DataLatency = 0; /* 此配置用不到这个参数 */
SRAM_Timing.AccessMode = FMC_ACCESS_MODE_A; /* 配置为模式A */
hsram.Init.NSBank = FMC_NORSRAM_BANK1; /* 使用的BANK1,即使用的片选FMC_NE1 */
hsram.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; /* 禁止地址数据复用 */
hsram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; /* 存储器类型SRAM */
hsram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_32; /* 32位总线宽度 */
hsram.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE; /* 关闭突发模式 */
hsram.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW; /* 用于设置等待信号的极性,关闭突发模式,此参数无效 */
hsram.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS; /* 关闭突发模式,此参数无效 */
hsram.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; /* 用于使能或者禁止写保护 */
hsram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; /* 关闭突发模式,此参数无效 */
hsram.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; /* 禁止扩展模式 */
hsram.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; /* 用于异步传输期间,使能或者禁止等待信号,这里选择关闭 */
hsram.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; /* 禁止写突发 */
hsram.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY; /* 仅同步模式才做时钟输出 */
hsram.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE; /* 使能写FIFO */
/* 初始化SRAM控制器 */
if (HAL_SRAM_Init(&hsram, &SRAM_Timing, &SRAM_Timing) != HAL_OK)
{
/* 初始化错误 */
Error_Handler(__FILE__, __LINE__);
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_Reset
* 功能说明: 硬件复位AD7606,复位之后恢复到正常工作状态。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_Reset(void)
{
RESET_0(); /* 退出复位状态 */
RESET_1(); /* 进入复位状态 */
RESET_1(); /* 仅用于延迟。 RESET复位高电平脉冲宽度最小50ns。 */
RESET_1();
RESET_1();
RESET_0(); /* 退出复位状态 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitAD7606
* 功能说明: 配置连接外部SRAM的GPIO和FSMC
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitAD7606(void)
{
AD7606_CtrlLinesConfig();
AD7606_FSMCConfig();
AD7606_Reset(); /* 复位 */
CONVST_1(); /* 启动转换的GPIO,平时设置为高 */
}
/*
*********************************************************************************************************
* 函 数 名: 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();
}
/*
*********************************************************************************************************
* 下面的函数用于定时采集模式。 TIM8硬件定时中断中读取ADC结果,存在全局FIFO
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* 函 数 名: AD7606_HasNewData
* 功能说明: 判断FIFO中是否有新数据
* 形 参: 无
* 返 回 值: 1 表示有,0表示暂无数据
*********************************************************************************************************
*/
uint8_t AD7606_HasNewData(void)
{
if (g_tAdcFifo.usCount > 0)
{
return 1;
}
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_FifoFull
* 功能说明: 判断FIFO是否满
* 形 参: 无
* 返 回 值: 1 表示满,0表示未满
*********************************************************************************************************
*/
uint8_t AD7606_FifoFull(void)
{
return g_tAdcFifo.ucFull;
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_ReadFifo
* 功能说明: 从FIFO中读取一个ADC值
* 形 参: _usReadAdc : 存放ADC结果的变量指针
* 返 回 值: 1 表示OK,0表示暂无数据
*********************************************************************************************************
*/
uint8_t AD7606_ReadFifo(uint16_t *_usReadAdc)
{
if (AD7606_HasNewData())
{
*_usReadAdc = g_tAdcFifo.sBuf[g_tAdcFifo.usRead];
if (++g_tAdcFifo.usRead >= ADC_FIFO_SIZE)
{
g_tAdcFifo.usRead = 0;
}
DISABLE_INT();
if (g_tAdcFifo.usCount > 0)
{
g_tAdcFifo.usCount--;
}
ENABLE_INT();
return 1;
}
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_StopRecord
* 功能说明: 停止采集定时器
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_StopRecord(void)
{
/* 配置PC8 输出低电平,关闭TIM */
bsp_SetTIMOutPWM(CONVST_GPIO, CONVST_PIN, CONVST_TIMX, CONVST_TIMCH, 1000, 10000);
HAL_GPIO_DeInit(CONVST_GPIO, CONVST_PIN);
CONVST_TIM8_CLK_DISABLE();
/* CONVST 启动ADC转换的GPIO = PC8 */
{
GPIO_InitTypeDef GPIO_InitStructure;
CONVST_RCC_GPIO_CLK_ENABLE();
/* 配置PC6 */
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; /* 设置推挽输出 */
GPIO_InitStructure.Pull = GPIO_NOPULL; /* 上下拉电阻不使能 */
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; /* GPIO速度等级 */
GPIO_InitStructure.Pin = CONVST_PIN;
HAL_GPIO_Init(CONVST_GPIO, &GPIO_InitStructure);
}
CONVST_1(); /* 启动转换的GPIO平时设置为高 */
/* 配置BUSY引脚,默认是普通IO状态 */
{
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_SYSCFG_CLK_ENABLE();
BUSY_RCC_GPIO_CLK_ENABLE(); /* 打开GPIO时钟 */
HAL_GPIO_DeInit(BUSY_GPIO, BUSY_PIN);
/* BUSY信号,使用的PC6,用于转换完毕检测 */
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; /* 设置推挽输出 */
GPIO_InitStructure.Pull = GPIO_NOPULL; /* 无上拉下拉 */
GPIO_InitStructure.Pin = BUSY_PIN;
HAL_GPIO_Init(BUSY_GPIO, &GPIO_InitStructure);
HAL_NVIC_DisableIRQ(BUSY_IRQn);
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_EnterAutoMode
* 功能说明: 配置硬件工作在自动采集模式,结果存储在FIFO缓冲区。
* 形 参: _ulFreq : 采样频率,单位Hz, 1k,2k,5k,10k,20K,50k,100k,200k
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_EnterAutoMode(uint32_t _ulFreq)
{
/* 配置PC8为TIM8_CH3功能,输出占空比50%的方波 */
bsp_SetTIMOutPWM(CONVST_GPIO, CONVST_PIN, CONVST_TIMX, CONVST_TIMCH, _ulFreq, 5000);
/* 配置PC6, BUSY 作为中断输入口,下降沿触发 */
{
GPIO_InitTypeDef GPIO_InitStructure;
CONVST_RCC_GPIO_CLK_ENABLE(); /* 打开GPIO时钟 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING; /* 中断下降沿触发 */
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStructure.Pin = BUSY_PIN;
HAL_GPIO_Init(BUSY_GPIO, &GPIO_InitStructure);
HAL_NVIC_SetPriority(BUSY_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(BUSY_IRQn);
}
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_StartRecord
* 功能说明: 开始采集
* 形 参: _ulFreq : 采样频率,单位Hz , 对于AD7606来说,范围1 - 200KHz
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_StartRecord(uint32_t _ulFreq)
{
AD7606_StopRecord();
AD7606_Reset(); /* 复位硬件 */
AD7606_StartConvst(); /* 启动采样,避免第1组数据全0的问题 */
g_tAdcFifo.usRead = 0; /* 必须在开启定时器之前清0 */
g_tAdcFifo.usWrite = 0;
g_tAdcFifo.usCount = 0;
g_tAdcFifo.ucFull = 0;
AD7606_EnterAutoMode(_ulFreq);
}
/*
*********************************************************************************************************
* 函 数 名: AD7606_ISR
* 功能说明: 定时采集中断服务程序
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void AD7606_ISR(void)
{
uint8_t i;
AD7606_ReadNowAdc();
for (i = 0; i < 8; i++)
{
g_tAdcFifo.sBuf[g_tAdcFifo.usWrite] = g_tAD7606.sNowAdc[i];
if (++g_tAdcFifo.usWrite >= ADC_FIFO_SIZE)
{
g_tAdcFifo.usWrite = 0;
}
if (g_tAdcFifo.usCount < ADC_FIFO_SIZE)
{
g_tAdcFifo.usCount++;
}
else
{
g_tAdcFifo.ucFull = 1; /* FIFO满,主程序来不及处理数据 */
}
}
}
/*
*********************************************************************************************************
* 函 数 名: EXTI9_5_IRQHandler
* 功能说明: 外部中断服务程序。
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
#ifdef EXTI9_5_ISR_MOVE_OUT /* bsp.h 中定义此行,表示本函数移到stam32xx_it.c,避免重复定义 */
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(BUSY_PIN);
}
#if 0
/*
*********************************************************************************************************
* 函 数 名: EXTI9_5_IRQHandler
* 功能说明: 外部中断服务程序入口, AD7606_BUSY 下降沿中断触发
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == BUSY_PIN)
{
AD7606_ISR();
}
}
#endif
#endif
|
|