利用STM32HAL库发送一定频率的脉冲并用主从模式进行计数

一、实验目的

    使用两个TIM时钟分别发送不同频率的脉冲,并使用从定时器对两路脉冲分别计数。

二、实验内容

2.1 引脚配置

    初始化配置:三件套

    配置TIM1时钟通道3作为第一路脉冲发送,配置TIM2时钟通道1作为第二路脉冲发送。

    TIM1的Clock Source(时钟源)为内部时钟,频率为168MHZ, Prescaler(预分频系数):即PSC寄存器值设为168-1,计数脉冲频率:168MHz÷168=1MHz,即每秒产生1百万个计数信号,每个计数脉冲的时长:1秒/1M=1us,Counter Period (计数周期):  即ARR寄存器值,多少个计数脉冲作为1个波形周期。

    TIM2的Clock Source(时钟源)为内部时钟,频率为84MHZ。

    Repetition Counter(重复计数器):   简单地理解,多少个周期才触发1次中断;

    auto-reload preload (自动重载值的预装载):  当改变周期值ARR时,是否等到下一个更新事件再写入数值,使得数值的更改不影响执行中的波形。

注:

  • TIM1、8、9、10、11的时钟频率是168MHz;
  • 其它TIM的时钟频率是84MHz。 

    设置TRGO(Trigger Outpu)参数,Enable 主从模式,Update Event 作为触发事件。

    配置TIM4作为TIM1的从定时器,计数脉冲 ,配置TIM8作为TIM2的从定时器,计数脉冲 。

    配置从模式和触发源 ,打开中断

 

 2.2 发送脉冲并计数程序

       设置ARR的值来设定发送脉冲的频率,1M/(ARR+1) = fpwm;设置CCR的值为(ARR+1) *0.5来设定发送脉冲的占空比为50%。

  uint16_t pwmVal1=500;   //PWM??? 
  uint16_t ARR1=1000-1;   //PWM???
  
  uint16_t pwmVal2=500;   //PWM??? 
  uint16_t ARR2=1000-1;   //PWM???


void set_pwm_param(uint16_t f1,uint16_t f2) 
{			
			 ARR1 = 1000000/f1 - 1;
			 pwmVal1 = (ARR1+1)*0.5;
			
				
			 ARR2 = 1000000/f2 - 1;
			 pwmVal2 = (ARR2+1)*0.5;
				
			 TIM1->CCR3 = pwmVal1;
			 TIM1->ARR  = ARR1;
				
			 TIM2->CCR1 = pwmVal2;
			 TIM2->ARR  = ARR2;

}

    调用函数设定两路脉冲的频率,并开启脉冲发送。 开启TIM4和TIM8的中断,并设定两个定时器的自动重装载计数值作为输出脉冲的个数

	set_pwm_param(5000,10000);              //set pwm1 frequence and pwm2 frequence 

    __HAL_TIM_SET_AUTORELOAD(&htim4,1000-1); //ÉèÖÃÒªÊä³öµÄPWMÂö³åÊý1000¸ö
	__HAL_TIM_SET_AUTORELOAD(&htim8,5000-1); //ÉèÖÃÒªÊä³öµÄPWMÂö³åÊý1000¸ö
	HAL_TIM_Base_Start_IT(&htim4);               //Æô¶¯´Ó¶¨Ê±Æ÷
	HAL_TIM_Base_Start_IT(&htim8);               //Æô¶¯´Ó¶¨Ê±Æ÷

    HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);
    HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);	

    在中断回调函数里面编写程序,当两个计数脉冲的时钟触发更新中断,清除定时器中断标志位并停止主定时器的脉冲输出。这样使得主定时器输出给定数目的脉冲。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{	
 if(__HAL_TIM_GET_FLAG(&htim4, TIM_FLAG_CC2) != RESET)  //????????   
        {
            __HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC2);      //??????
            HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);   //??????
            HAL_TIM_Base_Stop_IT(&htim4);         //??????
