×
单片机 > 单片机程序设计 > 详情

STM32驱动直流电机的程序与电路设计

发布时间:2020-06-09 发布时间:
|

本文介绍如何使用STM32F103单片机,通过官方固件库,设置高级定时器TIM1输出嵌入死区的互补PWM,来驱动直流电机的程序设计与电路设计。硬件电路采用IR2110S芯片作为mos管的驱动,驱动IRF840组成的H桥。IR2110S芯片使用中,有一个比较难理解的点——自举电容,本文对其原理也有涉及。

原理图文件

上图是系统的简化原理图,左侧是单片机。中间是IR2110S芯片,为了方便讲解,把芯片内部结构列出一些。右侧是MOS管组成的H桥。其中M是直流电机,有正反转。其中VCC是15V,MOTOR_VCC是24V,电压可以改变,最大不超过500V。单片机一般是3.3V或5V,无法直接驱动电机。可以借助H桥来实现对直流电机的控制。

H桥由于形似H得名。

VT1,VT4导通,电机正转

VT2,VT3导通,电机翻转

VT1,VT3导通,短路,板子烧坏

VT2,VT4,导通短路。

所以,驱动电机的问题就变成了MOS管导通的问题。

实际电路中我选用了IRF840,这是N沟道的MOS管。N-MOS导通的条件:VGS大于一定值

对于IRF840,VGS>10V

所以MOS管导通的问题就变成了VGS>10V的问题


如果,VT1与VT3都独立配置一个电源,独立配置一套驱动,导通问题就变得简单了。但是,电路设计会变得复杂。

我们使用1个驱动芯片IR2110S,一路驱动电源。

简单介绍下IR2110S芯片

IR2110是独立一桥臂双通道,栅极驱动,高压,高速单片机专用功率器件集成驱动电路。2片IR2110就能构成H桥驱动电路。

IR2110S是3.3V版本

感兴趣的可以自己来做个阅读理解。

简单来说,IR2110是个3.3V控制10-20V的一个驱动。开关速度也很快,120ns

内部结构

右上角的两个MOS管,中间是非门连接,不会同时导通。

中间一系列怎么变化,我也不是很清楚。

HIN是1,VM1导通,VM2截止。VB与HO连在一起

HIN是0,VM1截止,VM2导通。VS与HO连在一起

LIN是1,VM3导通,VM4截止。VCC与LO连在一起

LIN是0,VM3截止,VM4导通。LO与COM连在一起

先看下桥臂。左侧下桥臂导通,很简单:

LIN为高,VM3导通,VCC接在LO上(暂时忽略二极管压降),VGS= VCC,导通


上桥臂导通的情况,先假设没有电容。

VM1导通时,VCC接在HO上,为G极提供了接近15V的电压。但是,VS的电压是多少?不知道。

如果,VT3导通,VS就是0,VT1也导通了,烧坏。

如果VT4导通,VS通过电机接地(电机内部可以先等效为电阻)。但是VT1导通以后,VS接近24V,HO只有15V,VT1又截止了。电机还是不能工作。

我们面临的问题是,上桥臂没有地。怎么办?

这个时候,就需要自举电容。

VT4导通,VS接地。电容一端是地,一端是15V,所以VCC通过D给C充电。

又因为VM1导通,所以C横跨在GS上。所以,C可以作为电压源,为GS供电。这是一个悬浮的电压源。

VT1导通后,VS接近24V,不再是地。所以VCC15无法为G提供足够的电压。

自举电容可以放电维持VT1工作,电容存有15V的电,可以保持MOS管的导通。由于电容两极的压差不能突变,而电容下边变成了对地24V(暂不考虑MOS管压降),所以这一瞬间,电容上边的电压是对地39V。这时,VCC无法为电容充电。由于二极管的存在,电容的电不会倒灌给VCC。

电容电量又是有限的,放电会导致电容的电压降低。等到两级压差不到10V的时候,VT1又不工作了。并且,此时IR2110芯片内部的欠压检测逻辑就会工作,把HO拉到VS,让VGS=0。

