找回密码
 立即注册
查看: 253|回复: 2

AI8051U pwm时钟最低可以达到多少K

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-01-03 16:36:23
已绑定手机

1

主题

2

回帖

27

积分

新手上路

积分
27
发表于 2024-12-5 10:17:11 | 显示全部楼层 |阅读模式

我这边的时钟是外部11.0592Mhz,倍频到PLL:96Mhz--MCLK:96Mhz---分频到SysCLK:32Mhz。这一支路没问题。但是PWM的最低时钟只能分频为3MHZ,无论HSCLKDIV,PWM_CLKDIV怎么设置都不行,只能设置为HSCLKDIV*PWM_CLKDIV=32,即PWM的最低时钟只能分频为3MHZ。

上例子:

/---------------------------------------------------------------------/ / --- Web: www.STCAI.com ---------------------------------------------/ /---------------------------------------------------------------------/

/***** 功能说明 **

本例程基于AI8051U为主控芯片的实验箱进行编写测试。

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

高速高级PWM定时器 PWM1P/PWM1N,PWM2P/PWM2N,PWM3P/PWM3N,PWM4P/PWM4N 每个通道都可独立实现PWM输出,或者两两互补对称输出.

8个通道PWM设置对应P0的8个端口.

通过P0口上连接的8个LED灯,利用PWM实现呼吸灯效果.

PWM周期和占空比可以根据需要自行设置,最高可达65535.

下载时, 选择时钟 24MHz (用户可自行修改频率).

**/

include "AI8051U.h"

include "stdio.h"

include "intrins.h"

typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32;

/** 用户定义宏 ***/

define MAIN_Fosc 32000000UL

define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率, 1000次/秒

/*****/

define HSCK_MCLK 0

define HSCK_PLL 1

define HSCK_SEL HSCK_PLL

define PLL_96M 0

define PLL_144M 1

define PLL_SEL PLL_144M

define CKMS 0x80

define HSIOCK 0x40

define MCK2SEL_MSK 0x0c

define MCK2SEL_SEL1 0x00

define MCK2SEL_PLL 0x04

define MCK2SEL_PLLD2 0x08

define MCK2SEL_IRC48 0x0c

define MCKSEL_MSK 0x03

define MCKSEL_HIRC 0x00

define MCKSEL_XOSC 0x01

define MCKSEL_X32K 0x02

define MCKSEL_IRC32K 0x03

define ENCKM 0x80

define PCKI_MSK 0x60

define PCKI_D1 0x00

define PCKI_D2 0x20

define PCKI_D4 0x40

define PCKI_D8 0x60

/***** 本地常量声明 **/

define PWM1_0 0x00 //P:P1.0 N:P1.1

define PWM1_1 0x01 //P:P0.0 N:P0.1

define PWM1_2 0x02 //P:P2.0 N:P2.1

define PWM2_0 0x00 //P:P1.2 N:P1.3

define PWM2_1 0x04 //P:P0.2 N:P0.3

define PWM2_2 0x08 //P:P2.2 N:P2.3

define PWM3_0 0x00 //P:P1.4 N:P1.5

define PWM3_1 0x10 //P:P0.4 N:P0.5

define PWM3_2 0x20 //P:P2.4 N:P2.5

define PWM4_0 0x00 //P:P1.6 N:P1.7

define PWM4_1 0x40 //P:P0.6 N:P0.7

define PWM4_2 0x80 //P:P2.6 N:P2.7

define ENO1P 0x01

define ENO1N 0x02

define ENO2P 0x04

define ENO2N 0x08

define ENO3P 0x10

define ENO3N 0x20

define ENO4P 0x40

define ENO4N 0x80

define PWM_PERIOD 60000 //设置周期值

/***** 本地变量声明 **/

bit B_1ms; //1ms标志

u16 PWM1_Duty; u16 PWM2_Duty; u16 PWM3_Duty; u16 PWM4_Duty;

bit PWM1_Flag; bit PWM2_Flag; bit PWM3_Flag; bit PWM4_Flag;

void PllConfig(void); void HSPwmConfig(void); void UpdatePwm(void);

void HSPwmConfig1(void); void UpdatePwm1(void);

long ldata[3]; unsigned long int lint;

