找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1357|回复: 16
打印 上一主题 下一主题
收起左侧

EC11编码器基于运算解码的算法(原创)

  [复制链接]
跳转到指定楼层
楼主
EC11编码器基于运算解码的算法(原创)

EC11旋转编码器是一种基于脉冲发生的装置,它的编码逻辑如下图


单片机解码方式主要有几种:
1、MCU定时器自带编码器模式,如GD32、STM32等;
2、使用外部IO中断,在中断时根据A或B的电平状态,来确定编码器的方向并计数;
3、在主程序里循环扫描或定时器中断扫描的方式;
我现在以第3种扫描算法方面来跟大家分享:
目前网上搜索到的代码,基本都是以时序AB相的状态,基于逻辑条件来解码,如:
  1. char Encoder_EC11_Scan()     /*  这里只是部分代码  */
  2. {
  3. //以下储存A、B上一次值的变量声明为静态全局变量,方便对EC11对应的IO口做初始化
  4. //  static char EC11_A_Last = 0;
  5. //  static char EC11_B_Last = 0;
  6.     char ScanResult = 0;    //返回编码器扫描结果,用于分析编码器的动作
  7.                             //返回值的取值:   0:无动作;      1:正转;           -1:反转;  
  8.                             //                  2:只按下按键;    3:按着按键正转;   -3:按着按键反转

  9.                             //======================================================//
  10.     if(EC11_Type == 0)      //================一定位对应一脉冲的EC11================//
  11.     {                       //======================================================//
  12.         if(EC11_A_Now != EC11_A_Last)   //以A为时钟,B为数据。正转时AB反相,反转时AB同相
  13.         {
  14.             if(EC11_A_Now == 0)
  15.             {
  16.                 if(EC11_B_Now ==1)      //只需要采集A的上升沿或下降沿的任意一个状态,若A下降沿时B为1,正转                    
  17.                     ScanResult = 1;     //正转

  18.                 else                    //反转
  19.                     ScanResult = -1;
  20.             }
  21.             EC11_A_Last = EC11_A_Now;   //更新编码器上一个状态暂存变量
  22.             EC11_B_Last = EC11_B_Now;   //更新编码器上一个状态暂存变量
  23.         }
  24.     }
  25. return ScanResult;      //返回值的取值:   0:无动作;      1:正转;           -1:反转;
  26. }
复制代码
也有lkc8210发表的非常不错的方法:一定位一脉冲的EC11旋转编码器最简洁的单片机驱动代码
我通过研究,原创了基于运算解码的算法,先上代码
//算法一
uint8_t KeyA_Last;
uint8_t KeyB_Last;
uint8_t KeyA_Now;
uint8_t KeyB_Now;
int EC_Counter;
int EC_CountTemp;

void Encoder_Ini()
{
    KeyA_Last = P10;
    KeyB_Last = P11;
}
void Encoder_Run()
{
    KeyA_Now = P10;
    KeyB_Now = P11;
EC_Counter +=(1 ^ (KeyA_Last ^ KeyB_Last)) * (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)); //更新计数
    KeyA_Last = KeyA_Now;
    KeyB_Last = KeyB_Now;
}



眼尖的网友可以看到,我的扫描解码程序里并没有逻辑判断,EC_Counter计数值会自动解码加减,什么情况?
我先来解析一下算法:
上次A、B电平相等时,A=1,B=1,或A=0,B=0时,KeyA_Last ^ KeyB_Last的异或运行结果会等于0,这时1^0就变成了1,
这个运算的作用就是如果上次AB相等,就可能会更新EC_Counter的值,因为这个结果后面跟着乘号,如果上次AB不相等时,运算结果为0,0乘以任何数仍为0,
EC_Counter的值就+=0,不变;
A相的电平发生变化时(上升沿或下降沿),KeyA_Last^KeyA_Now运算的结果=1;
A相的电平未发生变化,KeyA_Last^Key_Now运算的结果=0;
同理,B相的电平发生变化时(上升沿或下降沿),KeyB_Last^KeyB_Now运算的结果=1;
B相的电平未发生变化,KeyB_Last^KeyB_Now运算的结果=0;


