STM32G4 电机外设篇(三) TIM1 发波 和 ADC COMP DAC级联

news2025/6/3 22:14:11

目录

  • 一、STM32G4 电机外设篇(三) TIM1 发波 和 ADC COMP DAC级联
      • 1 TIM1 高级定时器发波
        • 1.1 stm32cubemx配置
      • 2 TIM1 ADC COMP DAC级联
        • 2.1 stm32cubemx配置
    • 附学习参考网址
      • 欢迎大家有问题评论交流 (* ^ ω ^)

一、STM32G4 电机外设篇(三) TIM1 发波 和 ADC COMP DAC级联

1 TIM1 高级定时器发波

  • 本章接线图详见之前的文章,记住要断开三相电机的uvw接线,否则输出的pwm波会影响电机
1.1 stm32cubemx配置
  • 本实验计划使用TIM1发出3对互补的PWM波,来模拟驱动电机
    在这里插入图片描述

  • 打开之前文章的STM32CubeMx,配置时钟源和TIM1
    在这里插入图片描述

  • 使用通道4触发ADC采样,配置PWM但是不输出

  • RCR设置为1
    在这里插入图片描述

  • RCR可以理解为一个队计时器触发频率的分频
    在这里插入图片描述

  • 设置完成后打开keil文件,修改代码

    1. 注释User Code 4中的中断处理函数,约在291行
//User Code PV中修改
float temp[3];
uint8_t tempData[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x7F};

//User Code 2中修改
HAL_OPAMP_Start(&hopamp1);//使能运放
HAL_OPAMP_Start(&hopamp2);
HAL_OPAMP_Start(&hopamp3);
HAL_UART_Receive_IT(&huart3, (uint8_t *)&aRxBuffer, 1);
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//自校验,减少采样误差
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
TIM1->PSC = 30000;
TIM1->ARR = 10000;
TIM1->CCR1 = 2000;
TIM1->CCR2 = 5000;
TIM1->CCR3 = 8000;
HAL_TIM_Base_Start(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);

 /* USER CODE BEGIN WHILE */修改
while(1)
{
//		HAL_ADC_Start(&hadc1);
//		HAL_ADC_Start(&hadc2);//使能规则组转捿
//		HAL_ADCEx_InjectedStart_IT(&hadc1);
//		HAL_ADCEx_InjectedStart_IT(&hadc2);//使能规则组转换,并产生注入组中断
//		temp[0] = HAL_ADC_GetValue(&hadc1);
//		temp[1] = HAL_ADC_GetValue(&hadc2) * 0.02094726f; //根据分压电阻计算
//		memcpy(tempData, (uint8_t *)&temp, sizeof(temp));
//		HAL_UART_Transmit_DMA(&huart3, (uint8_t *)tempData, 24);
//		HAL_Delay(1);
	if((GPIOA->IDR & GPIO_PIN_8)!=0)
	{
		temp[0] = 1.0f;
	}
	else
	{
		temp[0] = 0.0f;
	}
	if((GPIOA->IDR & GPIO_PIN_9)!=0)
	{
		temp[1] = 3.0f;
	}
	else
	{
		temp[1] = 2.0f;
	}
	if((GPIOA->IDR & GPIO_PIN_10)!=0)
	{
		temp[2] = 5.0f;
	}
	else
	{
		temp[2] = 4.0f;
	}
	memcpy(tempData, (uint8_t *)&temp, sizeof(temp));
	HAL_UART_Transmit_DMA(&huart3, (uint8_t *)tempData, 16);
}
   /* USER CODE END WHILE */
  • 打开VOFA,就能看到成功的PWM曲线图像
    在这里插入图片描述

