BLDC开发笔记3.霍尔接口与触发换相

摘要:
当霍尔接口初始化使用高级控制定时器(TIM1或TIM8)生成PWM信号以驱动电机时,工作过程TIMx_CH1、TIMx_CH2和TIMx_ CH3的三个引脚接收的霍尔信号被传输到输入通道TI1。来自TI1的信号通过输入滤波器(配置有滤波器长度)和边沿检测器(输入触发器的有效极性,即,可以触发上升沿和下降沿),以生成脉冲信号TI1F_ ED,TIMx_ ARR设置为其最大值(计数器必须通过TI1的变化清零)。

希望看过的各位对错误之处可以帮忙指正。

长期更新。

霍尔接口初始化

使用高级控制定时器(TIM1或TIM8)产生PWM信号驱动马达时,可以用另一个通用TIMx(TIM2、TIM3、 TIM4或TIM5)定时器作为“接口定时器”来连接霍尔传感器 。这里选用定时器3。

stm32的通用定时器内部集成了针对霍尔/编码器信号处理的电路。如下图:
BLDC开发笔记3.霍尔接口与触发换相第1张

工作过程

  1. TIMx_CH1、TIMx_CH2和TIMx_CH3三个引脚接受到的霍尔信号,经过输入异或(XOR)功能,传到输入通道TI1
  2. 信号从TI1的经过输入滤波器(配置滤波长度)和边沿检测器(输入触发有效极性,这里配置为双极性有效,即上升沿和下降沿都能触发)后产生脉冲信号TI1F_ED,经过选择器后作为TRC输入,再将TRC作为输入捕获通道IC1的输入信号。IC1PS就是计数器的捕获触发信号(脉冲),决定什么时候将计数器的值传进输入捕获寄存器。整个过程就是映射过程。
  3. 配置时基,内部时钟分频后作为计数器时钟,将从模式控制器配置为复位模式,每当3个输入之一变化时,计数器从新从0开始计数,计数到下一个变化开始为止,这个计数器值CNT就反映了两个霍尔状态之间的时间间隔,通过这个值我们可以计算出电机的转速信息。

注意,TI1F_ED是一个脉冲,根据这点之后触发也是脉冲触发。如下图,当异或后信号发生跳变,都会产生一个脉冲 TI1F_ED。
BLDC开发笔记3.霍尔接口与触发换相第2张

GPIO初始化

先在头文件进行宏定义

#define HALL_TIMx                        TIM3
#define HALL_TIM_APBxClock_FUN           RCC_APB1PeriphClockCmd
#define HALL_TIM_CLK                     RCC_APB1Periph_TIM3
#define HALL_TIM_PERIOD                  0xFFFF           //ARR,计数周期,配置为最大65535
#define HALL_TIM_PRESCALER               (72-1)           //预分频系数为72
#define HALL_TIM_Channel_x               TIM_Channel_1    //通道1

#define HALL_TIM_GPIO_REMAP              GPIO_FullRemap_TIM3  //引脚重映射
#define HALL_TIM_GPIO_CLK                RCC_APB2Periph_GPIOC
#define HALL_TIM_CH1_PIN                 GPIO_Pin_6
#define HALL_TIM_CH1_GPIO                GPIOC
#define HALL_TIM_CH2_PIN                 GPIO_Pin_7
#define HALL_TIM_CH2_GPIO                GPIOC
#define HALL_TIM_CH3_PIN                 GPIO_Pin_8
#define HALL_TIM_CH3_GPIO                GPIOC

#define HALL_TIM_IRQn                    TIM3_IRQn
#define HALL_TIM_IRQHANDLER              TIM3_IRQHandler

需要注意的是,时基编程中,要将TIMx_ARR置为其最大值(计数器必须通过TI1的变化清零)。设置预分频器得到
的最大计数器周期,它需要长于霍尔传感器上的两次变化的时间间隔,不然就会发生溢出,这里进行72分频后,计数器时钟是1Mhz,所以计数周期是1us*65535=65.535ms。

GPIO初始化配置

将定时器3的3个GPIO初始化,配置为上拉输入模式

void HALL_TIMx_GPIO_Init(void)
{
  //GPIO初始化结构体
  GPIO_InitTypeDef GPIO_InitStructure;
  
  //打开GPIOC和复用功能时钟
  RCC_APB2PeriphClockCmd(HALL_TIM_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE); 
  
  //GPIOC_6初始化
  GPIO_InitStructure.GPIO_Pin = HALL_TIM_CH1_PIN;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉输入
  GPIO_Init(HALL_TIM_CH1_GPIO, &GPIO_InitStructure);
  
  //GPIOC_7初始化
  GPIO_InitStructure.GPIO_Pin = HALL_TIM_CH2_PIN; 
  GPIO_Init(HALL_TIM_CH2_GPIO, &GPIO_InitStructure);
  
  //GPIOC_8初始化
  GPIO_InitStructure.GPIO_Pin = HALL_TIM_CH3_PIN; 
  GPIO_Init(HALL_TIM_CH3_GPIO, &GPIO_InitStructure);

  //引脚重映射
  GPIO_PinRemapConfig(HALL_TIM_GPIO_REMAP,ENABLE);  
}

霍尔接口配置

  1. 配置定时器3的时基
  2. 将定时器3配置为输入捕获模式,将IC1映射到TRC
  3. 从模式控制器配置为复位模式
  4. 使能触发中断
void HALL_TIMx_Configuration(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;  //时基初始化结构体
	TIM_ICInitTypeDef TIM_ICInitStruct;  //输入捕获初始化结构体
		
	//打开定时器3时钟
	HALL_TIM_APBxClock_FUN(HALL_TIM_CLK,ENABLE);
	//时基参数配置
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;  //时钟分割:TDTS = TCK_INT ,采样频率=72M
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_CenterAligned1;  //中心对齐模式
	TIM_TimeBaseInitStruct.TIM_Period=HALL_TIM_PERIOD;  //重装值,计数周期
	TIM_TimeBaseInitStruct.TIM_Prescaler=HALL_TIM_PRESCALER;  //预分频系数
	//时基初始化
	TIM_TimeBaseInit(HALL_TIMx,&TIM_TimeBaseInitStruct);
	
	//输入捕获通道1配置
	TIM_ICInitStruct.TIM_Channel=HALL_TIM_Channel_x;  //通道1
	TIM_ICInitStruct.TIM_ICFilter=0x00;  //滤波长度:0
	TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_BothEdge;  //上升沿和下降沿
	TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;  //配置输入信号分频,不分频
	TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_TRC;  //将IC1映射到 TRC上
	TIM_ICInit(HALL_TIMx,&TIM_ICInitStruct);  //输入捕获初始化
	
        //配置中断优先级
        HALL_IT_Configuration();  
	
	//使能Timx霍尔传感器接口,实际上就是完成将CH1、CH2和CH3异或输入
	TIM_SelectHallSensor(HALL_TIMx,ENABLE);  
	//输入触发源选择,选择TI1F_ED
	TIM_SelectInputTrigger(HALL_TIMx, TIM_TS_TI1F_ED);
	
	//从模式选择,复位模式
	TIM_SelectSlaveMode(HALL_TIMx, TIM_SlaveMode_Reset); 
	//主从模式选择
	TIM_SelectMasterSlaveMode(HALL_TIMx, TIM_MasterSlaveMode_Enable); 
	
	//允许触发中断
	TIM_ITConfig(HALL_TIMx, TIM_IT_Trigger, ENABLE); 
	
	//使能定时器
	TIM_Cmd(HALL_TIMx, ENABLE);
	
	//清除TIMx中断标志位
	TIM_ClearITPendingBit (HALL_TIMx,TIM_IT_Trigger);
	
}

其中,中断优先级配置函数为

void HALL_IT_Configuration(void)
{
    //NVIC初始化结构体
    NVIC_InitTypeDef NVIC_InitStruct;
  
    //中断优先级配置
    NVIC_InitStruct.NVIC_IRQChannel=HALL_TIM_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
    NVIC_Init(&NVIC_InitStruct);
}

中断优先级我将霍尔触发中断配置为最高级。

霍尔接口总初始化函数

就是调用我们前面写的两个配置函数。

void HALL_TIMx_Init(void)
{
    HALL_TIMx_GPIO_Init();
    HALL_TIMx_Configuration();	
}

中断服务函数

使能了中断,不要忘记编写中断服务函数,我习惯将其放在main.c里面,也看过放在 it.c里面

值得一提的是,通用定时器中断类型并不体现在中断服务函数名称上,通用定时器的中断服务函数名就只有一个,可以在启动文件里面轻易找到她,她是通过判断中断标志位,区分哪一种中断。

void HALL_TIM_IRQHANDLER(void)
{
  if(TIM_GetITStatus(TIM3,TIM_IT_Trigger)!=RESET)
  {
     HALL_TIMx_Callback();  //读取霍尔信号并换相
     TIM_ClearITPendingBit(TIM3,TIM_IT_Trigger);  //清除触发中断标志位
  }
}

