zhp 发表于 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的时钟源)
/*************功能说明    **************

时钟说明:由内部IRC产生24MHz的时钟分频为6M提供给HPLL当作HPLL输入时钟,PLL锁频到246MHz输出作为高速PWM的时钟源,

PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P2.0口输出频率为24.6MHz,占空比为20%的PWM型号

PWM高速捕获说明:PWMB的CC5和CC6通道配置为捕获输入模式,CC5口P2.0口捕获信号的周期值,CC6从P2.0口捕获信号的占空比

测试说明:最后通过查询方式得到周期值和占空比并从串口送到PC显示

下载时, 选择默认IRC时钟 24MHz。

******************************************/

#include "stc32g.h"
#include "stdio.h"

#define FOSC            24000000UL

#define BAUD            (65536 - FOSC/4/115200)

#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,表示写数据
}

char ReadPWMB(char addr)
{
    char dat;
   
    while (HSPWMB_ADR & 0x80);            //等待前一个异步读写完成
    HSPWMB_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
                                          //HSPWMB_ADDR寄存器的最高位写1,表示读数据
    while (HSPWMB_ADR & 0x80);            //等待当前异步读取完成
    dat = HSPWMB_DAT;                     //读取异步数据
   
    return dat;
}

void WritePWMB(char addr, char dat)
{
    while (HSPWMB_ADR & 0x80);            //等待前一个异步读写完成
    HSPWMB_DAT = dat;                     //准备需要写入的数据
    HSPWMB_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
                                          //HSPWMB_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;
   
    SCON = 0x52;
    AUXR = 0x40;
    TMOD = 0x00;
    TL1 = BAUD;
    TH1 = BAUD >> 8;
    TR1 = 1;

    //选择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相关寄存器异步访问功能
   
   
    HSPWMA_CFG = 0x03;                      //使能PWMA相关寄存器异步访问功能
    HSPWMB_CFG = 0x03;                      //使能PWMB相关寄存器异步访问功能
   
    PWMA_PS = 0x01;                         //PWMA_CC1高速PWM输出到P2.0口
                                          //PWMB_CC5/PWMB_CC6从P2.0口进行捕获
                                          //注意:PWMA_PS和PWMB_PS属于I/O控制寄存器,不能使用异步方式进行读写

    //通过异步方式设置PWMA/PWMB的相关寄存器
    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, 0x01);       //使能PWM信号输出到端口
    WritePWMA((char)&PWMA_BKR, 0x80);       //使能主输出
    WritePWMA((char)&PWMA_CCR1H, 0x00);   //设置输出PWM的占空比
    WritePWMA((char)&PWMA_CCR1L, 0x02);
    WritePWMA((char)&PWMA_ARRH, 0x00);      //设置输出PWM的周期
    WritePWMA((char)&PWMA_ARRL, 0x09);
    WritePWMA((char)&PWMA_CR1, 0x01);       //开始PWM计数

    WritePWMB((char)&PWMB_CCER1, 0x00);
    WritePWMB((char)&PWMB_CCMR1, 0x01);   //CC5为输入模式,且映射到TI5FP5上
    WritePWMB((char)&PWMB_CCMR2, 0x02);   //CC6为输入模式,且映射到TI6FP5上
    WritePWMB((char)&PWMB_CCER1, 0x31);   //使能CC5上的捕获功能(上升沿捕获)
    WritePWMB((char)&PWMB_SMCR, 0x54);      //上升沿复位模式
    WritePWMB((char)&PWMB_CR1, 0x01);       //开始PWM计数
   
    while (1)
    {
      if (ReadPWMB((char)&PWMB_SR1) & 0x02)   //等待捕获完成
      {
            WritePWMB((char)&PWMB_SR1, 0x00);   //清除完成标志
            
            //读取捕获到的周期值
            printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5H) & 0xff);
            printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5L) & 0xff);
            printf(" ");
            
            //读取捕获到的占空比值
            printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6H) & 0xff);
            printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6L) & 0xff);
            printf("\n");
      }
    }
}


