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事件解析的更多相关文章

  1. 六步实现Spring.NET 与 NHibernate 的整合

    最近刚完成一个项目,其中对数据库的架构用到的是Spring.NET 与 NHibernate相结合的产物.对于这两项技术,我自己也不是太熟悉,不过好在网上有很多关于这方面的介绍文档,在这里就不多说了. ...

  2. 轻松六步教会你如何修改system.img.ext4文件

    http://bbs.xiaomi.cn/thread-2943923-1-1.html 希望更多的ROM作者,看了此教程后,学会ROM制作,给大家带来更多更好的ROM 首先下载如下包 Linux U ...

  3. 【Linux开发】linux设备驱动归纳总结(六):2.分享中断号

    linux设备驱动归纳总结(六):2.分享中断号 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  4. 古有七步成诗,今有六步完成DevOps上华为云DevCloud实践

    引言: 在“DevOps能力之屋(Capabilities House of DevOps)”中,华为云DevCloud提出(工程方法+最佳实践+生态)×工具平台=DevOps能力.华为云DevClo ...

  5. c# ado 连接数据库 六步曲

    建立连接分为六步:1.定义连接字符串,oracle 的连接字符串为: private static string connString = "Data Source=192.168.1.13 ...

  6. STM8S和STM8L调试串口中断的注意点

    1. STM8L串口中断注意点 在调试PM2.5传感器GP2Y1051的时候,发现在仿真的时候开始能够进行数据的接受,但是如果暂停之后就不能接受数据,其实只是接收了一次完整的数据. 问题程序 解决方法 ...

  7. Event Recommendation Engine Challenge分步解析第六步

    一.请知晓 本文是基于: Event Recommendation Engine Challenge分步解析第一步 Event Recommendation Engine Challenge分步解析第 ...

  8. Stm32L0串口中断接收使用

    最新在做LoRa的项目,使用的是STM32L072和SX1276,需要做一个串口透传模块,刚开始做demo的时候不考虑功耗,所以串口发送和接收直接使用下列函数执行: HAL_UART_Transmit ...

  9. STM32 串口中断总结

    原文:https://blog.csdn.net/weixin_42480952/article/details/82981409 最近在学习使用dma传输方式进行串口通讯,感觉这个很详细,存一下 . ...

  10. 【Vue实战之路】二、路由使用基础,六步搞定Vue-router

    vue-router的出现是为了解决路由与视图(实际项目中的单文件组件)的对应关系.若单单为了实现交互时对相应组件的渲染,则通过vue的基础操作完全可以实现,那么为什么要是用vue-router呢,个 ...

随机推荐

  1. cookie时效无限延长方案

    作者:京东科技 刘清洁 1.痛点(*) 自动化测试有2种形式,接口自动化和UI自动化.而UI自动化经常会被登录节点堵塞,例如验证码.图形.滑块等,尽管有些方式可以识别图形和定位滑块位置,但成功率都不高 ...

  2. 【论文翻译】LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS

    LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS 论文地址:https://arxiv.org/pdf/2106.09685.pdf 代码地址:ht ...

  3. [Linux]CPU架构/指令集:RISC / CISC | arm | amd | X86/i386 | aarch64

    1 前言 本文是解决在软件开发.软件交付过程中,常常需要找寻与服务器硬件的CPU架构适配的软件包时,开发者和交付者又时常摸不着头脑.[迷迷糊糊]地就下载了某个所谓"适配".&quo ...

  4. MordernC++之 auto 和 decltype

    在C++11标准中,auto作为关键字被引入,可以用来自动推导变量类型,auto可以用于定义变量,函数返回值,lambda表达式等,在定义变量时可以使用auto来代替具体类型,编译器根据变量初始化表达 ...

  5. 【Spring专题】「技术原理」从源码角度去深入分析关于Spring的异常处理ExceptionHandler的实现原理

    ExceptionHandler的作用 ExceptionHandler是Spring框架提供的一个注解,用于处理应用程序中的异常.当应用程序中发生异常时,ExceptionHandler将优先地拦截 ...

  6. Golang一日一库之logrus

    前言 之前一篇文章介绍了 日志库zap https://www.cnblogs.com/zichliang/p/17311480.html 毋庸置疑,zap库无论是Golang在项目中 还是生产中都极 ...

  7. if, if else, else if 的区别,以js为例

    一个具有迷惑性的例子,底下的两种情况可以看做两个循环,第一个只要满足一个条件就跳出循环,第二个是不管满足几个条件,都会往下走直至循环结束. 1 var a = 5; 2 if (a > 3) { ...

  8. JS 打开本地应用软件

    我们有遇到可以直接打开QQ的跳转链接,也有遇到过直接启动office打开文档. 具体是如何操作的呢? 添加注册表项 首先需要在注册表中添加应用软件的启动地址,操作方式如下 在HKEY_CLASSES_ ...

  9. [Pytorch框架] 3.3 通过Sin预测Cos

    文章目录 3.3 通过Sin预测Cos 3.3 通过Sin预测Cos %matplotlib inline import torch import torch.nn as nn from torch. ...

  10. python使用docxtpl生成word模板

    python-docxtpl包简单使用和实战,Python处理word,docx文件. 最近需要处理一些爬虫得到的数据来进行一些自动化报告的操作,因为需要生成的是word的报告,所以估选用docxtp ...