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

[复制链接]
5666|35
 楼主| yuyy1989 发表于 2023-6-24 19:00 | 显示全部楼层 |阅读模式
本帖最后由 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
转换为波形是这样的
QQ截图20230624185009.png
从手册里看MCPWM的介绍,貌似找不到合适的波形输出,改一下这个序列,因为电机引脚有个下拉电阻
QQ截图20230622202336.png
我想是不是不用的引脚直接拉低也行,所以变成
1 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1
再转成波形
QQ截图20230624185025.png
这次就很容易找到对应的了
QQ截图20230624185302.png
中心对齐输出,但是CH<n>N要翻转一下
先用上一贴的手动控制IO的方法试了一下,这个序列是可以转起来的,接下来编写MCPWM的代码
为了保证能转起来,IO的切换速度尽量靠近手动控制IO的速度,手动控制IO时是每10ms转动三分之一,换成一个PWM周期是30ms,频率在30Hz左右,用12M的系统时钟可以正好得到这个频率,但是在实际使用时发现设置成12M时钟后MCU不工作了,尝试24M时钟可以正常工作,因此最终频率设置成了50Hz
工程需添加库文件lks32mc07x_mcpwm.c
QQ截图20230624183920.png
代码示例
  1. #include "lks32mc07x.h"
  2. #include "yuyy_delay.h"

  3. void led_init(void)
  4. {
  5.     GPIO_InitTypeDef GPIO_InitStruct;
  6.     GPIO_StructInit(&GPIO_InitStruct);
  7.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  8.     GPIO_InitStruct.GPIO_Pin =  LED_PINS;
  9.     GPIO_Init(LED_GPIO, &GPIO_InitStruct);
  10.     GPIO_ResetBits(LED_GPIO, LED1_PIN|LED2_PIN);
  11.     GPIO_SetBits(LED_GPIO, LED3_PIN);
  12. }

  13. void key_init()
  14. {
  15.     GPIO_InitTypeDef GPIO_InitStruct;
  16.     GPIO_StructInit(&GPIO_InitStruct);
  17.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
  18.     GPIO_InitStruct.GPIO_Pin =  KEY_PINS;
  19.     GPIO_Init(KEY_GPIO, &GPIO_InitStruct);
  20. }

  21. void uvw_testinit()
  22. {
  23.     GPIO_InitTypeDef GPIO_InitStruct;
  24.     GPIO_StructInit(&GPIO_InitStruct);
  25.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  26.     GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
  27.     GPIO_Init(GPIO1, &GPIO_InitStruct);
  28.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_4, AF3_MCPWM);
  29.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_5, AF3_MCPWM);
  30.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_6, AF3_MCPWM);
  31.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_7, AF3_MCPWM);
  32.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_8, AF3_MCPWM);
  33.     GPIO_PinAFConfig(GPIO1, GPIO_PinSource_9, AF3_MCPWM);
  34. }

  35. #define MCU_MCLK                       (24000000LL)       /**<  PWM模块运行主频 */
  36. #define PWM_MCLK                       ((u32)MCU_MCLK)    /**<  PWM模块运行主频 */
  37. #define PWM_MCLK_DIV                   3
  38. #if(PWM_MCLK_DIV == 0)
  39. #define PWM_PRSC                        
  40. #elif(PWM_MCLK_DIV == 1)
  41. #define PWM_PRSC                       2
  42. #elif(PWM_MCLK_DIV == 2)
  43. #define PWM_PRSC                       4
  44. #elif(PWM_MCLK_DIV == 3)
  45. #define PWM_PRSC                       8            /**< *< *<  PWM模块运行预分频器 */
  46. #endif
  47. #define PWM_FREQ0                      ((u16)50)       /**< *<  MCPWM_CNT0PWM斩波频率 */

  48. /**<  电机控制PWM 周期计数器值 */
  49. #define MCPWM_PERIOD0                    ((u16) (PWM_MCLK / (u32)(2 * PWM_FREQ0 *(PWM_PRSC)))) //15位 最大32767
  50. #define MCPWM_WIDTH  (MCPWM_PERIOD0*2/3)

  51. #define DEADTIME_NS                    ((u16)1200)       /**<  死区时间 */
  52. #define DEADTIME                       (u16)(((unsigned long long)PWM_MCLK * (unsigned long long)DEADTIME_NS)/1000000000uL)

  53. void mcpwm_init()
  54. {
  55.     MCPWM_InitTypeDef MCPWM_InitStructure;
  56.     MCPWM_StructInit(&MCPWM_InitStructure);

  57.     MCPWM_InitStructure.MCLK_EN = ENABLE;              /* 模块时钟开启 */
  58.     MCPWM_InitStructure.CLK_DIV = PWM_MCLK_DIV;                   /* MCPWM时钟分频设置 */

  59.     MCPWM_InitStructure.IO_FLT_CLKDIV  = 12;  /* 急停事件(来自IO口信号)数字滤波器时间设置 */
  60.     MCPWM_InitStructure.CMP_FLT_CLKDIV = 12;  /* 急停事件(来自比较器信号)数字滤波器时间设置 */

  61.     MCPWM_InitStructure.AUEN = MCPWM0_ALL_AUPDAT; /*自动加载使能*/

  62.     /* MCPWM0_CNT0 */

  63.     MCPWM_InitStructure.BASE_CNT0_EN = ENABLE;                /* 主计数器开始计数使能开关 */
  64.     MCPWM_InitStructure.TH0 = MCPWM_PERIOD0;                    /* 计数周期设置即MCPWM输出周期*/

  65.     MCPWM_InitStructure.TH00 = (u16)(-MCPWM_PERIOD0+5);
  66.     MCPWM_InitStructure.TH01 = (u16)(-MCPWM_PERIOD0+MCPWM_WIDTH-5);
  67.     MCPWM_InitStructure.TH10 = (u16)(-MCPWM_PERIOD0+MCPWM_WIDTH+5);
  68.     MCPWM_InitStructure.TH11 = (u16)(MCPWM_PERIOD0-MCPWM_WIDTH-5);
  69.     MCPWM_InitStructure.TH20 = (u16)(MCPWM_PERIOD0-MCPWM_WIDTH+5);
  70.     MCPWM_InitStructure.TH21 = (u16)(MCPWM_PERIOD0-5);

  71.     MCPWM_InitStructure.MCPWM_WorkModeCH0 = MCPWM0_CENTRAL_PWM_MODE; /* MCPWM CH0工作模式:中心对齐PWM模式 */
  72.     MCPWM_InitStructure.MCPWM_WorkModeCH1 = MCPWM0_CENTRAL_PWM_MODE; /* 通道工作模式设置,中心对齐或边沿对齐 */
  73.     MCPWM_InitStructure.MCPWM_WorkModeCH2 = MCPWM0_CENTRAL_PWM_MODE;
  74.     MCPWM_InitStructure.DeadTimeCH012N = DEADTIME;/* 死区时间设置 */
  75.     MCPWM_InitStructure.DeadTimeCH012P = DEADTIME;
  76.     MCPWM_InitStructure.CMP_CTRL_CNT0  = DISABLE ;/* CMP控制CNT0失能 */
  77.     MCPWM_InitStructure.EVT_CNT0_EN    = DISABLE ;/* MCPWM_CNT1外部触发失能 */
  78.     MCPWM_InitStructure.EVT0           = DISABLE ;

  79.     MCPWM_InitStructure.TR0_UP_INTV     = DISABLE;
  80.     MCPWM_InitStructure.TR0_T0_UpdateEN = ENABLE ;
  81.     MCPWM_InitStructure.TR0_T1_UpdateEN = DISABLE ;
  82.     MCPWM_InitStructure.TR0_AEC         = DISABLE;

  83.     MCPWM_InitStructure.T0_Update0_INT_EN = DISABLE; /* T0更新事件 中断关闭 */
  84.     MCPWM_InitStructure.T1_Update0_INT_EN = DISABLE ; /* T1更新事件 中断使能 */
  85.     MCPWM_InitStructure.Update1_INT_EN = DISABLE;     /* CNT0 更新事件 中断使能  */

  86.     MCPWM_InitStructure.CH0N_Polarity_INV = ENABLE;           /* CH0N通道输出极性设置 | 正常输出或取反输出*/
  87.     MCPWM_InitStructure.CH0P_Polarity_INV = DISABLE;          /* CH0P通道输出极性设置 | 正常输出或取反输出 */
  88.     MCPWM_InitStructure.CH1N_Polarity_INV = ENABLE;
  89.     MCPWM_InitStructure.CH1P_Polarity_INV = DISABLE;
  90.     MCPWM_InitStructure.CH2N_Polarity_INV = ENABLE;
  91.     MCPWM_InitStructure.CH2P_Polarity_INV = DISABLE;

  92.     MCPWM_InitStructure.Switch_CH0N_CH0P =  DISABLE;           /* 通道交换选择设置 | CH0P和CH0N是否选择信号交换 */
  93.     MCPWM_InitStructure.Switch_CH1N_CH1P =  DISABLE;           /* 通道交换选择设置 */
  94.     MCPWM_InitStructure.Switch_CH2N_CH2P =  DISABLE;           /* 通道交换选择设置 */

  95.     /* 默认电平设置 默认电平输出不受MCPWM_IO01和MCPWM_IO23的 BIT0、BIT1、BIT8、BIT9、BIT6、BIT14通道交换和极性控制的影响,直接控制通道输出 */
  96.     MCPWM_InitStructure.CH0P_default_output = MCPWM0_LOW_LEVEL;
  97.     MCPWM_InitStructure.CH0N_default_output = MCPWM0_HIGH_LEVEL;
  98.     MCPWM_InitStructure.CH1P_default_output = MCPWM0_LOW_LEVEL;      /* CH1P对应引脚在空闲状态输出低电平 */
  99.     MCPWM_InitStructure.CH1N_default_output = MCPWM0_HIGH_LEVEL;     /* CH1N对应引脚在空闲状态输出高电平 */
  100.     MCPWM_InitStructure.CH2P_default_output = MCPWM0_LOW_LEVEL;
  101.     MCPWM_InitStructure.CH2N_default_output = MCPWM0_HIGH_LEVEL;

  102.     MCPWM_InitStructure.CH0N_FAIL_EN = ENABLE ;
  103.     MCPWM_InitStructure.CH0P_FAIL_EN = ENABLE ;
  104.     MCPWM_InitStructure.CH1N_FAIL_EN = ENABLE ;
  105.     MCPWM_InitStructure.CH1P_FAIL_EN = ENABLE ;
  106.     MCPWM_InitStructure.CH2N_FAIL_EN = ENABLE ;
  107.     MCPWM_InitStructure.CH2P_FAIL_EN = ENABLE ;

  108.     MCPWM_InitStructure.FAIL0_INPUT_EN   = DISABLE ;//FAIL_0CAP
  109.     MCPWM_InitStructure.FAIL0_INT_EN     = DISABLE;
  110.     MCPWM_InitStructure.FAIL0_Signal_Sel = MCPWM0_FAIL_SEL_CMP ;//FAIL_0CAP
  111.     MCPWM_InitStructure.FAIL0_Polarity   = MCPWM0_HIGH_LEVEL_ACTIVE ;

  112.     MCPWM_InitStructure.FAIL1_INPUT_EN   = DISABLE ;//FAIL_0CAP
  113.     MCPWM_InitStructure.FAIL1_INT_EN     = DISABLE;
  114.     MCPWM_InitStructure.FAIL1_Signal_Sel = MCPWM0_FAIL_SEL_IO ;//FAIL_0CAP
  115.     MCPWM_InitStructure.FAIL1_Polarity   = MCPWM0_HIGH_LEVEL_ACTIVE ;

  116.     MCPWM_InitStructure.HALT_PRT0        = DISABLE ;
  117.     MCPWM_InitStructure.FAIL_0CAP        = DISABLE ;
  118.     MCPWM_Init(&MCPWM_InitStructure);
  119.    
  120.     NVIC_SetPriority(MCPWM0_IRQn, 1);
  121.     NVIC_EnableIRQ(MCPWM0_IRQn);
  122. }

  123. void MCPWM0_IRQHandler(void)
  124. {
  125.         
  126. }

  127. void mcu_init(void)
  128. {
  129.     __disable_irq();         /* 关闭中断 中断总开关 */
  130.     SYS_WR_PROTECT = 0x7a83; /*使能系统寄存器写操作*/
  131.     FLASH_CFG |= 0x00080000; /* enable prefetch ,FLASH预取加速使能*/        
  132.     IWDG_DISABLE();                                                /*关闭清零看门狗*/
  133.     SYS_MclkChoice(SYS_MCLK_24M_RC); /*选择当前主时钟频率*/
  134.     led_init();        
  135.     key_init();
  136.     uvw_testinit();
  137.     mcpwm_init();
  138.     yuyy_delay_us(100);          /* 延时等待硬件初始化稳定 */
  139.     SYS_WR_PROTECT = 0x0;    /*关闭系统寄存器写操作*/
  140.     __enable_irq();          /* 开启总中断 */
  141. }

  142. int main(void)
  143. {
  144.     uint8_t run = 0;
  145.     uint8_t key_start_downcount = 0;
  146.     uint8_t key_stop_downcount = 0;
  147.     uint8_t runstep = 0;
  148.     mcu_init();
  149.     while (1)
  150.     {
  151.         if(Bit_RESET == GPIO_ReadInputDataBit(KEY_GPIO,KEY_START_PIN))
  152.         {
  153.             if(key_start_downcount < 0xFF)
  154.                 key_start_downcount++;
  155.         }
  156.         else
  157.         {
  158.             if(key_start_downcount > 3 && run == 0)
  159.             {
  160.                 run = 1;
  161.                 runstep = 0;
  162.                 PWMOutputs(ENABLE);
  163.             }
  164.             key_start_downcount = 0;
  165.         }
  166.         
  167.         if(Bit_RESET == GPIO_ReadInputDataBit(KEY_GPIO,KEY_STOP_PIN))
  168.         {
  169.             if(key_stop_downcount < 0xFF)
  170.                 key_stop_downcount++;
  171.         }
  172.         else
  173.         {
  174.             if(key_stop_downcount > 3 && run > 0)
  175.             {
  176.                 run = 0;
  177.                 runstep = 0;
  178.                 PWMOutputs(DISABLE);
  179.             }
  180.             key_stop_downcount = 0;
  181.         }
  182.         
  183.         if(runstep > 0)
  184.             runstep--;
  185.         else
  186.         {
  187.             runstep = 20;
  188.             switch(run)
  189.             {
  190.                 case 1:
  191.                     GPIO_SetBits(LED_GPIO, LED1_PIN);
  192.                     GPIO_ResetBits(LED_GPIO, LED2_PIN);
  193.                     GPIO_SetBits(LED_GPIO, LED3_PIN);
  194.                     run = 2;
  195.                     break;
  196.                 case 2:
  197.                     GPIO_ResetBits(LED_GPIO, LED1_PIN);
  198.                     GPIO_SetBits(LED_GPIO, LED2_PIN);
  199.                     GPIO_SetBits(LED_GPIO, LED3_PIN);
  200.                     run = 3;
  201.                     break;
  202.                 case 3:
  203.                     GPIO_ResetBits(LED_GPIO, LED1_PIN);
  204.                     GPIO_ResetBits(LED_GPIO, LED2_PIN);
  205.                     GPIO_ResetBits(LED_GPIO, LED3_PIN);
  206.                     run = 1;
  207.                     break;
  208.                 default:
  209.                     GPIO_ResetBits(LED_GPIO, LED1_PIN);
  210.                     GPIO_ResetBits(LED_GPIO, LED2_PIN);
  211.                     GPIO_SetBits(LED_GPIO, LED3_PIN);
  212.                     run = 0;
  213.                     break;
  214.             }
  215.         }
  216.         yuyy_delay_ms(10);
  217.     }
  218. }