现以反转时序来分析,从EC11编码器的波形可以看出,
反转时,初始状态要么A=1 ,B=1,要么A=0,B=0,在此以默认A=1,B=1来举例计算:
第一步: A=1,B=1,此时 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)= 1^(1^1)=1,
     KeyA_Last^KeyA_Now=1^1=0,
     KeyB_Last^KeyB_Now =1^1=0,
     右边运算结果:1*(0-0)= 0,即EC_Counter+=0


第二步: A=1,B=0 此时 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=1 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^1)=1,
    KeyA_Last^KeyA_Now=1^1=0,
    KeyB_Last^KeyB_Now =1^0=1,
    右边运算结果:1*(0-1)= -1,即EC_Counter+= -1;
第三步: A=0,B=0 此时 KeyA_Last=1,  KeyB_Last =0,  KeyA_Now=0 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^0)=0,
    KeyA_Last^KeyA_Now=1^0=1,
    KeyB_Last^KeyB_Now =0^0=0,
    右边运算结果:0*(1-0)=0,即EC_Counter+=0

第四步: A=0,B=1 此时 KeyA_Last=0,  KeyB_Last =0,  KeyA_Now=0 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^0)=1,
    KeyA_Last^KeyA_Now=0^0=0,
    KeyB_Last^KeyB_Now =0^1=1,
    右边运算结果:1*(0-1)=-1,即EC_Counter+=-1

第五步: A=1,B=1 此时 KeyA_Last=0,  KeyB_Last =1  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^1)=0,
    KeyA_Last^KeyA_Now=0^1=1,
    KeyB_Last^KeyB_Now =1^1=0,
    右边运算结果:0*(1-0)=0,即EC_Counter+=0


继续反转的话,又到了第二步;


正转时,初始状态要么A=1 ,B=1,要么A=0,B=0,在此以A=1,B=1来举例计算:
第一步: A=1,B=1,此时 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)= 1^(1^1)=1,
     KeyA_Last^KeyA_Now=1^1=0,
     KeyB_Last^KeyB_Now =1^1=0,
     右边运算结果:1*(0-0)= 0,即EC_Counter+=0


第二步: A=0,B=1 此时 KeyA_Last=1,  KeyB_Last =1,  KeyA_Now=0 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^1)=1,
    KeyA_Last^KeyA_Now=1^0=1,
    KeyB_Last^KeyB_Now =1^1=0,
    右边运算结果:1*(1-0)= 1,即EC_Counter+= 1;
第三步: A=0,B=0 此时 KeyA_Last=0,  KeyB_Last =1,  KeyA_Now=0 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^1)=0,
    KeyA_Last^KeyA_Now=0^0=0,
    KeyB_Last^KeyB_Now =1^0=1,
    右边运算结果:0*(0-1)=0,即EC_Counter+=0

第四步: A=1,B=0 此时 KeyA_Last=0,  KeyB_Last =0,  KeyA_Now=1 ,  KeyB_Now=0
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(0^0)=1,
    KeyA_Last^KeyA_Now=0^1=1,
    KeyB_Last^KeyB_Now =0^0=0,
    右边运算结果:1*(1-0)=1,即EC_Counter+=1

第五步: A=1,B=1 此时 KeyA_Last=1,  KeyB_Last =0  KeyA_Now=1 ,  KeyB_Now=1
     1 ^ (KeyA_Last ^ KeyB_Last)=1^(1^0)=0,
    KeyA_Last^KeyA_Now=1^1=0,
    KeyB_Last^KeyB_Now =0^1=1,
    右边运算结果:0*(0-1)=0,即EC_Counter+=0


继续正转的话,又到了第二步;

从上面运算可以,公式以双倍频(旋转嘀嗒一格,两次计数)解码EC11编码器;