2 TIM1 ADC COMP DAC级联

  • 电机控制环路主要涉及的外设功能包含高级定时器TIM1的发波,OPAMP 及 ADC 准确的采样三相电流,并在三相电流过流时及时封波,避免损坏硬件
  • 本文将会使用STM32G4内部 TIM1ADCCOMP DAC级联使用
    在这里插入图片描述
  • TIM1 发波时序和电流采样触发
    在这里插入图片描述
  • 在最高点前一点采样,因为采样需要一个短暂的时间,这个时间段电流最稳定
  • 三相电流过流封波时序
    在这里插入图片描述
2.1 stm32cubemx配置
  • 在上一章的工程基础上增加TIM1通道4的触发源,作为ADC电流采样注入组的触发源,分别修改ADC1和ADC2的注入组转换触发源为TIM1比较4事件,增加PB1引脚功能
    在这里插入图片描述

  • 设置DAC_CHI连接MCU内部外设,其它参数默认

  • 使能比较器负向为DAC3,触发方式为上升沿触发
    在这里插入图片描述

  • 设置封波实现的break触发,设置GPIO4,生成代码,在这里插入图片描述

  • 打开Keil软件修改代码

uint8_t adc1_in1, adc1_in2, adc1_in3;
float IA, IB, IC;
uint8_t ADC_offset, IA_Offset, IB_Offset, IC_Offset;
float load_data[5];
float temp[5];
uint8_t tempData[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x7F};


 /* USER CODE BEGIN 2 */
HAL_OPAMP_Start(&hopamp1);//使能运放
HAL_OPAMP_Start(&hopamp2);
HAL_OPAMP_Start(&hopamp3);
HAL_UART_Receive_IT(&huart3, (uint8_t *)&aRxBuffer, 1);
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);//自校验,减少采样误差
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
TIM1->ARR = 8000-1;
TIM1->CCR4 = 8000-2;
HAL_TIM_Base_Start(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
HAL_ADCEx_InjectedStart_IT(&hadc1);
HAL_ADCEx_InjectedStart(&hadc2);
HAL_DAC_Start(&hdac3, DAC_CHANNEL_1);
HAL_DAC_SetValue(&hdac3, DAC_CHANNEL_1,	DAC_ALIGN_12B_R, 3000);
HAL_COMP_Start(&hcomp1);

 /* USER CODE BEGIN WHILE */
while(1)
{
	HAL_ADC_Start(&hadc1);
	HAL_ADC_Start(&hadc2);
	Vpoten = HAL_ADC_GetValue(&hadc1);
	adc_vbus = HAL_ADC_GetValue(&hadc2);
	Vbus = adc_vbus * 3.3f/4096*26;
	HAL_Delay(10);
}

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
    UNUSED(GPIO_Pin);
	if(Button2_Pin == GPIO_Pin)
	{
		HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
		HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
		HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
		HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
		HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
		HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
	}
	if(Button3_Pin == GPIO_Pin)
	{
		HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
		HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
		HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
		HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
		HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
		HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
	}
}

//注入中断处理程序
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	static uint8_t cnt;
	/* Prevent unused argument(s)compilation warning */
	UNUSED(hadc);
	if(hadc == &hadc1)
	{
		if(ADC_offset == 0)
		{
			cnt++;
			adc1_in1 = hadc1.Instance->JDR1;
			adc1_in2 = hadc2.Instance->JDR1;
			adc1_in3 = hadc1.Instance->JDR2;
			IA_Offset += adc1_in1;
			IB_Offset += adc1_in2;
			IC_Offset += adc1_in3;
			if(cnt >= 10)
			{
				ADC_offset =1;
				IA_Offset = IA_Offset/10;
				IB_Offset = IB_Offset/10;
				IC_Offset = IC_Offset/10;
			}
		}
		else
		{
			adc1_in1 = hadc1.Instance->JDR1;
			IA = (adc1_in1 - IA_Offset)*0.0193359375f;
			adc1_in2 = hadc2.Instance->JDR1;
			IB = (adc1_in2 - IB_Offset)*0.0193359375f;
			adc1_in3 = hadc1.Instance->JDR2;
			IC = (adc1_in3 - IC_Offset)*0.0193359375f;
			TIM1->CCR1= 2000;
			TIM1->CCR2= 4000;
			TIM1->CCR3= 6000;
			load_data[0] = IA;
			load_data[1] = IB;
			load_data[2] = IC;
			load_data[3]= 0;
			load_data[4]= 0;
			memcpy(tempData,(uint8_t*)&load_data, sizeof(load_data));
			HAL_UART_Transmit_DMA(&huart3,(uint8_t *)tempData, 6*4);
		}
	}
}
  • 不知道为啥产生了一个4.4A的偏差
    在这里插入图片描述