正式接电机使用前,如果有示波器最好用示波器看一下波形是否正常,以免烧坏电机
运行效果
WeChat_20230624182058 00_00_00-00_00_30.gif
这只是一个刚入门无刷电机的人做的一个简单的用MCPWM驱动电机的示例,后面会继续研究无刷电机的控制方法

评论

赞~!学习一下!  发表于 2023-6-26 10:08
jiangyimfs 发表于 2023-6-24 19:30 | 显示全部楼层
问一下楼主,问了什么型号的小电机,感觉跟我用的挺像的
 楼主| yuyy1989 发表于 2023-6-24 19:39 | 显示全部楼层
jiangyimfs 发表于 2023-6-24 19:30
问一下楼主,问了什么型号的小电机,感觉跟我用的挺像的

微信图片_20230624193912.jpg
jiangyimfs 发表于 2023-6-24 19:54 | 显示全部楼层
真的跟我用的电机一样的,这个 电机是2对极,电阻是7Ω,兄那有其他的参数吗?
 楼主| yuyy1989 发表于 2023-6-24 20:00 | 显示全部楼层
jiangyimfs 发表于 2023-6-24 19:54
真的跟我用的电机一样的,这个 电机是2对极,电阻是7Ω,兄那有其他的参数吗? ...

没有,在淘宝上看着便宜就买了,卖家那也没详细参数
八层楼 发表于 2023-7-6 17:02 | 显示全部楼层
这种电机专用的pwm模块和普通的pwm模块相比 有哪些差别呢
tpgf 发表于 2023-7-6 17:26 | 显示全部楼层
每个通道均控制一对输出,接着这些输出可控制某些片外操作,例如控制电机中的一组线圈
观海 发表于 2023-7-6 21:33 | 显示全部楼层

