搜索
bottom↓
回复: 19

超简单的旋转编码开关程序!

[复制链接]

出0入8汤圆

发表于 2019-2-22 13:20:34 | 显示全部楼层 |阅读模式
//INT0--PD2,INT1--PD3
//编码开关A接外部中断(AVR M8的PD2)B用来判断方向(连到M8的PD3), C接地
//外部中断设置INT0引脚上任意的逻辑电平变化都将引发中断
// rcs_right:正旋,rcs_left:反旋
*/

void init_rcs(void)
{
   DDRD &=~0x0c;                                    //00001100;~11110011
   PORTD |=0x0c;
   MCUCR=0x01;                                      //INT0任意电平变化触发
   GICR=0x40;                                       //INT0外部中断使能
   SREG=0x80;                                       //使能全局中断
}

#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
   GICR=0;                                          //禁止外部中断
   if ((PIND & 0x04))                               //A为高电平时
     if (!(PIND & 0x08)) rcs_right=1;else rcs_left=1; //B为0正旋,否则反旋
   else                                             //A为低电平时
     if (!(PIND & 0x08)) rcs_left=1;else rcs_right=1; //B为0反旋,否则正旋
   GICR=0x40;
}
正旋处理程序......
反旋处理程序......
不用任何形式的滤波,反应灵敏无丢码,绝对好使。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入4汤圆

发表于 2019-2-22 14:43:18 | 显示全部楼层
按键类的检测,需不需要滤波和硬件有关系吧。

出0入8汤圆

 楼主| 发表于 2019-2-22 15:12:17 | 显示全部楼层
gmyu 发表于 2019-2-22 14:43
按键类的检测,需不需要滤波和硬件有关系吧。

普通按键接法,不加硬件滤波,上面的处理程序也没有做防抖处理

出0入0汤圆

发表于 2019-2-22 15:35:30 | 显示全部楼层
硬件不加滤波不可靠吧

出0入8汤圆

 楼主| 发表于 2019-2-22 15:45:54 | 显示全部楼层
four_zhg 发表于 2019-2-22 15:35
硬件不加滤波不可靠吧

试试就知道了!

出0入0汤圆

发表于 2019-2-22 15:56:34 | 显示全部楼层
下来试试。谢谢分享!

出0入0汤圆

发表于 2019-2-22 16:02:08 | 显示全部楼层
编码器算法模拟

实际上,有心看的人,自己去拿个编码器的图来对一对,一切就明郎了。

出0入0汤圆

发表于 2019-2-22 16:29:48 | 显示全部楼层
以前上学用mega16做1024线的正交编码程序,怎么做都会丢脉冲,用stm32一下就搞定。

出0入475汤圆

发表于 2019-2-22 17:28:35 来自手机 | 显示全部楼层
楼主的简单做法需要旋钮完全标准,然而很多标准编码器会出现脉冲不是完全理性的情况,的确需要正交处理才行,就如8楼说的,怎么都会丢或者多脉冲,上示波器一看什么都明白了

出0入0汤圆

发表于 2019-2-22 17:42:54 | 显示全部楼层
外部中断是大坑,用过就知道

出0入8汤圆

 楼主| 发表于 2019-2-22 19:41:50 来自手机 | 显示全部楼层
lianglee 发表于 2019-2-22 17:23
任何事情看起来都很简单,做出来也简单,然而要把它做好,做到最好。就不简单了。

如果是100分为满分,我 ...

拿出来100分的代码看看

出0入0汤圆

发表于 2019-2-22 20:14:42 | 显示全部楼层
lut[16]={0,0,1,-1,0....}

isr@1ms
begin
    static state<<PORT_bitA<<PORT_bitB;
    state &= 0x0f;
    return lut[state];
end

出0入475汤圆

发表于 2019-2-22 21:09:11 来自手机 | 显示全部楼层
jianjun42 发表于 2019-2-22 19:41
拿出来100分的代码看看

我来换个说法,在我看来,其实这里不是代码的问题,你的代码本身没有什么问题,如果按照理论的编码器输出时序的话。这里应该是东西能不能达到你说的完全好用的问题。明天我看看能不能找出几年前抓的100线编码器的输出波形抓图,一旦你看了以后也会觉得可能不是能很适合实际使用,那个编码器还是非常出名的一个东西,好像几千块钱一个,开始我也就按照理论的时许写,觉得肯定是对的,然而反馈不准采取采集波形,

出0入0汤圆

发表于 2019-2-23 10:37:14 | 显示全部楼层
本帖最后由 rf_smart 于 2019-2-23 10:39 编辑

