找回密码
 立即注册
楼主: admin

硬件三角函数运算器, 硬件浮点运算器, 追风剑-STC32F12K64-56MHz,FOC方案征集

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

积分
3599
发表于 2023-6-13 20:09:17 | 显示全部楼层
250MHz时钟源 PWM,  STC32F12K54-56MHz
——高速PWM应用1:  高速PWM输出
——高速PWM应用2:捕获外部高速脉宽(查询方式)
——高速PWM应用3:捕获外部高速脉宽(中断方式)


高速PWM应用2: 捕获外部高速脉宽(查询方式)
高速PWM可使用内建500MHz高速HPLL作为时钟源【输出高速PWM】/【捕获外部高速脉宽】
(注:500MHz的HPLL时钟2分频输出50%占空比的PLL输出时钟可作为高速PWM的时钟源)
  1. /*************  功能说明    **************
  2. 时钟说明:由内部IRC产生24MHz的时钟分频为6M提供给HPLL当作HPLL输入时钟,PLL锁频到246MHz输出作为高速PWM的时钟源,
  3. PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P2.0口输出频率为24.6MHz,占空比为20%的PWM型号
  4. PWM高速捕获说明:PWMB的CC5和CC6通道配置为捕获输入模式,CC5口P2.0口捕获信号的周期值,CC6从P2.0口捕获信号的占空比
  5. 测试说明:最后通过查询方式得到周期值和占空比并从串口送到PC显示
  6. 下载时, 选择默认IRC时钟 24MHz。
  7. ******************************************/
  8. #include "stc32g.h"
  9. #include "stdio.h"
  10. #define FOSC            24000000UL
  11. #define BAUD            (65536 - FOSC/4/115200)
  12. #define HSCK_MCLK       0
  13. #define HSCK_PLL        1
  14. #define HSCK_SEL        HSCK_PLL
  15. #define HSIOCK          0x40
  16. #define ENHPLL          0x80
  17. #define HPLLDIV_52      0x00
  18. #define HPLLDIV_54      0x01
  19. #define HPLLDIV_56      0x02
  20. #define HPLLDIV_58      0x03
  21. #define HPLLDIV_60      0x04
  22. #define HPLLDIV_62      0x05
  23. #define HPLLDIV_64      0x06
  24. #define HPLLDIV_66      0x07
  25. #define HPLLDIV_68      0x08
  26. #define HPLLDIV_70      0x09
  27. #define HPLLDIV_72      0x0A
  28. #define HPLLDIV_74      0x0B
  29. #define HPLLDIV_76      0x0C
  30. #define HPLLDIV_78      0x0D
  31. #define HPLLDIV_80      0x0E
  32. #define HPLLDIV_82      0x0F
  33. #define ENCKM           0x80
  34. #define PCKI_MSK        0x60
  35. #define PCKI_D1         0x00
  36. #define PCKI_D2         0x20
  37. #define PCKI_D4         0x40
  38. #define PCKI_D8         0x60
  39. void delay()
  40. {
  41.     int i;
  42.     for (i=0; i<100; i++);
  43. }
  44. char ReadPWMA(char addr)
  45. {
  46.     char dat;
  47.    
  48.     while (HSPWMA_ADR & 0x80);              //等待前一个异步读写完成
  49.     HSPWMA_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
  50.                                             //HSPWMA_ADDR寄存器的最高位写1,表示读数据
  51.     while (HSPWMA_ADR & 0x80);              //等待当前异步读取完成
  52.     dat = HSPWMA_DAT;                       //读取异步数据
  53.    
  54.     return dat;
  55. }
  56. void WritePWMA(char addr, char dat)
  57. {
  58.     while (HSPWMA_ADR & 0x80);              //等待前一个异步读写完成
  59.     HSPWMA_DAT = dat;                       //准备需要写入的数据
  60.     HSPWMA_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
  61.                                             //HSPWMA_ADDR寄存器的最高位写0,表示写数据
  62. }
  63. char ReadPWMB(char addr)
  64. {
  65.     char dat;
  66.    
  67.     while (HSPWMB_ADR & 0x80);              //等待前一个异步读写完成
  68.     HSPWMB_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
  69.                                             //HSPWMB_ADDR寄存器的最高位写1,表示读数据
  70.     while (HSPWMB_ADR & 0x80);              //等待当前异步读取完成
  71.     dat = HSPWMB_DAT;                       //读取异步数据
  72.    
  73.     return dat;
  74. }
  75. void WritePWMB(char addr, char dat)
  76. {
  77.     while (HSPWMB_ADR & 0x80);              //等待前一个异步读写完成
  78.     HSPWMB_DAT = dat;                       //准备需要写入的数据
  79.     HSPWMB_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
  80.                                             //HSPWMB_ADDR寄存器的最高位写0,表示写数据
  81. }
  82. int main()
  83. {
  84.     EAXFR = 1;
  85.    
  86.     P0M0 = 0; P0M1 = 0;
  87.     P1M0 = 0; P1M1 = 0;
  88.     P2M0 = 0; P2M1 = 0;
  89.     P3M0 = 0; P3M1 = 0;
  90.     P4M0 = 0; P4M1 = 0;
  91.     P5M0 = 0; P5M1 = 0;
  92.    
  93.     SCON = 0x52;
  94.     AUXR = 0x40;
  95.     TMOD = 0x00;
  96.     TL1 = BAUD;
  97.     TH1 = BAUD >> 8;
  98.     TR1 = 1;
  99.     //选择HPLL输入时钟分频,保证输入时钟为6M
  100.     USBCLK &= ~PCKI_MSK;
  101. #if (FOSC == 6000000UL)
  102.     USBCLK |= PCKI_D1;                      //PLL输入时钟1分频
  103. #elif (FOSC == 12000000UL)
  104.     USBCLK |= PCKI_D2;                      //PLL输入时钟2分频
  105. #elif (FOSC == 24000000UL)
  106.     USBCLK |= PCKI_D4;                      //PLL输入时钟4分频
  107. #elif (FOSC == 48000000UL)
  108.     USBCLK |= PCKI_D8;                      //PLL输入时钟8分频
  109. #else
  110.     USBCLK |= PCKI_D4;                      //默认PLL输入时钟4分频
  111. #endif
  112.     //设置HPLL的除频系数
  113. //    HPLLCR = HPLLDIV_52;                  //F_HPLL=6M*52/2=156M
  114. //    HPLLCR = HPLLDIV_54;                  //F_HPLL=6M*54/2=162M
  115. //    HPLLCR = HPLLDIV_56;                  //F_HPLL=6M*56/2=168M
  116. //    HPLLCR = HPLLDIV_58;                  //F_HPLL=6M*58/2=174M
  117. //    HPLLCR = HPLLDIV_60;                  //F_HPLL=6M*60/2=180M
  118. //    HPLLCR = HPLLDIV_62;                  //F_HPLL=6M*62/2=186M
  119. //    HPLLCR = HPLLDIV_64;                  //F_HPLL=6M*64/2=192M
  120. //    HPLLCR = HPLLDIV_66;                  //F_HPLL=6M*66/2=198M
  121. //    HPLLCR = HPLLDIV_68;                  //F_HPLL=6M*68/2=204M
  122. //    HPLLCR = HPLLDIV_70;                  //F_HPLL=6M*70/2=210M
  123. //    HPLLCR = HPLLDIV_72;                  //F_HPLL=6M*72/2=216M
  124. //    HPLLCR = HPLLDIV_74;                  //F_HPLL=6M*74/2=222M
  125. //    HPLLCR = HPLLDIV_76;                  //F_HPLL=6M*76/2=228M
  126. //    HPLLCR = HPLLDIV_78;                  //F_HPLL=6M*78/2=234M
  127. //    HPLLCR = HPLLDIV_80;                  //F_HPLL=6M*80/2=240M
  128.     HPLLCR = HPLLDIV_82;                    //F_HPLL=6M*82/2=246M
  129.     //启动HPLL
  130.     HPLLCR |= ENHPLL;                       //使能HPLL
  131.     delay();                                //等待HPLL时钟稳定
  132.     //选择HSPWM/HSSPI时钟
  133. #if (HSCK_SEL == HSCK_MCLK)
  134.     CLKSEL &= ~HSIOCK;                      //HSPWM/HSSPI选择主时钟为时钟源
  135. #elif (HSCK_SEL == HSCK_PLL)
  136.     CLKSEL |= HSIOCK;                       //HSPWM/HSSPI选择PLL输出时钟为时钟源
  137. #else
  138.     CLKSEL &= ~HSIOCK;                      //默认HSPWM/HSSPI选择主时钟为时钟源
  139. #endif
  140.     HSCLKDIV = 0;                           //HSPWM/HSSPI时钟源不分频
  141.    
  142.     HSPWMA_CFG = 0x03;                      //使能PWMA相关寄存器异步访问功能
  143.    
  144.    
  145.     HSPWMA_CFG = 0x03;                      //使能PWMA相关寄存器异步访问功能
  146.     HSPWMB_CFG = 0x03;                      //使能PWMB相关寄存器异步访问功能
  147.    
  148.     PWMA_PS = 0x01;                         //PWMA_CC1高速PWM输出到P2.0口
  149.                                             //PWMB_CC5/PWMB_CC6从P2.0口进行捕获
  150.                                             //注意:PWMA_PS和PWMB_PS属于I/O控制寄存器,不能使用异步方式进行读写
  151.     //通过异步方式设置PWMA/PWMB的相关寄存器
  152.     WritePWMA((char)&PWMA_CCER1, 0x00);
  153.     WritePWMA((char)&PWMA_CCMR1, 0x00);     //CC1为输出模式
  154.     WritePWMA((char)&PWMA_CCMR1, 0x60);     //OC1REF输出PWM1(CNT<CCR时输出有效电平1)
  155.     WritePWMA((char)&PWMA_CCER1, 0x05);     //使能CC1/CC1N上的输出功能
  156.     WritePWMA((char)&PWMA_ENO, 0x01);       //使能PWM信号输出到端口
  157.     WritePWMA((char)&PWMA_BKR, 0x80);       //使能主输出
  158.     WritePWMA((char)&PWMA_CCR1H, 0x00);     //设置输出PWM的占空比
  159.     WritePWMA((char)&PWMA_CCR1L, 0x02);
  160.     WritePWMA((char)&PWMA_ARRH, 0x00);      //设置输出PWM的周期
  161.     WritePWMA((char)&PWMA_ARRL, 0x09);
  162.     WritePWMA((char)&PWMA_CR1, 0x01);       //开始PWM计数
  163.     WritePWMB((char)&PWMB_CCER1, 0x00);
  164.     WritePWMB((char)&PWMB_CCMR1, 0x01);     //CC5为输入模式,且映射到TI5FP5上
  165.     WritePWMB((char)&PWMB_CCMR2, 0x02);     //CC6为输入模式,且映射到TI6FP5上
  166.     WritePWMB((char)&PWMB_CCER1, 0x31);     //使能CC5上的捕获功能(上升沿捕获)
  167.     WritePWMB((char)&PWMB_SMCR, 0x54);      //上升沿复位模式
  168.     WritePWMB((char)&PWMB_CR1, 0x01);       //开始PWM计数
  169.    
  170.     while (1)
  171.     {
  172.         if (ReadPWMB((char)&PWMB_SR1) & 0x02)   //等待捕获完成
  173.         {
  174.             WritePWMB((char)&PWMB_SR1, 0x00);   //清除完成标志
  175.             
  176.             //读取捕获到的周期值
  177.             printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5H) & 0xff);
  178.             printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5L) & 0xff);
  179.             printf(" ");
  180.             
  181.             //读取捕获到的占空比值
  182.             printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6H) & 0xff);
  183.             printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6L) & 0xff);
  184.             printf("\n");
  185.         }
  186.     }
  187. }
