首页 > 评测 > 【凌鸥创芯电机开发板LKS32MC071CBT8评测报告】6.用MCPWM让电机转起来

【凌鸥创芯电机开发板LKS32MC071CBT8评测报告】6.用MCPWM让电机转起来

  
  • 作者:
  • 来源:
  • [导读]
  • 本帖最后由 yuyy1989 于 2023-6-24 19:01 编辑 #申请原创# 6.用MCPWM让电机转起来 之前用手动控制IO的方法成功让电机转了起来,不过LKS32MC071有电机控制专用的MCPWM模块,是一个精确控制电机驱动波形输出的

本帖最后由 yuyy1989 于 2023-6-24 19:01 编辑

#申请原创# 6.用MCPWM让电机转起来
之前用手动控制IO的方法成功让电机转了起来,不过LKS32MC071有电机控制专用的MCPWM模块,是一个精确控制电机驱动波形输出的模块。
首先对上一贴的控制序列做个处理,UP UN VP VN WP WN序列
1 1 0 0 0 1
0 1 1 1 0 0
0 0 0 1 1 1
停止时
0 1 0 1 0 1
转换为波形是这样的


从手册里看MCPWM的介绍,貌似找不到合适的波形输出,改一下这个序列,因为电机引脚有个下拉电阻


我想是不是不用的引脚直接拉低也行,所以变成
1 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1
再转成波形

这次就很容易找到对应的了

中心对齐输出,但是CH<n>N要翻转一下
先用上一贴的手动控制IO的方法试了一下,这个序列是可以转起来的,接下来编写MCPWM的代码
为了保证能转起来,IO的切换速度尽量靠近手动控制IO的速度,手动控制IO时是每10ms转动三分之一,换成一个PWM周期是30ms,频率在30Hz左右,用12M的系统时钟可以正好得到这个频率,但是在实际使用时发现设置成12M时钟后MCU不工作了,尝试24M时钟可以正常工作,因此最终频率设置成了50Hz
工程需添加库文件lks32mc07x_mcpwm.c