上传一个改进过的代码,一个完整的脉冲后才判断是正转还是反转,用的STM8S,A相设置为边缘中断,
引脚定义
#define B_phase       1<<7      //编码器接PC6,PC7
#define A_phase       1<<6
#define        A_STATE              (PC_IDR&A_phase)        //读引脚电平
#define        B_STATE              (PC_IDR&B_phase)        //读引脚电平
IO初始化
void io_init(void)
{
  PC_DDR=0;//输入
PC_CR1|=0xFF;//上拉
  PC_CR2=A_phase;          //PC6口中断
  EXTI_CR1=0x30;        //上升沿和下降沿触发
}
#pragma vector=0x07//PC6外部中断处理,对编码器解码
__interrupt void Encoder(void)
{
  if((!A_STATE)&&(active==0))  //下降沿来临
  {
    active=1;//设置检测标志
    B_ago=B_STATE;//保存此时B相状态;
  }
  else if((A_STATE)&&(active==1))//上升沿来临,一个完整的脉冲过来再处理数据
  {
    B_now=B_STATE;//保存此时B相状态;
    if(B_ago<B_now)//反转处理
      {}
    else if(B_ago>B_now)//正转处理
      {}
    active=0;B_ago=0;B_now=0;//处理完成,恢复检测标志用于下一次检测
  }
}

出0入475汤圆

发表于 2019-2-23 15:05:55 | 显示全部楼层
1a2b3c 发表于 2019-2-22 21:09
我来换个说法,在我看来,其实这里不是代码的问题,你的代码本身没有什么问题,如果按照理论的编码器输出 ...

找到图了,器件好像是一个什么川的日本的100线编码器还是啥玩意,带电源那种,出来就是AB相位的信号,拨盘上面一圈刻度,0~100转到哪里表示输出多少脉冲,当然不代表普通2块钱的电位器那样的无源飞梭的旋转编码器也会出现这样的问题。


图中正常的相位和波形根本不用去看,看楼主的方式怎么写代码都可以,但是后面那个脉冲就会丢跟头的了。。。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2019-2-23 16:37:02 | 显示全部楼层






typedef struct
{
  encoder_phase_state phase_state[KNOB_COUNT];
        uint8_t rotate_dir[KNOB_COUNT];
        uint8_t tick_count[KNOB_COUNT];
        int32_t pos_old[KNOB_COUNT];
        int32_t pos_new[KNOB_COUNT];
        uint8_t id[KNOB_COUNT];

}knob_struct;

static int32_t knob_read_count(knob_struct *handle, uint8_t axis)
{
    const int8_t phase_ab_states[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 };
    static int32_t encoder_output[KNOB_COUNT];
    static int8_t phase_ab[KNOB_COUNT]; //AB key read out, Previous in the high 2 bits and current in the low two bits;
    static bool first_time_run = true;

    if(first_time_run == true)
    {
        first_time_run = false;

        for(uint8_t idx = 0; idx < KNOB_COUNT; idx++)
        {
            encoder_output[idx] = 0x0000;
            phase_ab[idx] = 0x00;
        }
    }

    phase_ab[axis] <<= 2; //bit 2..3 now contain the previous AB key read-out;

    if(handle->phase_state[axis].phase_a)
    {

        phase_ab[axis] |= 0x02; //set the 1st bit if A is high now;
    }

    if(handle->phase_state[axis].phase_b)
    {
        phase_ab[axis] |= 0x01; //set the 0th bit if B is high;
    }

    phase_ab[axis] &= 0x0f; //only retain phase_ab' last 4 bits (A_previous, B_previous, A_current, B_current)
    encoder_output[axis] += phase_ab_states[phase_ab[axis]];

    handle->pos_new[axis] = encoder_output[axis] >> 1;
    return (encoder_output[axis] >> 1);                              //if you want to return absolute steps.
   
}

这个是我一直用的,主要用于控制面板旋钮操作用的。  1ms 读一次即可。不需要中断,任意一个个IO电平输入即可。

如果是电机的。这种就不合适了。

出1310入193汤圆

发表于 2019-2-23 19:37:26 来自手机 | 显示全部楼层
编码器程序,标记一下。

出0入8汤圆

 楼主| 发表于 2019-2-25 10:12:45 | 显示全部楼层
lianglee 发表于 2019-2-23 20:05
没有谁胆敢说自己的代码就是100分,
就算牛X如微软件的PC软件都会有BUG。
我也不能写出100分的代码。

一段代码的适用性很重要,我这段代码就是业余情况下的普通旋钮操作,不是做产品,简单、好用就够了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 13:36

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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