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. 六位一体Serverless化应用,帮你摆脱服务器的烦恼

    ​ 随着互联网技术的飞速发展,越来越多的应用横空出世,是以不可避免带来了大量的服务器需求.大部分的开发者都选择购买或者租用服务器,然而这样也带来了诸多的烦恼. 1.硬件成本高昂 购买服务器费用昂贵,除 ...

  2. day02-搭建微服务基础环境01

    搭建微服务基础环境01 1.创建父工程,用于聚合其他微服务模块 1.1创建父项目 说明:我们先创建一个父项目,该父项目会去管理多个微服务模块(module),如下: (1)File-New-Proje ...

  3. 迁移学习《Pseudo-Label : The Simple and Efficient Semi-Supervised Learning Method for Deep Neural Networks》

    论文信息 论文标题:Pseudo-Label : The Simple and Efficient Semi-Supervised Learning Method for Deep Neural Ne ...

  4. sqlite3使用2

    一. 在cmd中打开SQLite 1.进入数据库 通过输入 d:cd D:\--\SQLitesqlite3 进入数据库 查看数据库的基本信息: .help 显示各种重要的SQLite点命令的列表.s ...

  5. [数据库/MYSQL]MYSQL开启Bin-Log

    1 概述: MYSQL数据库的二进制日志----bin log 什么是二进制日志(binlog)? MySQL的二进制日志binlog,可以说是MySQL最重要的日志,它记录了所有的DDL和DML语句 ...

  6. 迁移学习(SPI)《Semi-Supervised Domain Adaptation by Similarity based Pseudo-label Injection》

    论文信息 论文标题:Semi-Supervised Domain Adaptation by Similarity based Pseudo-label Injection论文作者:Abhay Raw ...

  7. Springboot一些常用注解

    Springboot启动注解 @SpringbootApplication 这个注解是Springboot最核心的注解,用在Springboot的主类上,标识这是一个Springboot应用,用来开启 ...

  8. Nvidia GPU虚拟化

    1 背景 随着Nvidia GPU在渲染.编解码和计算领域发挥着越来越重要的作用,各大软件厂商对于Nvidia GPU的研究也越来越深入,尽管Nvidia倾向于生态闭源,但受制于极大的硬件成本压力,提 ...

  9. Linux shell和环境变量

    环境变量 存储有关shell会话和工作环境信息:允许在内存中存储数据. 注意什么时候要用$ 什么时候不用$:用到变量,需要$;操作变量,不需要$.printenv除外 分为两类: 全局变量:对shel ...

  10. Search Engine + Recommendation System

    PageRank 该网络的 邻接矩阵 通过变换可以变成 概率转移 矩阵 设该转移矩阵为M,最终每个节点的重要性向量为r,则有了一个状态转移方程\(M \cdot r = r\),(虽然严格意义上,应该 ...