siiuwyhw 发表于 2025-10-16 22:06:00

STC32G12K128编码器模式无法实现4倍频求助

void PWM_Config()
{
EAXFR=1;
P6M1 = 0xFF;   
P6M0 = 0x00;   

PWMA_PS=0X0A;//PWM1P功能切换到P6.0,PWM2P功能切换到P6.2

PWMA_ENO = 0x00;                                          // 配置成 TRGI 的 pin 需关掉 ENO 对应 bit 并配成 input
       
PWMA_PSCRH=0X00;
PWMA_PSCRL=0X00;

        PWMA_CCMR1 = 0x21;                                         // 通道模式配置为输入,接编码器 , 滤波器 4 时钟
        PWMA_CCMR2 = 0x21;                                         // 通道模式配置为输入,接编码器 , 滤波器 4 时钟

        PWMA_CCER1 = 0x55;                                         // 配置通道使能和极性
        PWMA_CCER2 = 0x55;                                         // 配置通道使能和极性
       
//        PWMA_SMCR = 0x01;                                         // 编码器模式 1
//        PWMA_SMCR = 0x02;                                         // 编码器模式 2       
        PWMA_SMCR = 0x03;                                         // 编码器模式 3
       
        PWMA_IER = 0x02;                                                 // 使能中断
        PWMA_CR1 |= 0x01;                                         // 使能PWM计数器

EA = 1;                                        //CPU开放中断,打开总中断。
}

void Encoder_Check()                                        //检测编码器计数值
{
        newcount = cnt_H * 256 + cnt_L;        //获取新的计数器值
        if(newcount < count)                                 //如果新计数值 小于 计数值
        {
                leftmove = 1;                                                        //左转标志置1
                count = newcount;                                        //更新计数值
                numberchange = 1;
                if(number > 0) number--;
        }
        else if(newcount > count)                //如果新计数值 大于 计数值
        {
                rightmove = 1;                                                //右转标志置1
                count = newcount;                                        //更新计数值
                numberchange = 1;
                if(number < 60000) number++;
        }
}

/******************** PWM 中断读编码器计数值 **************************/
void PWM_ISR() interrupt 26
{
//        P20 = ~P20;
        if (PWMA_SR1 & 0X02)                                //捕获1中断标志置1时
        {
                cnt_H = PWMA_CCR1H;                                //读取PWM计数器高8位               
                cnt_L = PWMA_CCR1L;                                //读取PWM计数器低8位
                PWMA_SR1 &= ~0X02;                                //清零捕获1中断标志
                Encoder_Check();                                        //检测编码器计数值
        }
}

使用编码器模式3,但是实现不了4倍频,模式1、模式2和模式3效果都是一样的,1200线光电编码器,3个模式都是取1200个数(旋转一圈),各位高人帮忙分析一下,感谢

国芯人工智能 发表于 2025-10-16 22:08:00

你好,感谢你在论坛上分享这个问题。关于你提到的 STC32G12K128 编码器模式无法实现 4 倍频 的问题,我将从硬件配置、寄存器设置、编码器模式原理等角度进行分析,并尝试给出可能的解决方案。

一、问题分析

你提供的代码片段中,使用了 STC32G12K128 的 PWM 模块配置为编码器接口模式,试图通过 PWM 外设来读取编码器信号。但目前无法实现 4 倍频功能。

1. 编码器 4 倍频原理简介

编码器通常输出两路正交信号 A 和 B,相位差为 90°。通过检测这两路信号的边沿变化,可以实现以下几种倍频模式:
1 倍频:只检测 A 或 B 的上升沿。
2 倍频:检测 A 的上升沿和下降沿。
4 倍频:检测 A 和 B 的上升沿和下降沿,共 4 个边沿。

要实现 4 倍频,需要 PWM 模块支持编码器接口模式,并正确配置相关寄存器以识别四边沿。

