TIM-BLDC六步换相-串口中断模拟检测霍尔信号换相-软件COM事件解析
TIM-BLDC六步换相-串口中断模拟检测霍尔信号换相-软件COM事件解析
一、COM事件解析
COM事件简介:COM事件即换相事件只用于高级定时器当中,其主要目的是用在BLDC方波的控制中,用于同时更新6路PWM的状态,即同时更新占空比的目的,从而达到3相同时换相;如果不使用COM事件,由于代码是按顺序执行,程序中会按代码顺序更新6路PWM的状态,会造成通道之间存在延迟。
COM事件产生有两种方式,本文介绍直接通过软件产生COM事件
即:TIM_GenerateEvent(TIM1,TIM_EventSource_COM);
COM事件使能
TIM_CCPreloadControl(TIM1,ENABLE);

COM事件使能后,操作CCxE、CCxNE、OCxM位时,只有当COM事件发生后,功能才会生效。
COM事件验证
case 6://W+U-(由W+V-换相到此状态)
TIM1->CH3CVR=10;
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Enable);
TIM1->CH1CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Enable);//U-
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Disable);//V相由高电平变为低电平
//程序中使能COM事件
TIM_CCPreloadControl(TIM1,ENABLE);
TIM_GenerateEvent(TIM1,TIM_EventSource_COM);

可以看出在由W+V-换相到W+U-的过程中,U-由低电平变为高电平/V-由高电平变为低电平,这两个事件是同时发生的。
//程序中失能COM事件
TIM_CCPreloadControl(TIM1,DISABLE);

可以看出在由W+V-换相到W+U-的过程中,事件1:U-由低电平变为高电平/事件2:V-由高电平变为低电平,这两个事件是按照程序当中先执行事件1再执行事件2的顺序进行的,二者之间存在4.88us的延时
二、串口中断模拟检测霍尔信号换相

在120°导通区间,上桥臂开关管采用PWM调制,下桥臂恒通
串口接收5/4/6/2/3/1数据完成从U+V-→W+V-→W+U-→V+U-→V+W-→U+ W-的六步换相
程序实际运行波形图如下:

