STM32F407 2个高级定时器生成2路无刷电机波形以及相电流采集程序(寄存器版)

stm32f407 高级定时1、定时8 生成20k 中心PWM 波形 并分别用其通道4 触发ADC1 ADC2 采样 用于分别两无刷电机foc 电流环控制,ADC1产生50us的电流采集完成中断,用于foc算法周期运算

主要参考高级定时器的寄存器和ADC寄存器

首先,要使用STM32F407的高级定时器1和定时器8生成20kHz的中心PWM波形,你需要进行以下步骤:

  1. 配置时钟:使能GPIO和相应的定时器时钟。

  2. 配置GPIO:选择用于输出PWM的引脚,并将这些引脚配置为复用功能。

  3. 配置定时器:对定时器1和定时器8进行相应的配置,使其能够生成PWM信号。

    • 配置定时器的基本参数:将定时器的模式设置为PWM模式。
    • 配置定时器的时钟分频器。
    • 配置定时器的周期值,并设置PWM信号的占空比。
  4. 配置ADC:使能ADC1和ADC2的时钟,并对它们进行相应的配置。

    • 配置ADC的时钟分频器。
    • 配置ADC的模式:选择连续模式,使得它们能够不间断地进行采样。
    • 配置ADC的触发源:选择定时器的通道4作为触发源。
  5. 配置ADC中断:使能ADC1的转换完成中断,并编写中断处理函数。在中断处理函数中进行foc算法的周期运算。

  6. 启动定时器和ADC

#include <string.h>
#include <MCU_HAL.h>      //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 2static 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;        // 预分频器 = 0TIM1->ARR = pwmTiks;  // 周期// 重复计数器设置(如适用)TIM1->RCR = TIM_1_8_RCR;// 配置时钟源TIM1->CR2 = 0;// TIM1->CR2 |= TIM_CR2_MMS_1; // 主模式选择:更新事件产生TRGOTIM1->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->CCMR1 = 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;   // 通道1TIM1->CCER |= 5 << 4;   // 通道2TIM1->CCER |= 5 << 8;   // 通道3TIM1->CCER |= 1 << 12;  // 通道4 极性高// 断开与死区时间配置TIM1->BDTR = deadTiks;  // 最大不超过255 tickTIM1->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,AF1GPIO_AF_Set(GPIOA, 9, 1);   // PA8,AF1GPIO_AF_Set(GPIOA, 10, 1);  // PA8,AF1GPIO_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,AF1GPIO_AF_Set(GPIOB, 14, 1);  // PA8,AF1GPIO_AF_Set(GPIOB, 15, 1);  // PA8,AF1MX_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;        // 预分频器 = 0TIM8->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;   // 通道1TIM8->CCER |= 5 << 4;   // 通道2TIM8->CCER |= 5 << 8;   // 通道3TIM8->CCER |= 1 << 12;  // 通道4 极性高// 断开与死区时间配置TIM8->BDTR = deadTiks;  // 最大不超过255 tickTIM8->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,AF3GPIO_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,AF1GPIO_AF_Set(GPIOB, 1, 3);  // PA8,AF1GPIO_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,AF1GPIO_AF_Set(GPIOC, 7, 3);  // PA8,AF1GPIO_AF_Set(GPIOC, 8, 3);  // PA8,AF1MX_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;     // 注入通道序列长度:2ADC1->JSQR |= (10 << 10);  // 注入通道3   对应 adc 通道ADC1->JSQR |= (11 << 15);  // 注入通道4ADC1->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);  //// // 启动ADC1MY_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;     // 注入通道序列长度:2ADC2->JSQR |= (12 << 10);  // 注入通道3ADC2->JSQR |= (13 << 15);  // 注入通道4ADC2->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);  //
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/705128.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用友GRP-U8 bx_dj_check.jsp SQL注入漏洞复现(XVE-2024-10537)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

Anaconda安装-超详细版(2024)

