用的原子哥F103RC。
外部信号下降沿触发单通道ADC 1MHz(系统主频54MHz)连续采样,目前设置为采样4500个点,大约是5ms完成,中间的等待时间由定时器来决定。采样的同时将数据通过DMA传输到指定内存,等采样完后进行计算。
目前信号由信号发生器给定。如下图的信号发生器波形,触发的方波和正弦波频率都是42.55Hz。每个下降沿到上升沿间的正选波信号为固定采样信号。
功能都能实现,现在问题Debug中看到的数据每次都采样的都是正弦波不同的位置,而不是我下降沿触发的指定采集位置,而且每次都是不同位置,也就是采集到的相位在变化。实在想不明白问题在哪?求各路大神指教。
部分重要代码如下:
extern TIM_HandleTypeDef TIM2InitStructure; //定时器初始化结构体,在Timer.c文件中定义
extern ADC_HandleTypeDef PB1_ADCStructure; //ADC初始化结构体,在ADC.c文件中定义
extern DMA_HandleTypeDef ADCxDMAChannel; //DMA初始化结构体,在DMA.c文件中定义
//外部中断设置为PB0端口
void EXTI_Init(void)
{
GPIO_InitTypeDef EXTI_GPIOStructure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
EXTI_GPIOStructure.Mode = GPIO_MODE_IT_FALLING; //下降沿触发
EXTI_GPIOStructure.Pin = GPIO_PIN_0;
EXTI_GPIOStructure.Pull = GPIO_PULLUP; //内部上拉
HAL_GPIO_Init(GPIOB,&EXTI_GPIOStructure);
//中断线0-PB0
HAL_NVIC_SetPriority(EXTI0_IRQn,2,3); //抢占优先级为2,响应优先级为3
HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线0
}
//中断服务函数
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); //调用中断处理公用函数,由此函数调用中断回调函数
}
//中断服务程序中需要做的事情
//在HAL库中所有的外部中断服务函数都会调用此函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //GPIO_Pin:中断引脚号
{
switch(GPIO_Pin)
{
case GPIO_PIN_0:
ADCFunction(279);
break;
}
}
void ADCFunction(u16 TimerValue)
{
StateBit = true;
HAL_ADC_Start(&PB1_ADCStructure); //开启ADC
Delay_us(10);
__HAL_DMA_ENABLE(&ADCxDMAChannel);
// __HAL_DMA_ENABLE_IT(&ADCxDMAChannel, DMA_IT_TC);
//(u32)DMAPartA为存储地址,由我们自行定义,4500为读取位数
HAL_ADC_Start_DMA(&PB1_ADCStructure,(u32*)&DMACache,4500);
__HAL_TIM_ENABLE_IT(&TIM2InitStructure,TIM_IT_UPDATE);
__HAL_TIM_ENABLE(&TIM2InitStructure);
do
{
Delay_us(1);
}
while(StateBit == true);
HAL_ADC_Stop(&PB1_ADCStructure); //关闭ADC
__HAL_TIM_DISABLE(&TIM2InitStructure); //关闭定时器2,到需要时开启
__HAL_TIM_DISABLE_IT(&TIM2InitStructure,TIM_IT_UPDATE); //关闭更新中断,到需要时再开启
TIM2->CNT = TimerValue; //重装载计数寄存器
__HAL_DMA_DISABLE(&ADCxDMAChannel);
}
定时器我设置为7000ms
定时器部分代码:
//定时器时钟来源是APB1的时钟,我设置的APB1时钟为SYSCLK的4分频,为14MHz,当APB1分频系数不为1时,TIMxCLK的频率为APB1的2倍,即28MHz
//定时器定时时间计算time = (Prescaler + 1) * (Period + 1) / TIMxCLK,例如1s = (13999+1)*(1999+1)/28MHz
//目前需求定时时间为7000us,即28MHz*0.007s = 196000计时周期------》TimerValue = 979; SelfDefCLKDivision = 199
void TIM2Init(u16 TimerValue, u16 SelfDefCLKDivision)
{
TIM2InitStructure.Instance = TIM2;
TIM2InitStructure.Init.Prescaler = SelfDefCLKDivision; //可自行设置的分频系数,此数值在0到255之间
TIM2InitStructure.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数器
TIM2InitStructure.Init.Period = TimerValue; //自动重装载值
TIM2InitStructure.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟分频系数,系数为1
HAL_TIM_Base_Init(&TIM2InitStructure); //定时器初始化
__HAL_TIM_CLEAR_IT(&TIM2InitStructure,TIM_IT_UPDATE); //清除定时器标志位,屏蔽因系统复位而导致的意外进入中断
HAL_TIM_Base_Start_IT(&TIM2InitStructure); //使能定时器2和定时器2更新中断:TIM_IT_UPDATE
__HAL_TIM_DISABLE(&TIM2InitStructure); //关闭定时器2,到需要时开启
__HAL_TIM_DISABLE_IT(&TIM2InitStructure,TIM_IT_UPDATE); //关闭更新中断,到需要时再开启
TIM2->CNT = TimerValue; //重装载计数寄存器
}
//定时器底层驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用,用来控制所有的定时器初始化
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
__HAL_RCC_TIM2_CLK_ENABLE(); //使能TIM2时钟
HAL_NVIC_SetPriority(TIM2_IRQn,1,1); //设置中断优先级,抢占优先级1,响应优先级1
HAL_NVIC_EnableIRQ(TIM2_IRQn); //开启ITM2中断
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>