对一个连续的波进行采样,采集250个点,我知道可以用DMA做,但是现在只想利用TIM中断来触发ADC进行采样,采集后输出的数据非常不理想,请大家帮我看看。
#include "timer.h"
#include "led.h"
#include "usart.h"
#include "adc.h"
#define ADC_Buff_LEN 250
extern int Buff[250];
extern int b;
定时器设置
//arr:自动重装值。
//psc:时钟预分频数
void TIM2_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB2Periph_GPIOA, ENABLE); //使能定时器1时钟
//设置该引脚为复用输出功能,输出TIM2 CH2的PWM脉冲波形 GPIOA.1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2_CH2对应PA1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//初始化TIM2
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision =0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式向上计数方式: CNT < CCRx ≤ ARR (特别地, 0 < CCRx),
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM2 Channel2 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OCInitStructure.TIM_Pulse = 500; //设置待装入捕获比较寄存器的脉冲值,高于脉冲值就会产生高电平
TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM2 OC2
//设置中断
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化外设 NVIC 寄存器
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);// CC1IE 捕获中断
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器
TIM_Cmd(TIM2, ENABLE);
TIM_CtrlPWMOutputs(TIM2, ENABLE);
//TIM_ARRPreloadConfig(TIM2,DISABLE); //预装载寄存器的内容被立即传送到影子寄存器
}
void TIM2_IRQHandler(void)
{ // volatile int b=0;
// int a = 0;
static int x = 0;//用作给数组计数,记满250个为止
if ( TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //判断状态寄存器 TIM2_SR[2] 是否发生了更新中断
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //软件清除状态寄存器 TIM2_SR[2] 捕获/比较2 中断中断标志
// for(a=0;a<5;a++) //串口输出
// { // USART_SendData(USART1,Buff[a] );
// printf("%d ",Buff[a]);
// }
// if(a==5)
// printf("
");
if(x <= 249)
{
Buff[x]=ADC_GetConversionValue(ADC1);
x++;
}
if(x > 249)
{
b=1;
x=0;
// for(a=0;a<=249;a++) //串口输出
// { // USART_SendData(USART1,Buff[a] );
// printf("%d ",Buff[a]); //关闭ADC1 DMA传输
// }
// x=0; //
}
}
}
接下来是ADC.C
void ADC_Configuration(void) //ADC配置函数
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE); //使能ADC和GPIOA时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置时钟(12MHz),在RCC里面还应配置APB2=AHB时钟72MHz
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE); //使能ADC和GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //采集电压的引脚为PA管脚2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入模式
GPIO_Init(GPIOA, &GPIO_InitStructure); //GPIO组
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //关闭通道扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //注意不要使用持续转换模式,否则只要触发一次,//后续的转换就会永不停歇(除非CONT清0),这样第一次以后的ADC,就不是由TIM2_CC2来触发了
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//配置TIM2_CC2为触发源
// ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//配置TIM2_CC2为触发源
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_41Cycles5);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_ExternalTrigConvCmd(ADC1, ENABLE); //设置外部触发模式使能(这个“外部“其实仅仅是相//对于ADC模块的外部,实际上还是在STM32内部)
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1); //Start Calibration register
while(ADC_GetCalibrationStatus(ADC1)); //waiting for finishing the calibration
}
主函数
#include "usart.h"
#include "delay.h"
#include "key.h"
#include "dma.h"
#include "timer.h"
#include "adc.h"
int Buff[250];
//extern uint16_t ADC_RegularConvertedValueTab[32];
//这里可以使用两种定时器触发模式,一种是TIM2 CH2对应PA1,一种是TIM_CH1对应PA8
u8 flag=0;
int b; //标志位
int main(void)
{
int a;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(9600); //串口初始化为115200
LED_Init(); //初始化与LED连接的硬件接口
// LCD_Init(); //初始化LCD
KEY_Init(); //按键初始化
ADC_Configuration();
// ADC_DMA_Config();
TIM2_PWM_Init(1439,0);
while(1)
{
if(b==1)
{
for(a=0;a<=249;a++) //串口输出
{ // USART_SendData(USART1,Buff[a] );
printf("%d ",Buff[a]);
a=0; //关闭ADC1 DMA传输
}
}
}
}
结果file:///C:Users杨AppDataRoamingTencentUsers2918317304QQWinTempRichOleL6A@6P0WSTAMSGQKR83D8~L.png
关系到毕设,求大家找找毛病
一周热门 更多>