当前位置: 首页 > news >正文

STC32G144K246,高速PWM@240Mhz 运行测试

高速PWM@240MHz 运行测试, STC32G144K246:
程序使用CHIPID参数固定内部时钟为24Mhz,
且通过HPLL功能升频至480MHz
其中,给CPU的为120MHz分频时钟,
PWM外设的为240MHz分频时钟
串口使用115200波特率,
内部带有异步写入PWMA@240MHz和异步读取示例
效果是P60~P67上输出一个互补且循环自增的占空比,
表现为LED灯从最暗到最亮然后再继续循环
 


实际测量程序输出为:
58Khz,PWMA无预分频,PWMA_ARR设置为4096,
所以58Khz*4096=237Mhz,与理论值240Mhz接近
 


以下为程序代码和编译通过的程序文件:
这个是与CPU同频的PWM输出示例

STC32G144K246 输出PWM测试.zip (74.59 KB, 下载次数: 4)
这个是与CPU不同频率的PWM输出示例

STC32G144K246 240MHz-HSPWM.zip (212.39 KB, 下载次数: 3)
程序内容:

 
  1. #include "STC32G.H"
  2. #include "stdio.h"
  3. #include "stdarg.h"
  4. //本例程使用CHIPID内预置参数,设置HIRC为24MHz
  5. //使用HPLL1,提供60Mhz,80Mhz,120Mhz的设置例程
  6. #define Fosc_60Mhz 0 //系统时钟为60Mhz
  7. #define Fosc_80Mhz 1 //系统时钟为80Mhz
  8. #define Fosc_120Mhz 2//系统时钟为120Mhz
  9. #define Main_Fosc Fosc_120Mhz //设置系统时钟为120Mhz
  10. void CLK_Init(void);                                //设置系统时钟,由Main_Fosc定义设置
  11. void Timer0_Init(void);                        //定时器0初始化函数
  12. void Io_Init(void);                                        //I/O口初始化函数,设置P32为开漏+打开内部上拉电阻模式
  13. void Uart1_Init(void);                        //串口初始化函数,500000bps
  14. void Pwm_Init(void);                                //PWM初始化函数
  15. void UpdatePwm(void);                                //更新PWM占空比函数
  16. void UpdateHSPwm(void);                        //更新高速PWM占空比函数
  17. void WritePWMA(char addr, char dat);        //异步方式写入PWM寄存器
  18. char ReadPWMA(char addr);                                                        //异步方式读出PWM寄存器
  19. void uart_send(int num);
  20. bit P32_OUT = 1;                                                //用于确定输出电平
  21. char uart_buff[64] = {0};
  22. unsigned int PWM1_Duty = 100, PWM2_Duty = 500, PWM3_Duty = 2000, PWM4_Duty = 4000, Duty_All = 0;
  23. void Delay100ms(void)        //@120MHz
  24. {
  25.         unsigned long edata i;
  26.         _nop_();
  27.         _nop_();
  28.         i = 2999998UL;
  29.         while (i) i--;
  30. }
  31. unsigned int read_pwmh = 0, read_pwml = 0;
  32. void main(void)
  33. {
  34.         EAXFR = 1;                                        //使能访问扩展RAM区特殊功能寄存器(XFR)
  35.         CKCON &= ~0x07;                        //清空[2:0],设置外部数据总线等待时钟为0(最快),默认为7
  36.         CLK_Init();                                        //设置HPLL时钟为指定频率
  37.         Timer0_Init();                        //初始化定时器0,50毫秒@120MHz
  38.         Uart1_Init();                                //串口初始化函数,115200bps
  39.         Pwm_Init();                                        //PWM初始化函数
  40.         HSPWMA_CFG = 0x03;        //使能 PWMA 相关寄存器异步访问功能
  41.         HPLL2CR &= ~(3<<5);        //清空高速外设时钟选择
  42.         HPLL2CR |= (0<<5);        //选择HPLL1/2
  43.         Io_Init();                                        //初始化I/O口,设置P32等效为原准双向口模式(开漏模式+打开内部上拉电阻)
  44.         EA = 1;                                                        //打开总中断
  45.         while(1)
  46.         {
  47.                 //用户程序
  48.                 Duty_All = (Duty_All+150)&0xfff;//限制最大值4095
  49.                 PWM1_Duty = PWM2_Duty = PWM3_Duty = PWM4_Duty = Duty_All;//调整占空比
  50.                 //UpdatePwm();//更新占空比
  51.                 UpdateHSPwm();
  52.                 read_pwmh = (unsigned char)ReadPWMA((char)&PWMA_CCR1H);
  53.                 read_pwml = (unsigned char)ReadPWMA((char)&PWMA_CCR1L);
  54.                 uart_send(sprintf(uart_buff, "read_pwm_cnt:0x%x%x, duty:%u\r\n",read_pwmh, read_pwml, Duty_All));//串口回传当前占空比
  55.                 Delay100ms();
  56.         }
  57. }
  58. bit uart_flag = 0;
  59. void send_dat(char c)
  60. {
  61.         uart_flag = 1;
  62.         SBUF = c;
  63.         while(uart_flag);
  64. }
  65. int data dat_len = 0;
  66. void uart_send(int num)
  67. {
  68.         for(dat_len = 0; dat_len<num; dat_len++)
  69.         {
  70.                 send_dat(uart_buff[dat_len]);
  71.         }
  72. }
  73. void Uart1_Isr(void) interrupt 4
  74. {
  75.         if (TI)                                //检测串口1发送中断
  76.         {
  77.                 TI = 0;                        //清除串口1发送中断请求位
  78.                 uart_flag = 0;
  79.         }
  80.         if (RI)                                //检测串口1接收中断
  81.         {
  82.                 RI = 0;                        //清除串口1接收中断请求位
  83.         }
  84. }
  85. void Uart1_Init(void)        //115200bps@120MHz
  86. {
  87.         SCON = 0x50;                //8位数据,可变波特率
  88.         AUXR |= 0x40;                //定时器时钟1T模式
  89.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  90.         TMOD &= 0x0F;                //设置定时器模式
  91.         TL1 = 0xFC;                        //设置定时初始值
  92.         TH1 = 0xFE;                        //设置定时初始值
  93.         ET1 = 0;                        //禁止定时器中断
  94.         TR1 = 1;                        //定时器1开始计时
  95.         ES = 1;                                //使能串口1中断
  96. }
  97. char data off_t0_cnt = 0;
  98. void Timer0_Isr(void) interrupt 1
  99. {
  100.         if(P32_OUT == 1&&P32 == 0&&off_t0_cnt<100)off_t0_cnt++;        //判断外部P32按键按下一定时间时,关闭定时器0
  101.         if(off_t0_cnt>5)TR0 = 0;//注:仅在P32输出为1的时候,外部的按键按下才能被读到
  102.         P32_OUT = ~P32_OUT;//每隔10ms亮/灭切换一次
  103.         P32 = P32_OUT;                //将输出电平给P32管脚
  104. }
  105. void Timer0_Init(void)                //50毫秒@120MHz
  106. {
  107.         TM0PS = 0x5B;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
  108.         AUXR |= 0x80;                        //定时器时钟1T模式
  109.         TMOD &= 0xF0;                        //设置定时器模式
  110.         TL0 = 0x3F;                                //设置定时初始值
  111.         TH0 = 0x01;                                //设置定时初始值
  112.         TF0 = 0;                                //清除TF0标志
  113.         TR0 = 1;                                //定时器0开始计时
  114.         ET0 = 1;                                //使能定时器0中断
  115.         T0CLKO = 1;                        //使能P35输出定时器溢出时钟
  116. }
  117. void Io_Init(void)
  118. {
  119.         P3M0 = 0x26; P3M1 = 0xdd;
  120.         P3PU = 0x05;
  121.         P3SR = 0xdc;
  122.         P3DR = 0xdc;
  123.         P6M0 = 0xff; P6M1 = 0x00; //推挽输出,P6,PWM
  124.         P6SR = 0x00; //转换速度和驱动电流最大,P6
  125.         P6DR = 0x00;
  126. }
  127. void Delay10ms(void)        //@120MHz
  128. {
  129.         unsigned long edata i;
  130.         _nop_();
  131.         _nop_();
  132.         i = 299998UL;
  133.         while (i) i--;
  134. }
  135. void CLK_Init(void)
  136. {
  137.         #if Main_Fosc == Fosc_120Mhz
  138.         WTST = 4;CLKDIV = 2;                 //设置系统时钟=480MHz/2/2=120MHz,(因为CLKSEL选择时,已经将HPLL/2了)
  139.         #elif Main_Fosc == Fosc_80Mhz
  140.         WTST = 3;CLKDIV = 3;         //设置系统时钟=480MHz/2/3=80MHz
  141.         #elif Main_Fosc == Fosc_60Mhz
  142.         WTST = 2;CLKDIV = 4;         //设置系统时钟=480MHz/2/4=60MHz
  143.         #endif
  144.         //以下为超过60MHz时,系统时钟使用HPLL方式提供
  145.         VRTRIM = CHIPID22;                //载入27MHz频段的VRTRIM值
  146.         IRTRIM = CHIPID12;                //指定当前HIRC为24MHz,此时会覆盖掉ISP设置的时钟频率
  147.         IRCBAND &= ~0x03;                        //清空频段选择
  148.         IRCBAND |= 0x01;                        //选择27Mhz频段
  149.         HPLLCR &= ~0x10;            //选择HPLL输入时钟源为HIRC
  150.         HPLLPDIV = 4;                                        //24MHz/4=6MHz,需要保证输入HPLL的时钟在6MHz附近
  151.         HPLLCR |= 0x0e;             //HPLL=6MHz*80=480MHz
  152.         HPLLCR |= 0x80;             //使能HPLL
  153.         Delay10ms();
  154.         CLKSEL &= ~0x03;                        //BASE_CLK选择为HIRC,用以提供给HPLL
  155.         CLKSEL &= ~0x0c;                        //清空主时钟源选择
  156.         CLKSEL |= 1<<2;                                //设置主时钟源为内部 HPLL1 输出/2
  157. }
  158. #define PWM1_1      0x00    //P:P1.0  N:P1.1
  159. #define PWM1_2      0x01    //P:P2.0  N:P2.1
  160. #define PWM1_3      0x02    //P:P6.0  N:P6.1
  161. #define PWM2_1      0x00    //P:P1.2/P5.4  N:P1.3
  162. #define PWM2_2      0x04    //P:P2.2  N:P2.3
  163. #define PWM2_3      0x08    //P:P6.2  N:P6.3
  164. #define PWM3_1      0x00    //P:P1.4  N:P1.5
  165. #define PWM3_2      0x10    //P:P2.4  N:P2.5
  166. #define PWM3_3      0x20    //P:P6.4  N:P6.5
  167. #define PWM4_1      0x00    //P:P1.6  N:P1.7
  168. #define PWM4_2      0x40    //P:P2.6  N:P2.7
  169. #define PWM4_3      0x80    //P:P6.6  N:P6.7
  170. #define PWM4_4      0xC0    //P:P3.4  N:P3.3
  171. #define ENO1P       0x01
  172. #define ENO1N       0x02
  173. #define ENO2P       0x04
  174. #define ENO2N       0x08
  175. #define ENO3P       0x10
  176. #define ENO3N       0x20
  177. #define ENO4P       0x40
  178. #define ENO4N       0x80
  179. void Pwm_Init(void)
  180. {
  181.         PWMA_CCER1 = 0x00;  //写 CCMRx 前必须先清零 CCxE 关闭通道
  182.         PWMA_CCER2 = 0x00;
  183.         PWMA_CCMR1 = 0x60;  //通道模式配置
  184.         PWMA_CCMR2 = 0x60;
  185.         PWMA_CCMR3 = 0x60;
  186.         PWMA_CCMR4 = 0x60;
  187.         PWMA_CCER1 = 0x55;  //配置通道输出使能和极性
  188.         PWMA_CCER2 = 0x55;
  189.         PWMA_ARRH = 0x0f;   //设置周期时间
  190.         PWMA_ARRL = 0xff;
  191.         PWMA_DTR = 0x40;   //设置死区时间
  192.         PWMA_PSCRH = 0;    //设置预分频器
  193.         PWMA_PSCRL = 0;    //设置预分频器
  194.         PWMA_ENO = 0x00;
  195.         PWMA_ENO |= ENO1P; //使能输出
  196.         PWMA_ENO |= ENO1N; //使能输出
  197.         PWMA_ENO |= ENO2P; //使能输出
  198.         PWMA_ENO |= ENO2N; //使能输出
  199.         PWMA_ENO |= ENO3P; //使能输出
  200.         PWMA_ENO |= ENO3N; //使能输出
  201.         PWMA_ENO |= ENO4P; //使能输出
  202.         PWMA_ENO |= ENO4N; //使能输出
  203.         PWMA_PS = 0x00;  //高级 PWM 通道输出脚选择位
  204.         PWMA_PS |= PWM1_3; //选择 PWM1_3 通道
  205.         PWMA_PS |= PWM2_3; //选择 PWM2_3 通道
  206.         PWMA_PS |= PWM3_3; //选择 PWM3_3 通道
  207.         PWMA_PS |= PWM4_3; //选择 PWM4_3 通道
  208.         
  209.         UpdatePwm();
  210.         
  211.         PWMA_BKR = 0x80; //使能主输出
  212.         PWMA_CR1 |= 0x01; //开始计时
  213. }
  214. void UpdatePwm(void)
  215. {
  216.         PWMA_CCR1H = (unsigned char)(PWM1_Duty >> 8); //设置占空比时间
  217.         PWMA_CCR1L = (unsigned char)(PWM1_Duty);
  218.         PWMA_CCR2H = (unsigned char)(PWM2_Duty >> 8); //设置占空比时间
  219.         PWMA_CCR2L = (unsigned char)(PWM2_Duty);
  220.         PWMA_CCR3H = (unsigned char)(PWM3_Duty >> 8); //设置占空比时间
  221.         PWMA_CCR3L = (unsigned char)(PWM3_Duty);
  222.         PWMA_CCR4H = (unsigned char)(PWM4_Duty >> 8); //设置占空比时间
  223.         PWMA_CCR4L = (unsigned char)(PWM4_Duty);
  224. }
  225. void UpdateHSPwm(void)
  226. {
  227.         WritePWMA((char)&PWMA_CCR1H,(unsigned char)(PWM1_Duty >> 8));
  228.         WritePWMA((char)&PWMA_CCR1L,(unsigned char)(PWM1_Duty));
  229.         WritePWMA((char)&PWMA_CCR2H,(unsigned char)(PWM2_Duty >> 8));
  230.         WritePWMA((char)&PWMA_CCR2L,(unsigned char)(PWM2_Duty));
  231.         WritePWMA((char)&PWMA_CCR3H,(unsigned char)(PWM3_Duty >> 8));
  232.         WritePWMA((char)&PWMA_CCR3L,(unsigned char)(PWM3_Duty));
  233.         WritePWMA((char)&PWMA_CCR4H,(unsigned char)(PWM4_Duty >> 8));
  234.         WritePWMA((char)&PWMA_CCR4L,(unsigned char)(PWM4_Duty));
  235. }
  236. char ReadPWMA(char addr)
  237. {
  238.         char dat;
  239.         while (HSPWMA_ADR & 0x80);//等待前一个异步读写完成
  240.         HSPWMA_ADR = addr | 0x80;//设置间接访问地址,只需要设置原 XFR 地址的低 7 位。HSPWMA_ADR 寄存器的最高位写 1,表示读数据
  241.         while (HSPWMA_ADR & 0x80);//等待当前异步读取完成
  242.         dat = HSPWMA_DAT;//读取异步数据
  243.         return dat;
  244. }
  245. void WritePWMA(char addr, char dat)
  246. {
  247.         while (HSPWMA_ADR & 0x80);//等待前一个异步读写完成
  248.         HSPWMA_DAT = dat;//准备需要写入的数据
  249.         HSPWMA_ADR = addr & 0x7f;//设置间接访问地址,只需要设置原 XFR 地址的低 7 位。HSPWMA_ADR 寄存器的最高位写 0,表示写数据
  250. }

