求助一个逻辑比较绕的PWM程序
写一段STC32G8K64单片机的PWM代码,要求如下:P2.3为PWM输出脚,当P1.1和P1.4中有一个为低电平或者都为低电平时,P1.0为高电平,则P2.3输出90%占空比的PMW,当P1.1或P1.4为高电平时输出的占空比逐渐降为0,时间2秒,当P1.1和P1.4中有一个为低电平,P1.0再次为高电平,则输出90%占空比的PMW,当P1.1或则P1.4为高电平时输出的占空比逐渐降为0,时间2秒,以此循环。针对您提出的PWM控制逻辑,以下是基于STC32G8K64单片机的实现方案。该程序通过定时器生成PWM信号,并根据P11、P14和P10的状态变化动态调整占空比,满足您所描述的循环控制逻辑。
一、硬件配置说明
PWM输出引脚:P23
状态检测引脚:P11、P14(用于判断是否进入高电平状态)
控制引脚:P10(用于触发90%占空比输出)
二、功能逻辑说明
1. 初始状态:
当 P11 和 P14 中有一个为低电平,或两者都为低电平时,且 P10 为高电平,则 P23 输出 90% 占空比的 PWM。
2. 状态转换:
当 P11 或 P14 变为高电平时,PWM 占空比从 90% 开始逐渐降为 0%,耗时 2 秒。
一旦 P11 和 P14 再次变为低电平(或其中一个为低),且 P10 为高电平,则重新输出 90% 占空比,再次进入降频过程。
3. 循环机制:
整个逻辑在 P11/P14 状态变化下不断循环执行。
三、代码实现(基于STC32G8K64)
c
include "stc32g8k64.h"
define PWMPIN P23 // PWM输出引脚
define P11PIN P11 // 状态检测引脚
define P14PIN P14 // 状态检测引脚
define P10PIN P10 // 控制引脚
volatile uint8t pwmduty = 90; // 初始占空比为90%
volatile uint8t state = 0; // 0:正常输出 1:下降中
volatile uint32t timercount = 0; // 计时计数器
// 初始化PWM
void PWMInit(void) {
// 设置P23为PWM输出
P2M1 &= ~0x08; // P23设置为普通IO
P2M2 |= 0x08;
// 配置定时器2为PWM模式
TMOD &= 0x0F; // 清除T2控制位
TMOD |= 0x20; // T2为模式2(8位自动重装)
TH2 = 0xFF; // 初始值设为0xFF(16MHz系统时钟,约1ms周期)
TL2 = 0xFF;
RCAP2H = 0xFF;
RCAP2L = 0xFF;
ET2 = 1; // 使能T2中断
EA = 1; // 全局中断使能
TR2 = 1; // 启动T2
// 设置PWM占空比
PWMDutySet(pwmduty);
}
// 设置PWM占空比
void PWMDutySet(uint8t duty) {
uint16t period = 256; // 定时器2为8位,最大256
uint16t pulse = (dutyperiod) / 100;
if (pulse > period) pulse = period;
TH2 = 0xFF - (period - pulse);
TL2 = 0xFF - (period - pulse);
}
// 定时器2中断服务函数
void Timer2ISR(void) interrupt 5 {
static uint32t cnt = 0;
cnt++;
if (cnt >= 2000) { // 2秒(假设系统频率为16MHz,1ms中断一次)
cnt = 0;
if (state == 1) {
if (pwmduty > 0) {
pwmduty--;
PWMDutySet(pwmduty);
} else {
state = 0;
}
}
}
}
// 检测输入状态
void CheckStatus(void) {
static uint8t lastp11 = 1;
static uint8t lastp14 = 1;
static uint8t lastp10 = 1;
uint8t p11 = P11PIN;
uint8t p14 = P14PIN;
uint8t p10 = P10PIN;
if ((p11 == 0 || p14 == 0) && p10 == 1) {
if (state == 0) {
pwmduty = 90;
PWMDutySet(pwmduty);
state = 0;
}
} else {
if (state == 0) {
state = 1;
timercount = 0;
}
}
lastp11 = p11;
lastp14 = p14;
lastp10 = p10;
}
int main(void) {
// 初始化端口
P1M1 = 0x00;
P1M2 = 0xFF;
P2M1 = 0x00;
P2M2 = 0xFF;
PWMInit();
while (1) {
CheckStatus();
}
}
四、注意事项
系统时钟:本代码基于16MHz系统时钟编写,若实际使用不同频率,请调整定时器相关参数。
PWM精度:由于使用的是8位定时器,占空比精度为1%,90%占空比为230/256。
延时控制:2秒的降频时间依赖于定时器中断频率,建议使用更精确的定时方式以提升稳定性。
如需进一步优化或扩展功能(如增加LED指示、串口调试等),可继续补充需求。
[本文内容由国芯人工智能辅助生成,仅供参考] 既有电平状态,又有边沿状态处理,文字描述容易出错,不如画个简单真值表看得清楚 网老四 发表于 2025-7-7 14:07
既有电平状态,又有边沿状态处理,文字描述容易出错,不如画个简单真值表看得清楚 ...
那我重新描述问题,这个描述错误了
页:
[1]