一、背景
1、为什么要做这个测评
1)在操作步进电机时,有时候需要只产生几个脉冲;
2)需要使用定时器的ETR功能,用于测量外部脉冲的个数。
2、产生指定脉冲的方法有如下:
- 利用RCR寄存器结合单脉冲模式;
计数器发生RCR+1个溢出动作后触发更新事件,在单脉冲模式下,定时器发生更新事件时将停止计数并实现指定个数的脉冲输出
- 利用DMA实时修改CCR寄存器的模式;
基于定时器事件触发DMA从而动态修改CCR寄存器的值最终实现指定个数的脉冲输出
- 利用定时器主从模式;
利用两个定时器级联成主从模式,一个定时器输出门控信号,控制另外一个定时器的计数工作
- 利用中断对脉冲实现计数模式
基于定时器更新事件或比较事件对脉冲个数进行实时计数,到达指定数据后通过修改CCR或ARR寄存器的值来停止后续PWM的输出
本次测评就按主从定时器的方式产生指定脉冲,并进行ETR计数。
大致原理如下:
使用主定时器5,产生PWM(配置为使能触发,触发事件为更新事件),使用从定时器(配置门控模式,使能中断)计算主定时器5产生的脉冲个数,此时,从定时器就会产生中断,中断后就立马关闭主定时器和从定时器,同时ETR输出计数个数
二、工程配置
1、新建工程;
2、配置时钟
3、配置主定时器5
4、配置从定时器3
1)查看内部定时器5与哪一个定时器连接,如下图。因此需要配置定时器3的触发源为ITR4
具体配置如下:
开启定时器3中断
5、计数定时器配置
配置ETR2功能即可
三、代码编写
1、开启定时器2;开启定时器5 PWM输出;开启定时器3中断
具体代码如下:
主函数
/* USER CODE BEGIN PV */
uint16_t pwmNumTable [] = {10,20,50,100,500,2000,5000,10000,30000,50000};
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
PUTCHAR_PROTOTYPE {
uint8_t c=ch;
HAL_UART_Transmit(&huart2, &c, 1, 50);
return ch;
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t i = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
MX_USART2_UART_Init();
MX_ICACHE_Init();
MX_TIM2_Init();
MX_TIM5_Init();
/* USER CODE BEGIN 2 */
printf("sys init");
__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
HAL_TIM_Base_Start(&htim2);
// __HAL_TIM_SET_AUTORELOAD(&htim3,100); //设置要输出的PWM脉冲数 PwmNum个
// HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_2); //启动主定时器PWM输出
// HAL_TIM_Base_Start_IT(&htim3); //启动从定时器
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
//HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_2); //关闭主定时器
HAL_Delay(1000);
printf("TIM2 cnt = %d ",TIM2->CNT);
TIM2->CNT = 0;
__HAL_TIM_SET_AUTORELOAD(&htim3,pwmNumTable[i]); //设置要输出的PWM脉冲数 PwmNum个
i++;
if (i >= 10 ) {
i = 0;
}
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_2); //启动主定时器PWM输出
HAL_TIM_Base_Start_IT(&htim3); //启动从定时器
}
/* USER CODE END 3 */
}
定时器3中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim3)
{
if(__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_CC4) != RESET) //判断是否触发中断
{
__HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_CC4); //清除中断标志
HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_2); //关闭主定时器
HAL_TIM_Base_Stop_IT(&htim3); //关闭从定时器
}
}
}
四、验证
ETR计数将根据定义的数组更新脉冲个数,依次输出10,20,50,100,500,2000,5000,10000,30000,50000;
串口实际输出如图:
注意事项:
1、ETR的计数的GPIO需要配置为上拉模式,否则,会出现误计数的情况。
2、定时5的通道引脚与ETR引脚连接。
工程代码: