找回密码
 立即注册
查看: 100|回复: 1

求助一个控制PWM输出的菜鸟问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-07-08 08:13:36

4

主题

12

回帖

92

积分

注册会员

积分
92
发表于 2025-7-8 08:18:05 | 显示全部楼层 |阅读模式
求助写一段STC32G8K64单片机的PWM代码,要求如下:P2.3为PWM输出脚,当P1.1为低电平,P1.0为高电平时,P0.0输出高电平,P2.3输出90%占空比的PMW,当P1.1为高电平时输出的占空比逐渐降为0,时间2秒,当P1.4为低电平,P1.0为高电平,P0.0为高电平时,P2.3输出90%占空比的PMW,当P1.4为高电平时输出的占空比逐渐降为0,时间2秒,以此循环。
回复

使用道具 举报 送花

3

主题

2074

回帖

996

积分

等待验证会员

积分
996
发表于 2025-7-8 08:23:00 | 显示全部楼层
尊敬的用户,您好!

感谢您的提问。以下是针对STC32G8K64单片机的PWM控制代码实现方案,满足您提出的各项逻辑要求。

一、硬件配置说明
P23:作为PWM输出引脚;
P10、P11、P14、P00:用于逻辑判断;
PWM频率:建议使用定时器方式实现;
占空比变化:通过改变PWM比较寄存器值实现;
循环控制:通过状态切换实现。

二、代码实现思路

1. 初始化系统时钟、GPIO、定时器;
2. 配置P23为PWM输出;
3. 根据P10、P11、P14、P00的状态判断当前工作模式;
4. 在相应模式下控制PWM占空比变化(从90%到0%,持续2秒);
5. 循环执行上述过程。

三、代码示例(基于STC32G8K64)
  1. c
  2. include "stc32g.h"
  3. define PWMFREQ      10000    // PWM频率10kHz
  4. define PWMMAXCNT   (FCPU / PWMFREQ) // 定时器最大计数值
  5. define DUTY90       (PWMMAXCNT  9 / 10) // 90%占空比
  6. volatile uint8t mode = 0;     // 模式标识:0-正常;1-下降
  7. volatile uint16t duty = DUTY90;
  8. volatile uint32t timer = 0;
  9. // 初始化系统时钟
  10. void SystemClockInit(void)
  11. {
  12.     CLK->CLKSEL = 0x00;         // 使用内部8MHz时钟
  13. }
  14. // 初始化GPIO
  15. void GPIOInit(void)
  16. {
  17.     P1M1 &= ~0x0C;              // P11、P10设为通用输入
  18.     P1M0 &= ~0x0C;
  19.    
  20.     P1M1 &= ~0x10;              // P14设为通用输入
  21.     P1M0 &= ~0x10;
  22.    
  23.     P0M1 &= ~0x01;              // P00设为通用输出
  24.     P0M0 |= 0x01;
  25.    
  26.     P2M1 &= ~0x08;              // P23设为PWM输出
  27.     P2M0 |= 0x08;
  28. }
  29. // 初始化定时器
  30. void TimerInit(void)
  31. {
  32.     T0CON = 0x0B;               // 定时器0模式3,16位自动重载
  33.     TH0 = 0x00;
  34.     TL0 = 0x00;
  35.     ET0 = 1;                    // 使能定时器0中断
  36.     EA = 1;                     // 全局中断使能
  37. }
  38. // PWM初始化
  39. void PWMInit(void)
  40. {
  41.     PWM0CTL = 0x00;             // PWM0模式选择
  42.     PWM0CH0 = 0x00;             // PWM0通道0初始值
  43.     PWM0CH1 = 0x00;             // PWM0通道1初始值
  44.     PWM0CH2 = 0x00;             // PWM0通道2初始值
  45.     PWM0CH3 = 0x00;             // PWM0通道3初始值
  46.    
  47.     PWM0CN = 0x00;              // PWM0使能
  48.     PWM0T = 0x00;               // PWM0周期设置
  49. }
  50. // 设置PWM占空比
  51. void SetPWMDuty(uint16t value)
  52. {
  53.     PWM0CH0 = value & 0xFF;
  54.     PWM0CH1 = (value >> 8) & 0xFF;
  55. }
  56. // 延时函数
  57. void Delayms(uint16t ms)
  58. {
  59.     uint16t i, j;
  60.     for(i = 0; i < ms; i++)
  61.         for(j = 0; j < 1200; j++);
  62. }
  63. // 主函数
  64. void main(void)
  65. {
  66.     SystemClockInit();
  67.     GPIOInit();
  68.     TimerInit();
  69.     PWMInit();
  70.     P00 = 1;                    // 默认高电平
  71.     while(1)
  72.     {
  73.         if(P10 == 1 && P11 == 0) // P10高,P11低
  74.         {
  75.             P00 = 1;
  76.             SetPWMDuty(DUTY90);
  77.             mode = 0;
  78.             timer = 0;
  79.             
  80.             while(timer < 2000) // 2秒
  81.             {
  82.                 if(mode == 0)
  83.                 {
  84.                     if(timer >= 2000)
  85.                         break;
  86.                     timer++;
  87.                     Delayms(1);
  88.                 }
  89.             }
  90.             // 占空比逐渐下降
  91.             for(duty = DUTY90; duty > 0; duty--)
  92.             {
  93.                 SetPWMDuty(duty);
  94.                 Delayms(10);           // 每10ms下降一次
  95.             }
  96.         }
  97.         else if(P14 == 0 && P10 == 1 && P00 == 1) // P14低,P10高,P00高
  98.         {
  99.             SetPWMDuty(DUTY90);
  100.             mode = 0;
  101.             timer = 0;
  102.             while(timer < 2000)
  103.             {
  104.                 if(mode == 0)
  105.                 {
  106.                     if(timer >= 2000)
  107.                         break;
  108.                     timer++;
  109.                     Delayms(1);
  110.                 }
  111.             }
  112.             for(duty = DUTY90; duty > 0; duty--)
  113.             {
  114.                 SetPWMDuty(duty);
  115.                 Delayms(10);
  116.             }
  117.         }
  118.         // 循环
  119.     }
  120. }
复制代码

四、注意事项

1. PWM频率与占空比计算:根据实际需求调整PWMFREQ和DUTY90的值;
2. 延时精度:本代码采用简单延时函数,适用于一般应用,若需更高精度可使用定时器中断;
3. 逻辑判断顺序:请确保各条件判断顺序合理,避免冲突;
4. 代码扩展性:可将不同模式封装为函数以提高可读性和维护性。

如需进一步优化或添加功能(如动态调节PWM频率、多路PWM等),欢迎继续提问。

祝您开发顺利!

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-8-11 15:14 , Processed in 0.117976 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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