MCPWM每个通道包括:
1个32位定时器/计数器(TC);

1个32位界限寄存器(LIM);

1个32匹配寄存器(MAT);

1个10位死区时间寄存器(DT)和相应的10位死区时间计数器;

1个32位捕获寄存器;

2个极性可调整的输出(MCOA和MCOB);

1个周期中断、1个脉宽中断和1个捕获中断。


guanjiaer 发表于 2023-7-7 08:42 | 显示全部楼层
电机转起来之后总有一种有点偏心的样子
heimaojingzhang 发表于 2023-7-7 09:19 | 显示全部楼层
是不是基本上所有的mcpwm都具有三个通道啊
keaibukelian 发表于 2023-7-7 09:59 | 显示全部楼层
当电机的负载变大的时候 必然需要更大的扭矩 此时需要如何控制呢
 楼主| yuyy1989 发表于 2023-7-7 15:41 | 显示全部楼层
keaibukelian 发表于 2023-7-7 09:59
当电机的负载变大的时候 必然需要更大的扭矩 此时需要如何控制呢

本人电机小白,目前还不知道如何控制
dreamwang123 发表于 2023-7-21 10:13 | 显示全部楼层
本帖最后由 dreamwang123 于 2023-7-21 10:29 编辑

很好
 楼主| yuyy1989 发表于 2023-7-21 10:18 | 显示全部楼层
