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 ...
随机推荐
- 如何精简 Prometheus 的指标和存储占用
前言 随着 Prometheus 监控的组件.数量.指标越来越多,Prometheus 对计算性能的要求会越来越高,存储占用也会越来越多. 在这种情况下,要优化 Prometheus 性能, 优化存储 ...
- python3获取列表逆序的五种方式
前言 我们将这几种方式分为两类,一种是对列表本身进行操作,改变对应内存中的值,另一种是带有返回值的,相当于拷贝了一份 对列表内存中进行操作 sort() 函数 a = [1,2,3,4] a.sort ...
- 目标检测模型的评价标准-AP与mAP
目录 目录 目录 前言 一,精确率.召回率与F1 1.1,准确率 1.2,精确率.召回率 1.3,F1 分数 1.4,PR 曲线 1.4.1,如何理解 P-R 曲线 1.5,ROC 曲线与 AUC 面 ...
- 【Java SE】课程目录
〇.课程简介 一.前言入门 二.数据类型.运算符.方法 三.流程控制 四.Idea.方法 五.数组 六.类.对象.封装.构造 七.Scanner类.Random类.ArrayList类 八.Strin ...
- Blazor组件自做十二 : Blazor Pdf Reader PDF阅读器 组件 (新版 7.1 移除pdfobject)
Blazor Pdf Reader PDF阅读器 组件 示例: https://www.blazor.zone/PdfReaders https://blazor.app1.es/pdfReaders ...
- uniapp 打包app 引入高德地图
一.高德地图注册key值 二.项目中添加配置 三.项目中引用 <view class="home-btom-box" > <view class="ho ...
- SpringBoot基础学习笔记
Springboot框架: springboot官网参考 Sringboot是整合spring技术栈的一站式框架,其简化配置,实现了自动化配置 Springboot基础结构: 1.pom.xml文件: ...
- day12-功能实现11
家居网购项目实现011 以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git 27.功能25-事务管理 27.1下订单问题思考 在生成 ...
- [OpenCV实战]12 使用深度学习和OpenCV进行手部关键点检测
目录 1 背景 2 实现 3 结果和代码 4 参考 手部关键点检测是在手指上找到关节以及在给定图像中找到指尖的过程.它类似于在脸部(面部关键点检测)或身体(人体姿势估计)上找到关键点.但是手部检测不同 ...
- Go+beego接入OSS上传
路由 f, h, err := c.GetFile("uploadFile") if err != nil { logx.Error("getfile err " ...