有网友问,如果我只要单倍频旋转嘀嗒一下,单次计数),又怎么解码?
这时,可以要根据你的编码器默认电平来改,默认A=1,B=1时,
加个条件即可
if(KeyA_Last==0 && KeyB_Last==0)  //只有上次都为0时(要与默认值相反),才更新计数
{
   EC_Counter += (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)); //计数值运算
}
默认A=0,B=0时,
加个条件即可
if(KeyA_Last==1 && KeyB_Last==1)  //只有上次都为1时(要与默认值相反),才更新计数
{
   EC_Counter += (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)); //计数值运算
}

单倍频的程序代码如下:
  1. uint8_t KeyA_Last;
  2. uint8_t KeyB_Last;
  3. uint8_t KeyA_Now;
  4. uint8_t KeyB_Now;
  5. int EC_Counter;
  6. int EC_CountTemp;

  7. void Encoder_Ini()
  8. {
  9.     KeyA_Last = P10;
  10.     KeyB_Last = P11;
  11. }
  12. void Encoder_Run()
  13. {
  14.     KeyA_Now = P10;
  15.     KeyB_Now = P11;
  16.     if(KeyA_Last==1 && KeyB_Last==1)  //注意此处与编码器默认的电平相
  17.     {
  18.      EC_Counter +=(int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now));//如要调整加减方向,请修改此
  19.     }
  20.     KeyA_Last = KeyA_Now;
  21.     KeyB_Last = KeyB_Now;
  22. }
复制代码
以上算法是不是很特别?以上代码我通过了验证,如果不用定时中断扫描,正常12格/秒手速旋转无问题,如果加1ms的定时中断扫描,80格/秒手速旋转无问题;编译后代码在N76E003里,汇编行数50行,大小增加100byte
如果网友只需要单倍频,也可以用我下面的算法,汇编行数更少40多行,大小增加72byte,
AB状态一起处理,具体原理大家去分析

//算法二 编译最小,但只适合单倍频
int EC_Counter;
int EC_CountTemp;

uint8_t KeyAB_Last;
uint8_t KeyAB_Now;

void Encoder_Ini()
{
  KeyAB_Last =P1 & 0x03;
}
void Encoder_Run()
{
    uint8_t Temp;
    KeyAB_Now =(P1 & 0x03);
    Temp=KeyAB_Now^KeyAB_Last;
    if(KeyAB_Last==00) //注意此处与编码器默认的电平相反
    {  
      EC_Counter +=(int)((Temp&0x01)-(Temp>>1)); //如要调整方向,请修改此处
    }
                KeyAB_Last=KeyAB_Now;
}

如果有网友说:你上面单倍频的算法,忽略了过程中的一部分,会不会有问题?
我可以放心的告诉大家,我验证的效果和算法一效果相当,可以使用,当然如果你不放心,我还有一种就是把所有的步骤都考虑进去的算法,如下:



//算法三 编译最大,但有考虑顺序步骤,只适合单倍
uint8_t EC_Index;
uint8_t EC_Last;
uint8_t EC_Now;
int EC_Counter;
int EC_CountTemp;
void Encoder_Ini()
{
   EC_Last=P1 & 0x03;
   EC_Counter=0;
         EC_Index=0x40;
}
void Encoder_Run()
{
        uint8_t temp;
        EC_Now=P1 & 0x03;
        temp=EC_Now^EC_Last;
        EC_Last=EC_Now;        
        EC_Index>>=temp;
        if(EC_Now==0x03)  //注意是编码器默认的电平
        {
           EC_Index=0x40;
        }
        if(EC_Index==2 || EC_Index==4)
        {
                EC_Counter+=(EC_Index-3);  //如要调整方向,请修改此处
                EC_Index=0x40;
        }
}

