TIM + DMA + ADC
#include "public.h"
#define FFT_POINT (256)
static uint16_t _DmaBuffer[FFT_POINT];
static uint16_t _AdcBuffer[FFT_POINT];
static uint8_t F_DMA_TC;
static int32_t FFT_InBuffer[FFT_POINT];
static int32_t FFT_OutBuffer[FFT_POINT];
#define FFT_MagBuffer _AdcBuffer
static void _InitClk(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
static void _InitGpio(void) {
SocGpio_SetMode(SocGpio_GetPinIndex(0<<4|1), INPUT_MODE_AIN);
SocGpio_SetMode(SocGpio_GetPinIndex(0<<4|0), OUTPUT_MODE_PUSH_PULL);
}
static void _InitDMA(void) {
DMA_InitTypeDef def;
// 初始化
def.DMA_PeripheralBaseAddr = (uint32_t)(&ADC1->DR); // 外设地址
def.DMA_MemoryBaseAddr = (uint32_t)(&_DmaBuffer[0]); // 内存地址
def.DMA_DIR = DMA_DIR_PeripheralSRC; // 从外设复制到内存
def.DMA_BufferSize = ASIZE(_DmaBuffer); // 内存元素个数
def.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址固定
def.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增
def.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设元素大小16字节
def.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 内存元素大小16字节
def.DMA_Mode = DMA_Mode_Circular; // 循环采集
def.DMA_Priority = DMA_Priority_High; // 循环
def.DMA_M2M = DMA_M2M_Disable; // 外设到内存
DMA_Init(DMA1_Channel1, &def);
// 中断
NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
DMA_ClearFlag(DMA1_FLAG_TC1);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
}
static void _InitAdc(void) {
ADC_InitTypeDef def;
// 初始化
ADC_StructInit(&def);
def.ADC_Mode = ADC_Mode_Independent; // 独立模式
def.ADC_ScanConvMode = DISABLE; // 单通道
def.ADC_ContinuousConvMode = DISABLE; // 定时器触发,不连续转换
def.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;// 转换不受外界决定
def.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐
def.ADC_NbrOfChannel = 1; // 扫描通道数
ADC_Init(ADC1, &def);
// 通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
// 校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
}
static void _InitTim(void) {
TIM_TimeBaseInitTypeDef def;
TIM_TimeBaseStructInit(&def);
def.TIM_Period = 100-1;
def.TIM_Prescaler = 72-1;
def.TIM_ClockDivision = TIM_CKD_DIV1;
def.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &def);
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
TIM_Cmd(TIM3, ENABLE);
}
void cr4_fft_256_stm32(void *pssOUT, void *pssIN, u16 Nbin);
static void _FFT_Proc(void) {
for (uint16_t i = 0; i < FFT_POINT; i++) {
FFT_InBuffer[i] = (_AdcBuffer[i]-1990) << 16;
}
#if 0
printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
FFT_InBuffer[1], FFT_InBuffer[2], FFT_InBuffer[3], FFT_InBuffer[4],
FFT_InBuffer[5], FFT_InBuffer[6], FFT_InBuffer[7], FFT_InBuffer[8],
FFT_InBuffer[9], FFT_InBuffer[10], FFT_InBuffer[11], FFT_InBuffer[12]);
#endif
cr4_fft_256_stm32(FFT_OutBuffer, FFT_InBuffer, FFT_POINT);
#if 0
printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
_AdcBuffer[1], _AdcBuffer[2], _AdcBuffer[3], _AdcBuffer[4],
_AdcBuffer[5], _AdcBuffer[6], _AdcBuffer[7], _AdcBuffer[8],
_AdcBuffer[9], _AdcBuffer[10], _AdcBuffer[11], _AdcBuffer[12]);
#endif
}
#if 0
void GetPowerMag(void)
{
signed short lX,lY;
float X,Y,Mag;
unsigned short i;
for(i=0; i<NPT; i++)
{
lX = (lBufOutArray[i] << 16) >> 16;
lY = (lBufOutArray[i] >> 16);
//除以32768再乘65536是为了符合浮点数计算规律
X = NPT * ((float)lX) / 32768;
Y = NPT * ((float)lY) / 32768;
Mag = sqrt(X * X + Y * Y)*1.0/ NPT;
if(i == 0)
lBufMagArray[i] = (unsigned long)(Mag * 32768);
else
lBufMagArray[i] = (unsigned long)(Mag * 65536);
}
}
#endif
static void _Send(uint8_t ch) {
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, ch);
}
// STEP:39Hz
static void _FFT_GetMag(void) {
int16_t x, y;
for (uint16_t i = 1; i <= 64; i++) {
x = FFT_OutBuffer[i]&0xFFFF;
y = FFT_OutBuffer[i]>>16;
//printf("%d: %d, %d\n", i, x, y);
FFT_MagBuffer[i] = sqrt(x*x + y*y); // 存在超过25为有信号, 需要连续好几个周期的判断,以便防抖
}
}
void SocAdc_Init(void) {
_InitClk();
_InitGpio();
_InitDMA();
_InitAdc();
_InitTim();
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void SocAdc_Main(void) {
if (F_DMA_TC) {
F_DMA_TC = 0;
memcpy(_AdcBuffer, _DmaBuffer, sizeof(_DmaBuffer));
GPIOA->BSRR = GPIO_Pin_0;
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
_FFT_Proc();
_FFT_GetMag();
#if 1
_Send(0xFF);
for (uint16_t i = 1; i <= 64; i++) { // 不要第一个分量
if (FFT_MagBuffer[i] > 0xFE) {
_Send(0xFE);
} else {
_Send(FFT_MagBuffer[i]);
}
}
#endif
#if 0
printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
FFT_MagBuffer[1], FFT_MagBuffer[2], FFT_MagBuffer[3], FFT_MagBuffer[4],
FFT_MagBuffer[5], FFT_MagBuffer[6], FFT_MagBuffer[7], FFT_MagBuffer[8],
FFT_MagBuffer[9], FFT_MagBuffer[10], FFT_MagBuffer[11], FFT_MagBuffer[12]);
#endif
}
}
// DMA的ADC通道中断
void DMA1_Channel1_IRQHandler(void) {
if (DMA_GetFlagStatus(DMA1_FLAG_TC1)) {
DMA_ClearFlag(DMA1_FLAG_TC1);
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
F_DMA_TC = 1;
GPIOA->BRR = GPIO_Pin_0;
}
}
TIM + DMA + ADC的更多相关文章
- STM32F103ZET6 之 ADC+TIM+DMA+USART 综合实验
1.实验目的 1)使用 TIM1 触发 ADC,ADC 采集的数据通过DMA 传至内存,然后通过串口打印出采集的数据: 2)学会 DMA 传输数据并将数据进行保存: 3)验证ADC 的采样率与实际设置 ...
- STM32之DMA+ADC
借用小甲鱼的经典:各位互联网的广大网友们.大家早上中午晚上好..(打下小广告,因为小甲鱼的视频真的很不错).每次看小甲鱼的视频自学都是比较轻松愉快的..我在想,如果小甲鱼出STM32的视频,我会一集不 ...
- ADC-单通道DMA到多通道DMA ADC采集修改事项
1. 使能通道IO,因为从单通道到多通道,需要添加规则转换通道数,故需要使能扫描模式,否则只能扫描第一个通道: 2. DMA模式配置需修改为循环传输模式,否则只转换一次: 3. 开启ADC规则转换通道 ...
- 案例 stm32单片机,adc的双通道+dma 内部温度
可以这样理解 先配置adc :有几个通道就配置几个通道. 然后配置dma,dma是针对adc的,而不是针对通道的. 一开始我以为一个adc通道对应一个dma通道.(这里是错的,其实是我想复杂了) 一个 ...
- STM32F103VET6 ADC采集64点做FFT变换
http://www.stmcu.org/module/forum/thread-598459-1-11.html http://bbs.21ic.com/icview-589756-1-1.html ...
- 关于STM32 DMA相关总结[概述知识点]
关于DMA相关知识的总结,写给未来的自己,希望有帮助.立个Flag[坚持写博客总结自己工作或学习记录自己的生活] ------------------------------------------- ...
- 【STM32H7教程】第32章 STM32H7的TIM定时器基础知识和HAL库API
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第32章 STM32H7的TIM定时器基础知识和H ...
- 9. DMA
9.1 介绍 Direct memory access(DMA) 直接存储器访问. 这两个DMA控制器总共有16个流(每个控制器8个),每个流用于管理来自一个或多个外围设备的内存访问请求.每个流总共可 ...
- ADC配置成定时器触发的启发
百度文库:https://wenku.baidu.com/view/99d39413f78a6529647d5344.html STM32关于使用定时器触发ADC转换的解决办法和详细说明 本人在使用S ...
- DMA Stream/Channel Outputting via GPIOC[0..7]
Ok, so quickly mashing up another example using a different TIM, DMA Stream/Channel for illustration ...
随机推荐
- PGL图学习之图神经网络GNN模型GCN、GAT[系列六]
PGL图学习之图神经网络GNN模型GCN.GAT[系列六] 项目链接:一键fork直接跑程序 https://aistudio.baidu.com/aistudio/projectdetail/505 ...
- HDLBits答案——Verification: Writing Testbenches
1 clock module top_module ( ); reg clk; dut U1(.clk(clk)); initial begin clk = 0; end always begin # ...
- 推荐一款 .NET 编写的 嵌入式平台的开源仿真器--Renode
Renode 是一个开发框架,通过让你模拟物理硬件系统来加速物联网和嵌入式系统开发. Renode 可以模拟 Cortex-M.RISC-V 等微控制器,不仅可以模拟 CPU指令,还可以模拟外设,甚至 ...
- label studio 结合 MMDetection 实现数据集自动标记、模型迭代训练的闭环
前言 一个 AI 方向的朋友因为标数据集发了篇 SCI 论文,看着他标了两个多月的数据集这么辛苦,就想着人工智能都能站在围棋巅峰了,难道不能动动小手为自己标数据吗?查了一下还真有一些能够满足此需求的框 ...
- vivo大数据日志采集Agent设计实践
作者:vivo 互联网存储技术团队- Qiu Sidi 在企业大数据体系建设过程中,数据采集是其中的首要环节.然而,当前行业内的相关开源数据采集组件,并无法满足企业大规模数据采集的需求与有效的数据采集 ...
- docker部署项目
@ 目录 前言 一.下载安装docker: 1.前提工作 1.1 查看linux版本 1.2 yum包更新到最新 1.3 安装工具包 1.4 设置yum源并更新yum包索引 2.安装docker 2. ...
- O-MVLL:支持ARM64的基于LLVM的代码混淆模块
O-MVLL介绍 O-MVLL的开发灵感来自于另一个著名的基于LLVM的代码混淆项目ollvm,并在其基础上做了创新和改进.O-MVLL的混淆逻辑实现方式也是通过LLVM Pass,支持也仅会支持AR ...
- CTF中RSA常见类型解法
Python脚本 #十六进制转ASCII编码 import binascii print(binascii.unhexlify(hex(m)[2:])) #rsa import gmpy2 phi = ...
- 虚假新闻检测(CADM)《Unsupervised Domain Adaptation for COVID-19 Information Service with Contrastive Adversarial Domain Mixup》
论文信息 论文标题:Unsupervised Domain Adaptation for COVID-19 Information Service with Contrastive Adversari ...
- CSP-S2022 游记
Day 998244350 模拟赛场场被学弟吊打.最后几天写了一堆随机化乱搞题以及奇怪的搜索,都是 CSP 不曾考的玩意(书接下文). 点分治已经敲烂了.最后两场每场一个. Day 499122175 ...