当前位置:网站首页>电赛必备技能___定时ADC+DMA+串口通信
电赛必备技能___定时ADC+DMA+串口通信
2022-08-05 00:06:00 【c语言的神】
一,TIM定时
ADC采样是stm32学习中的必备技能,但是初期学习ADC采样大多没有采样频率这中要求,都是只要采样到一个数据就显示出来或者发送到串口,这样有一些不足之处,就是当你需要采集一个固定的频率的信号是,需要对他进行处理,所以对这个信号进行采样的数量必须要是可控的,不可能说你这个周期采样了100点,下个周期采样了120个点,这样无疑增加数据处理的难度。所以我们需要有一个信号来触发ADC的采样,且这个信号是有着固定频率,而且是可调的。这个时候我们应该想到用定时器的外部触发去实现这个功能。

可以使用定时器去产生一个脉冲信号去触发ADC,通道调整脉冲的频率去控制ADC的采样时间。脉冲信号的占空比,我设置为50%,没有试过其他占空比。
二,ADC+DMA+串口
ADC+DMA这部分的思路是,先用一个大的数组把所有通道采集的信号收集起来,然后按照各个通道在规则组的顺序,依次取出,比如说我有4个通道,规则组顺序为1,2,3,4。那么我在DMA数组ADC_ConvertedValue里面通道1就是数组里面的k,k+1,k+2,k+3(k=0)。再放到相应的数组里面,分别进行处理。这里有一个细节就是我申请的是DMA的中断,这样当DMA的传输计数器为0是触发中断,我这里把ADC_ConvertedValue的数组的大小与传输计数器一样,这样我当我把数据收集齐的时候,进入中断里面把所有的数取出来。串口部分过于简单不再赘述。
三,代码部分
#include "adc.h"
#include "delay.h"
#include "usart.h"
#define ADC1_DR_Address ((u32)0x4001244C) //ADC1的地址
uint16_t ADC_ConvertedValue[4096];
uint16_t sys_out1[1024];
uint16_t sys_out2[1024];
uint16_t sys_out3[1024];
uint16_t sys_out4[1024];
uint8_t flag_adc;
int cnt=0;
int k=0;
void TIM2_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=arr;
TIM_TimeBaseInitStructure.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_Pulse=20;//CCR
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC2Init(TIM2, & TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE); //使能TIMx
TIM_CtrlPWMOutputs(TIM2, ENABLE);
}
void DMA1_Init()
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//DMA1初始化
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC1地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue; //内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //方向(从外设到内存)
DMA_InitStructure.DMA_BufferSize = 4096; //传输内容的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增,
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord ; //外设数据单位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ; //内存数据单位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //DMA模式:循环传输
DMA_InitStructure.DMA_Priority = DMA_Priority_High ; //优先级:高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存的传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //配置DMA1
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //使能传输完成中断
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_Cmd(DMA1_Channel1,ENABLE);
}
void Adc_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1通道时钟
//PA6 PA7 PC4 PC5作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
DMA1_Init();
TIM2_Init(39,17);//100k的采样率
//ADC1初始化
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立ADC模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //关闭扫描方式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //关闭连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; //使用外部触发模式
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 4; //要转换的通道数目
ADC_Init(ADC1, &ADC_InitStructure);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //配置ADC时钟,为PCLK2的6分频,即12Hz
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 3, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 4, ADC_SampleTime_1Cycles5);
//使能ADC、DMA
ADC_DMACmd(ADC1,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1); //复位校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); //等待校准寄存器复位完成
ADC_StartCalibration(ADC1); //ADC校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准完成
ADC_ExternalTrigConvCmd(ADC1, ENABLE); //设置外部触发模式使能
}
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){
for(k=0;k<4096;k+=4){
sys_out1[cnt]=ADC_ConvertedValue[k];
sys_out2[cnt]=ADC_ConvertedValue[k+1];
sys_out3[cnt]=ADC_ConvertedValue[k+2];
sys_out4[cnt]=ADC_ConvertedValue[k+3];
cnt++;
if(cnt==1024)
{
flag_adc=1;
ADC_Cmd(ADC1,DISABLE);
DMA_Cmd(DMA1_Channel1,DISABLE);
cnt=0;
}
}
}
DMA_ClearITPendingBit(DMA1_IT_TC1);
}
flag_adc是用来确定你的采样周期的,可以选择一直循环,也可以执行相应次数。有疑问可以在下面留言。
边栏推荐
- 游戏3D建模入门,有哪些建模软件可以选择?
- 《MySQL入门很轻松》第2章:MySQL管理工具介绍
- 【云原生--Kubernetes】调度约束
- The master teaches you the 3D real-time character production process, the game modeling process sharing
- IDEA 文件编码修改
- NebulaGraph v3.2.0 Release Note, many optimizations such as the performance of querying the shortest path
- 性能测试如何准备测试数据
- 小黑leetcode之旅:95. 至少有 K 个重复字符的最长子串
- 英特尔WiFi 7产品将于2024年亮相 最高速度可达5.8Gbps
- Mysql based
猜你喜欢

SQL关联表更新

从单体架构迁移到 CQRS 后,我觉得 DDD 并不可怕

Cloud native - Kubernetes 】 【 scheduling constraints

大师教你3D实时角色制作流程,游戏建模流程分享

KT6368A Bluetooth certification problem_FCC and BQB_CE_KC certification or other instructions

How to automatically push my new articles to my fans (very simple, can't learn to hit me)

NebulaGraph v3.2.0 Release Note,对查询最短路径的性能等多处优化

Implementation principle of golang coroutine

英特尔WiFi 7产品将于2024年亮相 最高速度可达5.8Gbps

数据类型-整型(C语言)
随机推荐
ARC129E Yet Another Minimization 题解 【网络流笔记】
Day118. Shangyitong: order list, details, payment
如何写好测试用例
2022年华数杯数学建模
IDEA file encoding modification
[CVA Valuation Training Camp] Financial Modeling Guide - Lecture 1
[Happy Qixi Festival] How does Nacos realize the service registration function?
STC89C52RC的P4口的应用问题
阅读笔记:如何理解DevOps?
typeScript - Partially apply a function
【手撕AHB-APB Bridge】~ AMBA总线 之 AHB
uniapp horizontal tab (horizontal scrolling navigation bar) effect demo (organization)
3. Actual combat---crawl the result page corresponding to Baidu's specified entry (a simple page collector)
2022牛客暑期多校训练营5(BCDFGHK)
【云原生--Kubernetes】调度约束
【LeetCode】双指针题解汇总
Cython
Laravel 实现redis分布式锁
RK3399平台开发系列讲解(内核调试篇)2.50、嵌入式产品启动速度优化
论文解读( AF-GCL)《Augmentation-Free Graph Contrastive Learning with Performance Guarantee》