/* 主函数 *****/ void main(void) { WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快 EAXFR = 1; //扩展寄存器(XFR)访问使能 CKCON = 0; //提高访问XRAM速度

P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    ldata[0]=0x1234;
    ldata[1]=0x5678;
    ldata[2]=0x9876;
    lint=0xaabbccdd;

        //*******************************timer0
  TM0PS=0;
  ET0 = 1;    //允许中断
//  PT0 = 1;    //高优先级中断
TMOD &= ~0x03;
TMOD |= 1;  //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
//  T0_CT = 1;  //计数

// T0_CT = 0; //定时 T0CLKO = 1; //输出时钟 // T0CLKO = 0; //不输出时钟 T0x12 = 0; //12T mode TH0 = (u8)((65536UL - Timer0_Reload/12) / 256); TL0 = (u8)((65536UL - Timer0_Reload/12) % 256);

  P6SR = 0x00;    //IO口电平转换速度加快
    PWMB_PS = 0x00;    //高级 PWM 通道输出脚选择位
PWMB_PS |= 0x01; //选择 PWM5_2 通道


  PllConfig();
HSPwmConfig1();



PWM1_Flag = 0;
PWM2_Flag = 0;
PWM3_Flag = 0;
PWM4_Flag = 0;

PWM1_Duty = 0;
PWM2_Duty = 256;
PWM3_Duty = 512;
PWM4_Duty = 1024;




TR0=1;
P22 = 0;    //给LED供电
EA = 1;     //打开总中断


while (1);

}

/** Timer0 1ms中断函数 ****/ void timer0(void) interrupt 1 { TH0 = (u8)((65536UL - Timer0_Reload/12) / 256); TL0 = (u8)((65536UL - Timer0_Reload/12) % 256);

/* if(!PWM4_Flag) { PWM4_Duty++; if(PWM4_Duty > PWM_PERIOD) PWM4_Flag = 1; } else { PWM4_Duty--; if(PWM4_Duty <= 0) PWM4_Flag = 0; }

UpdatePwm1();

    */

}

//======================================================================== // 函数: delay(void) // 描述: 延时函数. // 参数: none. // 返回: none. // 版本: V1.0, 2022-03-16 //======================================================================== void delay(void) { u8 i; for(i=0; i<100; i++); }

//======================================================================== // 函数: WritePWMB(void) // 描述: 异步读取PWMA特殊功能寄存器函数. // 参数: addr: 写入特殊功能寄存器地址. // 参数: dat: 写入特殊功能寄存器内容. // 返回: none. // 版本: V1.0, 2022-03-16 //======================================================================== void WritePWMB(u8 addr, u8 dat) { while (HSPWMB_ADR & 0x80); //等待前一个异步读写完成 HSPWMB_DAT = dat; //准备需要写入的数据 HSPWMB_ADR = addr & 0x7f; //设置间接访问地址,只需要设置原XFR地址的低7位 //HSPWMA_ADDR寄存器的最高位写0,表示写数据 }

//======================================================================== // 函数: HSPwmConfig(void) // 描述: PWM初始化函数. // 参数: none. // 返回: none. // 版本: V1.0, 2022-03-16 //======================================================================== void HSPwmConfig1(void) { HSPWMB_CFG = 0x03; //使能PWMB相关寄存器异步访问功能

//通过异步方式设置PWMA的相关寄存器
WritePWMB((u8)&PWMB_CCER1, 0x00);

WritePWMB((u8)&PWMB_CCER2, 0x00);

  WritePWMB((u8)&PWMB_CCER1, 0x00);

WritePWMB((u8)&PWMB_CCER2, 0x00);


WritePWMB((u8)&PWMB_CCMR1, 0x68);            //通道模式配置


WritePWMB((u8)&PWMB_CCER1, 0x33);            //配置通道输出使能和极性
WritePWMB((u8)&PWMB_CCER2, 0x33);


WritePWMB((u8)&PWMB_CCMR1, 0x68);                           //开启PWMB_CCR5预转载功能(需要CC5E=1才可写)

/* WritePWMB((u8)&PWMB_CCR5H, 0); //设置输出PWM的占空比 WritePWMB((u8)&PWMB_CCR5L, 10);

WritePWMB((u8)&PWMB_ARRH,(u8)(PWM_PERIOD >> 8));   //设置输出PWM的周期
WritePWMB((u8)&PWMB_ARRL,(u8)PWM_PERIOD);

*/

WritePWMB((u8)&PWMB_CCR5H, 1);    //设置输出PWM的占空比
WritePWMB((u8)&PWMB_CCR5L, 0xf4); 

WritePWMB((u8)&PWMB_ARRH,0x03);   //设置输出PWM的周期
WritePWMB((u8)&PWMB_ARRL,0xe8);


    WritePWMB((u8)&PWMB_BKR, 0x80);                //使能主输出
    WritePWMB((u8)&PWMB_CR1, 0x81);                //使能ARR预装载,开始PWM计数



    WritePWMB((u8)&PWMB_ENO,0);    //使能PWM信号输出端口
    WritePWMB((u8)&PWMB_ENO, 1);    //使能PWM信号输出端口

    PWMB_PS = 0x00;    //高级 PWM 通道输出脚选择位

PWMB_PS |= 0x01; //选择 PWM5_2 通道 ----测试用的P1.1

    // PWMB_PS |= 0x02; //选择 PWM5_2 通道  ----PMOS--p2.1

}

