这个是我们的4通道CC配置。
[C] 纯文本查看 复制代码 /*
*********************************************************************************************************
* 函 数 名: bsp_InitHardTimer
* 功能说明: 配置 TIMx,用于us级别硬件定时。TIMx将自由运行,永不停止.
* TIMx可以用TIM2 - TIM5 之间的TIM, 这些TIM有4个通道, 挂在 APB1 上,输入时钟=SystemCoreClock / 2
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitHardTimer(void)
{
TIM_HandleTypeDef TimHandle = {0};
uint32_t usPeriod;
uint16_t usPrescaler;
uint32_t uiTIMxCLK;
TIM_TypeDef* TIMx = TIM_HARD;
RCC_TIM_HARD_CLK_ENABLE(); /* 使能TIM时钟 */
/*-----------------------------------------------------------------------
bsp.c 文件中 void SystemClock_Config(void) 函数对时钟的配置如下:
System Clock source = PLL (HSE)
SYSCLK(Hz) = 400000000 (CPU Clock)
HCLK(Hz) = 200000000 (AXI and AHBs Clock)
AHB Prescaler = 2
D1 APB3 Prescaler = 2 (APB3 Clock 100MHz)
D2 APB1 Prescaler = 2 (APB1 Clock 100MHz)
D2 APB2 Prescaler = 2 (APB2 Clock 100MHz)
D3 APB4 Prescaler = 2 (APB4 Clock 100MHz)
因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = APB1 x 2 = 200MHz;
因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = APB2 x 2 = 200MHz;
APB4上面的TIMxCLK没有分频,所以就是100MHz;
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14,LPTIM1
APB2 定时器有 TIM1, TIM8 , TIM15, TIM16,TIM17
APB4 定时器有 LPTIM2,LPTIM3,LPTIM4,LPTIM5
----------------------------------------------------------------------- */
if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15) || (TIMx == TIM16) || (TIMx == TIM17))
{
/* APB2 定时器时钟 = 200M */
uiTIMxCLK = SystemCoreClock / 2;
}
else
{
/* APB1 定时器 = 200M */
uiTIMxCLK = SystemCoreClock / 2;
}
usPrescaler = uiTIMxCLK / 1000000 - 1; /* 分频比 = 1 */
if (TIMx == TIM2 || TIMx == TIM5)
{
usPeriod = 0xFFFFFFFF;
}
else
{
usPeriod = 0xFFFF;
}
/*
设置分频为usPrescaler后,那么定时器计数器计1次就是1us
而参数usPeriod的值是决定了最大计数:
usPeriod = 0xFFFF 表示最大0xFFFF微秒。
usPeriod = 0xFFFFFFFF 表示最大0xFFFFFFFF微秒。
*/
TimHandle.Instance = TIMx;
TimHandle.Init.Prescaler = usPrescaler;
TimHandle.Init.Period = usPeriod;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
{
Error_Handler(__FILE__, __LINE__);
}
/* 配置定时器中断,给CC捕获比较中断使用 */
{
HAL_NVIC_SetPriority(TIM_HARD_IRQn, 0, 2);
HAL_NVIC_EnableIRQ(TIM_HARD_IRQn);
}
/* 启动定时器 */
HAL_TIM_Base_Start(&TimHandle);
}
/*
*********************************************************************************************************
* 函 数 名: bsp_StartHardTimer
* 功能说明: 使用TIM2-5做单次定时器使用, 定时时间到后执行回调函数。可以同时启动4个定时器通道,互不干扰。
* 定时精度正负1us (主要耗费在调用本函数的执行时间)
* TIM2和TIM5 是32位定时器。定时范围很大
* TIM3和TIM4 是16位定时器。
* 形 参: _CC : 捕获比较通道几,1,2,3, 4
* _uiTimeOut : 超时时间, 单位 1us. 对于16位定时器,最大 65.5ms; 对于32位定时器,最大 4294秒
* _pCallBack : 定时时间到后,被执行的函数
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void * _pCallBack)
{
uint32_t cnt_now;
uint32_t cnt_tar;
TIM_TypeDef* TIMx = TIM_HARD;
/* H743速度较快,无需补偿延迟,实测精度正负1us */
cnt_now = TIMx->CNT;
cnt_tar = cnt_now + _uiTimeOut; /* 计算捕获的计数器值 */
if (_CC == 1)
{
s_TIM_CallBack1 = (void (*)(void))_pCallBack;
TIMx->CCR1 = cnt_tar; /* 设置捕获比较计数器CC1 */
TIMx->SR = (uint16_t)~TIM_IT_CC1; /* 清除CC1中断标志 */
TIMx->DIER |= TIM_IT_CC1; /* 使能CC1中断 */
}
else if (_CC == 2)
{
s_TIM_CallBack2 = (void (*)(void))_pCallBack;
TIMx->CCR2 = cnt_tar; /* 设置捕获比较计数器CC2 */
TIMx->SR = (uint16_t)~TIM_IT_CC2; /* 清除CC2中断标志 */
TIMx->DIER |= TIM_IT_CC2; /* 使能CC2中断 */
}
else if (_CC == 3)
{
s_TIM_CallBack3 = (void (*)(void))_pCallBack;
TIMx->CCR3 = cnt_tar; /* 设置捕获比较计数器CC3 */
TIMx->SR = (uint16_t)~TIM_IT_CC3; /* 清除CC3中断标志 */
TIMx->DIER |= TIM_IT_CC3; /* 使能CC3中断 */
}
else if (_CC == 4)
{
s_TIM_CallBack4 = (void (*)(void))_pCallBack;
TIMx->CCR4 = cnt_tar; /* 设置捕获比较计数器CC4 */
TIMx->SR = (uint16_t)~TIM_IT_CC4; /* 清除CC4中断标志 */
TIMx->DIER |= TIM_IT_CC4; /* 使能CC4中断 */
}
else
{
return;
}
}
/*
*********************************************************************************************************
* 函 数 名: TIMx_IRQHandler
* 功能说明: TIM 中断服务程序
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void TIM_HARD_IRQHandler(void)
{
uint16_t itstatus = 0x0, itenable = 0x0;
TIM_TypeDef* TIMx = TIM_HARD;
itstatus = TIMx->SR & TIM_IT_CC1;
itenable = TIMx->DIER & TIM_IT_CC1;
if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
{
TIMx->SR = (uint16_t)~TIM_IT_CC1;
TIMx->DIER &= (uint16_t)~TIM_IT_CC1; /* 禁能CC1中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack1();
}
itstatus = TIMx->SR & TIM_IT_CC2;
itenable = TIMx->DIER & TIM_IT_CC2;
if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
{
TIMx->SR = (uint16_t)~TIM_IT_CC2;
TIMx->DIER &= (uint16_t)~TIM_IT_CC2; /* 禁能CC2中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack2();
}
itstatus = TIMx->SR & TIM_IT_CC3;
itenable = TIMx->DIER & TIM_IT_CC3;
if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
{
TIMx->SR = (uint16_t)~TIM_IT_CC3;
TIMx->DIER &= (uint16_t)~TIM_IT_CC3; /* 禁能CC2中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack3();
}
itstatus = TIMx->SR & TIM_IT_CC4;
itenable = TIMx->DIER & TIM_IT_CC4;
if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
{
TIMx->SR = (uint16_t)~TIM_IT_CC4;
TIMx->DIER &= (uint16_t)~TIM_IT_CC4; /* 禁能CC4中断 */
/* 先关闭中断,再执行回调函数。因为回调函数可能需要重启定时器 */
s_TIM_CallBack4();
}
}
#endif
|