打印
[DemoCode下载]

N76E003 控制开环无刷直流(BLDC)电机

[复制链接]
286|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wanduzi|  楼主 | 2024-2-25 19:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
EC_N76E003_Open_Loop_BLDC_Motor_V1.00 (3).zip (639.95 KB)
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* [url=home.php?mod=space&uid=247401]@brief[/url]    Open Loop BLDC Motor
*
* @note
* Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/

/*---------------------------------------------------------------------------------------------------------*/
/* Pin Functions                                                                                           */
/*---------------------------------------------------------------------------------------------------------*/
//P07 - HALL Sensor W Phase, HALL_W
//P06 - HALL Sensor V Phase, HALL_V
//P05 - HALL Sensor U Phase, HALL_U
//P12 - Upper-arm MOS control of U phase, uh
//P14 - Lower-arm MOS control of U phase, ul
//P10 - Upper-arm MOS control of V phase, vh
//P00 - Lower-arm MOS control of V phase, vl
//P01 - Upper-arm MOS control of W phase, wh
//P03 - Lower-arm MOS control of W phase, wl
//P15 - Motor on/off switch
//P02 - UART RX
//P16 - UART TX
//P17 - ADC input

/*---------------------------------------------------------------------------------------------------------*/
/* Include File                                                                                            */
/*---------------------------------------------------------------------------------------------------------*/
#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"

/*---------------------------------------------------------------------------------------------------------*/
/* Macro                                                                                                   */
/*---------------------------------------------------------------------------------------------------------*/

#define UART1_DEBUG 0

#define ABS(X) (X) >= 0 ? (X) : -(X)

#define TIMER0_VALUE 65536-13333  //10ms
#define MotorBoostDuty 0.15

#define HallSensorPhase1 (0x05<<5)
#define HallSensorPhase2 (0x01<<5)
#define HallSensorPhase3 (0x03<<5)
#define HallSensorPhase4 (0x02<<5)
#define HallSensorPhase5 (0x06<<5)
#define HallSensorPhase6 (0x04<<5)

#define ADC_CONVERT_FINISH 1
#define MOTOR_ON_OFF_SWITCH P15
#define MOTOR_OFF 0

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
unsigned char data g_u8HallSensorMotorPhaseState = 0;
unsigned char data g_u8TimerIntCount;
unsigned char data g_u8TH0_Tmp, g_u8TL0_Tmp;
unsigned short data g_u16CurrentSpeed = 0;

/*---------------------------------------------------------------------------------------------------------*/
/* Functions                                                                                               */
/*---------------------------------------------------------------------------------------------------------*/

void CheckMotorPhaseByHallSensor(unsigned char HallSensorInput)
{
    switch (HallSensorInput)
    {
        case HallSensorPhase1:
        {
            g_u8HallSensorMotorPhaseState = 1;
            break;
        }
        case HallSensorPhase2:
        {
            g_u8HallSensorMotorPhaseState = 2;
            break;
        }
        case HallSensorPhase3:
        {
            g_u8HallSensorMotorPhaseState = 3;
            break;
        }
        case HallSensorPhase4:
        {
            g_u8HallSensorMotorPhaseState = 4;
            break;
        }
        case HallSensorPhase5:
        {
            g_u8HallSensorMotorPhaseState = 5;
            break;
        }
        case HallSensorPhase6:
        {
            g_u8HallSensorMotorPhaseState = 6;
            break;
        }
    }
}

void ChangeMotorPhaseClockwise(void)
{
    /* Change motor phase to next phase. */
    switch (g_u8HallSensorMotorPhaseState)
    {
        case 1:
        {
            PMEN = 0xfe; //uh
            PMD = 0x20; //wl
            break;
        }
        case 2:
        {
            PMEN = 0xfb; //vh
            PMD = 0x20; //wl
            break;
        }
        case 3:
        {
            PMEN = 0xfb; //vh
            PMD = 0x02; //ul
            break;
        }
        case 4:
        {
            PMEN = 0xef; //wh
            PMD = 0x02; //ul
            break;
        }
        case 5:
        {
            PMEN = 0xef; //wh
            PMD = 0x08; //vl
            break;
        }
        case 6:
        {
            PMEN = 0xfe; //uh
            PMD = 0x08; //vl
            break;
        }
    }
}

