STCMCUNT015 发表于 2023-6-13 10:40

征集 开源 FOC 电机控制方案@STC32F12K54-64MHz 为高校《单片机应用及原理》课程

征集 开源 FOC 电机控制方案@STC32F12K54-64MHz 为高校《单片机应用及原理》课程
===硬件材料费 www.STCAIMCU.com 公司出,辛苦费 RMB5000 !
有强大的专门支持FOC运算的硬件单精度浮点运算器,外部加上普通的运放就可以做FOC控制了
为32位8051世界共同进步,期待大家在此开源 STC32F12K54-64MHz-LQFP48的 FOC 方案

32位8051世界大礼,追风剑-STC32F12K54-64MHz,还是 STC的 那个 8051 回来了 !
少年强则国强,6/1 儿童节 新生代32位8051全面出击,全球 【免费+包邮】 送
硬件单精度浮点运算器/8051世界革命性的进步,64MHz 主频! 强大的DMA支持
===8K 高速 edata/堆栈/RTOS, 4k xdata/DMA缓冲区, 288MHz PWM时钟源
===奋起一剑斩不周,扳倒乾坤天且休!
自带【硬件 USB 仿真】,【硬件 USB 高速下载】,同时支持【SWD仿真】,【串口仿真】
追风剑-STC32F12K54-64MHz-LQFP48转DIP48核心功能实验板
https://www.stcaimcu.com/data/attachment/forum/202306/04/112815yxc60jj4vxs6mos8.png
这个 STC32F12K54 的内部高达 [60MHz-HIRC] 的高速 HIRC,不好做,
【5.5V ~ 2V 的压飘】,【-40度 ~ +85度的温漂】,对 60MHz的内部 HIRC是一大难题 !
暂时的解决方案就是用外部 32768 RTC 时钟来自动动态追频,动态调教内部高频时钟到 60MHz,
误差在 +/- 0.3% !
用内部高速IRC取代外部高频时钟的好处是 【对外电磁辐射小,抗干扰强】

后记,网友调侃:
平常吹水,自说水平高,现在【没能力开源个8051做的 FOC 方案,帮助大家共同进步 】!
只能说还是要虚心学习,共同进步

深圳国芯人工智能有限公司-核心功能实验板www.stcai.com/hxgnsyb

深圳国芯人工智能有限公司https://www.stcai.com/sy

STCMCUNT015 发表于 2023-6-14 14:11

250MHz时钟源 PWM, STC32F12K54-64MHz
——高速PWM应用1:高速PWM输出
——高速PWM应用2:捕获外部高速脉宽(查询方式)
——高速PWM应用3:捕获外部高速脉宽(中断方式)

高速PWM应用1:   高速PWM输出
高速PWM可使用内建500MHz高速HPLL作为时钟源【输出高速PWM】/【捕获外部高速脉宽】
(注:500MHz的HPLL时钟2分频输出50%占空比的PLL输出时钟可作为高速PWM的时钟源)

