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.rhkb.cn/news/328543.html

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

相关文章

c++20---std::erase----std::erase_if

问题&#xff1a;如何删除满足条件的所有元素。 erase #include <iostream> #include <algorithm> #include <vector>int main(){std::vector<int> vec{1,2,3,1,1,1,1,1};std::erase(vec,1);for(int v:vec) std::cout<<v<<" "…

【计算机网络】物理层 通信基础、奈氏准则、香农公式 习题2

下列说法中正确的是( )。 A. 信道与通信电路类似&#xff0c;一条可通信的电路往往包含一个信道 B.调制是指把模拟数据转换为数字信号的过程 C. 信息传输速率是指通信信道上每秒传输的码元数 D.在数值上&#xff0c;波特率等于比特率与每符号所含的比特数的比值 信息传输速率&a…

CentOs安装

安装 开发工具 &#xff1a;GCC、 JDK、mysql 如果出现蓝屏&#xff0c;要在BIOS开启虚拟化支持&#xff0c;或者移除打印机。

西南大学计算机考研,选学硕还是专硕?西南大学计算机考研考情分析!

西南大学&#xff08;Southwest University&#xff09;是教育部直属&#xff0c;教育部、农业农村部、重庆市共建的重点综合大学&#xff0c;是国家首批"双一流"建设高校&#xff0c;"211工程"和"985工程优势学科创新平台"建设高校。现任党委书…

牛客NC343 和大于等于K的最短子数组【困难 前缀和 Java/Go】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/3e1fd3d19fb0479d94652d49c7e1ead1 思路 本答案利用前缀和解答&#xff0c;Java&#xff0c;Go答案通过&#xff0c;但是同样的代码用PHP的话有一个测试用例超时 应该还有更优秀的答案&#xff0c;后面找到更优…

fastadmin对登录token的处理

fastadmin对token的操作 最近开发遇到一个场景&#xff0c;需要绕过验证获取登录&#xff0c;所以恶补了一下这个知识点&#xff0c;这个主要就是控制fastadmin的token的问题 代码分步实现 class Xcxuser extends Api {//关于鉴权protected $noNeedLogin [login,getopenid,…

AWS简介

AWS AWS&#xff0c;全称为Amazon Web Services&#xff0c;是亚马逊公司旗下的云计算服务平台&#xff0c;自2006年起向全球用户提供广泛而深入的云计算服务。AWS是全球最全面、应用最广泛的云平台之一&#xff0c;它从全球的数据中心提供超过200项功能齐全的服务&#xff0c…

ospf基础

ospf 概述&#xff1a; 什么是ospf 开放式最短路径优先协议&#xff0c;一种最受欢迎的动态路由协议版本&#xff1a;ospfv2&#xff08;ipv4&#xff09;和ospfv3&#xff08;ipv6&#xff09;ospf位于OSI参考模型的第三层&#xff0c;数据封装在ip报头的后面协议号&#xf…

(2)双指针练习:复写零

复写零 题目链接&#xff1a;1089. 复写零 - 力扣&#xff08;LeetCode&#xff09; 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不要在超过该数组长度的位置写入元素。请对输入…

详解绝对路径和相对路径的区别

绝对路径和相对路径是用于描述文件或目录在文件系统中位置的两种不同方式。 绝对路径&#xff08;Absolute Path&#xff09;是从文件系统的根目录开始的完整路径&#xff0c;可以唯一地确定一个文件或目录的位置。在不同的操作系统中&#xff0c;根目录的表示方式可能略有不同…

那些年我与c++的叫板(一)--string类自实现

引子&#xff1a;我们学习了c中的string类&#xff0c;那我们能不能像以前数据结构一样自己实现string类呢&#xff1f;以下是cplusplus下的string类&#xff0c;我们参考参考&#xff01; 废话不多说&#xff0c;直接代码实现&#xff1a;&#xff08;注意函数之间的复用&…

【Qt】Qt开源项目

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

波搜索算法(WSA)-2024年SCI新算法-公式原理详解与性能测评 Matlab代码免费获取

​ 声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、初始化阶段 二、全…

计算机Java项目|Springboot高校心理教育辅导设计与实现

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

ThreadLocal,一次到位

一、定义 ThreadLocal是线程私有变量&#xff0c;用于保存每个线程的私有数据。 那么什么情况下需要进行线程隔离 二、源码分析 public class ThreadLocalTest01 {ThreadLocal<Integer> t new ThreadLocal<>();public void test() {t.set(1);Integer integer…

前馈神经网络FNN、多层感知机MLP和反向传播推导

目录 一、前馈神经网络FNN 激活函数的使用 二、多层感知机MLP MLP的典型结构 多层感知机MLP的特点 和前馈神经网络FNN的区别 三、传播推导 1、前向传播(Forward propagation) &#xff08;1&#xff09;输入层到隐藏层 &#xff08;2&#xff09;隐藏层到输出层 2、…

如何去除字符串两侧的空白字符?

TRIM函数会去掉字符串左侧和右侧的空格&#xff0c;语法是&#xff1a;TRIM(字符串) excel中&#xff0c;TRIM函数能去掉字符串左侧和右侧的空格&#xff0c;它的ASCII码是32。 以下设定一个字符串组合&#xff0c;它的第一个字符中空格&#xff0c;最后一个字符是换行符 &q…

头歌实践教学平台:CG1-v1.0-点和直线的绘制

第3关&#xff1a;OpenGL直线绘制 一.任务描述 根据下面要求&#xff0c;在右侧修改代码&#xff0c;绘制出预期输出的图片。平台会对你编写的代码进行测试。 1.本关任务 理解基本图形元素光栅化的基本原理&#xff1b; 了解和使用OpenGL的生成直线的命令&#xff0c;来验证…

MySQL深入理解MVCC机制(详解)

深入理解MVCC 1、MVCC定义 MVCC:Multi-Version Concurrency Control&#xff0c;多版本并发控制机制。 在mysql中&#xff0c;为了满足事务的四大特性之一的隔离性&#xff0c;就是当前事务中的查询的数据不受其他事务的增删改操作的影响&#xff0c;因此mysql主要是通过这个…

VUE之旅—day2

文章目录 Vue生命周期和生命周期的四个阶段created应用—新闻列表渲染mounted应用—进入页面搜索框就获得焦点账单统计&#xff08;Echarts可视化图表渲染&#xff09; Vue生命周期和生命周期的四个阶段 思考&#xff1a; 什么时候可以发送初始化渲染请求&#xff1f;&#xff…