STC32G144K246,高速PWM@240Mhz 运行测试
https://www.stcaimcu.com/thread-20680-1-1.html
(出处: 国芯人工智能技术交流网站)

http://www.dtcms.com/a/528039.html

相关文章:

  • OpenHarmony轻量级内核LiteOS-M技术详解与应用实践
  • hive自定义函数
  • 做新媒体每天必看的网站wordpress exif
  • Elasticsearch从入门到进阶——分布式特性
  • Elasticsearch并发更新冲突问题与解决
  • 数据结构14:查找
  • 怎样做网站模板wordpress用阿里云oss
  • Spring Java配置:告别XML新时代
  • Flutter 异步进阶:Isolate 与 compute 的性能优化实践
  • 太原网站建设模板网页制作的公司怎么注册
  • Linux拓展
  • 亚马逊云渠道商:本地SSD缓存如何保障数据安全?
  • seo外包公司排名深圳网站优化最好的方法
  • SQL优化详解与案例、以及索引失效场景;
  • llama.cpp:Linux_x86端测试Qwen2.5-Omni
  • Java-160 MongoDB副本集部署实战 单机三实例/多机同法 10 分钟起集群 + 选举/读写/回滚全流程
  • 使用RedisTemplate设计一个消息队列?
  • 海龟交易系统R
  • 【攻防实战】Redis未授权RCE联动metasploit打穿三层内网(上)
  • 织梦网站图片修改不了wordpress模板开发 2016
  • .Net Framework 3.5下载安装教程(附安装包)
  • pycharm远程提交Git
  • PLM实施专家宝典:离散制造企业工程变更的“流程金融”方案
  • Orleans分布式系统架构详细分析
  • 建设网站的价钱深圳宝安上市公司网站建设报价
  • F034 vue+neo4j 体育知识图谱系统|体育文献知识图谱vue+flask知识图谱管理+d3.js可视化
  • 【day10】分治
  • 【Go】C++转Go:数据结构练习(一)排序算法
  • 每天学习一个新注解——@SafeVarargs
  • valgrind交叉编译android版本