//			HAL_GPIO_WritePin(GPIOE, EN1_Pin, GPIO_PIN_RESET);
        }
   if(__HAL_TIM_GET_FLAG(&htim8, TIM_FLAG_CC2) != RESET)  //????????   
        {
            __HAL_TIM_CLEAR_FLAG(&htim8, TIM_FLAG_CC2);      //??????
            HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);   //??????
            HAL_TIM_Base_Stop_IT(&htim8);         //??????
//			HAL_GPIO_WritePin(GPIOE, EN12_Pin, GPIO_PIN_RESET);
        }
}			

 

 

 

 

### STM32 HAL 定时器主从模式 PWM配置教程 #### 配置概述 在STM32中,定时器可以通过主从模式来实现复杂的PWM功能。具体来说,主定时器负责生成PWM信号,而从定时器则通过外部触发源对接收到的PWM脉冲进行计数。当从定时器达到预设值时,会触发中断并停止主定时器和从定时器的工作[^2]。 为了实现这一功能,通常会选择一个通用定时器作为主定时器(如TIM2),另一个通用定时器作为从定时器(如TIM3)。主定时器生成PWM信号并通过内部触发线路(ITR1)驱动从定时器工作。这种方式允许精确控制输出的PWM脉冲数量[^4]。 --- #### 示例代码 以下是基于HAL的一个简单示例代码,展示如何使用主从模式生成固定数量的PWM脉冲: ```c #include "stm32f4xx_hal.h" // 主定时器 TIM2 和 从定时器 TIM3 的句柄声明 TIM_HandleTypeDef htim2; // 主定时器 (TIM2) TIM_HandleTypeDef htim3; // 从定时器 (TIM3) void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void); // 初始化主定时器 TIM2 static void MX_TIM3_Init(void); // 初始化从定时器 TIM3 int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); // 初始化主定时器 TIM2 MX_TIM2_Init(); // 初始化从定时器 TIM3 MX_TIM3_Init(); while (1) { // 启动主定时器 TIM2 开始生成 PWM 波形 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 等待从定时器完成计数后自动关闭主/从定时器 HAL_Delay(1000); // 延迟模拟等待时间 } } /** * @brief 初始化主定时器 TIM2 */ static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 8399; // 设置分频系数为8400-1=8399 -> 1kHz频率 htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 999; // 自由运行周期设置为1ms htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; // 使用更新事件触发从定时器 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 占空比为50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } } /** * @brief 初始化从定时器 TIM3 */ static void MX_TIM3_Init(void) { TIM_SlaveConfigTypeDef sSlaveConfig = {0}; TIM_IC_InitTypeDef sConfigIC = {0}; htim3.Instance = TIM3; htim3.Init.Prescaler = 8399; // 分频系数同样为8400-1=8399 -> 1kHz频率 htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 9999; // 计数到10ms htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim3) != HAL_OK) { Error_Handler(); } sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNALTRIGGER; // 外部触发模式 sSlaveConfig.InputTrigger = TIM_TS_ITR1; // ITR1 来自主定时器 TIM2 更新事件 if (HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig) != HAL_OK) { Error_Handler(); } // 中断回调函数注册 HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM3_IRQn); } /** * @brief 从定时器 TIM3 中断服务程序 */ void TIM3_IRQHandler(void) { HAL_TIM_IRQHandler(&htim3); } /** * @brief 从定时器 TIM3 捕获/比较中断回调函数 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { // 当从定时器溢出时,停止主定时器和从定时器 __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 0); // 清零占空比 HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1); // 停止主定时器 HAL_TIM_Base_Stop(&htim3); // 停止从定时器 } } ``` --- #### 关键点解析 1. **主定时器初始化** 主定时器(如TIM2)被配置为PWM输出模式,并通过`TIM_TRGO_UPDATE`将其更新事件传递给从定时器。这使得每次PWM波形生成完成后都能触发出从定时器的操作^。 2. **从定时器初始化** 从定时器(如TIM3)被配置为外部触发模式,接受来自主定时器的更新事件作为触发源。一旦从定时器计数到达设定的最大值,则触发从中断^。 3. **中断处理逻辑** 在从定时器的中断服务程序中,执行必要的清理操作,例如停止主定时器和从定时器的工作,确保不会继续生成多余的PWM脉冲[^3]^。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值