原理解析:
B对应P11 A对应P10
默认编码器值为高电平,即A=1,B=1,
反转分析:
第一步:A=1,B=1,EC_Last=0x03 , EC_Now=0x03  为什么会是0x03 , 因为P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x03=0,因此temp=0;
EC_Index>>=temp 即 EC_Index>>=0;此时EC_Index不变,还是0x40 二进制是0100 0000
而且,细心的网友会发现,这句程序:
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}
因此EC_Index最后还是等于0x40
第二步:A=1,B=0,EC_Last=0x03 , EC_Now=0x01  为什么会是0x01 , 因为P1 & 0x03=xxxxxx01 & 00000011=00000001=0x01
EC_Now^EC_Last=0x01^0x03=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此时EC_Index=0x10 二进制是0001 0000

第三步:A=0,B=0,EC_Last=0x01 , EC_Now=0x00  为什么会是0x00 , 因为P1 & 0x03=xxxxxx00 & 00000011=00000000=0x00
EC_Now^EC_Last=0x00^0x01=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此时EC_Index=0x0F 二进制是0000 1000

第四步:A=0,B=1,EC_Last=0x00 , EC_Now=0x02  为什么会是0x02 , 因为P1 & 0x03=xxxxxx10 & 00000011=00000010=0x02
EC_Now^EC_Last=0x02^0x00=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此时EC_Index=0x02 二进制是0000 0010

此时,EC_Index=0x02 符合条件更新计数的条件 EC_Index==0x02 或 EC_Index==0x04
(EC_Index-3)=2-3=-1
EC_Counter+=(EC_Index-3) ,即EC_Counter+= - 1 ,自动减1了
第五步:A=1,B=1,EC_Last=0x02 , EC_Now=0x03  为什么会是0x03 , 因为P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x02=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此时EC_Index=0x01 二进制是0000 0001
细心的网友会发现,这句程序,
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}因此EC_Index最后还是等于0x40;运行到此步后,会从第二步继续循环;

正转分析:
第一步:A=1,B=1,EC_Last=0x03 , EC_Now=0x03  为什么会是0x03 , 因为P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x03=0,因此temp=0;
EC_Index>>=temp 即 EC_Index>>=0;此时EC_Index不变,还是0x40 二进制是0100 0000
而且,细心的网友会发现,这句程序:
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}

因此EC_Index最后还是等于0x40
第二步:A=0,B=1,EC_Last=0x03 , EC_Now=0x02  为什么会是0x02 , 因为P1 & 0x03=xxxxxx10 & 00000011=00000010=0x02
EC_Now^EC_Last=0x02^0x03=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此时EC_Index=0x20 二进制是0010 0000

第三步:A=0,B=0,EC_Last=0x02 , EC_Now=0x00  为什么会是0x00 , 因为P1 & 0x03=xxxxxx00 & 00000011=00000000=0x00
EC_Now^EC_Last=0x00^0x02=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此时EC_Index=0x0F 二进制是0000 1000

第四步:A=1,B=0,EC_Last=0x00 , EC_Now=0x01  为什么会是0x01 , 因为P1 & 0x03=xxxxxx01 & 00000011=00000001=0x01
EC_Now^EC_Last=0x01^0x00=1,因此temp=1;
EC_Index>>=temp 即 EC_Index>>=1;此时EC_Index=0x04 二进制是0000 0100