复制代码

PWM使用HPLL时钟(高速捕获-查询方式).zip

36.2 KB, 下载次数: 129

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

积分
3599
发表于 2023-6-13 20:15:33 | 显示全部楼层
250MHz时钟源 PWM,  STC32F12K54-56MHz
——高速PWM应用1:  高速PWM输出
——高速PWM应用2:捕获外部高速脉宽(查询方式)
——高速PWM应用3:捕获外部高速脉宽(中断方式)


高速PWM应用3: 捕获外部高速脉宽(中断方式)
高速PWM可使用内建500MHz高速HPLL作为时钟源【输出高速PWM】/【捕获外部高速脉宽】
(注:500MHz的HPLL时钟2分频输出50%占空比的PLL输出时钟可作为高速PWM的时钟源)
  1. /*************  功能说明    **************
  2. 时钟说明:由内部IRC产生24MHz的时钟分频为6M提供给HPLL当作HPLL输入时钟,PLL锁频到246MHz输出作为高速PWM的时钟源,
  3. PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P2.0口输出频率为24.6MHz,占空比为20%的PWM型号
  4. PWM高速捕获说明:PWMB的CC5和CC6通道配置为捕获输入模式,CC5口P2.0口捕获信号的周期值,CC6从P2.0口捕获信号的占空比
  5. 测试说明:最后通过中断方式得到周期值和占空比并从串口送到PC显示(注意要避免中断与主循环同时调用相同函数)
  6. 下载时, 选择默认IRC时钟 24MHz。
  7. ******************************************/
  8. #include "stc32g.h"
  9. #include "stdio.h"
  10. #define FOSC            24000000UL
  11. #define BAUD            (65536 - FOSC/4/115200)
  12. #define HSCK_MCLK       0
  13. #define HSCK_PLL        1
  14. #define HSCK_SEL        HSCK_PLL
  15. #define HSIOCK          0x40
  16. #define ENHPLL          0x80
  17. #define HPLLDIV_52      0x00
  18. #define HPLLDIV_54      0x01
  19. #define HPLLDIV_56      0x02
  20. #define HPLLDIV_58      0x03
  21. #define HPLLDIV_60      0x04
  22. #define HPLLDIV_62      0x05
  23. #define HPLLDIV_64      0x06
  24. #define HPLLDIV_66      0x07
  25. #define HPLLDIV_68      0x08
  26. #define HPLLDIV_70      0x09
  27. #define HPLLDIV_72      0x0A
  28. #define HPLLDIV_74      0x0B
  29. #define HPLLDIV_76      0x0C
  30. #define HPLLDIV_78      0x0D
  31. #define HPLLDIV_80      0x0E
  32. #define HPLLDIV_82      0x0F
  33. #define ENCKM           0x80
  34. #define PCKI_MSK        0x60
  35. #define PCKI_D1         0x00
  36. #define PCKI_D2         0x20
  37. #define PCKI_D4         0x40
  38. #define PCKI_D8         0x60
  39. void delay()
  40. {
  41.     int i;
  42.     for (i=0; i<100; i++);
  43. }
  44. char ReadPWMA(char addr)
  45. {
  46.     char dat;
  47.    
  48.     while (HSPWMA_ADR & 0x80);              //等待前一个异步读写完成
  49.     HSPWMA_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
  50.                                             //HSPWMA_ADDR寄存器的最高位写1,表示读数据
  51.     while (HSPWMA_ADR & 0x80);              //等待当前异步读取完成
  52.     dat = HSPWMA_DAT;                       //读取异步数据
  53.    
  54.     return dat;
  55. }
  56. void WritePWMA(char addr, char dat)
  57. {
  58.     while (HSPWMA_ADR & 0x80);              //等待前一个异步读写完成
  59.     HSPWMA_DAT = dat;                       //准备需要写入的数据
  60.     HSPWMA_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
  61.                                             //HSPWMA_ADDR寄存器的最高位写0,表示写数据
  62. }
  63. char ReadPWMB(char addr)
  64. {
  65.     char dat;
  66.    
  67.     while (HSPWMB_ADR & 0x80);              //等待前一个异步读写完成
  68.     HSPWMB_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
  69.                                             //HSPWMB_ADDR寄存器的最高位写1,表示读数据
  70.     while (HSPWMB_ADR & 0x80);              //等待当前异步读取完成
  71.     dat = HSPWMB_DAT;                       //读取异步数据
  72.    
  73.     return dat;
  74. }
  75. void WritePWMB(char addr, char dat)
  76. {
  77.     while (HSPWMB_ADR & 0x80);              //等待前一个异步读写完成
  78.     HSPWMB_DAT = dat;                       //准备需要写入的数据
  79.     HSPWMB_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
  80.                                             //HSPWMB_ADDR寄存器的最高位写0,表示写数据
  81. }
  82. int main()
  83. {
  84.     EAXFR = 1;
  85.    
  86.     P0M0 = 0; P0M1 = 0;
  87.     P1M0 = 0; P1M1 = 0;
  88.     P2M0 = 0; P2M1 = 0;
  89.     P3M0 = 0; P3M1 = 0;
  90.     P4M0 = 0; P4M1 = 0;
  91.     P5M0 = 0; P5M1 = 0;
  92.    
  93.     SCON = 0x52;
  94.     AUXR = 0x40;
  95.     TMOD = 0x00;
  96.     TL1 = BAUD;
  97.     TH1 = BAUD >> 8;
  98.     TR1 = 1;
  99.     //选择HPLL输入时钟分频,保证输入时钟为6M
  100.     USBCLK &= ~PCKI_MSK;
  101. #if (FOSC == 6000000UL)
  102.     USBCLK |= PCKI_D1;                      //PLL输入时钟1分频
  103. #elif (FOSC == 12000000UL)
  104.     USBCLK |= PCKI_D2;                      //PLL输入时钟2分频
  105. #elif (FOSC == 24000000UL)
  106.     USBCLK |= PCKI_D4;                      //PLL输入时钟4分频
  107. #elif (FOSC == 48000000UL)
  108.     USBCLK |= PCKI_D8;                      //PLL输入时钟8分频
  109. #else
  110.     USBCLK |= PCKI_D4;                      //默认PLL输入时钟4分频
  111. #endif
  112.     //设置HPLL的除频系数
  113. //    HPLLCR = HPLLDIV_52;                  //F_HPLL=6M*52/2=156M
  114. //    HPLLCR = HPLLDIV_54;                  //F_HPLL=6M*54/2=162M
  115. //    HPLLCR = HPLLDIV_56;                  //F_HPLL=6M*56/2=168M
  116. //    HPLLCR = HPLLDIV_58;                  //F_HPLL=6M*58/2=174M
  117. //    HPLLCR = HPLLDIV_60;                  //F_HPLL=6M*60/2=180M
  118. //    HPLLCR = HPLLDIV_62;                  //F_HPLL=6M*62/2=186M
  119. //    HPLLCR = HPLLDIV_64;                  //F_HPLL=6M*64/2=192M
  120. //    HPLLCR = HPLLDIV_66;                  //F_HPLL=6M*66/2=198M
  121. //    HPLLCR = HPLLDIV_68;                  //F_HPLL=6M*68/2=204M
  122. //    HPLLCR = HPLLDIV_70;                  //F_HPLL=6M*70/2=210M
  123. //    HPLLCR = HPLLDIV_72;                  //F_HPLL=6M*72/2=216M
  124. //    HPLLCR = HPLLDIV_74;                  //F_HPLL=6M*74/2=222M
  125. //    HPLLCR = HPLLDIV_76;                  //F_HPLL=6M*76/2=228M
  126. //    HPLLCR = HPLLDIV_78;                  //F_HPLL=6M*78/2=234M
  127. //    HPLLCR = HPLLDIV_80;                  //F_HPLL=6M*80/2=240M
  128.     HPLLCR = HPLLDIV_82;                    //F_HPLL=6M*82/2=246M
  129.     //启动HPLL
  130.     HPLLCR |= ENHPLL;                       //使能HPLL
  131.     delay();                                //等待HPLL时钟稳定
  132.     //选择HSPWM/HSSPI时钟
  133. #if (HSCK_SEL == HSCK_MCLK)
  134.     CLKSEL &= ~HSIOCK;                      //HSPWM/HSSPI选择主时钟为时钟源
  135. #elif (HSCK_SEL == HSCK_PLL)
  136.     CLKSEL |= HSIOCK;                       //HSPWM/HSSPI选择PLL输出时钟为时钟源
  137. #else
  138.     CLKSEL &= ~HSIOCK;                      //默认HSPWM/HSSPI选择主时钟为时钟源
  139. #endif
  140.     HSCLKDIV = 0;                           //HSPWM/HSSPI时钟源不分频
  141.    
  142.     HSPWMA_CFG = 0x03;                      //使能PWMA相关寄存器异步访问功能
  143.     HSPWMB_CFG = 0x07;                      //使能PWMB相关寄存器异步访问功能,并使能异步模式的PWMB中断
  144.    
  145.     PWMA_PS = 0x01;                         //PWMA_CC1高速PWM输出到P2.0口
  146.                                             //PWMB_CC5/PWMB_CC6从P2.0口进行捕获
  147.                                             //注意:PWMA_PS和PWMB_PS属于I/O控制寄存器,不能使用异步方式进行读写
  148.     //通过异步方式设置PWMA/PWMB的相关寄存器
  149.     WritePWMA((char)&PWMA_CCER1, 0x00);
  150.     WritePWMA((char)&PWMA_CCMR1, 0x00);     //CC1为输出模式
  151.     WritePWMA((char)&PWMA_CCMR1, 0x60);     //OC1REF输出PWM1(CNT<CCR时输出有效电平1)
  152.     WritePWMA((char)&PWMA_CCER1, 0x05);     //使能CC1/CC1N上的输出功能
  153.     WritePWMA((char)&PWMA_ENO, 0x01);       //使能PWM信号输出到端口
  154.     WritePWMA((char)&PWMA_BKR, 0x80);       //使能主输出
  155.     WritePWMA((char)&PWMA_CCR1H, 0x00);     //设置输出PWM的占空比
  156.     WritePWMA((char)&PWMA_CCR1L, 0x02);
  157.     WritePWMA((char)&PWMA_ARRH, 0x00);      //设置输出PWM的周期
  158.     WritePWMA((char)&PWMA_ARRL, 0x09);
  159.     WritePWMA((char)&PWMA_CR1, 0x01);       //开始PWM计数
  160.     WritePWMB((char)&PWMB_CCER1, 0x00);
  161.     WritePWMB((char)&PWMB_CCMR1, 0x01);     //CC5为输入模式,且映射到TI5FP5上
  162.     WritePWMB((char)&PWMB_CCMR2, 0x02);     //CC6为输入模式,且映射到TI6FP5上
  163.     WritePWMB((char)&PWMB_CCER1, 0x31);     //使能CC5上的捕获功能(上升沿捕获)
  164.     WritePWMB((char)&PWMB_SMCR, 0x54);      //上升沿复位模式
  165.     WritePWMB((char)&PWMB_CR1, 0x01);       //开始PWM计数
  166.     WritePWMB((char)&PWMB_IER, 0x02);       //使能CC5捕获中断
  167.    
  168.     EA = 1;
  169.    
  170.     while (1);
  171. }
  172. void PWMB_ISR() interrupt 27
  173. {
  174.     if (ReadPWMB((char)&PWMB_SR1) & 0x02)   //等待捕获完成
  175.     {
  176.         WritePWMB((char)&PWMB_SR1, 0x00);   //清除完成标志
  177.         
  178.         //读取捕获到的周期值
  179.         printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5H) & 0xff);
  180.         printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5L) & 0xff);
  181.         printf(" ");
  182.         
  183.         //读取捕获到的占空比值
  184.         printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6H) & 0xff);
  185.         printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6L) & 0xff);
  186.         printf("\n");
  187.     }
  188. }