void ChangeMotorPhaseCounterClockwise(void)
{
    /* Change motor phase to next phase. */
    switch (g_u8HallSensorMotorPhaseState)
    {
        case 6:
        {
            PMEN = 0xfe; //uh
            PMD = 0x20; //wl
            break;
        }
        case 5:
        {
            PMEN = 0xfb; //vh
            PMD = 0x20; //wl
            break;
        }
        case 4:
        {
            PMEN = 0xfb; //vh
            PMD = 0x02; //ul
            break;
        }
        case 3:
        {
            PMEN = 0xef; //wh
            PMD = 0x02; //ul
            break;
        }
        case 2:
        {
            PMEN = 0xef; //wh
            PMD = 0x08; //vl
            break;
        }
        case 1:
        {
            PMEN = 0xfe; //uh
            PMD = 0x08; //vl
            break;
        }
    }
}

void InitPWM(unsigned short *u16PWMDutyValue, unsigned char *u8OldMotorPhaseState)
{
    /* Initialize the pwm mode and clock. */
    PWM_GP_MODE_ENABLE;
    PWM_SYNCHRONIZED_MODE;
    PWM_CLOCK_FSYS;
    PWMPH = 0x01;
    PWMPL = 0xF3;
    /*----------------------------------------------------------------------
        PWM frequency = Fpwm/((PWMPH,PWMPL) + 1), Fpwm = Fsys/PWM_CLOCK_DIV
                      = (16MHz)/(0x1F3 + 1)
                      = 32KHz (0.03125 ms)
    ----------------------------------------------------------------------*/
    /* Set PWM duty value on motor boost. */
    *u16PWMDutyValue = 0x1F3 * MotorBoostDuty;
   
    /* Initialize the pwm value */
    PWM0H = HIBYTE(*u16PWMDutyValue);
    PWM0L = LOBYTE(*u16PWMDutyValue);

    /* Initialize the Motor phase parameter */
    *u8OldMotorPhaseState = 0xFF;
    CheckMotorPhaseByHallSensor((P0 & 0xE0));

    /* Initialize the pwm pin mode and close whole MOS. */
    PMEN = 0xff;
    PMD = 0x00;
}

void InitGPIO(void)
{
    Set_All_GPIO_Quasi_Mode;
    P05_Input_Mode;
    P06_Input_Mode;
    P07_Input_Mode;
    P15_Input_Mode;
    P04_PushPull_Mode;
    P12_PushPull_Mode;
    P14_PushPull_Mode;
    P10_PushPull_Mode;
    P00_PushPull_Mode;
    P01_PushPull_Mode;
    P03_PushPull_Mode;
    PWM0_P12_OUTPUT_ENABLE; /* P12 - Upper-arm MOS control of U phase, uh */
    PWM1_P14_OUTPUT_ENABLE; /* P14 - Lower-arm MOS control of U phase, ul */
    PWM2_P10_OUTPUT_ENABLE; /* P10 - Upper-arm MOS control of V phase, vh */
    PWM3_P00_OUTPUT_ENABLE; /* P00 - Lower-arm MOS control of V phase, vl */
    PWM4_P01_OUTPUT_ENABLE; /* P01 - Upper-arm MOS control of W phase, wh */
    PWM5_P03_OUTPUT_ENABLE; /* P03 - Lower-arm MOS control of W phase, wl */
    Enable_ADC_AIN0; /* ADC input */

    PICON = 0xFC;   /* PORT 0 interrupt (Pin int control) */
    PINEN = 0XE0;   /* Generates the pin interrupt when falling edge trigger */
    PIPEN = 0XE0;   /* Generates the pin interrupt when rising edge trigger */
    set_EPI;        /* Enable pin interrupt */
    set_EX0;        /* Enable external interrupt */
}

