stm32f407 高级定时1、定时8 生成20k 中心PWM 波形 并分别用其通道4 触发ADC1 ADC2 采样 用于分别两无刷电机foc 电流环控制,ADC1产生50us的电流采集完成中断,用于foc算法周期运算
主要参考高级定时器的寄存器和ADC寄存器
首先,要使用STM32F407的高级定时器1和定时器8生成20kHz的中心PWM波形,你需要进行以下步骤:
配置时钟:使能GPIO和相应的定时器时钟。
配置GPIO:选择用于输出PWM的引脚,并将这些引脚配置为复用功能。
配置定时器:对定时器1和定时器8进行相应的配置,使其能够生成PWM信号。
配置ADC:使能ADC1和ADC2的时钟,并对它们进行相应的配置。
配置ADC中断:使能ADC1的转换完成中断,并编写中断处理函数。在中断处理函数中进行foc算法的周期运算。
启动定时器和ADC
- #include
- #include
//for downlayer interface include the CHAL port - #include "CHAL_Config.h" //
-
- #define TIM_1_8_CLOCK_HZ 168000000
- // #define TIM_1_8_PERIOD_CLOCKS 3500 //24k
- #define TIM_1_8_PERIOD_CLOCKS 4199 // 20k
- #define TIM_1_8_DEADTIME_CLOCKS 20
- #define TIM_APB1_CLOCK_HZ 84000000
- #define TIM_APB1_PERIOD_CLOCKS 4096
- #define TIM_APB1_DEADTIME_CLOCKS 40
- #define TIM_1_8_RCR 2
-
- static void MX_ADC1_Init(void);
- static void MX_ADC2_Init(void);
-
- void CHAL_Pwm1Init(char *HIVersion, uint32_t runFreq, uint32_t deadTime, uint32_t sampHalfTime)
- {
- uint32_t pwmTiks = CPUFREQ / 2 / runFreq;
- uint8_t deadTiks = deadTime / CPURATE;
- // 使能TIM1时钟
- RCC->APB2ENR |= 1 << 0;
-
- // 配置TIM1基本设置
- TIM1->CR1 = 0;
- TIM1->CR1 |= (1 << 5); // 中心对齐模式 1 递减时产生
- TIM1->CR1 |= (1 << 0); // 使能计数器
- // TIM1->CR1 |= TIM_CR1_ARPE; // 自动重载预装载使能
- // TIM1->CR1 |= TIM_CR1_CKD_0; // 时钟分频因子 = /1
-
- // 设置预分频器和周期
- TIM1->PSC = 0; // 预分频器 = 0
- TIM1->ARR = pwmTiks; // 周期
-
- // 重复计数器设置(如适用)
- TIM1->RCR = TIM_1_8_RCR;
-
- // 配置时钟源
- TIM1->CR2 = 0;
- // TIM1->CR2 |= TIM_CR2_MMS_1; // 主模式选择:更新事件产生TRGO
- TIM1->CCMR1 = 0;
- TIM1->CCMR1 |= 7 << 4; // PWM模式
- TIM1->CCMR1 |= 1 << 3; // 输出比较预装载使能
- TIM1->CCMR1 |= 7 << 12; // PWM模式
- TIM1->CCMR1 |= 1 << 11; // 输出比较预装载使能8 重复计数器8 重复计数器寄存器 (TIMx_RCR)寄存器 (TIMx_RCR)
- TIM1->CCMR2 = 0;
-
- TIM1->CCMR2 |= 7 << 4; // PWM模式
- TIM1->CCMR2 |= 1 << 3; // 输出比较预装载使能
- TIM1->CCMR2 |= 7 << 12; // PWM模式
- TIM1->CCMR2 |= 1 << 11; // 输出比较预装载使能
- // 设置初始脉冲值(通道1、2、3)
- TIM1->CCR1 = 0;
- TIM1->CCR2 = 0;
- TIM1->CCR3 = 0;
- TIM1->CCR4 = 1;
-
- // 设置极性(通道1、2、3)
- TIM1->CCER = 0;
- /* 0 1 2 3 */
- /* CCE=1 CCP=0 CCNE=1 CCPN=0 */
- /* 0x5 */
- TIM1->CCER |= 5 << 0; // 通道1
- TIM1->CCER |= 5 << 4; // 通道2
- TIM1->CCER |= 5 << 8; // 通道3
- TIM1->CCER |= 1 << 12; // 通道4 极性高
-
- // 断开与死区时间配置
- TIM1->BDTR = deadTiks; // 最大不超过255 tick
- TIM1->BDTR |= 1 << 15; // 输出使能
-
- /* gpio 初始化 */
- RCC->AHB1ENR |= 1 << 0; // 使能PORTA口时钟
- RCC->AHB1ENR |= 1 << 1; // 使能PORTB口时钟
-
- GPIO_Set(GPIOA, PIN8 | PIN9 | PIN10, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_50M,
- GPIO_PUPD_PD); // PA9,PA10,复用功能,上拉输出
- GPIO_AF_Set(GPIOA, 8, 1); // PA8,AF1
- GPIO_AF_Set(GPIOA, 9, 1); // PA8,AF1
- GPIO_AF_Set(GPIOA, 10, 1); // PA8,AF1
- GPIO_Set(GPIOB, PIN13 | PIN14 | PIN15, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_50M,
- GPIO_PUPD_PD); // PA9,PA10,复用功能,上拉输出
- GPIO_AF_Set(GPIOB, 13, 1); // PA8,AF1
- GPIO_AF_Set(GPIOB, 14, 1); // PA8,AF1
- GPIO_AF_Set(GPIOB, 15, 1); // PA8,AF1
- MX_ADC1_Init();
- }
-
- void CHAL_M1_DisPwm123(void) { TIM1->CCER = 0x1000; }
-
- void CHAL_M1_EnaPwm123(void) { TIM1->CCER = 0x1555; }
-
- void CHAL_Pwm2Init(char *HIVersion, uint32_t runFreq, uint32_t deadTime, uint32_t sampHalfTime)
- {
- uint32_t pwmTiks = CPUFREQ / 2 / runFreq;
- uint8_t deadTiks = deadTime / CPURATE;
- // 使能TIM2时钟
- RCC->APB2ENR |= 1 << 1;
-
- // 配置TIM2基本设置
- TIM8->CR1 = 0;
- TIM8->CR1 |= (1 << 5); // 中心对齐模式 1 递减时产生
- TIM8->CR1 |= (1 << 0); // 使能计数器
- // TIM8->CR1 |= TIM_CR1_ARPE; // 自动重载预装载使能
- // TIM8->CR1 |= TIM_CR1_CKD_0; // 时钟分频因子 = /1
-
- // 设置预分频器和周期
- TIM8->PSC = 0; // 预分频器 = 0
- TIM8->ARR = pwmTiks; // 周期
-
- // 重复计数器设置(如适用)
- TIM8->RCR = TIM_1_8_RCR;
-
- // 配置时钟源
- TIM8->CR2 = 0;
- // TIM8->CR2 |= TIM_CR2_MMS_1; // 主模式选择:更新事件产生TRGO
-
- // PWM模式配置(通道1、2、3)
- TIM8->CCMR1 = 0;
- TIM8->CCMR1 |= 7 << 4; // PWM模式
- TIM8->CCMR1 |= 1 << 3; // 输出比较预装载使能
- TIM8->CCMR1 |= 7 << 12; // PWM模式
- TIM8->CCMR1 |= 1 << 11; // 输出比较预装载使能
- TIM8->CCMR2 = 0;
- TIM8->CCMR2 |= 7 << 4; // PWM模式
- TIM8->CCMR2 |= 1 << 3; // 输出比较预装载使能
- TIM8->CCMR2 |= 7 << 12; // PWM模式
- TIM8->CCMR2 |= 1 << 11; // 输出比较预装载使能
- // 设置初始脉冲值(通道1、2、3)
- TIM8->CCR1 = 0;
- TIM8->CCR2 = 0;
- TIM8->CCR3 = 0;
- TIM8->CCR4 = 1;
-
- // 设置极性(通道1、2、3)
- TIM8->CCER = 0;
- /* 0 1 2 3 */
- /* CCE=1 CCP=0 CCNE=1 CCPN=0 */
- /* 0x5 */
- TIM8->CCER |= 5 << 0; // 通道1
- TIM8->CCER |= 5 << 4; // 通道2
- TIM8->CCER |= 5 << 8; // 通道3
- TIM8->CCER |= 1 << 12; // 通道4 极性高
-
- // 断开与死区时间配置
- TIM8->BDTR = deadTiks; // 最大不超过255 tick
- TIM8->BDTR |= 1 << 15; // 输出使能
-
- /* gpio 初始化 */
- RCC->AHB1ENR |= 1 << 0; // 使能PORTA口时钟
- RCC->AHB1ENR |= 1 << 1; // 使能PORTB口时钟
- RCC->AHB1ENR |= 1 << 2; // 使能PORTc口时钟
-
- GPIO_Set(GPIOA, PIN7, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_50M,
- GPIO_PUPD_PD); // PA9,PA10,复用功能,上拉输出
- GPIO_AF_Set(GPIOA, 7, 3); // PA8,AF3
- GPIO_Set(GPIOB, PIN0 | PIN1 | PIN15, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_50M,
- GPIO_PUPD_PD); // PA9,PA10,复用功能,上拉输出
- GPIO_AF_Set(GPIOB, 0, 3); // PA8,AF1
- GPIO_AF_Set(GPIOB, 1, 3); // PA8,AF1
-
- GPIO_Set(GPIOC, PIN6 | PIN7 | PIN8, GPIO_MODE_AF, GPIO_OTYPE_PP, GPIO_SPEED_50M,
- GPIO_PUPD_PD); // PA9,PA10,复用功能,上拉输出
- GPIO_AF_Set(GPIOC, 6, 3); // PA8,AF1
- GPIO_AF_Set(GPIOC, 7, 3); // PA8,AF1
- GPIO_AF_Set(GPIOC, 8, 3); // PA8,AF1
- MX_ADC2_Init();
- }
-
- void CHAL_M2_DisPwm123(void) { TIM8->CCER = 0x1000; }
-
- void CHAL_M2_EnaPwm123(void) { TIM8->CCER = 0x1555; }
-
-
-
- /**
- * @brief ADC1 初始化函数
- * @param 无
- * @retval 无
- */
- static void MX_ADC1_Init(void)
- {
- // 使能ADC1时钟
- RCC->APB2ENR |= 1 << 8;
- // ADC1->CR1 = 0x180;
-
- ADC1->CR1 |= 1 << 8; // 使能扫描模式
- ADC1->CR1 |= 1 << 7; // 注入通道中断完成中断使能
- ADC1->CR2 = 0;
- ADC1->CR2 |= 1 << 10; // ADC 使能
- ADC1->CR2 |= 2 << 20; // 下降沿触发 注入通道检测
- ADC1->CR2 |= 0 << 16; // 注入通道 TIM1 CC4 事件
- ADC1->CR2 |= 1 << 0; // ADC 使能
- ADC1->HTR = 0x0FFF;
- // ADC1->CR2 = 0x0200401;
- ADC1->HTR = 0x0FFF;
-
- ADC1->JSQR = 0;
- ADC1->JSQR |= 1 << 20; // 注入通道序列长度:2
- ADC1->JSQR |= (10 << 10); // 注入通道3 对应 adc 通道
- ADC1->JSQR |= (11 << 15); // 注入通道4
- ADC1->SMPR1 = 0;
- ADC1->SMPR1 |= 0 << 0; // 注入通道8采样时间: 3个周期
- ADC1->SMPR1 |= 0 << 3; // 注入通道12采样时间:3个周期
-
- RCC->AHB1ENR |= 1 << 2; // 使能PORTC口时钟
-
- GPIO_Set(GPIOC, PIN0 | PIN1, GPIO_MODE_AIN, 0, 0, GPIO_PUPD_PU); //
-
- // // 启动ADC1
- MY_NVIC_Init(0, 0, ADC_IRQn, 0); // 抢占1,子优先级3,组2
- }
-
- /**
- * @brief ADC2 初始化函数
- * @param 无
- * @retval 无
- */
- static void MX_ADC2_Init(void)
- {
- // 使能ADC2时钟
- RCC->APB2ENR |= 1 << 9;
- // ADC2->CR1 = 0x180;
- ADC2->CR1 = 0;
- ADC2->CR1 |= 1 << 8; // 使能扫描模式
- ADC2->CR2 = 0;
- ADC2->CR2 |= 1 << 10; // ADC 使能
- ADC2->CR2 |= 2 << 20; // 下降沿触发 注入通道检测
- ADC2->CR2 |= 0xe << 16; // 注入通道 TIM8 CC4 事件
- ADC2->CR2 |= 1 << 0; // ADC 使能
- ADC2->HTR = 0x0FFF;
-
- // // // 配置注入通道(通道8、12、6、13)
- ADC2->JSQR = 0;
- ADC2->JSQR |= 1 << 20; // 注入通道序列长度:2
- ADC2->JSQR |= (12 << 10); // 注入通道3
- ADC2->JSQR |= (13 << 15); // 注入通道4
-
- ADC2->SMPR1 = 0;
-
- ADC2->SMPR1 |= 0 << 0; // 注入通道8采样时间: 3个周期
- ADC2->SMPR1 |= 0 << 3; // 注入通道12采样时间:3个周期
-
- RCC->AHB1ENR |= 1 << 2; // 使能PORTC口时钟
-
- GPIO_Set(GPIOC, PIN2 | PIN3, GPIO_MODE_AIN, 0, 0, GPIO_PUPD_PU); //
- }


