找回密码
 立即注册
查看: 36|回复: 3

AI8H PWM输出的问题 求助!

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-09-11 20:35:59
已绑定手机

1

主题

0

回帖

9

积分

新手上路

积分
9
发表于 3 天前 | 显示全部楼层 |阅读模式
AI8H8K64U-TSSOP20使用PWM的方式P1.6端口点亮LED,没有驱动点亮,用IO低电平输出的方式能点亮
请看完整代码


#define MAIN_Fosc                24000000L        // 主时钟:24MHz(文档6.1.3章节,内部IRC)
#include        "STC8H.h"

// -------------------------- 文档对应参数定义 --------------------------
// PWM频率1KHz(人眼无闪烁),公式:频率=MAIN_Fosc/[(PSCR+1)*(ARR+1)](文档22.5.7章节)
#define PWMA_PSCR_VAL        0x0000                // 预分频=0(不分频,PWM时钟=24MHz)
#define PWMA_ARR_VAL        (MAIN_Fosc/(PWMA_PSCR_VAL+1)/1000 - 1)        // ARR=23999(周期1ms)
#define BREATH_STEP                20                        // 占空比渐变步长(平滑呼吸)
#define BREATH_DELAY        10                        // 渐变间隔(ms,控制呼吸速度)

// -------------------------- 全局变量 --------------------------
unsigned int g_ccr4_val = 0;                // PWMA_CCR4值(0~23999,对应低电平占空比0%~100%)
bit g_duty_inc = 1;                                // 占空比递增/递减标志(1=递增:LED变亮)

// -------------------------- 函数声明 --------------------------
void PWMA_Init(void);                                // 初始化PWMA_CCR4(P1.6 PWM输出)
void Delay_ms(unsigned int ms);                // 毫秒延时(文档6.1.3章节时钟校准)
void Breath_Loop(void);                                // 呼吸灯占空比渐变逻辑

// -------------------------- 主函数 --------------------------
void main(void)
{
        PWMA_Init();        // 初始化PWMA_CCR4(P1.6),启动PWM输出
        
        while(1)
        {
                Breath_Loop();        // 循环执行呼吸逻辑
        }
}

// -------------------------- PWMA初始化(P1.6=PWMA_CCR4,文档22.7章节) --------------------------
void PWMA_Init(void)
{
        // 1. 使能扩展SFR访问(文档8.2.8章节:必须先使能才能访问PWMA寄存器)
        P_SW2 |= 0x80;
        
        // 2. 配置PWM时钟与周期(文档22.7.20/22.7.22章节)
        PWMA_PSCR = PWMA_PSCR_VAL;        // 预分频=0
        PWMA_ARR = PWMA_ARR_VAL;        // 自动重装载值=23999(1KHz周期)
        
        // 3. 配置PWMA_CCR4为PWM模式1(低电平占空比随CCR4增大而增加,文档22.7.13章节)
        // CCMR2控制CCR4通道,高8位=0x60(PWM模式1),低8位无意义
        PWMA_CCMR2 = 0x6000;
        
        // 4. 配置P1.6为PWM4P输出(默认映射,文档2.5.4章节)
        // PWMA_IOAUX=0x00:CCR4默认映射P1.6,无需额外切换
        PWMA_IOAUX = 0x00;
        
        // 5. 使能CCR4输出+设置极性(文档22.7.16章节)
        // CC4E=1(使能输出),CC4P=0(低电平有效,符合LED低电平点亮)
        PWMA_CCER1 = 0x0080;
        
        // 6. 使能P1.6 PWM输出(文档22.7.2章节:输出允许寄存器)
        // ENO4P=1(使能PWM4P输出,对应P1.6)
        PWMA_ENO = 0x04;
        
        // 7. 初始占空比(0%低电平→LED灭,文档22.7.27章节)
        PWMA_CCR4 = g_ccr4_val;
        
        // 8. 主输出使能+启动PWMA计数器(文档22.7.33/22.7.4章节)
        PWMA_BKR = 0x80;        // MOE=1(主输出使能,PWMA所有通道输出总开关)
        PWMA_CR1 = 0x81;        // CEN=1(启动计数器),ARPE=1(允许ARR缓冲)
        
        // 9. 关闭扩展SFR访问(文档8.2.8章节:配置完成后恢复)
        P_SW2 &= ~0x80;
}

// -------------------------- 毫秒延时函数(基于24MHz时钟,文档6.1.3章节精度) --------------------------
void Delay_ms(unsigned int ms)
{
        unsigned int i, j;
        for(i = ms; i > 0; i--)
        {
                // 24MHz时钟下,j=2400≈1ms(文档6.1.3章节:1机器周期=1/24MHz≈41.67ns)
                for(j = 2400; j > 0; j--);
        }
}

