记录一个定时器200us间隔采样的调试

文章讨论了在使用STM32L431CB芯片进行采样时遇到的问题,即采样间隔与理论计算不符。作者发现当使用2M晶振和特定的定时器配置时,由于回调函数中的额外操作导致实际采样间隔比预期长。通过更换为8M晶振并直接在定时器回调中执行采样操作,实现了理论上的244us采样间隔,优化了性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        有一个小板子芯片是STM32L431CB,用的内部晶振,时钟频率2M。之前是要500us的间隔采样,倒也能调的到,就是间隔的参数要手工调,和理论对不上。下面是大概的代码:         

  //定时器初始化
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 242;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

//定时器中断回调函数
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == (&htim1))
	{
		if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
			HAL_TIM_OC_Stop_IT(htim, TIM_CHANNEL_1);			/* ½ûÄÜCC1ÖÐ¶Ï */
			/* ÏȹرÕÖжϣ¬ÔÙÖ´Ðлص÷º¯Êý¡£ÒòΪ»Øµ÷º¯Êý¿ÉÄÜÐèÒªÖØÆô¶¨Ê±Æ÷ */
			s_TIM_CallBack1();
		}

}

//开启定时器的函数
void StartOnceHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void * _pCallBack)
{
	uint32_t cnt_now;
	uint32_t cnt_tar;

	cnt_now = __HAL_TIM_GET_COUNTER(&htim1);					/* ¶ÁÈ¡µ±Ç°µÄ¼ÆÊýÆ÷Öµ */
	cnt_tar = cnt_now + _uiTimeOut;				/* ¼ÆËã²¶»ñµÄ¼ÆÊýÆ÷Öµ */
	
	if (_CC == 1)
	{
		s_TIM_CallBack1 = (void (*)(void))_pCallBack;
		__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, cnt_tar);		/* 
		__HAL_TIM_CLEAR_IT(&htim1, TIM_IT_CC1);
		HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_1);								/* 
	}
}

//采样函数,定时器回调函数会调用这个函数
void Adc_Sample(void)
{
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9);
    StartOnceHardTimer(1, CAIYANG_JIANGE, Adc_Sample);
}

理论上我2048点采样,采样间隔是488,但是这里我要把采样间隔的宏设为288。。。

        这次要4096采样,我把采样间隔的宏调小点,发现不管怎么调,示波器量到的时间间隔都是300多us,而我需要244us的间隔。

        之后换了8M的晶振,然后对代码进行了调整,将采样直接放在定时器的回调函数中,像下面这样:

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == (&htim1))
	{
		if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
			
			HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_9);

			HAL_ADC_Start(&hadc1);

			HAL_ADC_PollForConversion(&hadc1, 5);
			AdcSample_BaseStruct.value[AdcSample_BaseStruct.cnt * 2 + 1] = 0;
			AdcSample_BaseStruct.value[AdcSample_BaseStruct.cnt * 2] = Adc_value;

			if (++AdcSample_BaseStruct.cnt > ADC_SAMPLES_NUMBERS - 1)
			{
				AdcSample_BaseStruct.cnt = 0;
				AdcSample_BaseStruct.flag = 1;
				HAL_TIM_OC_Stop_IT(htim, TIM_CHANNEL_1);			/* ½ûÄÜCC1ÖÐ¶Ï */
			}
		}
}

//定时器初始化部分
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 243;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

这时发现采样间隔就是244us。和理论计算完全一致。

为什么会这样呢?因为2M的时候本来指令就执行的慢,而且在回调函数内又加了好多的函数调来调去,一大段代码执行完就需要很长的时间了,所以采样间隔就对不上了。

        记录一下,免的过半年忘了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值