[*]/*************功能说明    **************
[*]
[*]时钟说明:由内部IRC产生24MHz的时钟分频为6M提供给HPLL当作HPLL输入时钟,PLL锁频到246MHz输出作为高速PWM的时钟源,
[*]
[*]PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P1.0/P1.1口输出频率为2.46MHz,占空比为50%的互补对称带死区的PWM波形
[*]
[*]下载时, 选择默认IRC时钟 24MHz。
[*]
[*]******************************************/
[*]
[*]#include "stc32g.h"
[*]
[*]#define FOSC            24000000UL
[*]
[*]#define HSCK_MCLK       0
[*]#define HSCK_PLL      1
[*]#define HSCK_SEL      HSCK_PLL
[*]
[*]#define HSIOCK          0x40
[*]
[*]#define ENHPLL          0x80
[*]#define HPLLDIV_52      0x00
[*]#define HPLLDIV_54      0x01
[*]#define HPLLDIV_56      0x02
[*]#define HPLLDIV_58      0x03
[*]#define HPLLDIV_60      0x04
[*]#define HPLLDIV_62      0x05
[*]#define HPLLDIV_64      0x06
[*]#define HPLLDIV_66      0x07
[*]#define HPLLDIV_68      0x08
[*]#define HPLLDIV_70      0x09
[*]#define HPLLDIV_72      0x0A
[*]#define HPLLDIV_74      0x0B
[*]#define HPLLDIV_76      0x0C
[*]#define HPLLDIV_78      0x0D
[*]#define HPLLDIV_80      0x0E
[*]#define HPLLDIV_82      0x0F
[*]
[*]#define ENCKM         0x80
[*]#define PCKI_MSK      0x60
[*]#define PCKI_D1         0x00
[*]#define PCKI_D2         0x20
[*]#define PCKI_D4         0x40
[*]#define PCKI_D8         0x60
[*]
[*]void delay()
[*]{
[*]    int i;
[*]
[*]    for (i=0; i<100; i++);
[*]}
[*]
[*]char ReadPWMA(char addr)
[*]{
[*]    char dat;
[*]
[*]    while (HSPWMA_ADR & 0x80);            //等待前一个异步读写完成
[*]    HSPWMA_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
[*]                                          //HSPWMA_ADDR寄存器的最高位写1,表示读数据
[*]    while (HSPWMA_ADR & 0x80);            //等待当前异步读取完成
[*]    dat = HSPWMA_DAT;                     //读取异步数据
[*]
[*]    return dat;
[*]}
[*]
[*]void WritePWMA(char addr, char dat)
[*]{
[*]    while (HSPWMA_ADR & 0x80);            //等待前一个异步读写完成
[*]    HSPWMA_DAT = dat;                     //准备需要写入的数据
[*]    HSPWMA_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
[*]                                          //HSPWMA_ADDR寄存器的最高位写0,表示写数据
[*]}
[*]
[*]int main()
[*]{
[*]    EAXFR = 1;
[*]
[*]    P0M0 = 0; P0M1 = 0;
[*]    P1M0 = 0; P1M1 = 0;
[*]    P2M0 = 0; P2M1 = 0;
[*]    P3M0 = 0; P3M1 = 0;
[*]    P4M0 = 0; P4M1 = 0;
[*]    P5M0 = 0; P5M1 = 0;
[*]
[*]    //选择HPLL输入时钟分频,保证输入时钟为6M
[*]    USBCLK &= ~PCKI_MSK;
[*]#if (FOSC == 6000000UL)
[*]    USBCLK |= PCKI_D1;                      //PLL输入时钟1分频
[*]#elif (FOSC == 12000000UL)
[*]    USBCLK |= PCKI_D2;                      //PLL输入时钟2分频
[*]#elif (FOSC == 24000000UL)
[*]    USBCLK |= PCKI_D4;                      //PLL输入时钟4分频
[*]#elif (FOSC == 48000000UL)
[*]    USBCLK |= PCKI_D8;                      //PLL输入时钟8分频
[*]#else
[*]    USBCLK |= PCKI_D4;                      //默认PLL输入时钟4分频
[*]#endif
[*]
[*]    //设置HPLL的除频系数
[*]//    HPLLCR = HPLLDIV_52;                  //F_HPLL=6M*52/2=156M
[*]//    HPLLCR = HPLLDIV_54;                  //F_HPLL=6M*54/2=162M
[*]//    HPLLCR = HPLLDIV_56;                  //F_HPLL=6M*56/2=168M
[*]//    HPLLCR = HPLLDIV_58;                  //F_HPLL=6M*58/2=174M
[*]//    HPLLCR = HPLLDIV_60;                  //F_HPLL=6M*60/2=180M
[*]//    HPLLCR = HPLLDIV_62;                  //F_HPLL=6M*62/2=186M
[*]//    HPLLCR = HPLLDIV_64;                  //F_HPLL=6M*64/2=192M
[*]//    HPLLCR = HPLLDIV_66;                  //F_HPLL=6M*66/2=198M
[*]//    HPLLCR = HPLLDIV_68;                  //F_HPLL=6M*68/2=204M
[*]//    HPLLCR = HPLLDIV_70;                  //F_HPLL=6M*70/2=210M
[*]//    HPLLCR = HPLLDIV_72;                  //F_HPLL=6M*72/2=216M
[*]//    HPLLCR = HPLLDIV_74;                  //F_HPLL=6M*74/2=222M
[*]//    HPLLCR = HPLLDIV_76;                  //F_HPLL=6M*76/2=228M
[*]//    HPLLCR = HPLLDIV_78;                  //F_HPLL=6M*78/2=234M
[*]//    HPLLCR = HPLLDIV_80;                  //F_HPLL=6M*80/2=240M
[*]    HPLLCR = HPLLDIV_82;                  //F_HPLL=6M*82/2=246M
[*]
[*]    //启动HPLL
[*]    HPLLCR |= ENHPLL;                     //使能HPLL
[*]
[*]    delay();                              //等待HPLL时钟稳定
[*]
[*]    //选择HSPWM/HSSPI时钟
[*]#if (HSCK_SEL == HSCK_MCLK)
[*]    CLKSEL &= ~HSIOCK;                      //HSPWM/HSSPI选择主时钟为时钟源
[*]#elif (HSCK_SEL == HSCK_PLL)
[*]    CLKSEL |= HSIOCK;                     //HSPWM/HSSPI选择PLL输出时钟为时钟源
[*]#else
[*]    CLKSEL &= ~HSIOCK;                      //默认HSPWM/HSSPI选择主时钟为时钟源
[*]#endif
[*]
[*]    HSCLKDIV = 0;                           //HSPWM/HSSPI时钟源不分频
[*]
[*]    HSPWMA_CFG = 0x03;                      //使能PWMA相关寄存器异步访问功能
[*]
[*]    PWMA_PS = 0x00;                         //PWMA_CC1/CC1N高速PWM输出到CC1/CC1N口
[*]                                          //注意:PWMA_PS属于I/O控制寄存器,不能使用异步方式进行读写
[*]
[*]    //通过异步方式设置PWMA的相关寄存器
[*]    WritePWMA((char)&PWMA_CCER1, 0x00);
[*]    WritePWMA((char)&PWMA_CCMR1, 0x00);   //CC1为输出模式
[*]    WritePWMA((char)&PWMA_CCMR1, 0x60);   //OC1REF输出PWM1(CNT<CCR时输出有效电平1)
[*]    WritePWMA((char)&PWMA_CCER1, 0x05);   //使能CC1/CC1N上的输出功能
[*]    WritePWMA((char)&PWMA_ENO, 0x03);       //使能PWM信号输出到端口P1.0/P1.1
[*]    WritePWMA((char)&PWMA_BKR, 0x80);       //使能主输出
[*]    WritePWMA((char)&PWMA_CCR1H, 0);      //设置PWM占空比为50个PWM时钟
[*]    WritePWMA((char)&PWMA_CCR1L, 50);
[*]    WritePWMA((char)&PWMA_ARRH, 0);         //设置输出PWM的周期为100个PWM时钟
[*]    WritePWMA((char)&PWMA_ARRL, 99);
[*]    WritePWMA((char)&PWMA_DTR, 10);         //设置互补对称输出PWM的死区
[*]    WritePWMA((char)&PWMA_CR1, 0x01);       //开始PWM计数
[*]
[*]//P2 = ReadPWMA((char)&PWMA_ARRH);      //异步方式读取寄存器
[*]//P0 = ReadPWMA((char)&PWMA_ARRL);
[*]
[*]    while (1);
[*]}
[*]
[*]

复制代码



页: [1]
查看完整版本: 征集 开源 FOC 电机控制方案@STC32F12K54-64MHz 为高校《单片机应用及原理》课程