复制代码

PWM使用HPLL时钟(高速捕获-中断方式).zip

40.08 KB, 下载次数: 128

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

积分
3599
发表于 2023-6-14 09:59:03 | 显示全部楼层
307MHz时钟源 PWM, STC32F12K54-56MHz
——高速PWM应用1:  高速PWM输出
——高速PWM应用2:捕获外部高速脉宽(查询方式)
——高速PWM应用3:捕获外部高速脉宽(中断方式)

高速PWM应用1: 高速PWM输出(CPU工作频率60MHz+ICache)
高速PWM可使用内建500MHz高速HPLL作为时钟源【输出高速PWM】/【捕获外部高速脉宽】
(特别的:高速HPLL时钟输入范围6M~12M。本范例高速HPLL输入频率为7.5MHz,

产生615MHz的HPLL时钟2分频输出50%占空比的PLL输出频率307.5MHz可作为高速PWM的时钟源)
  1. /*************  功能说明    **************
  2. 时钟说明:由内部IRC产生60MHz的时钟当作CPU时钟,同时8分频产生7.5M提供给HPLL
  3.           当作HPLL输入时钟,PLL锁频到307.5MHz输出作为高速PWM的时钟源,
  4. PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P1.0/P1.1口输出频率为3.705MHz,
  5.                  占空比为50%的互补对称带死区的PWM波形
  6. CPU时钟说明:ISP下载软件根据CPU工作频率为60MHz,会自动将WTST设置为2
  7.              用户代码中不用对WTST进行设置。范例中使能了ICACHE功能,
  8.              可有效的提高代码执行效率
  9. 下载时, 选择默认IRC时钟 60MHz。
  10. ******************************************/
  11. #include "stc32g.h"
  12. #define FOSC            60000000UL
  13. #define HSCK_MCLK       0
  14. #define HSCK_PLL        1
  15. #define HSCK_SEL        HSCK_PLL
  16. #define HSIOCK          0x40
  17. #define ENHPLL          0x80
  18. #define HPLLDIV_52      0x00
  19. #define HPLLDIV_54      0x01
  20. #define HPLLDIV_56      0x02
  21. #define HPLLDIV_58      0x03
  22. #define HPLLDIV_60      0x04
  23. #define HPLLDIV_62      0x05
  24. #define HPLLDIV_64      0x06
  25. #define HPLLDIV_66      0x07
  26. #define HPLLDIV_68      0x08
  27. #define HPLLDIV_70      0x09
  28. #define HPLLDIV_72      0x0A
  29. #define HPLLDIV_74      0x0B
  30. #define HPLLDIV_76      0x0C
  31. #define HPLLDIV_78      0x0D
  32. #define HPLLDIV_80      0x0E
  33. #define HPLLDIV_82      0x0F
  34. #define ENCKM           0x80
  35. #define PCKI_MSK        0x60
  36. #define PCKI_D1         0x00
  37. #define PCKI_D2         0x20
  38. #define PCKI_D4         0x40
  39. #define PCKI_D8         0x60
  40. void delay()
  41. {
  42.     int i;
  43.     for (i=0; i<100; i++);
  44. }
  45. void ICacheOn()
  46. {
  47.     bit fEA;
  48.    
  49.     if (WTST > 0)                           //WTST为0时不需要且不能使能ICACHE
  50.     {
  51.         fEA = EA;                           //保存EA
  52.         EA = 0;                             //关闭中断
  53.         _nop_();
  54.         _nop_();
  55.         TA = 0xaa;                          //写入触发命令序列1
  56.                                             //此处不能有其他任何指令
  57.         TA = 0x55;                          //写入触发命令序列2
  58.                                             //此处不能有其他任何指令
  59.         ICHECR = 0x01;                      //写保护暂时关闭,可以修改ICHECR中的EN位
  60.                                             //EN位再次进入写保护状态
  61.         _nop_();
  62.         _nop_();
  63.         EA = fEA;                           //恢复EA
  64.     }
  65. }
  66. char ReadPWMA(char addr)
  67. {
  68.     char dat;
  69.    
  70.     while (HSPWMA_ADR & 0x80);              //等待前一个异步读写完成
  71.     HSPWMA_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
  72.                                             //HSPWMA_ADDR寄存器的最高位写1,表示读数据
  73.     while (HSPWMA_ADR & 0x80);              //等待当前异步读取完成
  74.     dat = HSPWMA_DAT;                       //读取异步数据
  75.    
  76.     return dat;
  77. }
  78. void WritePWMA(char addr, char dat)
  79. {
  80.     while (HSPWMA_ADR & 0x80);              //等待前一个异步读写完成
  81.     HSPWMA_DAT = dat;                       //准备需要写入的数据
  82.     HSPWMA_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
  83.                                             //HSPWMA_ADDR寄存器的最高位写0,表示写数据
  84. }
  85. int main()
  86. {
  87.     ICacheOn();                             //使能ICACHE功能
  88.    
  89.     EAXFR = 1;
  90.    
  91.     P0M0 = 0; P0M1 = 0;
  92.     P1M0 = 0; P1M1 = 0;
  93.     P2M0 = 0; P2M1 = 0;
  94.     P3M0 = 0; P3M1 = 0;
  95.     P4M0 = 0; P4M1 = 0;
  96.     P5M0 = 0; P5M1 = 0;
  97.     //选择HPLL输入时钟分频
  98.     USBCLK &= ~PCKI_MSK;
  99.     USBCLK |= PCKI_D8;                      //PLL输入时钟8分频
  100.     //设置HPLL的除频系数
  101.     HPLLCR = HPLLDIV_82;                    //F_HPLL=60M/8*82/2=307.5M
  102.     //启动HPLL
  103.     HPLLCR |= ENHPLL;                       //使能HPLL
  104.     delay();                                //等待HPLL时钟稳定
  105.     //选择HSPWM/HSSPI时钟
  106. #if (HSCK_SEL == HSCK_MCLK)
  107.     CLKSEL &= ~HSIOCK;                      //HSPWM/HSSPI选择主时钟为时钟源
  108. #elif (HSCK_SEL == HSCK_PLL)
  109.     CLKSEL |= HSIOCK;                       //HSPWM/HSSPI选择PLL输出时钟为时钟源
  110. #else
  111.     CLKSEL &= ~HSIOCK;                      //默认HSPWM/HSSPI选择主时钟为时钟源
  112. #endif
  113.     HSCLKDIV = 0;                           //HSPWM/HSSPI时钟源不分频
  114.    
  115.     HSPWMA_CFG = 0x03;                      //使能PWMA相关寄存器异步访问功能
  116.    
  117.     PWMA_PS = 0x00;                         //PWMA_CC1/CC1N高速PWM输出到CC1/CC1N口
  118.                                             //注意:PWMA_PS属于I/O控制寄存器,不能使用异步方式进行读写
  119.     //通过异步方式设置PWMA的相关寄存器
  120.     WritePWMA((char)&PWMA_CCER1, 0x00);
  121.     WritePWMA((char)&PWMA_CCMR1, 0x00);     //CC1为输出模式
  122.     WritePWMA((char)&PWMA_CCMR1, 0x60);     //OC1REF输出PWM1(CNT<CCR时输出有效电平1)
  123.     WritePWMA((char)&PWMA_CCER1, 0x05);     //使能CC1/CC1N上的输出功能
  124.     WritePWMA((char)&PWMA_ENO, 0x03);       //使能PWM信号输出到端口P1.0/P1.1
  125.     WritePWMA((char)&PWMA_BKR, 0x80);       //使能主输出
  126.     WritePWMA((char)&PWMA_CCR1H, 0);        //设置PWM占空比为50个PWM时钟
  127.     WritePWMA((char)&PWMA_CCR1L, 50);
  128.     WritePWMA((char)&PWMA_ARRH, 0);         //设置输出PWM的周期为100个PWM时钟
  129.     WritePWMA((char)&PWMA_ARRL, 99);
  130.     WritePWMA((char)&PWMA_DTR, 10);         //设置互补对称输出PWM的死区
  131.     WritePWMA((char)&PWMA_CR1, 0x01);       //开始PWM计数
  132. //  P2 = ReadPWMA((char)&PWMA_ARRH);        //异步方式读取寄存器
  133. //  P0 = ReadPWMA((char)&PWMA_ARRL);
  134.     while (1);
  135. }