代码示例

 

  1. #include "lks32mc07x.h"
  2. #include "yuyy_delay.h"
  3.  
  4. void led_init(void)
  5. {
  6.     GPIO_InitTypeDef GPIO_InitStruct;
  7.     GPIO_StructInit(&GPIO_InitStruct);
  8.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  9.     GPIO_InitStruct.GPIO_Pin =  LED_PINS;
  10.     GPIO_Init(LED_GPIO, &GPIO_InitStruct);
  11.     GPIO_ResetBits(LED_GPIO, LED1_PIN|LED2_PIN);
  12.     GPIO_SetBits(LED_GPIO, LED3_PIN);
  13. }
  14.  
  15. void key_init()
  16. {
  17.     GPIO_InitTypeDef GPIO_InitStruct;
  18.     GPIO_StructInit(&GPIO_InitStruct);
  19.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
  20.     GPIO_InitStruct.GPIO_Pin =  KEY_PINS;
  21.     GPIO_Init(KEY_GPIO, &GPIO_InitStruct);
  22. }
  23.  
  24. void uvw_testinit()
  25. {
  26.     GPIO_InitTypeDef GPIO_InitStruct;
  27.     GPIO_StructInit(&GPIO_InitStruct);
  28.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  29.     GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
  30.     GPIO_Init(GPIO1, &GPIO_InitStruct);
  31.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_4, AF3_MCPWM);
  32.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_5, AF3_MCPWM);
  33.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_6, AF3_MCPWM);
  34.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_7, AF3_MCPWM);
  35.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_8, AF3_MCPWM);
  36.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_9, AF3_MCPWM);
  37. }
  38.  
  39. #define MCU_MCLK                       (24000000LL)       /**<  PWM模块运行主频 */
  40. #define PWM_MCLK                       ((u32)MCU_MCLK)    /**<  PWM模块运行主频 */
  41. #define PWM_MCLK_DIV                   3
  42. #if(PWM_MCLK_DIV == 0)
  43. #define PWM_PRSC                        
  44. #elif(PWM_MCLK_DIV == 1)
  45. #define PWM_PRSC                       2
  46. #elif(PWM_MCLK_DIV == 2)
  47. #define PWM_PRSC                       4
  48. #elif(PWM_MCLK_DIV == 3)
  49. #define PWM_PRSC                       8            /**< *< *<  PWM模块运行预分频器 */
  50. #endif
  51. #define PWM_FREQ0                      ((u16)50)       /**< *<  MCPWM_CNT0PWM斩波频率 */
  52.  
  53. /**<  电机控制PWM 周期计数器值 */
  54. #define MCPWM_PERIOD0                    ((u16) (PWM_MCLK / (u32)(2 * PWM_FREQ0 *(PWM_PRSC)))) //15位 最大32767
  55. #define MCPWM_WIDTH  (MCPWM_PERIOD0*2/3)
  56.  
  57. #define DEADTIME_NS                    ((u16)1200)       /**<  死区时间 */
  58. #define DEADTIME                       (u16)(((unsigned long long)PWM_MCLK * (unsigned long long)DEADTIME_NS)/1000000000uL)
  59.  
  60. void mcpwm_init()
  61. {
  62.     MCPWM_InitTypeDef MCPWM_InitStructure;
  63.     MCPWM_StructInit(&MCPWM_InitStructure);
  64.  
  65.     MCPWM_InitStructure.MCLK_EN = ENABLE;              /* 模块时钟开启 */
  66.     MCPWM_InitStructure.CLK_DIV = PWM_MCLK_DIV;                   /* MCPWM时钟分频设置 */
  67.  
  68.     MCPWM_InitStructure.IO_FLT_CLKDIV  = 12;  /* 急停事件(来自IO口信号)数字滤波器时间设置 */
  69.     MCPWM_InitStructure.CMP_FLT_CLKDIV = 12;  /* 急停事件(来自比较器信号)数字滤波器时间设置 */
  70.  
  71.     MCPWM_InitStructure.AUEN = MCPWM0_ALL_AUPDAT; /*自动加载使能*/
  72.  
  73.     /* MCPWM0_CNT0 */
  74.  
  75.     MCPWM_InitStructure.BASE_CNT0_EN = ENABLE;                /* 主计数器开始计数使能开关 */
  76.     MCPWM_InitStructure.TH0 = MCPWM_PERIOD0;                    /* 计数周期设置即MCPWM输出周期*/
  77.  
  78.     MCPWM_InitStructure.TH00 = (u16)(-MCPWM_PERIOD0+5);
  79.     MCPWM_InitStructure.TH01 = (u16)(-MCPWM_PERIOD0+MCPWM_WIDTH-5);
  80.     MCPWM_InitStructure.TH10 = (u16)(-MCPWM_PERIOD0+MCPWM_WIDTH+5);
  81.     MCPWM_InitStructure.TH11 = (u16)(MCPWM_PERIOD0-MCPWM_WIDTH-5);
  82.     MCPWM_InitStructure.TH20 = (u16)(MCPWM_PERIOD0-MCPWM_WIDTH+5);
  83.     MCPWM_InitStructure.TH21 = (u16)(MCPWM_PERIOD0-5);
  84.  
  85.     MCPWM_InitStructure.MCPWM_WorkModeCH0 = MCPWM0_CENTRAL_PWM_MODE; /* MCPWM CH0工作模式:中心对齐PWM模式 */
  86.     MCPWM_InitStructure.MCPWM_WorkModeCH1 = MCPWM0_CENTRAL_PWM_MODE; /* 通道工作模式设置,中心对齐或边沿对齐 */
  87.     MCPWM_InitStructure.MCPWM_WorkModeCH2 = MCPWM0_CENTRAL_PWM_MODE;
  88.     MCPWM_InitStructure.DeadTimeCH012N = DEADTIME;/* 死区时间设置 */
  89.     MCPWM_InitStructure.DeadTimeCH012P = DEADTIME;
  90.     MCPWM_InitStructure.CMP_CTRL_CNT0  = DISABLE ;/* CMP控制CNT0失能 */
  91.     MCPWM_InitStructure.EVT_CNT0_EN    = DISABLE ;/* MCPWM_CNT1外部触发失能 */
  92.     MCPWM_InitStructure.EVT0           = DISABLE ;
  93.  
  94.     MCPWM_InitStructure.TR0_UP_INTV     = DISABLE;
  95.     MCPWM_InitStructure.TR0_T0_UpdateEN = ENABLE ;
  96.     MCPWM_InitStructure.TR0_T1_UpdateEN = DISABLE ;
  97.     MCPWM_InitStructure.TR0_AEC         = DISABLE;
  98.  
  99.     MCPWM_InitStructure.T0_Update0_INT_EN = DISABLE; /* T0更新事件 中断关闭 */
  100.     MCPWM_InitStructure.T1_Update0_INT_EN = DISABLE ; /* T1更新事件 中断使能 */
  101.     MCPWM_InitStructure.Update1_INT_EN = DISABLE;     /* CNT0 更新事件 中断使能  */
  102.  
  103.     MCPWM_InitStructure.CH0N_Polarity_INV = ENABLE;           /* CH0N通道输出极性设置 | 正常输出或取反输出*/
  104.     MCPWM_InitStructure.CH0P_Polarity_INV = DISABLE;          /* CH0P通道输出极性设置 | 正常输出或取反输出 */
  105.     MCPWM_InitStructure.CH1N_Polarity_INV = ENABLE;
  106.     MCPWM_InitStructure.CH1P_Polarity_INV = DISABLE;
  107.     MCPWM_InitStructure.CH2N_Polarity_INV = ENABLE;
  108.     MCPWM_InitStructure.CH2P_Polarity_INV = DISABLE;
  109.  
  110.     MCPWM_InitStructure.Switch_CH0N_CH0P =  DISABLE;           /* 通道交换选择设置 | CH0P和CH0N是否选择信号交换 */
  111.     MCPWM_InitStructure.Switch_CH1N_CH1P =  DISABLE;           /* 通道交换选择设置 */
  112.     MCPWM_InitStructure.Switch_CH2N_CH2P =  DISABLE;           /* 通道交换选择设置 */
  113.  
  114.     /* 默认电平设置 默认电平输出不受MCPWM_IO01和MCPWM_IO23的 BIT0、BIT1、BIT8、BIT9、BIT6、BIT14通道交换和极性控制的影响,直接控制通道输出 */
  115.     MCPWM_InitStructure.CH0P_default_output = MCPWM0_LOW_LEVEL;
  116.     MCPWM_InitStructure.CH0N_default_output = MCPWM0_HIGH_LEVEL;
  117.     MCPWM_InitStructure.CH1P_default_output = MCPWM0_LOW_LEVEL;      /* CH1P对应引脚在空闲状态输出低电平 */
  118.     MCPWM_InitStructure.CH1N_default_output = MCPWM0_HIGH_LEVEL;     /* CH1N对应引脚在空闲状态输出高电平 */
  119.     MCPWM_InitStructure.CH2P_default_output = MCPWM0_LOW_LEVEL;
  120.     MCPWM_InitStructure.CH2N_default_output = MCPWM0_HIGH_LEVEL;
  121.  
  122.     MCPWM_InitStructure.CH0N_FAIL_EN = ENABLE ;
  123.     MCPWM_InitStructure.CH0P_FAIL_EN = ENABLE ;
  124.     MCPWM_InitStructure.CH1N_FAIL_EN = ENABLE ;
  125.     MCPWM_InitStructure.CH1P_FAIL_EN = ENABLE ;
  126.     MCPWM_InitStructure.CH2N_FAIL_EN = ENABLE ;
  127.     MCPWM_InitStructure.CH2P_FAIL_EN = ENABLE ;
  128.  
  129.     MCPWM_InitStructure.FAIL0_INPUT_EN   = DISABLE ;//FAIL_0CAP
  130.     MCPWM_InitStructure.FAIL0_INT_EN     = DISABLE;
  131.     MCPWM_InitStructure.FAIL0_Signal_Sel = MCPWM0_FAIL_SEL_CMP ;//FAIL_0CAP
  132.     MCPWM_InitStructure.FAIL0_Polarity   = MCPWM0_HIGH_LEVEL_ACTIVE ;
  133.  
  134.     MCPWM_InitStructure.FAIL1_INPUT_EN   = DISABLE ;//FAIL_0CAP
  135.     MCPWM_InitStructure.FAIL1_INT_EN     = DISABLE;
  136.     MCPWM_InitStructure.FAIL1_Signal_Sel = MCPWM0_FAIL_SEL_IO ;//FAIL_0CAP
  137.     MCPWM_InitStructure.FAIL1_Polarity   = MCPWM0_HIGH_LEVEL_ACTIVE ;
  138.  
  139.     MCPWM_InitStructure.HALT_PRT0        = DISABLE ;
  140.     MCPWM_InitStructure.FAIL_0CAP        = DISABLE ;
  141.     MCPWM_Init(&MCPWM_InitStructure);
  142.    
  143.     NVIC_SetPriority(MCPWM0_IRQn, 1);
  144.     NVIC_EnableIRQ(MCPWM0_IRQn);
  145. }
  146.  
  147. void MCPWM0_IRQHandler(void)
  148. {
  149.         
  150. }
  151.  
  152. void mcu_init(void)
  153. {
  154.     __disable_irq();         /* 关闭中断 中断总开关 */
  155.     SYS_WR_PROTECT = 0x7a83; /*使能系统寄存器写操作*/
  156.     FLASH_CFG |= 0x00080000; /* enable prefetch ,FLASH预取加速使能*/        
  157.     IWDG_DISABLE();                                                /*关闭清零看门狗*/
  158.     SYS_MclkChoice(SYS_MCLK_24M_RC); /*选择当前主时钟频率*/
  159.     led_init();        
  160.     key_init();
  161.     uvw_testinit();
  162.     mcpwm_init();
  163.     yuyy_delay_us(100);          /* 延时等待硬件初始化稳定 */
  164.     SYS_WR_PROTECT = 0x0;    /*关闭系统寄存器写操作*/
  165.     __enable_irq();          /* 开启总中断 */
  166. }
  167.  
  168. int main(void)
  169. {
  170.     uint8_t run = 0;
  171.     uint8_t key_start_downcount = 0;
  172.     uint8_t key_stop_downcount = 0;
  173.     uint8_t runstep = 0;
  174.     mcu_init();
  175.     while (1)
  176.     {
  177.         if(Bit_RESET == GPIO_ReadInputDataBit(KEY_GPIO,KEY_START_PIN))
  178.         {
  179.             if(key_start_downcount < 0xFF)
  180.                 key_start_downcount++;
  181.         }
  182.         else
  183.         {
  184.             if(key_start_downcount > 3 && run == 0)
  185.             {
  186.                 run = 1;
  187.                 runstep = 0;
  188.                 PWMOutputs(ENABLE);
  189.             }
  190.             key_start_downcount = 0;
  191.         }
  192.         
  193.         if(Bit_RESET == GPIO_ReadInputDataBit(KEY_GPIO,KEY_STOP_PIN))
  194.         {
  195.             if(key_stop_downcount < 0xFF)
  196.                 key_stop_downcount++;
  197.         }
  198.         else
  199.         {
  200.             if(key_stop_downcount > 3 && run > 0)
  201.             {
  202.                 run = 0;
  203.                 runstep = 0;
  204.                 PWMOutputs(DISABLE);
  205.             }
  206.             key_stop_downcount = 0;
  207.         }
  208.         
  209.         if(runstep > 0)
  210.             runstep--;
  211.         else
  212.         {
  213.             runstep = 20;
  214.             switch(run)
  215.             {
  216.                 case 1:
  217.                     GPIO_SetBits(LED_GPIO, LED1_PIN);
  218.                     GPIO_ResetBits(LED_GPIO, LED2_PIN);
  219.                     GPIO_SetBits(LED_GPIO, LED3_PIN);
  220.                     run = 2;
  221.                     break;
  222.                 case 2:
  223.                     GPIO_ResetBits(LED_GPIO, LED1_PIN);
  224.                     GPIO_SetBits(LED_GPIO, LED2_PIN);
  225.                     GPIO_SetBits(LED_GPIO, LED3_PIN);
  226.                     run = 3;
  227.                     break;
  228.                 case 3:
  229.                     GPIO_ResetBits(LED_GPIO, LED1_PIN);
  230.                     GPIO_ResetBits(LED_GPIO, LED2_PIN);
  231.                     GPIO_ResetBits(LED_GPIO, LED3_PIN);
  232.                     run = 1;
  233.                     break;
  234.                 default:
  235.                     GPIO_ResetBits(LED_GPIO, LED1_PIN);
  236.                     GPIO_ResetBits(LED_GPIO, LED2_PIN);
  237.                     GPIO_SetBits(LED_GPIO, LED3_PIN);
  238.                     run = 0;
  239.                     break;
  240.             }
  241.         }
  242.         yuyy_delay_ms(10);
  243.     }
  244. }
复制代码

正式接电机使用前,如果有示波器最好用示波器看一下波形是否正常,以免烧坏电机
运行效果


这只是一个刚入门无刷电机的人做的一个简单的用MCPWM驱动电机的示例,后面会继续研究无刷电机的控制方法

 

  • 本文系21ic原创,未经许可禁止转载!

网友评论