[DemoCode下载] N76E003 控制开环无刷直流(BLDC)电机

[复制链接]
1945|7
 楼主| wanduzi 发表于 2024-2-25 19:52 | 显示全部楼层 |阅读模式
EC_N76E003_Open_Loop_BLDC_Motor_V1.00 (3).zip (639.95 KB, 下载次数: 42)
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]    Open Loop BLDC Motor
  5. *
  6. * @note
  7. * Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/

  9. /*---------------------------------------------------------------------------------------------------------*/
  10. /* Pin Functions                                                                                           */
  11. /*---------------------------------------------------------------------------------------------------------*/
  12. //P07 - HALL Sensor W Phase, HALL_W
  13. //P06 - HALL Sensor V Phase, HALL_V
  14. //P05 - HALL Sensor U Phase, HALL_U
  15. //P12 - Upper-arm MOS control of U phase, uh
  16. //P14 - Lower-arm MOS control of U phase, ul
  17. //P10 - Upper-arm MOS control of V phase, vh
  18. //P00 - Lower-arm MOS control of V phase, vl
  19. //P01 - Upper-arm MOS control of W phase, wh
  20. //P03 - Lower-arm MOS control of W phase, wl
  21. //P15 - Motor on/off switch
  22. //P02 - UART RX
  23. //P16 - UART TX
  24. //P17 - ADC input

  25. /*---------------------------------------------------------------------------------------------------------*/
  26. /* Include File                                                                                            */
  27. /*---------------------------------------------------------------------------------------------------------*/
  28. #include "N76E003.h"
  29. #include "Common.h"
  30. #include "Delay.h"
  31. #include "SFR_Macro.h"
  32. #include "Function_define.h"

  33. /*---------------------------------------------------------------------------------------------------------*/
  34. /* Macro                                                                                                   */
  35. /*---------------------------------------------------------------------------------------------------------*/

  36. #define UART1_DEBUG 0

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

  38. #define TIMER0_VALUE 65536-13333  //10ms
  39. #define MotorBoostDuty 0.15

  40. #define HallSensorPhase1 (0x05<<5)
  41. #define HallSensorPhase2 (0x01<<5)
  42. #define HallSensorPhase3 (0x03<<5)
  43. #define HallSensorPhase4 (0x02<<5)
  44. #define HallSensorPhase5 (0x06<<5)
  45. #define HallSensorPhase6 (0x04<<5)

  46. #define ADC_CONVERT_FINISH 1
  47. #define MOTOR_ON_OFF_SWITCH P15
  48. #define MOTOR_OFF 0

  49. /*---------------------------------------------------------------------------------------------------------*/
  50. /* Global variables                                                                                        */
  51. /*---------------------------------------------------------------------------------------------------------*/
  52. unsigned char data g_u8HallSensorMotorPhaseState = 0;
  53. unsigned char data g_u8TimerIntCount;
  54. unsigned char data g_u8TH0_Tmp, g_u8TL0_Tmp;
  55. unsigned short data g_u16CurrentSpeed = 0;

  56. /*---------------------------------------------------------------------------------------------------------*/
  57. /* Functions                                                                                               */
  58. /*---------------------------------------------------------------------------------------------------------*/

  59. void CheckMotorPhaseByHallSensor(unsigned char HallSensorInput)
  60. {
  61.     switch (HallSensorInput)
  62.     {
  63.         case HallSensorPhase1:
  64.         {
  65.             g_u8HallSensorMotorPhaseState = 1;
  66.             break;
  67.         }
  68.         case HallSensorPhase2:
  69.         {
  70.             g_u8HallSensorMotorPhaseState = 2;
  71.             break;
  72.         }
  73.         case HallSensorPhase3:
  74.         {
  75.             g_u8HallSensorMotorPhaseState = 3;
  76.             break;
  77.         }
  78.         case HallSensorPhase4:
  79.         {
  80.             g_u8HallSensorMotorPhaseState = 4;
  81.             break;
  82.         }
  83.         case HallSensorPhase5:
  84.         {
  85.             g_u8HallSensorMotorPhaseState = 5;
  86.             break;
  87.         }
  88.         case HallSensorPhase6:
  89.         {
  90.             g_u8HallSensorMotorPhaseState = 6;
  91.             break;
  92.         }
  93.     }
  94. }

  95. void ChangeMotorPhaseClockwise(void)
  96. {
  97.     /* Change motor phase to next phase. */
  98.     switch (g_u8HallSensorMotorPhaseState)
  99.     {
  100.         case 1:
  101.         {
  102.             PMEN = 0xfe; //uh
  103.             PMD = 0x20; //wl
  104.             break;
  105.         }
  106.         case 2:
  107.         {
  108.             PMEN = 0xfb; //vh
  109.             PMD = 0x20; //wl
  110.             break;
  111.         }
  112.         case 3:
  113.         {
  114.             PMEN = 0xfb; //vh
  115.             PMD = 0x02; //ul
  116.             break;
  117.         }
  118.         case 4:
  119.         {
  120.             PMEN = 0xef; //wh
  121.             PMD = 0x02; //ul
  122.             break;
  123.         }
  124.         case 5:
  125.         {
  126.             PMEN = 0xef; //wh
  127.             PMD = 0x08; //vl
  128.             break;
  129.         }
  130.         case 6:
  131.         {
  132.             PMEN = 0xfe; //uh
  133.             PMD = 0x08; //vl
  134.             break;
  135.         }
  136.     }
  137. }

  138. void ChangeMotorPhaseCounterClockwise(void)
  139. {
  140.     /* Change motor phase to next phase. */
  141.     switch (g_u8HallSensorMotorPhaseState)
  142.     {
  143.         case 6:
  144.         {
  145.             PMEN = 0xfe; //uh
  146.             PMD = 0x20; //wl
  147.             break;
  148.         }
  149.         case 5:
  150.         {
  151.             PMEN = 0xfb; //vh
  152.             PMD = 0x20; //wl
  153.             break;
  154.         }
  155.         case 4:
  156.         {
  157.             PMEN = 0xfb; //vh
  158.             PMD = 0x02; //ul
  159.             break;
  160.         }
  161.         case 3:
  162.         {
  163.             PMEN = 0xef; //wh
  164.             PMD = 0x02; //ul
  165.             break;
  166.         }
  167.         case 2:
  168.         {
  169.             PMEN = 0xef; //wh
  170.             PMD = 0x08; //vl
  171.             break;
  172.         }
  173.         case 1:
  174.         {
  175.             PMEN = 0xfe; //uh
  176.             PMD = 0x08; //vl
  177.             break;
  178.         }
  179.     }
  180. }

  181. void InitPWM(unsigned short *u16PWMDutyValue, unsigned char *u8OldMotorPhaseState)
  182. {
  183.     /* Initialize the pwm mode and clock. */
  184.     PWM_GP_MODE_ENABLE;
  185.     PWM_SYNCHRONIZED_MODE;
  186.     PWM_CLOCK_FSYS;
  187.     PWMPH = 0x01;
  188.     PWMPL = 0xF3;
  189.     /*----------------------------------------------------------------------
  190.         PWM frequency = Fpwm/((PWMPH,PWMPL) + 1), Fpwm = Fsys/PWM_CLOCK_DIV
  191.                       = (16MHz)/(0x1F3 + 1)
  192.                       = 32KHz (0.03125 ms)
  193.     ----------------------------------------------------------------------*/
  194.     /* Set PWM duty value on motor boost. */
  195.     *u16PWMDutyValue = 0x1F3 * MotorBoostDuty;
  196.    
  197.     /* Initialize the pwm value */
  198.     PWM0H = HIBYTE(*u16PWMDutyValue);
  199.     PWM0L = LOBYTE(*u16PWMDutyValue);

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

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

  207. void InitGPIO(void)
  208. {
  209.     Set_All_GPIO_Quasi_Mode;
  210.     P05_Input_Mode;
  211.     P06_Input_Mode;
  212.     P07_Input_Mode;
  213.     P15_Input_Mode;
  214.     P04_PushPull_Mode;
  215.     P12_PushPull_Mode;
  216.     P14_PushPull_Mode;
  217.     P10_PushPull_Mode;
  218.     P00_PushPull_Mode;
  219.     P01_PushPull_Mode;
  220.     P03_PushPull_Mode;
  221.     PWM0_P12_OUTPUT_ENABLE; /* P12 - Upper-arm MOS control of U phase, uh */
  222.     PWM1_P14_OUTPUT_ENABLE; /* P14 - Lower-arm MOS control of U phase, ul */
  223.     PWM2_P10_OUTPUT_ENABLE; /* P10 - Upper-arm MOS control of V phase, vh */
  224.     PWM3_P00_OUTPUT_ENABLE; /* P00 - Lower-arm MOS control of V phase, vl */
  225.     PWM4_P01_OUTPUT_ENABLE; /* P01 - Upper-arm MOS control of W phase, wh */
  226.     PWM5_P03_OUTPUT_ENABLE; /* P03 - Lower-arm MOS control of W phase, wl */
  227.     Enable_ADC_AIN0; /* ADC input */

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

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

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

  245.     set_ET0;        /* enable Timer0 interrupt */
  246.     set_TR0;        /* Timer0 start */
  247. }

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

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

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

  262. void main(void)
  263. {
  264.     int data s16SpeedDiff = 0;
  265.     unsigned int data s16TargetSpeed = 0;
  266.     unsigned char data u8TimerCntForUART;
  267.     unsigned char data u8OldMotorPhaseState;
  268.     unsigned short data u16PWMDutyValue;
  269.     int data temp;
  270.     InitGPIO();
  271.    
  272. #ifdef UART1_DEBUG
  273.     /* Initialize UART1 for Debug */
  274.     u8TimerCntForUART = 0;
  275.     InitialUART1_Timer3(115200);
  276. #endif
  277.    
  278.     /* Initial PWM for controlling the 3 phase of motor */
  279.     InitPWM(&u16PWMDutyValue, &u8OldMotorPhaseState);
  280.     /* Initial Timer 0 for interrupt per 10 ms */
  281.     InitTimer0();

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

  284.     /* Clear ADC Flag and Reset Timer interrupt cnt */
  285.     clr_ADCF;
  286.     g_u8TimerIntCount = 0;
  287.    
  288.     /* Enable all interrupts */
  289.     set_EA;
  290.    
  291.     /* Start the ADC and PWM */
  292.     set_ADCS;
  293.     set_LOAD;
  294.     set_PWMRUN;

  295.     while (1)
  296.     {
  297.         /* Get Motor realtime speed by ADC */
  298.         if (ADCF == ADC_CONVERT_FINISH)
  299.         {
  300.             s16TargetSpeed = GetTargetSpeed();
  301.         }

  302.         if (MOTOR_ON_OFF_SWITCH == MOTOR_OFF)
  303.         {
  304.             /* Stop the motor */
  305.             clr_PWMRUN;
  306.             PMEN = 0xff;
  307.             PMD = 0x00;

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

  310.             /* Motor on/off switch is switching to on, re-initial the pwm for starting rotate. */
  311.             
  312.             /* Set PWM duty value on motor boost. */
  313.             u16PWMDutyValue = 0x1F3 * MotorBoostDuty;
  314.             
  315.             /* Initialize the pwm value */
  316.             PWM0H = HIBYTE(u16PWMDutyValue);
  317.             PWM0L = LOBYTE(u16PWMDutyValue);
  318.             
  319.             /* Initialize the Motor phase parameter */
  320.             u8OldMotorPhaseState = 0xFF;
  321.             CheckMotorPhaseByHallSensor((P0 & 0xE0));
  322.             
  323.             /* Start the PWM */
  324.             set_LOAD;
  325.             set_PWMRUN;
  326.             
  327.             /* Clear the Timer interrupt cnt */
  328.             g_u8TimerIntCount = 0;
  329.         }
  330.         else if (g_u8TimerIntCount >= 1) /* if the time past x * 10ms( x = 1 ), entering this if. */
  331.         {
  332.             /* Reset the timer interrupt times counter */
  333.             g_u8TimerIntCount = 0;

  334. #ifdef UART1_DEBUG
  335.             /* Print the speed of motor */
  336.             u8TimerCntForUART++;
  337.             if (u8TimerCntForUART >= 30)   //Per 300ms send UART data
  338.             {
  339.                 Send_Data_To_UART1(s16TargetSpeed);
  340.                 u8TimerCntForUART = 0;
  341.             }
  342. #endif
  343.             
  344.             /* Modified the PWM duty for tracing the target speed */
  345.             temp = ((((signed long int)0x1F3 * (signed long int)s16TargetSpeed)) / (signed long int)4500);
  346.             u16PWMDutyValue += (( temp > u16PWMDutyValue) ? 1 : (-1));

  347.             /* Set new PWM duty */
  348.             PWM0H = HIBYTE(u16PWMDutyValue);
  349.             PWM0L = LOBYTE(u16PWMDutyValue);
  350.             set_LOAD;
  351.         }

  352.         /* Change the Motor phase */
  353.         if (u8OldMotorPhaseState != g_u8HallSensorMotorPhaseState)
  354.         {
  355.             /* Record the last motor phase */
  356.             u8OldMotorPhaseState = g_u8HallSensorMotorPhaseState;
  357.             /* Change the motor phase */
  358.             ChangeMotorPhaseClockwise();
  359.         }
  360.     }
  361. }
  362. /*---------------------------------------------------------------------------------------------------------*/
  363. /* Interrupt                                                                                               */
  364. /*---------------------------------------------------------------------------------------------------------*/

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

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

  380. /*** (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 | 显示全部楼层
开环一般用于什么场景呢?
xinxianshi 发表于 2024-2-27 22:52 | 显示全部楼层
MCU是连接什么元件来驱动电机呢?
xinxianshi 发表于 2024-2-27 22:52 | 显示全部楼层
可以实现调速控制吗?
天灵灵地灵灵 发表于 2024-2-28 15:25 | 显示全部楼层
这种代码看着有点难懂。
夜晚有三年 发表于 2025-9-11 14:09 | 显示全部楼层
N76E003 通过定时器生成 6 路 PWM,按霍尔信号或换相表控制三相桥,依次导通对应桥臂,驱动 BLDC 开环运转
您需要登录后才可以回帖 登录 | 注册

本版积分规则

156

主题

1882

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部