复制代码



PWM使用HPLL时钟(输出高速PWM)-CPU@60M ICACHE.zip

21 KB, 下载次数: 135

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-6-14 16:56:33 | 显示全部楼层
HPLL的输入频率确实比我们原始定的规格【6~12M】的范围要宽,【2~16M】都可以
HPLL输出频率超过700M/2,也就是PWM输入时钟超过350M,测试4个样品均输出正常
HPLL输出频率超过800M/2,也就是PWM输入时钟超过400M,测试4个样品,两个样品PWM无输出

500MHz/2 后占空比是50% 的250MHz PWM时钟
==搞音频PWM发声,这个250MHz 的PWM时钟源因该很舒服了
16位PWM 当16位用,当10位用,当8位用,当2~16位用


16位PWM当8位用的PWM最高频率



16位PWM当10位用的PWM最高频率


16位PWM当16位用的PWM最高频率



回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:96
  • 最近打卡:2025-04-30 06:09:25

0

主题

12

回帖

476

积分

中级会员

积分
476
发表于 2023-6-15 06:41:04 | 显示全部楼层
模拟DAC精度如何呢

点评

PWM模拟DAC的实际效果,取决于你实际测量他的ADC电路, 用这个ADC来检测反馈控制,高了就调低,低了就调高 !!! 信号发生器演示视频,STC32G12K128实验箱,老梁示波器 - STC 实验箱/核心功能实验板,原理图,MCU  详情 回复 发表于 2023-6-15 06:59
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-6-15 06:59:21 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-05-01 06:58:22