void UpdatePwm1(void) {

WritePWMB((u8)&PWMB_CCR5H, (u8)(PWM4_Duty >> 8));    //设置输出PWM的占空比
WritePWMB((u8)&PWMB_CCR5L, (u8)PWM4_Duty);

}

//======================================================================== // 函数: PllConfig(void) // 描述: PWM时钟初始化函数. // 参数: none. // 返回: none. // 版本: V1.0, 2022-03-16 //======================================================================== void PllConfig(void) { //选择PLL输出时钟 /*

if(PLL_SEL == PLL_96M)

CLKSEL &= ~CKMS; //选择PLL的96M作为PLL的输出时钟

elif(PLL_SEL == PLL_144M)

CLKSEL |= CKMS; //选择PLL的144M作为PLL的输出时钟

else

CLKSEL &= ~CKMS; //默认选择PLL的96M作为PLL的输出时钟

endif

//选择PLL输入时钟分频,保证输入时钟为12M
USBCLK &= ~PCKI_MSK;

if(MAIN_Fosc == 12000000UL)

USBCLK |= PCKI_D1; //PLL输入时钟1分频

elif(MAIN_Fosc == 24000000UL)

USBCLK |= PCKI_D2; //PLL输入时钟2分频

elif(MAIN_Fosc == 48000000UL)

USBCLK |= PCKI_D4; //PLL输入时钟4分频

elif(MAIN_Fosc == 96000000UL)

USBCLK |= PCKI_D8; //PLL输入时钟8分频

else

USBCLK |= PCKI_D1; //默认PLL输入时钟1分频

endif

//启动PLL
USBCLK |= ENCKM;            //使能PLL倍频
USBCLK |= 0x10;            //使能时钟追频
delay();                    //等待PLL锁频

//选择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时钟源不分频


    */





  XOSCCR|=0xD8;//启用外部晶振
  while(!(XOSCCR&1));//等待时钟稳定
  CLKDIV=0x00;//时钟不分频



    CLKSEL &= ~CKMS;            //选择PLL的96M作为PLL的输出时钟
    CLKSEL |=MCKSEL_XOSC ;      //选择外部晶振--01--前端
 // CLKSEL |= MCKSEL_MSK;   //选择外部晶振--01

// USBCLK |= PCKI_D1; //输入时钟0分频(选择PLL输入时钟分频,保证输入时钟为12M) USBCLK &=~PCKI_MSK ;//输入时钟0分频(选择PLL输入时钟分频,保证输入时钟为12M) //启动PLL USBCLK |= ENCKM; //使能PLL倍频 USBCLK |= 0x10; //使能时钟追频 // delay_ms(1); //等待PLL锁频 delay(); //等待PLL锁频 delay(); //等待PLL锁频 CLKDIV = 3; //主时钟选择高速频率前,必须先设置分频系数,否则程序会当掉96M/3=32MHZ

CLKSEL |= MCK2SEL_PLL;   //选择内部PLL ---01---后端

// CLKSEL |= HSIOCK; //选择PLL输出时钟作为高速IO的时钟源-PLL输出96MHz/144MHz的PLLCLK为高速I/O时钟源--0X40

CLKSEL &= !HSIOCK;    //选择PLL输出时钟作为高速IO的时钟源-PLL输出96MHz/144MHz的PLLCLK为高速I/O时钟源--0X40
  //HSCLKDIV=HSCLKDIVV;   //1分频
    //PWMB_CLKDIV=PWMB_CLKDIVV;//96分频为1Mhz


    HSCLKDIV=96;   //96分频
    PWMB_CLKDIV=1;//200分频为5k





    MCLKOCR=32;




}

回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-01-03 16:36:23
已绑定手机

1

主题

2

回帖

27

积分

新手上路

积分
27
发表于 2024-12-5 10:19:05 | 显示全部楼层

HSCLKDIV=32;

PWMB_CLKDIV=1;

改成这样才正常

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-01-03 16:36:23
已绑定手机

1

主题

2

回帖

27

积分

新手上路

积分
27
发表于 2024-12-5 11:06:04 | 显示全部楼层

提示一下好像是设置分频很大的时候好像卡在这里:

void HSPwmConfig1(void) { HSPWMB_CFG = 0x03; //使能PWMB相关寄存器异步访问功能

//通过异步方式设置PWMA的相关寄存器
WritePWMB((u8)&PWMB_CCER1, 0x00);

WritePWMB((u8)&PWMB_CCER2, 0x00);

  WritePWMB((u8)&PWMB_CCER1, 0x00);

WritePWMB((u8)&PWMB_CCER2, 0x00);
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 06:49 , Processed in 0.145524 second(s), 58 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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