void InitTimer0(void)
{
    clr_T0M;        /* T0M=0, Timer0 Clock = Fsys/12 */
    TMOD |= 0x01;   /* Timer0 is 16-bit mode */
   
    /* Calculate the timer counter value for controlling the interrupt period on 10ms. */
    g_u8TH0_Tmp = HIBYTE(TIMER0_VALUE);
    g_u8TL0_Tmp = LOBYTE(TIMER0_VALUE);

    /* Sets the timer counter value for controlling the interrupt period. The period is setting on 10ms. */
    TH0 = g_u8TH0_Tmp;
    TL0 = g_u8TL0_Tmp;

    set_ET0;        /* enable Timer0 interrupt */
    set_TR0;        /* Timer0 start */
}

unsigned int GetTargetSpeed(void)
{
    unsigned int data s16TargetSpeed;
    /* ADC will sample the variable resistor value on ADCRH. */
    /* Calculate the percentage of Max rotate speed 4500 rpm to target speed. */
    s16TargetSpeed = (((unsigned long int)4500 * (unsigned long int)ADCRH) / 255);

    /* Set the upper bound and lower bound on 450 and 4500 rpm. */
    if (s16TargetSpeed < 450) s16TargetSpeed = 450;
    if (s16TargetSpeed > 4500) s16TargetSpeed = 4500;

    /* Clear ADN interrupt flag and re-trigger ADC to convert. */
    clr_ADCF;
    set_ADCS;
    return s16TargetSpeed;
}

void main(void)
{
    int data s16SpeedDiff = 0;
    unsigned int data s16TargetSpeed = 0;
    unsigned char data u8TimerCntForUART;
    unsigned char data u8OldMotorPhaseState;
    unsigned short data u16PWMDutyValue;
    int data temp;
    InitGPIO();
   
#ifdef UART1_DEBUG
    /* Initialize UART1 for Debug */
    u8TimerCntForUART = 0;
    InitialUART1_Timer3(115200);
#endif
   
    /* Initial PWM for controlling the 3 phase of motor */
    InitPWM(&u16PWMDutyValue, &u8OldMotorPhaseState);
    /* Initial Timer 0 for interrupt per 10 ms */
    InitTimer0();

    /* Reset timer and check the motor phase */
    CheckMotorPhaseByHallSensor((P0 & 0xE0));

    /* Clear ADC Flag and Reset Timer interrupt cnt */
    clr_ADCF;
    g_u8TimerIntCount = 0;
   
    /* Enable all interrupts */
    set_EA;
   
    /* Start the ADC and PWM */
    set_ADCS;
    set_LOAD;
    set_PWMRUN;

    while (1)
    {
        /* Get Motor realtime speed by ADC */
        if (ADCF == ADC_CONVERT_FINISH)
        {
            s16TargetSpeed = GetTargetSpeed();
        }

        if (MOTOR_ON_OFF_SWITCH == MOTOR_OFF)
        {
            /* Stop the motor */
            clr_PWMRUN;
            PMEN = 0xff;
            PMD = 0x00;

            /* If the on/off switch is keeping in off state, stay on this while loop. */
            while (MOTOR_ON_OFF_SWITCH == MOTOR_OFF);

            /* Motor on/off switch is switching to on, re-initial the pwm for starting rotate. */
            
            /* Set PWM duty value on motor boost. */
            u16PWMDutyValue = 0x1F3 * MotorBoostDuty;
            
            /* Initialize the pwm value */
            PWM0H = HIBYTE(u16PWMDutyValue);
            PWM0L = LOBYTE(u16PWMDutyValue);
            
            /* Initialize the Motor phase parameter */
            u8OldMotorPhaseState = 0xFF;
            CheckMotorPhaseByHallSensor((P0 & 0xE0));
            
            /* Start the PWM */
            set_LOAD;
            set_PWMRUN;
            
            /* Clear the Timer interrupt cnt */
            g_u8TimerIntCount = 0;
        }
        else if (g_u8TimerIntCount >= 1) /* if the time past x * 10ms( x = 1 ), entering this if. */
        {
            /* Reset the timer interrupt times counter */
            g_u8TimerIntCount = 0;

#ifdef UART1_DEBUG
            /* Print the speed of motor */
            u8TimerCntForUART++;
            if (u8TimerCntForUART >= 30)   //Per 300ms send UART data
            {
                Send_Data_To_UART1(s16TargetSpeed);
                u8TimerCntForUART = 0;
            }
#endif
            
            /* Modified the PWM duty for tracing the target speed */
            temp = ((((signed long int)0x1F3 * (signed long int)s16TargetSpeed)) / (signed long int)4500);
            u16PWMDutyValue += (( temp > u16PWMDutyValue) ? 1 : (-1));

            /* Set new PWM duty */
            PWM0H = HIBYTE(u16PWMDutyValue);
            PWM0L = LOBYTE(u16PWMDutyValue);
            set_LOAD;
        }

        /* Change the Motor phase */
        if (u8OldMotorPhaseState != g_u8HallSensorMotorPhaseState)
        {
            /* Record the last motor phase */
            u8OldMotorPhaseState = g_u8HallSensorMotorPhaseState;
            /* Change the motor phase */
            ChangeMotorPhaseClockwise();
        }
    }
}
/*---------------------------------------------------------------------------------------------------------*/
/* Interrupt                                                                                               */
/*---------------------------------------------------------------------------------------------------------*/