5

主题

184

回帖

1331

积分

金牌会员

积分
1331
发表于 2023-6-16 07:24:55 | 显示全部楼层
asx*** 发表于 2023-6-15 06:41
模拟DAC精度如何呢

PWM DAC's are very precise, because they are timing-determined.
Their drawback is the PWM needs to be filtered to give a varying analog value.
One trade off possible is to use two PWM pins and two resistors for faster updates.
Example if you use two 6 bit PWM and 10k and 640K resistors, you can output 4096 steps (12 bits) with faster PWM of SysCLK/64, which is more easily filtered externally.
The numbers given above of 250MHz and 307.5MHz PWM clocks, would give 3.90625MHz and 4.8046875MHz PWMs, for 2 x 6 bit, which can be easily filtered to give about 100kHz+ DAC performance.
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2023-6-19 14:03:16 | 显示全部楼层
STC32F12K54-56MHz-LQFP48,  7500片已到,全球发售,【免费+包邮】 送 !

另有 3万片途中,确保 全国大学生电子设计竞赛全部大学生智能车竞赛



HPLL的输入频率确实比我们原始定的规格【6~12M】的范围要宽,【2~16M】都可以

HPLL输出频率超过700M/2,也就是PWM输入时钟超过350M,测试4个样品均输出正常
HPLL输出频率超过800M/2,也就是PWM输入时钟超过400M,测试4个样品,两个样品PWM无输出