附学习参考网址

  1. STM32G4 FOC开发实战

欢迎大家有问题评论交流 (* ^ ω ^)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DAY 35 超大力王爱学Python

知识点回顾: 三种不同的模型可视化方法:推荐torchinfo打印summary权重分布可视化进度条功能:手动和自动写法,让打印结果更加美观推理的写法:评估模式 作业:调整模型定义时的超参数,对比下效果。…

【数据结构】图的存储(十字链表)

弧节点 tailvex数据域:存储弧尾一端顶点在顺序表中的位置下标;headvex 数据域:存储弧头一端顶点在顺序表中的位置下标;hlink 指针域:指向下一个以当前顶点作为弧头的弧;tlink 指针域:指向下一个…

Redis最佳实践——秒杀系统设计详解

基于Redis的高并发秒杀系统设计(十万级QPS) 一、秒杀系统核心挑战 瞬时流量洪峰:100万 QPS请求冲击库存超卖风险:精准扣减防止超卖系统高可用性:99.99%服务可用性要求数据强一致性:库存/订单/支付状态同步…

STM32软件spi和硬件spi

核心观点 本文主要介绍了SPI通信的两种实现方式:软件SPI和硬件SPI。详细阐述了SPI通信协议的基本概念、硬件电路连接方式、移位示意图、时序基本单元以及四种工作模式。同时,对W25Q64模块进行了详细介绍,包括其硬件电路、框图以及操作注意事…

深度刨析树结构(从入门到入土讲解AVL树及红黑树的奥秘)

目录 树的表示 二叉树的概念及结构(重点学习) 概念 : 特点: 树与非树 特殊的二叉树 二叉树的性质(重点) 二叉树的存储结构 堆的概念及结构 建堆方式: 向下调整算法 向上调整算法 建堆第一步初始化 建…

【Linux】shell的条件判断

目录 一.使用逻辑运算符判定命令执行结果 二.条件判断方法 三.判断表达式 3.1文件判断表达式 3.2字符串测试表达式 3.3整数测试表达式 3.4逻辑操作符 一.使用逻辑运算符判定命令执行结果 && 在命令执行后如果没有任何报错时会执行符号后面的动作|| 在命令执行后…

第九天:java注解