此时,EC_Index=0x04 符合条件更新计数的条件 EC_Index==0x02 或 EC_Index==0x04
(EC_Index-3)=4-3=1
EC_Counter+=(EC_Index-3) ,即EC_Counter+=1 ,自动加1了第五步:A=1,B=1,EC_Last=0x01 , EC_Now=0x03  为什么会是0x03 , 因为P1 & 0x03=xxxxxx11 & 00000011=00000011=0x03
EC_Now^EC_Last=0x03^0x01=2,因此temp=2;
EC_Index>>=temp 即 EC_Index>>=2;此时EC_Index=0x01 二进制是0000 0001
细心的网友会发现,这句程序,
if(EC_Now==0x03)
{
   EC_Index=0x40;  //重置EC_Index
}因此EC_Index最后还是等于0x40;运行到此步后,会从第二步继续循环;
从上面的分析可以看出,算法是有按顺序对每个步骤进行处理并关联到了temp和EC_Index的值,从而决定了EC_Counter的值
这个算法的核心是:
反转一格时,EC_Now^EC_Last的值是0,2,1,2, 1 的变化,第一步和第五步为默认状态,EC_Index重置为0x40,移位不起作用,
因此实际反转时,EC_Index右移了2+1+2=5次,最终等于2;
正转一格时,EC_Now^EC_Last的值是0,1,2,1,  2 的变化,第一步和第五步为默认状态,EC_Index重置为0x40,移位不起作用,
因此实际正转时,EC_Index右移了1+2+1=4次,最终等于4;

然后用 EC_Index-3 巧妙的得到了正负1,实现自动正反转加减;
现在可以解析EC_Index重置为0x40的意义:0x40二进制是0100 0000,右移位4或5次时能得到4和2的值,其他数值不行;


以上就是我原创的EC11编码器基于运算解码的算法,希望能给大家抛砖引玉。








评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏20 分享淘帖 顶3 踩
回复

使用道具 举报

沙发
ID:471574 发表于 2023-12-13 23:11 | 只看该作者
同时贴上lkc8210发表的算法:
//算法四: 编译大小不错,只适合单倍频
uint8_t KeyA_Last;
uint8_t KeyB_Last;
uint8_t KeyA_Now;
uint8_t KeyB_Now;
int EC_Counter;

void Encoder_Ini()
{
    KeyA_Last = P10;
    KeyB_Last = P11;
}

void Encoder_Run()
{
        KeyA_Now=P10;
        KeyB_Now=P11;
        if(!KeyA_Now && KeyA_Last && KeyB_Now)
        {
                EC_Counter++;
  }
        KeyA_Last=KeyA_Now;
        if(!KeyB_Now && KeyB_Last && KeyA_Now)
        {
                EC_Counter--;
  }
        KeyB_Last=KeyB_Now;
}
回复

使用道具 举报

板凳
ID:1064915 发表于 2023-12-14 08:28 | 只看该作者
好文章,需要认真学习
回复

使用道具 举报

地板
ID:156220 发表于 2023-12-14 10:14 | 只看该作者
讲解的蛮详细的,谢谢楼主的分享
回复

使用道具 举报

