找回密码
 立即注册
查看: 102|回复: 5

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

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-10-19 21:25:06
已绑定手机

1

主题

2

回帖

23

积分

新手上路

积分
23
发表于 2025-10-16 22:06:00 | 显示全部楼层 |阅读模式
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个数(旋转一圈),各位高人帮忙分析一下,感谢

回复

使用道具 举报 送花

3

主题

1848

回帖

544

积分

等待验证会员

积分
544
发表于 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 模块的编码器接口功能,以下是你配置中的关键部分:
  1. c
  2. PWMACCMR1 = 0x21; // 通道模式配置为输入,接编码器,滤波器 4 时钟
  3. PWMACCMR2 = 0x21;
  4. PWMACCER1 = 0x55; // 配置通道使能和极性
  5. PWMACCER2 = 0x55;
  6. 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 口设置为 准双向口,但编码器信号输入通常需要 输入模式(高阻态)。

建议改为:
  1. c
  2. P6M1 = 0x00;   // 设置为输入模式
  3. P6M0 = 0x00;
复制代码

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

2. PWMAENO 配置是否正确?

你注释中提到:
  1. c
  2. // 配置成 TRGI 的 pin 需关掉 ENO 对应 bit 并配成 input
  3. PWMAENO = 0x00;
复制代码

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

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

你配置了:
  1. c
  2. PWMASMCR = 0x03; // 编码器模式 3
复制代码

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

建议初始化时加上:
  1. c
  2. PWMACR1 = 0x00; // 清除原有配置
  3. PWMACR1 |= 0x01; // 启用计数器
复制代码

4. 中断处理是否正确?

你启用了中断:
  1. c
  2. PWMAIER = 0x02; // 使能中断
复制代码

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

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

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

四、建议的配置流程

以下是建议的编码器接口初始化流程:
  1. c
  2. void PWMConfig()
  3. {
  4.     EAXFR = 1; // 扩展寄存器访问使能
  5.     // 设置 P6 为输入模式
  6.     P6M1 = 0x00;
  7.     P6M0 = 0x00;
  8.     // 复用PWM1P和PWM2P到P60和P62
  9.     PWMAPS = 0x0A;
  10.     // 关闭 ENO 输出,防止干扰
  11.     PWMAENO = 0x00;
  12.     // 清空预分频寄存器
  13.     PWMAPSCRH = 0x00;
  14.     PWMAPSCRL = 0x00;
  15.     // 配置通道为输入模式,滤波器长度为 4 个系统时钟
  16.     PWMACCMR1 = 0x21;
  17.     PWMACCMR2 = 0x21;
  18.     // 使能通道并设置为上升沿触发
  19.     PWMACCER1 = 0x55;
  20.     PWMACCER2 = 0x55;
  21.     // 启用编码器模式 3(4 倍频)
  22.     PWMASMCR = 0x03;
  23.     // 使能中断(可选)
  24.     PWMAIER = 0x02;
  25.     // 启动计数器
  26.     PWMACR1 |= 0x01;
  27.     EA = 1; // 开启全局中断
  28. }
复制代码

五、中断服务函数建议
  1. c
  2. void PWMISR(void) interrupt 16
  3. {
  4.     if (PWMAISR & 0x02) // 检查是否为更新中断
  5.     {
  6.         cntL = PWMACNTRL; // 读取低字节
  7.         cntH = PWMACNTRH; // 读取高字节
  8.         PWMAISR &= ~0x02;   // 清除中断标志
  9.     }
  10. }
复制代码

六、总结

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

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

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

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

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

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:606
  • 最近打卡:2025-11-01 11:29:35
已绑定手机
已实名认证

122

主题

2948

回帖

7664

积分

版主

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

截图202510171048488946.jpg
截图202510171048454123.jpg

回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-10-19 21:25:06
已绑定手机

1

主题

2

回帖

23

积分

新手上路

积分
23
发表于 2025-10-17 13:43:46 | 显示全部楼层
王*** 发表于 2025-10-17 10:50
首先是需要设置PWMA_ARR的值为转一圈的最大值,例如1200线的设置最大值为(4800-1),-1是因为计数器从零开 ...

谢谢王工,我试一下
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-10-19 21:25:06
已绑定手机

1

主题

2

回帖

23

积分

新手上路

积分
23
发表于 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倍频后的所有值

点评

可以尝试使用TIE触发中断,每次触发的时候都会中断  详情 回复 发表于 2025-10-20 09:53
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:606
  • 最近打卡:2025-11-01 11:29:35
已绑定手机
已实名认证

122

主题

2948

回帖

7664

积分

版主

积分
7664
发表于 2025-10-20 09:53:51 | 显示全部楼层
siiu*** 发表于 2025-10-19 21:25
你好王工,我找到原因了,读取 PWMA_CCR的值也可以实现4倍频,问题出在编码器模式3的情况下,已经实现4倍 ...

可以尝试使用TIE触发中断,每次触发的时候都会中断
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-11-1 22:13 , Processed in 0.150103 second(s), 84 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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