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. DataLeap 数据资产实战:如何实现存储优化?

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 背景 DataLeap 作为一站式数据中台套件,汇集了字节内部多年积累的数据集成.开发.运维.治理.资产.安全等全 ...

  2. Springboot接入ChatGPT 续

    在之前的文章\(^{[ 1 ]}\)中,原方案的设计,是基于功能实现的角度去设计的,对于功能性的拓展,考虑不全面,结合收到的反馈意见,对项目进行了拓展优化.完成的优化拓展有如下几个方面 固定会话 历史 ...

  3. MySQL(十二)索引使用的情况分析

    索引使用的情况分析 数据准备 创建表student_info.course CREATE TABLE `student_info` ( `id` int NOT NULL AUTO_INCREMENT ...

  4. JUC(五)Callable

    Callable接口 创建线程的几种方式 继承Thread类 实现Runnable接口 通过Callable接口 线程池 使用Runnable接口无法获取到线程返回的结果,因此在jdk1.5后java ...

  5. DeFi4-稳定币

    稳定币--稳定 是一个相对的度量指标 波动性,收益率标准差 在一个时间段内最大跌幅 Fiat,例如: 欧元.英镑的波动率为6-12% (波动本身并不能反映价格的范围 稳定币 vs 锚定币 稳定币类型 ...

  6. node 请求接口,返回大小限制

    请求Node端中转接口时,遇到以下异常: Request_fileSize_limit Request_fields_limit Request_fieldSize_limit 遇到以上异常时,调试信 ...

  7. 学习Golang时遇到的似懂非懂的概念

    背景 这是我学习golang的第三天,大致已经掌握了golang的语法,但是着手开发的时候,却遇到了许多问题,例如golang导包机制.golang的项目管理规范.go mod生成project怎么管 ...

  8. 2022-08-04:输入:去重数组arr,里面的数只包含0~9。limit,一个数字。 返回:要求比limit小的情况下,能够用arr拼出来的最大数字。 来自字节。

    2022-08-04:输入:去重数组arr,里面的数只包含0~9.limit,一个数字. 返回:要求比limit小的情况下,能够用arr拼出来的最大数字. 来自字节. 答案2022-08-04: 从左 ...

  9. 2022-03-29:整个二维平面算是一张地图,给定[x,y],表示你站在x行y列, 你可以选择面朝的任何方向, 给定一个正数值angle,表示你视野的角度为, 这个角度内你可以看无穷远,这个角度外你

    2022-03-29:整个二维平面算是一张地图,给定[x,y],表示你站在x行y列, 你可以选择面朝的任何方向, 给定一个正数值angle,表示你视野的角度为, 这个角度内你可以看无穷远,这个角度外你 ...

  10. 2021-07-12:缺失的第一个正数。给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。比如[3,4,5

    2021-07-12:缺失的第一个正数.给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数.请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案.比如[3,4,5 ...