二、STC32G12K128 编码器模式配置分析

你使用的是 PWM 模块的编码器接口功能,以下是你配置中的关键部分:

c
PWMACCMR1 = 0x21; // 通道模式配置为输入,接编码器,滤波器 4 时钟
PWMACCMR2 = 0x21;
PWMACCER1 = 0x55; // 配置通道使能和极性
PWMACCER2 = 0x55;
PWMASMCR = 0x03;// 编码器模式 3

1. PWMACCMR1/2 配置分析
0x21 表示将通道配置为 输入模式,滤波器长度为 4 个系统时钟周期。
正确配置了输入滤波器,可以有效防止信号抖动。

2. PWMACCER1/2 配置分析
0x55 表示使能通道 1~4,且所有通道设置为上升沿触发。
这里需要注意:在编码器模式下,极性设置必须与信号的实际相位匹配,否则可能导致边沿无法识别。

3. PWMASMCR 配置分析

你尝试了三种模式:
0x01:编码器模式 1(仅 A 通道边沿计数)
0x02:编码器模式 2(仅 B 通道边沿计数)
0x03:编码器模式 3(A 和 B 的上升沿和下降沿都计数)

根据 STC32G 的参考手册,编码器模式 3 应该对应 4 倍频功能。但你在实际测试中未能实现,说明配置可能存在问题。

三、可能的问题点与解决方案

1. 引脚配置错误

你配置了 P6M1 = 0xFF,P6M0 = 0x00,即所有 P6 口设置为 准双向口,但编码器信号输入通常需要 输入模式(高阻态)。

建议改为:

c
P6M1 = 0x00;   // 设置为输入模式
P6M0 = 0x00;

或根据实际引脚功能,设置为 高阻输入模式,以避免内部上拉影响编码器信号电平。

2. PWMAENO 配置是否正确?

你注释中提到:

c
// 配置成 TRGI 的 pin 需关掉 ENO 对应 bit 并配成 input
PWMAENO = 0x00;

这说明你可能将某些 PWM 引脚复用为 TRGI(触发输入)使用。请确认:
是否将编码器信号连接到了支持编码器接口的通道?
是否关闭了对应的 ENO 位,避免输出干扰?

3. PWMASMCR 是否正确启用编码器模式?

你配置了:

c
PWMASMCR = 0x03; // 编码器模式 3

但需要注意:编码器模式必须与计数器方向控制配合使用。请确认:
是否清除了 DIR 位(计数方向)?
是否设置了正确的时钟源?

建议初始化时加上:

c
PWMACR1 = 0x00; // 清除原有配置
PWMACR1 |= 0x01; // 启用计数器

4. 中断处理是否正确?

你启用了中断:

c
PWMAIER = 0x02; // 使能中断

但未提供中断服务函数。建议检查:
是否编写了中断服务函数?
是否读取了状态寄存器(PWMAISR)并清除标志位?
是否在中断中更新了计数值?

5. 硬件连接是否正确?
编码器信号是否稳定?
是否存在信号干扰?是否使用屏蔽线?
是否在编码器信号端加了上拉电阻?

建议使用示波器观察编码器 A/B 信号的波形,确认其相位差为 90°,频率是否符合预期。

四、建议的配置流程

以下是建议的编码器接口初始化流程:

c
void PWMConfig()
{
    EAXFR = 1; // 扩展寄存器访问使能

    // 设置 P6 为输入模式
    P6M1 = 0x00;
    P6M0 = 0x00;

    // 复用PWM1P和PWM2P到P60和P62
    PWMAPS = 0x0A;

    // 关闭 ENO 输出,防止干扰
    PWMAENO = 0x00;

    // 清空预分频寄存器
    PWMAPSCRH = 0x00;
    PWMAPSCRL = 0x00;

    // 配置通道为输入模式,滤波器长度为 4 个系统时钟
    PWMACCMR1 = 0x21;
    PWMACCMR2 = 0x21;

    // 使能通道并设置为上升沿触发
    PWMACCER1 = 0x55;
    PWMACCER2 = 0x55;

    // 启用编码器模式 3(4 倍频)
    PWMASMCR = 0x03;

    // 使能中断(可选)
    PWMAIER = 0x02;

    // 启动计数器
    PWMACR1 |= 0x01;

    EA = 1; // 开启全局中断
}