zhp 发表于 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的时钟源)
/*************功能说明    **************

时钟说明:由内部IRC产生24MHz的时钟分频为6M提供给HPLL当作HPLL输入时钟,PLL锁频到246MHz输出作为高速PWM的时钟源,

PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P2.0口输出频率为24.6MHz,占空比为20%的PWM型号

PWM高速捕获说明:PWMB的CC5和CC6通道配置为捕获输入模式,CC5口P2.0口捕获信号的周期值,CC6从P2.0口捕获信号的占空比

测试说明:最后通过中断方式得到周期值和占空比并从串口送到PC显示(注意要避免中断与主循环同时调用相同函数)

下载时, 选择默认IRC时钟 24MHz。

******************************************/

#include "stc32g.h"
#include "stdio.h"

#define FOSC            24000000UL

#define BAUD            (65536 - FOSC/4/115200)

#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,表示写数据
}

char ReadPWMB(char addr)
{
    char dat;
   
    while (HSPWMB_ADR & 0x80);            //等待前一个异步读写完成
    HSPWMB_ADR = addr | 0x80;               //设置间接访问地址,只需要设置原XFR地址的低7位
                                          //HSPWMB_ADDR寄存器的最高位写1,表示读数据
    while (HSPWMB_ADR & 0x80);            //等待当前异步读取完成
    dat = HSPWMB_DAT;                     //读取异步数据
   
    return dat;
}

void WritePWMB(char addr, char dat)
{
    while (HSPWMB_ADR & 0x80);            //等待前一个异步读写完成
    HSPWMB_DAT = dat;                     //准备需要写入的数据
    HSPWMB_ADR = addr & 0x7f;               //设置间接访问地址,只需要设置原XFR地址的低7位
                                          //HSPWMB_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;
   
    SCON = 0x52;
    AUXR = 0x40;
    TMOD = 0x00;
    TL1 = BAUD;
    TH1 = BAUD >> 8;
    TR1 = 1;

    //选择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相关寄存器异步访问功能
    HSPWMB_CFG = 0x07;                      //使能PWMB相关寄存器异步访问功能,并使能异步模式的PWMB中断
   
    PWMA_PS = 0x01;                         //PWMA_CC1高速PWM输出到P2.0口
                                          //PWMB_CC5/PWMB_CC6从P2.0口进行捕获
                                          //注意:PWMA_PS和PWMB_PS属于I/O控制寄存器,不能使用异步方式进行读写

    //通过异步方式设置PWMA/PWMB的相关寄存器
    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, 0x01);       //使能PWM信号输出到端口
    WritePWMA((char)&PWMA_BKR, 0x80);       //使能主输出
    WritePWMA((char)&PWMA_CCR1H, 0x00);   //设置输出PWM的占空比
    WritePWMA((char)&PWMA_CCR1L, 0x02);
    WritePWMA((char)&PWMA_ARRH, 0x00);      //设置输出PWM的周期
    WritePWMA((char)&PWMA_ARRL, 0x09);
    WritePWMA((char)&PWMA_CR1, 0x01);       //开始PWM计数

    WritePWMB((char)&PWMB_CCER1, 0x00);
    WritePWMB((char)&PWMB_CCMR1, 0x01);   //CC5为输入模式,且映射到TI5FP5上
    WritePWMB((char)&PWMB_CCMR2, 0x02);   //CC6为输入模式,且映射到TI6FP5上
    WritePWMB((char)&PWMB_CCER1, 0x31);   //使能CC5上的捕获功能(上升沿捕获)
    WritePWMB((char)&PWMB_SMCR, 0x54);      //上升沿复位模式
    WritePWMB((char)&PWMB_CR1, 0x01);       //开始PWM计数
    WritePWMB((char)&PWMB_IER, 0x02);       //使能CC5捕获中断
   
    EA = 1;
   
    while (1);
}

void PWMB_ISR() interrupt 27
{
    if (ReadPWMB((char)&PWMB_SR1) & 0x02)   //等待捕获完成
    {
      WritePWMB((char)&PWMB_SR1, 0x00);   //清除完成标志
      
      //读取捕获到的周期值
      printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5H) & 0xff);
      printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR5L) & 0xff);
      printf(" ");
      
      //读取捕获到的占空比值
      printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6H) & 0xff);
      printf("%02x", (unsigned int)ReadPWMB((char)&PWMB_CCR6L) & 0xff);
      printf("\n");
    }
}

