打印
[DemoCode下载]

N76E003驱动无刷直流电机

[复制链接]
1059|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
捉虫天师|  楼主 | 2022-12-23 16:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [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. ***/
EC_N76E003_Open_Loop_BLDC_Motor_V1.00.zip (639.95 KB)

使用特权

评论回复
沙发
捉虫天师|  楼主 | 2022-12-23 17:00 | 只看该作者
本方案使用 NuMicro® N76E003 作为系统主芯片,搭配新唐 NCT3605 闸级驱动器实现闭回路控制的直流无刷马达 ( Brushless DC, BLDC ) 系统。 直流无刷马达控制方案采用 N76E003 微控制器作为主控芯片,透过 6 信道的 PWM 功能,产生三个相位 ( U, V, W ) 的占空比讯号至闸极驱动器,再透过闸级驱动器控制 MOS 以驱动马达旋转。系统会先使用 ADC 采样可变电阻的电压决定目标转速,再经由马达内部的传感器回授霍尔讯号计算实际转速,透过闭回路控制的回授补偿,即使负载大小改变也能快速修正回目标转速。 N76E003 是基于 1T 高效能 8051 核心的 8 位微控制器,最高速度可运行至 16 MHz,2.4V 至 5.5V宽电压范围输入,不须外挂 LDO 。N76E003 内建 18 K 字节 Flash ( APROM 及 LDROM 共享,LDROM 最大可设定至 4 K字节 ) 、256 字节 RAM 以及 768 字节 XRAM。N76E003 具有丰富外设,4 组 16 位 Timer、看门狗定时器 ( WDT ) 、唤醒定时器 ( WKT ) 、2 组 UART、 1 组 SPI 、 1 组 I²C 、3 组互补双通道 / 6 组单通道输出 PWM 以及 8 组 12 位的 ADC。 方案特色 NuMicro® 1T 8051 系列微控制器,最高可运行至 16 MHz 2.4V 至 5.5V 宽电压范围输入,不须外挂 LDO 支持 6 组单通道 / 3 组互补模式 PWM,控制三相马达 支持 8 组 12 位 ADC,提供高精度的可变电阻电压采样 闭回路控制系统,在外部负载大小改变时能够自动修正回目标转速 闸级驱动器 NCT3605 具有保护功能,能够防止 MOS 上下臂同时导通 相关IC N76E003 新唐直流无刷马达控制方案 ( Brushless DC, BLDC )

使用特权

评论回复
板凳
huangcunxiake| | 2022-12-25 18:11 | 只看该作者
值得学习,准备弄一套玩玩。

使用特权

评论回复
地板
小灵通2018| | 2022-12-26 11:31 | 只看该作者
外部电路怎么实现

使用特权

评论回复
5
小灵通2018| | 2022-12-26 11:32 | 只看该作者
是用电桥还是用啥

使用特权

评论回复
6
OKAKAKO| | 2022-12-26 14:41 | 只看该作者
楼主有详细的电气原理图分享一下嘛?

使用特权

评论回复
7
AdaMaYun| | 2022-12-27 09:27 | 只看该作者
叙述很详细,电路部分可以再说说嘛

使用特权

评论回复
8
huyi9898| | 2023-5-25 15:41 | 只看该作者
里面那一个语句定义了霍尔对应单片机的引脚号

使用特权

评论回复
9
huyi9898| | 2023-6-19 12:16 | 只看该作者
要是修改霍尔的引脚在哪里修改?有哪位看得懂指点一下

使用特权

评论回复
10
飞鼠智能| | 2023-10-19 22:40 | 只看该作者
楼主,我想知道,怎样实现反转?

使用特权

评论回复
11
飞鼠智能| | 2023-10-20 19:47 | 只看该作者
修改了替换了程序里的一句函数,还要对调两条霍尔线才将电机反转。这不是正确的方式。应用中需要正反转。求师傅指点。

使用特权

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

本版积分规则

196

主题

3127

帖子

7

粉丝