STM32
直播中

算一挂

8年用户 869经验值
私信 关注
[问答]

如何对Stm32中AB相编码器的寄存器进行配置呢

如何对STM32中AB相编码器的寄存器进行配置呢?其编码器模式该怎样去设置呢?

回帖(1)

王有罕

2021-12-15 11:22:06
Stm32关于AB相编码器的寄存器配置

本人目前大四…第一次写博客…感觉起步已经晚了很多…
之前有做过几个小项目…虽然都是小打小闹吧…最近在做毕业设计…果然基础不扎实导致了很多地方有问题…在此记录一下自己的经验与心得…希望能帮助到大家…
技术有限,希望厉害的同学不要笑话我…
先提一下背景…用的是正点原子配置好的工程…下面这个函数是正点原子sys.c里的
Stm32_Clock_Init(336,8,2,7);
初始化系统时钟…一开始没加的时候也能执行.不确定这句话会不会影响编码器的定时器时钟…个人感觉应该不影响

    RCC->AHB1ENR|=1<<4;
    RCC->APB2ENR|=1<<0;


    GPIOE->MODER&=~(3<<9*2);
        GPIOE->MODER|=2<<(9*2);
        GPIOE->OSPEEDR&=~(3<<(9*2));
        GPIOE->OSPEEDR|=3<<(9*2);
        GPIOE->OTYPER&=~(1<<9);
        GPIOE->OTYPER|=1<<9;
        GPIOE->PUPDR&=~(3<<(9*2));
        GPIOE->PUPDR|=1<<(9*2);
       
        GPIOE->MODER&=~(3<<11*2);
        GPIOE->MODER|=2<<(11*2);
        GPIOE->OSPEEDR&=~(3<<(11*2));
        GPIOE->OSPEEDR|=3<<(11*2);
        GPIOE->OTYPER&=~(1<<11);
        GPIOE->OTYPER|=1<<11;
        GPIOE->PUPDR&=~(3<<(11*2));
        GPIOE->PUPDR|=1<<(11*2);


        GPIOE->AFR[1] &=~(15<<(4*1));   
    GPIOE->AFR[1] &=~(15<<(4*3));
    GPIOE->AFR[1] |=(1<<(4*1));
        GPIOE->AFR[1] |=(1<<(4*3));
       
        最上面的两句话分别是使能PTE的时钟,以及使能TIM1的时钟…注意看手册的时候别移位移错了…之前把1<<4写成了1<<5,找了半天问题…汗(lll¬ω¬)…
然后就是更改寄存器配置,先清空引脚功能,设置成复用输出,然后改输出频率大小以及开漏和上拉电阻…最后复用功能为tim功能
虽然没测试过…但是感觉上述写起来可能有些麻烦…感觉可以精简写成
   
    RCC->AHB1ENR|=1<<4;
    RCC->APB2ENR|=1<<0;


        GPIOE->MODER&=~(3<<9*2);
        GPIOE->MODER|=2<<(9*2);
        GPIOE->MODER&=~(3<<11*2);
        GPIOE->MODER|=2<<(11*2);


        GPIOE->AFR[1] &=~(15<<(4*1));   
    GPIOE->AFR[1] &=~(15<<(4*3));
    GPIOE->AFR[1] |=(1<<(4*1));
        GPIOE->AFR[1] |=(1<<(4*3));
感觉这几句就可以了…因为毕竟要复用成别的功能…感觉输出频率和输出方式似乎可以不用设置…而且查到一个资料也有这种写法…这里先打一个问号?
下面是编码器模式的设置

        TIM1->DIER|=1<<0;
        TIM1->DIER|=1<<6;
        TIM1->PSC=0X0;
        TIM1->CCMR1&=0xFCFC;
        TIM1->CCMR1|=1<<0;
        TIM1->CCMR1|=1<<8;
        TIM1->CCMR1|=3<<4;
        TIM1->ARR=65534;
        TIM1->CCER|=0<<1;
        TIM1->CCER|=1<<0;
        TIM1->EGR|=1<<0;
        TIM1->CR1&=~(3<<8);
        TIM1->CR1&=~(3<<5);
        TIM1->CR1|=0<<7;
        TIM1->SMCR&=0xFFF8;
        TIM1->SMCR|=3<<0;
        TIM1->CNT|=1000;
        TIM1->CR1|=1<<0;
最上面两句关于dier寄存器的设置分别是更新中断使能位和触发中断使能位…是我查书关于输入捕捉脉冲的程序上有此使能,但是不确定编码器模式是否需要这两位使能
PSC寄存器,预分配值…这里直接0x0,表示计数器时钟频率就等于输入到预分频器的时钟频率…也就是不分频…这里的复位值也是0x00…所以感觉这句话也没啥用
CCMR1寄存器,前两句话的意思是配置为输入,将IC1 2映射到TI1 2上,这两句必须存在…因为我使用的是TIM1_CH1和CH2,如果你用的是CH3和CH4,就需要配置CCMR2这个寄存器…配置方法是一样的…第三句是一个滤波器…不确定效果如何…感觉我做的小项目不需要太高的精度…所以这里这句话有没有问题不大…
ARR寄存器,自动重载值…这个值越大…采集到的脉冲也越多…因为采集脉冲的时间也多…这个值最大0xffff
CCER寄存器,输入捕获用的寄存器…这里的配置是上升沿捕获脉冲…不过感觉开启编码器模式之后…这两句话并不需要
EGR寄存器,也是输入捕获用的寄存器…感觉也不需要
SMCR寄存器,这个是用来开启编码器模式的寄存器…





这里我是设置的编码器模式3
CNT寄存器…从这里可以读出记录的脉冲个数…这里初值写的1000,实际上写任何数都可以
CR1寄存器,使能计数器…这里就不赘述了
实际上,感觉比较有用的语句精简一下
      
        TIM1->ARR = 0xFFFF;
    TIM1->PSC = 0;
     
    TIM1->CCMR1 |=        1<<0;         
        TIM1->CCMR1 |=        1<<8;           
     
    TIM1->SMCR |=3<<0;               
    TIM1->CR1 |= 1<<0;              
没有试验过这样能不能用,可以试试…
然后就是再写一个定时器来读取CNT的值

        RCC->APB1ENR|=1<<1;
        TIM3->ARR=999;
        TIM3->PSC=7199;
        TIM3->DIER|=1<<0;
        TIM3->CR1|=0X01;
        MY_NVIC_Init(1,3,TIM3_IRQn,2);       
       
        int read_encoder(void)
        {
               
                encoder_num = (short)TIM1 ->CNT;
                TIM1 ->CNT = 0;
               
                return encoder_num;
       
        }
       
void TIM3_IRQHandler(void)
{
        if(TIM3->SR&0X0001)
        {
               
                a=read_encoder();
       
        }
        TIM3->SR&=~(1<<0);


}


a是全局变量,打开调试看看a的变化就可以了…

可以看到轮子在转





可以看到watch窗口里的变量也的确在变化
有错误的话请留言!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分