zhp 发表于 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的时钟源)
/*************功能说明    **************

时钟说明:由内部IRC产生60MHz的时钟当作CPU时钟,同时8分频产生7.5M提供给HPLL
          当作HPLL输入时钟,PLL锁频到307.5MHz输出作为高速PWM的时钟源,

PWM高速输出说明:PWMA的CC1通道配置为输出模式,并从P1.0/P1.1口输出频率为3.705MHz,
               占空比为50%的互补对称带死区的PWM波形

CPU时钟说明:ISP下载软件根据CPU工作频率为60MHz,会自动将WTST设置为2
             用户代码中不用对WTST进行设置。范例中使能了ICACHE功能,
             可有效的提高代码执行效率

下载时, 选择默认IRC时钟 60MHz。

******************************************/

#include "stc32g.h"

#define FOSC            60000000UL

#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++);
}

void ICacheOn()
{
    bit fEA;
   
    if (WTST > 0)                           //WTST为0时不需要且不能使能ICACHE
    {
      fEA = EA;                           //保存EA
      EA = 0;                           //关闭中断
      _nop_();
      _nop_();
      TA = 0xaa;                        //写入触发命令序列1
                                          //此处不能有其他任何指令
      TA = 0x55;                        //写入触发命令序列2
                                          //此处不能有其他任何指令
      ICHECR = 0x01;                      //写保护暂时关闭,可以修改ICHECR中的EN位
                                          //EN位再次进入写保护状态
      _nop_();
      _nop_();
      EA = fEA;                           //恢复EA
    }
}

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()
{
    ICacheOn();                           //使能ICACHE功能
   
    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输入时钟分频
    USBCLK &= ~PCKI_MSK;
    USBCLK |= PCKI_D8;                      //PLL输入时钟8分频

    //设置HPLL的除频系数
    HPLLCR = HPLLDIV_82;                  //F_HPLL=60M/8*82/2=307.5M

    //启动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);
}




神农鼎 发表于 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最高频率
https://www.stcaimcu.com/data/attachment/forum/202306/19/135245va7h529y8ryi02az.png

16位PWM当10位用的PWM最高频率
https://www.stcaimcu.com/data/attachment/forum/202306/19/135245gbxskr8rrlgrrbbj.png

16位PWM当16位用的PWM最高频率
https://www.stcaimcu.com/data/attachment/forum/202306/19/135245novl9eywyouwzz94.png


asxddz 发表于 2023-6-15 06:41:04

模拟DAC精度如何呢

神农鼎 发表于 2023-6-15 06:59:21

asxddz 发表于 2023-6-15 06:41
模拟DAC精度如何呢PWM模拟DAC的实际效果,取决于你实际测量他的ADC电路,
用这个ADC来检测反馈控制,高了就调低,低了就调高 !!!

信号发生器演示视频,STC32G12K128实验箱,老梁示波器 - STC 实验箱/核心功能实验板,原理图,MCU结构讨论区,大学教材 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)

jmg 发表于 2023-6-16 07:24:55

asxddz 发表于 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.

神农鼎 发表于 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最高频率
https://www.stcaimcu.com/data/attachment/forum/202306/19/135245va7h529y8ryi02az.png

16位PWM当10位用的PWM最高频率
https://www.stcaimcu.com/data/attachment/forum/202306/19/135245gbxskr8rrlgrrbbj.png

16位PWM当16位用的PWM最高频率
https://www.stcaimcu.com/data/attachment/forum/202306/19/135245novl9eywyouwzz94.png



马永锋 发表于 2023-6-20 15:41:09

购买的追风剑到货,发现引脚没有标注,使用起来找引脚就得半天。

WHX 发表于 2023-6-21 08:42:32

STC32F12K54-56MHz-LQFP48,8000片已到,【免费+包邮送】,是真的吗?
不会还是只针对全国大赛才供货吧?看来我们公司产品上面也该采用这款芯片了!
我目前尚在使用STC32G12K128——TSSOP-20的在开发中》。。。
页: 1 [2] 3
查看完整版本: 硬件三角函数运算器, 硬件浮点运算器, 追风剑-STC32F12K64-56MHz,FOC方案征集