dreamwang123 发表于 2023-7-21 10:13
问下,这个底板VCC输入多少电压的,电机又是DC105V,这里不是很理解

底板输入电压范围20-60V,这个电机24V也能转
dreamwang123 发表于 2023-7-21 10:30 | 显示全部楼层
yuyy1989 发表于 2023-7-21 10:18
底板输入电压范围20-60V,这个电机24V也能转

好的,谢谢
123wsy 发表于 2023-7-27 11:43 | 显示全部楼层
能拍一下你完整的运行图嘛,包括线是咋接的
 楼主| yuyy1989 发表于 2023-7-27 22:47 | 显示全部楼层
123wsy 发表于 2023-7-27 11:43
能拍一下你完整的运行图嘛,包括线是咋接的

微信图片_20230727224627.jpg
123wsy 发表于 2023-8-8 18:23 | 显示全部楼层
用LKS081控制一个12V电机,程序是凌欧提供的无感FOC例程,通电后,电机转动不到3秒就不转了,重新上电后重复这个情况,请问这是咋回事?
morrisk 发表于 2023-8-27 11:38 | 显示全部楼层
IO的切换速度尽量靠近手动控制IO的速度
leyangdai 发表于 2023-10-8 11:15 | 显示全部楼层
请问  凌鸥创芯电机开发板LKS32MC071CBT8 的相关资料从哪可以获取到呢? 方便给我发一份吗?小白学习用。 谢谢。  @yuyy1989
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

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