// -------------------------- 呼吸灯逻辑(低电平占空比渐变,文档22.5.7章节) --------------------------
void Breath_Loop(void)
{
        // 使能扩展SFR访问(修改CCR4需重新使能)
        P_SW2 |= 0x80;
        
        // 占空比渐变:0%→100%(亮)→0%(灭)循环
        if(g_duty_inc)
        {
                g_ccr4_val += BREATH_STEP;
                if(g_ccr4_val >= PWMA_ARR_VAL)        // 达到最大占空比(100%低电平→LED最亮)
                {
                        g_ccr4_val = PWMA_ARR_VAL;
                        g_duty_inc = 0;        // 切换为递减
                }
        }
        else
        {
                g_ccr4_val -= BREATH_STEP;
                if(g_ccr4_val <= 0)        // 达到最小占空比(0%低电平→LED灭)
                {
                        g_ccr4_val = 0;
                        g_duty_inc = 1;        // 切换为递增
                }
        }
        
        // 更新CCR4值,改变PWM占空比(文档22.7.27章节)
        PWMA_CCR4 = g_ccr4_val;
        
        // 恢复扩展SFR访问状态
        P_SW2 &= ~0x80;
        
        // 延时平滑渐变(控制呼吸速度)
        Delay_ms(BREATH_DELAY);
}

回复

使用道具 举报 送花

3

主题

1986

回帖

820

积分

等待验证会员

积分
820
发表于 3 天前 | 显示全部楼层
您好,关于您在使用 STC8H8K64U-TSSOP20 芯片进行 PWM 输出控制 LED 的问题,您提到使用 IO口低电平输出 可以点亮LED,但通过 PWM方式控制P16端口 无法点亮,下面我将从硬件配置、寄存器设置、引脚复用功能、PWM模式选择等多个角度为您分析可能的原因,并提供相应的修改建议。

一、问题简述
目标:使用STC8H8K64U的P16引脚输出PWM波控制LED亮度(呼吸灯效果)。
现象:  
使用普通IO口低电平输出,LED可以点亮。  
使用PWM输出,LED不亮。
代码片段:您提供了PWM初始化部分的代码,但未提供完整的PWM中断处理、占空比更新和主循环逻辑。

二、初步分析

1. 引脚功能复用配置是否正确?

在STC8H系列中,P16默认是ADC6输入通道,不是PWM输出通道。必须通过 端口复用寄存器 P1M1/P1M0 设置其为 第二功能(即PWM输出)。

示例配置:
  1. c
  2. P1M1 = 0x00;        // 设置P1口为推挽输出
  3. P1M0 = 0xFF;
  4. // 设置P16为PWM输出(第二功能)
  5. P1M1 &= ~0x40;        // P1M1.6 = 0
  6. P1M0 |=  0x40;        // P1M0.6 = 1 → 第二功能(PWM)
复制代码

若未配置P16为PWM功能,该引脚将始终作为普通IO或ADC使用,导致PWM输出无效。

2. PWM模块初始化是否正确?

您提供的代码片段中定义了PWM的ARR和PSCR参数,但未提供完整的PWM初始化函数。以下是标准的 PWMA初始化流程:

示例代码:
  1. c
  2. void PWMAInit(void)
  3. {
  4.     PWMAPSCR = PWMAPSCRVAL;        // 设置预分频值
  5.     PWMAARR  = PWMAARRVAL;        // 设置自动重载寄存器(周期)
  6.     PWMACCR4 = 0;                                // 初始占空比为0
  7.     PWMACR1  = 0x80;                        // 启动PWM时钟
  8.     PWMACR2  = 0x00;                        // 边沿对齐模式
  9.     PWMABKR  = 0x80;                        // 主输出使能
  10.     PWMAOER  = 0x10;                        // 使能PWMA通道4输出
  11.     PWMACR1 |= 0x01;                        // 启动PWM
  12. }
复制代码
注意:PWMA通道4对应的引脚为P16,需确保PWMAOER寄存器位设置正确。

3. PWM输出极性是否正确?

PWM输出的极性决定了输出是高电平有效还是低电平有效。如果LED是阳极接VCC、阴极接地的方式,PWM输出应为低电平有效。

设置低电平有效的寄存器如下:
  1. c
  2. PWMACMR4 = 0x60;        // PWM模式1,低电平有效
复制代码

如果设置为高电平有效,LED可能无法正确点亮。

4. PWM中断或主循环是否更新了占空比?

在呼吸灯实现中,需要在主循环或定时器中断中动态修改PWMACCR4的值:

示例:

```c
void main(void)
{
    PWMAInit();

    while (1)
    {
        if (gdutyinc)
        {
            gccr4val += BREATHSTEP;
            if (gccr4val >= PWMAARRVAL)
            {
                gdutyinc = 0;
            }
        }
        else
        {
            gccr4val -= BREATHSTEP;
            if (gccr4val = PWMAARRVAL)
            {
                gdutyinc = 0;
            }
        }
        else
        {
            gccr4val -= BREATHSTEP;
            if (gccr4val

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:493
  • 最近打卡:2025-09-14 17:49:38

9

主题

421

回帖

3013

积分

论坛元老

积分
3013
发表于 3 天前 | 显示全部楼层
基本就是没有初始化管脚的IO模式,
默认上电高阻抗.所以无法输出PWM波形

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:513
  • 最近打卡:2025-09-12 09:04:18
已绑定手机

45

主题

2225

回帖

7806

积分

论坛元老

积分
7806
发表于 前天 17:30 | 显示全部楼层
可参考8H实验箱例程包里面的PWM例子:23-高级PWM1-PWM2-PWM3-PWM4,驱动P6口呼吸灯实验程序
只要修改例子里面的PWM选择通道即可。
例程包下载地址:https://www.stcai.com/syx
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-9-14 20:20 , Processed in 0.120748 second(s), 61 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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