所以,自举电容电压小于10V之前,要充电。如果HIN一直是高电平,电容就没有充电的机会,等到自举电容的的电压跌落到某个阈值以下,HO就变为低电平。

此时可以关掉VT1,也就是断开VM1,VB与HO断开,不论是VCC还是电容都不再为G极提供电源。如果此时打开VT3,让VS接地,则电容一边是高电平,一边是低电平,开始充电。然后再断开VT3,打开VM1,VT4保持不变,让电容放电维持VT1导通,就可以循环往复,保持电机运行。

即,VT1的导通要依靠电容放电来维持。HIN不能为持续的高电平,占空比也不能达到100,或低频的PWM(频率低,一个周期内放电时间长)。必须是高频的PWM,保证自举电容有周期性的,足够的充电时间,才能维持较高的悬浮电源电压。

除此之外,还要注意死区问题,由于绝对不可以把同侧桥臂的上下半桥同时打开,而IR2110S,MOS管与电机切换状态都存在延时,导致从程序命令某半桥关断,到实际关断,有一段时间的延迟。例如,在延迟期间,上半桥正在关闭,下半桥暂时还不能打开,直到上半桥完全关闭,下半桥才能打开。中间等待的这段时间,就是死区。死区时间与硬件密切相关。笔者手上就有两个不同型号的电机,一个在3us的死区时可以工作,另一个则不可以。

所以,写程序要注意到上下桥不能同时导通,高频,不能是100的占空比,以及死区这几个问题。接下来尝试用STM32的高级定时器,输出嵌入死区的互补PWM。

以下是定时器1的初始化代码,使用两个通道输出PWM,一个周期是100us,频率是10KHz,3us的死区时间。默认通道一的占空比是50%,通道2的占空比是0%,让电机以47%(占空比减去死区)的速度正转。

通道2输出占空比是0,可以让右侧上半桥总是截止,下半桥总是导通。下半桥没有自举电容。如此一来,只需要左侧上半桥导通,就可以让电机正转。控制左侧桥臂的占空比,就能控制电机的占空比。

定时器1的通道1引脚是PA8PB13,通道2的输出引脚是PA9PB14。


void PWM_Configuration(void)

{

    GPIO_InitTypeDef    GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    //开启TIM和相应端口时钟

    //启动GPIO

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_GPIOB,

                     ENABLE);

    //启动AFIO

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    //启动TIM1

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);


    //GPIO做相应设置,为AF输出             //PA8,PB13一组互补输出  A9,PB14一组互补输出

    //PA.8/9口设置为TIM1的OC1输出口

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //PB.13/14口设置为TIM1_CH1N和TIM1_CH2N输出口

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_SetBits(GPIOA, GPIO_Pin_8 | GPIO_Pin_9);

    GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14);


    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    

    NVIC_InitStructure.NVIC_IRQChannel =  TIM1_UP_IRQn;    

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;       

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

    NVIC_Init(&NVIC_InitStructure);


    //TIM1基本计数器设置(设置PWM频率)10KHz 

    TIM_BaseInitStructure.TIM_Period = 100-1;      //10khz  好计算。按照1%的精确度,理论最大72000/100 = 720KHz

    TIM_BaseInitStructure.TIM_Prescaler = 72-1;

    TIM_BaseInitStructure.TIM_ClockDivision = 0;

    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数

    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);

    //启用ARR的影子寄存器(直到产生更新事件才更改设置)

    TIM_ARRPreloadConfig(TIM1, ENABLE);


    //TIM1_OC1模块设置(设置1通道占空比)

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//TIM脉冲宽度调制模式1

    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_OCNPolarity_High;//TIM输出比较极性高

    //TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;

    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

    TIM_OCInitStructure.TIM_Pulse = 50;//待装入捕获比较寄存器的脉冲值

    TIM_OC1Init(TIM1, &TIM_OCInitStructure);


    //启用CCR1寄存器的影子寄存器(直到产生更新事件才更改设置)

    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);


    

    //TIM1_OC2模块设置(设置2通道占空比)

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

    TIM_OCInitStructure.TIM_Pulse = 0;

关键字:STM32驱动  直流电机  自举电路  H桥  高级定时器  死区PWM 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计