三、完整程序代码如下:
#include "debug.h"
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_Printf_Init(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
}
void USART2_CFG( void )
{
NVIC_InitTypeDef NVIC_InitStructure= {0};
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM1_CH1_( u16 arr, u16 psc, u16 ccp)//TIM1_CH1 从定时器 输出波形
{
GPIO_InitTypeDef GPIO_InitStructure={0};
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
TIM_OCInitTypeDef TIM_OCInitStructure={0};
TIM_BDTRInitTypeDef TIM_BDTRInitStructure={0};
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure); //TIM1_CH1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure); //TIM1_CH2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure); //TIM1_CH3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure); //TIM1_CH1N
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure); //TIM1_CH2N
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure); //TIM1_CH3N
TIM_TimeBaseInitStructure.TIM_Period =arr;
TIM_TimeBaseInitStructure.TIM_Prescaler =psc;
TIM_TimeBaseInitStructure.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = ccp;
TIM_OC1Init( TIM1, &TIM_OCInitStructure );
TIM_OCInitStructure.TIM_Pulse = ccp;
TIM_OC2Init( TIM1, &TIM_OCInitStructure );
TIM_OCInitStructure.TIM_Pulse = ccp;
TIM_OC3Init( TIM1, &TIM_OCInitStructure );
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = 132;//
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
// TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
// TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Disable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Disable);
TIM_CCPreloadControl(TIM1,ENABLE);
// TIM_CCPreloadControl(TIM1,DISABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1,ENABLE);
TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Disable);
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Disable);
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Disable);
}
void USART2_IRQHandler( void )//串口2中断
{
__IO u8 CHannel = 0;
if( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )
{
CHannel = USART_ReceiveData( USART2 );
}
switch(CHannel)
{
case 1://U+ W-
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Disable);
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Disable);
TIM1->CH1CVR=60;
TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Enable);
TIM1->CH3CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Enable);
break;
case 2://V+U-
TIM1->CH2CVR=50;
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Enable);
TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Disable);
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Disable);
TIM1->CH1CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Enable);
break;
case 3://V+W-
TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Disable);
TIM1->CH2CVR=40;
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Enable);
TIM1->CH3CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Enable);
break;
case 4://W+V-
TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Disable);
TIM1->CH2CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Enable);
TIM1->CH3CVR=30;
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Enable);
break;
case 5://U+V-
TIM1->CH1CVR=20;
TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Enable);
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Disable);
TIM1->CH2CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Enable);
break;
case 6://W+U-
TIM1->CH3CVR=10;
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Enable);
TIM1->CH1CVR=100;
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Enable);
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Disable);
break;
default:
TIM_CCxCmd(TIM1,TIM_Channel_1,TIM_CCx_Disable);
TIM_CCxCmd(TIM1,TIM_Channel_2,TIM_CCx_Disable);
TIM_CCxCmd(TIM1,TIM_Channel_3,TIM_CCx_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_1,TIM_CCxN_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_2,TIM_CCxN_Disable);
TIM_CCxNCmd(TIM1,TIM_Channel_3,TIM_CCxN_Disable);
break;
}
TIM_GenerateEvent(TIM1,TIM_EventSource_COM);//产生COM事件
}
int main(void)
{
Delay_Init();
USART2_Printf_Init(115200);
USART2_CFG();
TIM1_CH1_(100-1,8-1,0);
while(1);
}
TIM-BLDC六步换相-串口中断模拟检测霍尔信号换相-软件COM事件解析的更多相关文章
- 六步实现Spring.NET 与 NHibernate 的整合
最近刚完成一个项目,其中对数据库的架构用到的是Spring.NET 与 NHibernate相结合的产物.对于这两项技术,我自己也不是太熟悉,不过好在网上有很多关于这方面的介绍文档,在这里就不多说了. ...
- 轻松六步教会你如何修改system.img.ext4文件
http://bbs.xiaomi.cn/thread-2943923-1-1.html 希望更多的ROM作者,看了此教程后,学会ROM制作,给大家带来更多更好的ROM 首先下载如下包 Linux U ...
- 【Linux开发】linux设备驱动归纳总结(六):2.分享中断号
linux设备驱动归纳总结(六):2.分享中断号 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- 古有七步成诗,今有六步完成DevOps上华为云DevCloud实践
引言: 在“DevOps能力之屋(Capabilities House of DevOps)”中,华为云DevCloud提出(工程方法+最佳实践+生态)×工具平台=DevOps能力.华为云DevClo ...
- c# ado 连接数据库 六步曲
建立连接分为六步:1.定义连接字符串,oracle 的连接字符串为: private static string connString = "Data Source=192.168.1.13 ...
- STM8S和STM8L调试串口中断的注意点
1. STM8L串口中断注意点 在调试PM2.5传感器GP2Y1051的时候,发现在仿真的时候开始能够进行数据的接受,但是如果暂停之后就不能接受数据,其实只是接收了一次完整的数据. 问题程序 解决方法 ...
- Event Recommendation Engine Challenge分步解析第六步
一.请知晓 本文是基于: Event Recommendation Engine Challenge分步解析第一步 Event Recommendation Engine Challenge分步解析第 ...
- Stm32L0串口中断接收使用
最新在做LoRa的项目,使用的是STM32L072和SX1276,需要做一个串口透传模块,刚开始做demo的时候不考虑功耗,所以串口发送和接收直接使用下列函数执行: HAL_UART_Transmit ...
- STM32 串口中断总结
原文:https://blog.csdn.net/weixin_42480952/article/details/82981409 最近在学习使用dma传输方式进行串口通讯,感觉这个很详细,存一下 . ...
- 【Vue实战之路】二、路由使用基础,六步搞定Vue-router
vue-router的出现是为了解决路由与视图(实际项目中的单文件组件)的对应关系.若单单为了实现交互时对相应组件的渲染,则通过vue的基础操作完全可以实现,那么为什么要是用vue-router呢,个 ...
随机推荐
- 微软 New Bing AI 申请与使用保姆级教程(免魔法)
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 最近的 AI 技术实在火爆,从 OpenAI 的 ChatGPT,到微软的 New Bi ...
- STM32 HAL库学习(F407ZGT6) (1)-晶振/时钟树
时钟树(以F407为例) 对于 STM32F4 系列的芯片,正常工作的主频可以达到 168Mhz,但并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及RTC只需要几十Khz的时钟即可.同一个 ...
- 部署kubernetes官网博客
部署kubernetes官网博客 访问 https://kubernetes.io/ 有些时候不问题,部署离线内网使用官网以及博客, 各位尝鲜可以访问 https://doc.oiox.cn/ 安装d ...
- docker方式实现redis数据持久化离线安装
保存镜像 root@hello:~# docker pull redis:latest latest: Pulling from library/redis a2abf6c4d29d: Already ...
- 使用frp进行内网穿透
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP.UDP.HTTP.HTTPS 等多种协议.可以将内网服务以安全.便捷的方式通过具有公网 IP 节点的中转暴露到公网. frp is a ...
- Redis 数据类型 String
Redis 数据类型 String Redis主要支持的数据类型有5种:String ,Hash ,List ,Set ,和 Sorted Set Redis 常用命令,思维导图 >>&g ...
- 在.NET 6.0中自定义接口路由
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本文中,我们将讨论ASP.NET Core中的新路由.我们将了解什么是接口(en ...
- 如何在现有项目中使用`Masa MiniApi`?
首先我们现有创建一个空的WebApi的项目模板,这个项目模板和MasaFramework本身没有任何关联,我们本博客只是使用的MasaFramework的MiniApi的包 创建Asp.NET Cor ...
- 上传了ipa但在苹果App Store中没有看到构建版本的问题
AU上传ipa出现下图红框提示说明成功上传,但有时App Store后台没有出现构建版本,请查看下面详细说明! 编辑 一.首先登录iTunes Connect 后台.查看ipa构建情况 http ...
- 基于Java开发的全文检索、知识图谱、工作流审批机制的知识库
一.项目介绍 一款全源码,可二开,可基于云部署.私有部署的企业级知识库云平台,应用在需要进行常用文档整理.分类.归集.检索的地方,适合知识密集型单位/历史文档丰富的单位,或者大型企业.集团. 为什么建 ...