扫盲&#xff1a;先装Python还是先装anaconda? 安装anaconda即可&#xff0c;不需要单独装python anaconda 是一个python的发行版&#xff0c;包括了python和很多常见的软件库, 和一个包管理器conda。 一、下载Anaconda 安装包&#xff08;官网和国内镜像资源&#xff09; …

2024年最新最全面的软件测试面试题(四)

1、在项目中如何保证软件质量? 项目质量不仅仅是某个人或某个团队来保障的&#xff0c;而是整个团队一起努力的结果&#xff0c;因此&#xff0c;在公司级别需要 有一个规范的项目流程。 产品&#xff0c;保证迭代过程中的产品逻辑&#xff0c;对于可能的兼容&#xff0c;升…

【Qt】Qt开源项目

1、Flameshot 截图工具 1.1 简介 Flameshot是一款功能强大但易于使用的屏幕截图软件,中文名称火焰截图。 Flameshot 简单易用并有一个CLI版本,所以可以从命令行来进行截图。 Flameshot 是一个Linux发行版中完全免费且开源的截图工具 1.2 源码 github:https://github.com…

连锁收银系统如何助力实体门店私域运营

作为实体门店&#xff0c;私域运营是提升客户黏性和增加复购率的重要策略之一。而连锁收银系统在私域运营中扮演了关键的角色&#xff0c;它不仅可以帮助门店管理客户信息和消费记录&#xff0c;还能够通过数据分析和营销功能提供个性化的服务和推广活动。下面看看连锁收银系统…

怎么识别数学公式?分享简单识别方法

怎么识别数学公式&#xff1f;在学术研究和日常工作中&#xff0c;数学公式无疑是一个常见且重要的元素。然而&#xff0c;手动输入复杂的数学公式往往既耗时又容易出错。幸运的是&#xff0c;随着科技的发展&#xff0c;现在我们有了一些高效的软件工具&#xff0c;可以帮助我…

OpenHarmony 实战开发——ArkUI canvas组件

canvas 是 ArkUI 开发框架里的画布组件&#xff0c;常用于自定义绘制图形。因为其轻量、灵活、高效等优点&#xff0c;被广泛应用于 UI 界面开发中。本期&#xff0c;我们将为大家介绍 ArkUI 开发框架中 canvas 组件的使用。 一、canvas 介绍 1.1 什么是 canvas&#xff1f; …

vue3.0+antdv的admin管理系统vue-admin-beautiful推荐

前言 几年前&#xff0c;笔者自学了vue这一优秀的前端框架&#xff0c;但苦于没项目练手&#xff0c;无意间发现了vue-admin-beautiful这一优秀的前端集成框架。当时就使用它做了一很有意思的小项目---终端监控云平台&#xff0c;实现了前端和后台的整体功能。整体方案介绍参见…

【C语言深度解剖】(12):C语言库函数的学习和模拟实现,一篇文章就够了!

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多C语言深度解剖点击专栏链接查看&…

界面组件DevExpress Reporting v24.1预览版 - 拥有原生Angular报表查看器

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 下一个主要更新(v24.1)将于6月初发布&#xff…

echarts实现金价可视化大屏(项目实战)

前言 最近由于某种原因参加了一个比赛&#xff0c;三天时间肝出来一个可视化大屏项目&#xff08;无后端&#xff09;&#xff0c;代码已开源&#xff0c;但是还在比赛期间不知道会不会影响到 技术使用&#xff1a;html&#xff0c;css&#xff0c;js&#xff0c;echarts&#…

机器学习中10种损失函数大梳理!建议收藏,你一定用得到

接上篇&#xff1a;机器学习中10种损失函数大梳理&#xff01;建议收藏&#xff0c;你一定用得到-CSDN博客 8、希尔伯特-施密特口袋 希尔伯特-施密特口袋&#xff08;Hinge-Schmidt Pocket&#xff09;是一种用于支持向量机训练的损失函数。它是一种改进的希尔伯特-施密特损失…