五、中断服务函数建议

c
void PWMISR(void) interrupt 16
{
    if (PWMAISR & 0x02) // 检查是否为更新中断
    {
      cntL = PWMACNTRL; // 读取低字节
      cntH = PWMACNTRH; // 读取高字节
      PWMAISR &= ~0x02;   // 清除中断标志
    }
}

六、总结

| 问题点 | 分析 | 建议 |
|--------|------|------|
| 引脚配置 | P6 设置为准双向口可能导致输入干扰 | 改为输入模式(P6M1=0x00, P6M0=0x00) |
| PWMAENO | 未明确关闭 ENO 输出 | 确保 ENO 对应位为 0 |
| PWMASMCR | 设置为编码器模式 3,理论上支持 4 倍频 | 检查是否与其他寄存器冲突 |
| 中断配置 | 启用了中断但未提供中断处理函数 | 补充中断服务函数并清除标志 |
| 硬件连接 | 未提及信号稳定性 | 使用示波器检查 A/B 相位和频率 |

如果你能提供更详细的硬件连接图、编码器型号、以及当前计数值变化的测试数据,我可以进一步帮你分析是否是硬件或软件配置问题。

希望以上分析对你有所帮助,祝你调试顺利!

如有其他问题,欢迎继续交流。

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

王昱顺 发表于 2025-10-17 10:50:48

首先是需要设置PWMA_ARR的值为转一圈的最大值,例如1200线的设置最大值为(4800-1),-1是因为计数器从零开始计数,不设置这个,会导致PWMA_CNT无法增长
PWM外设确实可以做到四倍频计数,只需要设置模式3即可
至于你说的设置三个都一样,是因为需要读的寄存器是PWMA_CNTH和PWMA_CNTL这两个寄存器,我看你发的程序读的是PWMA_CCR1寄存器,这个显然是不对的,需要改动一下




siiuwyhw 发表于 2025-10-17 13:43:46

王昱顺 发表于 2025-10-17 10:50
首先是需要设置PWMA_ARR的值为转一圈的最大值,例如1200线的设置最大值为(4800-1),-1是因为计数器从零开 ...

谢谢王工{:4_196:},我试一下

siiuwyhw 发表于 2025-10-19 21:25:06

王昱顺 发表于 2025-10-17 10:50
首先是需要设置PWMA_ARR的值为转一圈的最大值,例如1200线的设置最大值为(4800-1),-1是因为计数器从零开 ...

你好王工,我找到原因了,读取 PWMA_CCR的值也可以实现4倍频,问题出在编码器模式3的情况下,已经实现4倍频的功能了,但是中断还是按编码器脉冲数进的,我是1200线的编码器,不管哪种模式,旋转一圈都是进1200次中断,我之前的程序不是读的寄存器的值,而是自己定义了一个变量,进入中断更改变量的值,导致三种模式读数都一样。现在实现4倍频了,但还是有问题,我想监控4倍频之后每一个数据的值,查询的方式不够及时,有没有办法在中断中能读到4倍频后的所有值

王昱顺 发表于 2025-10-20 09:53:51

siiuwyhw 发表于 2025-10-19 21:25
你好王工,我找到原因了,读取 PWMA_CCR的值也可以实现4倍频,问题出在编码器模式3的情况下,已经实现4倍 ...

可以尝试使用TIE触发中断,每次触发的时候都会中断
页: [1]
查看完整版本: STC32G12K128编码器模式无法实现4倍频求助