需要提醒的是,这个中断服务函数里面一定不能有任何费时的操作,假设电机高速旋转,存在一个操作需要时间大于霍尔两个状态之间切换时间(在上一个PWM输出和惯性的影响下),那么存在漏步问题,电机将不按照顺序旋转下去,所以费时操作会影响下一个霍尔状态的读取,导致PWM输出不正确。

霍尔信号读取

可以看到,中断服务函数这里调用了函数 HALL_TIMx_Callback();她的作用是判断3个输入引脚上的电平,并将其合成霍尔组合信号,根据这个组合信号,当霍尔信号每一次变化,产生中断时,我们就可以按照霍尔换相表,调用在六步PWM输出里面写的换相函数BLDC_PHASE_CHANGE(pinstate);。

void HALL_TIMx_Callback(void)
{
	        uint8_t pinstate=0;
	
		if((HALL_TIM_CH1_GPIO->IDR & HALL_TIM_CH1_PIN) != (uint32_t)Bit_RESET)  //CH1状态获取
		{
			pinstate |= 0x01;
		}
		if((HALL_TIM_CH2_GPIO->IDR & HALL_TIM_CH2_PIN) != (uint32_t)Bit_RESET)  //CH2状态获取
		{
			pinstate |= 0x02;
		}
		if((HALL_TIM_CH3_GPIO->IDR & HALL_TIM_CH3_PIN) != (uint32_t)Bit_RESET)  //CH3状态获取
		{
			pinstate |= 0x04;
		}
	        //Usart_SendByte(pinstate);  //把霍尔换步信号发送到串口上,不测试时将其注释掉
	        BLDC_PHASE_CHANGE(pinstate); //调用换相函数 
}

开环波形测试

接上BLDC,我使用的是24V的鼓风机,将三相逆变电路板通电测试,通过示波器看其中两路波形(只有两路示波器)。

个人分析:可以看到,在切换通道时候出现了较高的反向电动势,但由于MOS管体二极管将其钳位在电源电压。

BLDC开发笔记3.霍尔接口与触发换相第3张

免责声明:文章转载自《BLDC开发笔记3.霍尔接口与触发换相》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Nmap 常用命令及抓包分析.NET Core:处理全局异常下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[STM32F103]PWM输入捕获配置

l 初始化定时器和通道对应IO的时钟。 l 初始化IO口,模式为输入:   GPIO_Init();       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入 l 初始化定时器ARR,PSC   TIM_TimeBaseInit(); l 初始化输入捕获通道   TIM_ICInit(); l...

BLDC开发笔记1.原理及硬件部分

最*有个项目用到了BLDC,正好我也对电机驱动很感兴趣。在这里整理一下学习笔记。 此笔记会持续更新。 BLDC工作原理 BLDC工作原理网上已经很多资料,这里不再详细累述,推荐鹏芃科艺的相关无刷直流永磁电动机工作原理(这是我见过最好的3D模型解剖):http://www.pengky.cn/yongciDJ/04-wushuaYCDDJ-YL11/wush...

BLDC开发笔记2.六步PWM输出

6步PWM互补输出 6步PWM输出是对 F103 的 TIM1 进行配置成PWM输出模式,带刹车和死区功能。按照模块化进行初始化配置。勾选keil中的C99标准(支持任意地方定义变量)。 GPIO初始化 打开相应功能模块时钟,将TIM1 的TIx引脚配置为复用推挽输出模式,BKIN(刹车)引脚配置为浮空输入模式。 通过在头文件进行宏定义配置,在硬件改变的时...

第五节:STM32输入捕获(用CubeMX学习STM32)

输入捕获学习 《用CubeMX学习STM32》 注释 点击上面蓝字进入完整专栏,这个系列所有文章都会整合到这个专栏 5、STM32定时器输入捕获 前言: STM32定时器输入捕获简介 STM32的输入捕获可以用于捕获脉宽, 测量时间 . 例如超声波测距模块就是需要用输入捕获功能, 通过测量输入脉冲的高电平脉宽 , 从而计算出测量物体的...

BLDC开发笔记4.转速的计算

以下结合自己的理解,如有错误请帮忙及时指正。 转速公式 转速的计算我现在是通过一定时间内,霍尔信号的边沿数量来计算的。这里每隔50ms在滴答定时器中断服务函数里面计算一次。霍尔信号每变化一次,就产生一次霍尔触发中断。因为我的电机是2对极,所以在一圈内有12个霍尔状态,即电机转动一圈会触发12次中断。假设在50ms内,霍尔触发了 n 次中断,我们可以得到转速...