void PinInterrupt_ISR(void) interrupt 7
{
    /* Detecting the motor phase by hall sensor. */
    CheckMotorPhaseByHallSensor(P0 & 0xe0);
    /* Clear the Pin interrupt flag. */
    PIF = 0x00;
}

void Timer0_ISR(void) interrupt 1
{
    /* Sets the timer counter value for controlling the interrupt period. The period is setting on 10ms. */
    TH0 = g_u8TH0_Tmp;
    TL0 = g_u8TL0_Tmp;
    /* Recorded the interrupt times. */
    g_u8TimerIntCount++;
}

/*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/


使用特权

评论回复
沙发
wanduzi|  楼主 | 2024-2-25 19:52 | 只看该作者
这段代码是用于控制开环无刷直流(BLDC)电机的,采用了 N76E003 微控制器。让我们逐步解析代码的主要组成部分和功能:

引脚功能:描述了微控制器各引脚的功能,包括连接到霍尔传感器、用于电机控制的MOSFET、用于调试的UART,以及用于传感的ADC输入等。

包含文件:N76E003 微控制器的标准包含文件。

宏:定义了代码中使用的各种常量和宏,如UART1_DEBUG、ABS(X)、TIMER0_VALUE等。

全局变量:声明了代码中使用的全局变量,包括电机相位状态、定时器中断计数、当前速度等。

函数:

CheckMotorPhaseByHallSensor:根据霍尔传感器的输入确定电机的相位。
ChangeMotorPhaseClockwise 和 ChangeMotorPhaseCounterClockwise:根据当前电机相位状态更改电机相位。
InitPWM:初始化 PWM(脉冲宽度调制)用于控制电机相位。
InitGPIO:初始化 GPIO(通用输入输出)引脚。
InitTimer0:初始化定时器0,用于每10毫秒生成中断。
GetTargetSpeed:根据 ADC 读数计算电机的目标速度。
main:主函数,其中实现了电机控制逻辑。它根据 ADC 读数和霍尔传感器检测到的电机相位变化不断调整电机速度。
中断服务子程序(ISR):

PinInterrupt_ISR:用于处理引脚中断的中断服务子程序,特别是用于通过霍尔传感器检测电机相位变化。
Timer0_ISR:用于定时操作和每10毫秒生成中断的定时器0的中断服务子程序。
总的来说,这段代码设置了微控制器以控制开环无刷直流电机。它从 ADC 输入读取电机速度,根据需要调整 PWM 占空比以维持所需速度,并根据霍尔传感器的信号更改电机相位。另外,如果启用了,它还包括通过UART1进行调试的功能

使用特权

评论回复
板凳
jiekou001| | 2024-2-26 17:19 | 只看该作者
开环控制无法实现速度设定吧

使用特权

评论回复
地板
捉虫天师| | 2024-2-27 22:08 | 只看该作者
开环一般用于什么场景呢?

使用特权

评论回复
5
xinxianshi| | 2024-2-27 22:52 | 只看该作者
MCU是连接什么元件来驱动电机呢?

使用特权

评论回复
6
xinxianshi| | 2024-2-27 22:52 | 只看该作者
可以实现调速控制吗?

使用特权

评论回复
7
天灵灵地灵灵| | 2024-2-28 15:25 | 只看该作者
这种代码看着有点难懂。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

129

主题

1655

帖子

3

粉丝