注解 1 什么是注解(Annotation) public class Test01 extends Object{//Override重写的注解Overridepublic String toString() {return "Test01{}";} }2 内置注解 2.1 Override Override重写的注解 Override public String toString() {ret…

十一、【核心功能篇】测试用例管理:设计用例新增编辑界面

【核心功能篇】测试用例管理:设计用例新增&编辑界面 前言准备工作第一步:创建测试用例相关的 API 服务 (src/api/testcase.ts)第二步:创建测试用例编辑页面组件 (src/views/testcase/TestCaseEditView.vue)第三步:配置测试用例…

Spring是如何实现属性占位符解析

Spring属性占位符解析 核心实现思路1️⃣ 定义占位符处理器类2️⃣ 处理 BeanDefinition 中的属性3️⃣ 替换具体的占位符4️⃣ 加载配置文件5️⃣ Getter / Setter 方法 源码见:mini-spring 在使用 Spring 框架开发过程中,为了实现配置的灵活性&#xf…

DDR4读写压力测试

1.1测试环境 1.1.1整体环境介绍 板卡: pcie-403板卡 主控芯片: Xilinx xcvu13p-fhgb2104-2 调试软件: Vivado 2018.3 代码环境: Vscode utf-8 测试工程: pcie403_user_top 1.1.2硬件介绍 UD PCIe-403…

编写测试用例

测试用例(Test Case)是用于测试系统的要素集合 目录 编写测试用例作用 编写测试用例要包含七大元素 测试用例的设计方法 1、等价类法 2、边界值法 3、正交表法 4、判定表法 5、错误推测法 6、场景法 编写测试用例作用 1、确保功能全面覆盖…

每日Prompt:隐形人

提示词 黑色棒球帽,白色抹胸、粉色低腰短裙、白色襪子,黑色鞋子,粉紅色背包,衣服悬浮在空中呈现动态姿势,虚幻引擎渲染风格,高清晰游戏CG质感,户外山林背景,画面聚焦在漂浮的衣服上…

TensorFlow深度学习实战(19)——受限玻尔兹曼机

TensorFlow深度学习实战(19)——受限玻尔兹曼机 0. 前言1. 受限玻尔兹曼机1.1 受限玻尔兹曼机架构1.2 受限玻尔兹曼机的数学原理 2. 使用受限玻尔兹曼机重建图像3. 深度信念网络小结系列链接 0. 前言 受限玻尔兹曼机 (Restricted Boltzmann Machine, RB…

告别手动绘图!基于AI的Smart Mermaid自动可视化图表工具搭建与使用指南

以下是对Smart Mermaid的简单介绍: 一款基于 AI 技术的 Web 应用程序,可将文本内容智能转换为 Mermaid 格式的代码,并将其渲染成可视化图表可以智能制作流程图、序列图、甘特图、状态图等等,并且支持在线调整、图片导出可以Docke…

【Oracle】安装单实例

个人主页:Guiat 归属专栏:Oracle 文章目录 1. 安装前的准备工作1.1 硬件和系统要求1.2 检查系统环境1.3 下载Oracle软件 2. 系统配置2.1 创建Oracle用户和组2.2 配置内核参数2.3 配置用户资源限制2.4 安装必要的软件包 3. 目录结构和环境变量3.1 创建Ora…

QT中更新或添加组件时出现“”qt操作至少需要一个处于启用状态的有效资料档案库“解决方法”

在MaintenanceTool.exe中点击下一步 第一个: 第二个: 第三个: 以上任意一个放入资料库中

论文速读《UAV-Flow Colosseo: 自然语言控制无人机系统》

论文链接:https://arxiv.org/abs/2505.15725项目主页:https://prince687028.github.io/UAV-Flow/ 0. 简介 近年来,无人机技术蓬勃发展,但如何让无人机像智能助手一样理解并执行人类语言指令,仍是一个前沿挑战。现有研…

ES6+中Promise 中错误捕捉详解——链式调用catch()或者async/await+try/catch

通过 unhandledrejection 捕捉未处理的 Promise 异常,手动将其抛出,最终让 window.onerror 捕捉,从而统一所有异常的处理逻辑 规范代码:catch(onRejected)、async...awaittry...catch 在 JavaScript 的 Pro…

解常微分方程组

Euler法 function euler_method % 参数设置 v_missile 450; % 导弹速度 km/h v_enemy 90; % 敌艇速度 km/h % 初始条件 x0 0; % 导弹初始位置 x y0 0; % 导弹初始位置 y xe0 120; % 敌艇初始位置 y t0 0; % 初始时间 % 时间步长和总时间 dt 0.01; % 时间步长 t_final …

C++实现汉诺塔游戏自动完成

目录 一、汉诺塔的规则二、数学递归推导式三、步骤实现(一)汉诺塔模型(二)递归实现(三)显示1.命令行显示2.SDL图形显示 四、处理用户输入及SDL环境配置五、总结六、源码下载 一、汉诺塔的规则 游戏由3根柱子和若干大小不一的圆盘组成,初始状态下,所有的…