5#
ID:514317 发表于 2023-12-14 11:56 | 只看该作者
经过测试   楼主的程序运行稳定    算法精简高效    感谢楼主
只是 (int)((KeyA_Last ^ KeyA_Now) - (KeyB_Last ^ KeyB_Now)这段编译报错   只好拆成2段
我也贴上我常用的   也是很稳定


if (PinA != PinA_O)        //当A发生跳变时采集B当前的状态,并将B与上一次的状态进行对比。
        {                                   //若A 0->1 时,B 1->0 正转;若A 1->0 时,B 0->1 正转;
                                                                                //若A 0->1 时,B 0->1 反转;若A 1->0 时,B 1->0 反转
                if (PinA == 1)     //EC11_A和上一次状态相比,为上升沿
                {
                if ((PinB_O == 1) && (PinB == 0))   //EC11_B和上一次状态相比,为下降沿
                        encoder_data++;                         //正转
                if ((PinB_O == 0) && (PinB == 1))   //EC11_B和上一次状态相比,为上升沿               
                        encoder_data--;                        //反转
                //>>>>>>>>>>>>>>>>下面为正转一次再反转或反转一次再正转处理<<<<<<<<<<<<<<<<//
                if ((PinB_O == PinB) && (PinB == 0))  //A上升沿时,采集的B不变且为0
                    encoder_data++;                                 //正转
                if ((PinB_O == PinB) && (PinB == 1))  //A上升沿时,采集的B不变且为1
                        encoder_data--;                                //反转
                }

                else                    //EC11_A和上一次状态相比,为下降沿
                {
                if ((PinB_O == 1) && (PinB == 0))   //EC11_B和上一次状态相比,为下降沿
                        encoder_data--;                        //反转
                if ((PinB_O == 0) && (PinB == 1))   //EC11_B和上一次状态相比,为上升沿
                        encoder_data++;                         //正转
                //>>>>>>>>>>>>>>>>下面为正转一次再反转或反转一次再正转处理<<<<<<<<<<<<<<<<//
                if ((PinB_O == PinB) && (PinB == 0))  //A上升沿时,采集的B不变且为0
                    encoder_data--;                                //反转
                if ((PinB_O == PinB) && (PinB == 1))  //A上升沿时,采集的B不变且为1   
                        encoder_data++;                                 //正转
                }
                PinA_O = PinA;   //更新编码器上一个状态暂存变量
                PinB_O = PinB;   //更新编码器上一个状态暂存变量
回复

使用道具 举报

6#
ID:471574 发表于 2023-12-14 13:08 | 只看该作者
lzzasd 发表于 2023-12-14 11:56
经过测试   楼主的程序运行稳定    算法精简高效    感谢楼主
只是 (int)((KeyA_Last ^ KeyA_Now) - (KeyB ...

编译什么提示?我是keil4 C51 编译正常,会不会少了个括号标点之类的?
回复

使用道具 举报

7#
ID:417804 发表于 2023-12-15 09:54 | 只看该作者
小白只能顶楼主
回复

使用道具 举报

8#
ID:514317 发表于 2023-12-16 10:27 | 只看该作者
zyhlove813 发表于 2023-12-14 13:08
编译什么提示?我是keil4 C51 编译正常,会不会少了个括号标点之类的?

APP_EC11.C(59):C193: '-': BAD OPERAND TYPE
后段那个 减号   拆成2段就正常了
回复

使用道具 举报

9#
ID:514317 发表于 2023-12-16 10:42 | 只看该作者
zyhlove813 发表于 2023-12-14 13:08
编译什么提示?我是keil4 C51 编译正常,会不会少了个括号标点之类的?

刚才看了下   是我定义的变量的问题    我的变量都是BIT 位类型的   编译就出错
楼主使用的是u8类型的   
回复

使用道具 举报

10#
ID:537530 发表于 2023-12-24 19:28 | 只看该作者
楼主钻研精神可嘉,学习了。
回复

使用道具 举报

11#
ID:471574 发表于 2023-12-25 13:07 | 只看该作者
发表于 2023-12-24 19:28
楼主钻研精神可嘉,学习了。

共同学习
回复

使用道具 举报

12#
ID:604453 发表于 2023-12-25 18:09 | 只看该作者
楼主的算法还需要硬件消抖电路吗
回复

使用道具 举报

13#
ID:604453 发表于 2023-12-25 19:14 | 只看该作者
代码精简高效,向楼主学习了
回复

使用道具 举报

14#
ID:471574 发表于 2023-12-25 21:04 | 只看该作者
lzuoxin 发表于 2023-12-25 18:09
楼主的算法还需要硬件消抖电路吗

正常应该是要的,我是网购的模块,带电阻和电容滤波,不硬件滤波,你自己可以试下。
回复

使用道具 举报

15#
ID:604453 发表于 2023-12-26 09:43 | 只看该作者
zyhlove813 发表于 2023-12-25 21:04
正常应该是要的,我是网购的模块,带电阻和电容滤波,不硬件滤波,你自己可以试下。

好的,我去试一下,谢谢!
回复

使用道具 举报

16#
ID:983641 发表于 2023-12-31 21:35 | 只看该作者
讲解得很详细。UP厉害人。
回复

使用道具 举报

17#
ID:471574 发表于 2024-1-16 18:04 | 只看该作者
youlinys 发表于 2023-12-31 21:35
讲解得很详细。UP厉害人。

通过不同的方法去实现目标,可能锻炼自己的思维能力
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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