500MHz/2 后占空比是50% 的250MHz PWM时钟
==搞音频PWM发声,这个250MHz 的PWM时钟源因该很舒服了
16位PWM 当16位用,当10位用,当8位用,当2~16位用
16位PWM当8位用的PWM最高频率



16位PWM当10位用的PWM最高频率


16位PWM当16位用的PWM最高频率




回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:488
  • 最近打卡:2025-05-01 11:54:45
已绑定手机

20

主题

293

回帖

4436

积分

论坛元老

积分
4436
发表于 2023-6-20 15:41:09 | 显示全部楼层
购买的追风剑到货,发现引脚没有标注,使用起来找引脚就得半天。

追风剑

追风剑
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:484
  • 最近打卡:2025-05-01 08:52:01
已绑定手机

23

主题

589

回帖

2813

积分

金牌会员

积分
2813
发表于 2023-6-21 08:42:32 | 显示全部楼层
STC32F12K54-56MHz-LQFP48,  8000片已到,【免费+包邮送】,是真的吗?
不会还是只针对全国大赛才供货吧?看来我们公司产品上面也该采用这款芯片了!
我目前尚在使用STC32G12K128——TSSOP-20的在开发中》。。。

点评

有官方淘宝旗舰店零售的  发表于 2023-6-22 02:09
批量生产先用 STC32G12K128, STC32G8K64  详情 回复 发表于 2023-6-21 14:54
不停地学习
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 19:26 , Processed in 0.159747 second(s), 109 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表