初出茅庐的小李第49篇博客之记录旋转编码器程序的一个奇怪现象

奇怪的是什么,同样的元器件,同样的逻辑(我觉得是同样的逻辑,可能理解的不完全正确,结果缺截然相反)

在这里插入图片描述

C语言代码移植结果竟然不一样??

前一段时间用Arduino uno 测试学习了编码器的辨别方向方法。
顺时针计数加
逆时针计数减
多么符合常识的逻辑
但是不知道移植到32平台上就需要反写一下代码
真的搞不明白

Arduino 代码实现

const int clkPin = 2;/*A相接口*/
const int dtPin  = 3;/*B相接口*/
const int swPin  = 4;/*按键接口*/
int encoderVal = 0;  /*记录当前的编码器值,为正顺时针方向,为负逆时针方向*/

int getEncoderTurn(void)
{
  static int oldA = HIGH;/*初始化A波形*/
  static int oldB = HIGH;/*初始化B波形*/
  int result = 0;        /*定义一个结果变量记录顺时针还是逆时针*/
 
  int newB = digitalRead(dtPin);
  int newA = digitalRead(clkPin);
  if(newA != oldA || newB != oldB)/*判断AB波形是否发生变化,有任意一个变化则满足条件,确认旋转*/
  {
    if(oldA == HIGH && newA == LOW)/*两个条件同时为真,A波形图产生一个下降沿11发生变化10*/
    {
      result = (oldB*2-1); /*顺时针返回1*2-1=1,逆时针返回0*2-1=-1*/
    }
  }
  oldA = newA;/*更新A波形值*/
  oldB = newB;/*更新B波形值*/
  return result;
}

void setup() 
{
  pinMode(clkPin,INPUT); /*信号输入单片机*/
  pinMode(dtPin,INPUT);  /*信号输入单片机*/
  pinMode(swPin,INPUT);  /*信号输入单片机*/
  digitalWrite(swPin,HIGH);   /*默认按键不触发*/
  Serial.begin(9600);         /*串口监视器波特率9600*/
}

void loop() 
{
  int change = getEncoderTurn();/*反馈信号子函数*/
  encoderVal = encoderVal + change;
  if(digitalRead(swPin) == LOW)
  {
    encoderVal = 0; /*按键被按下*/
  }
  Serial.println(encoderVal);/*打印编码器的值*/
}
/*
这里loop循环里不能添加延时函数,否则会发生不可预测的错误(有点儿坑)
这种写法可以验证编码器的工作原理,但是不适合和其他函数整合到一块儿使用
应该是加入了延时会影响波形的判断,程序需要进一步改进和优化
*/

STM32代码实现

bmq.c
#include "bmq.h"
#include "sys.h"
#include "delay.h"
#include "stdio.h"

void EC11_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
 	
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
 
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//SWITCH 引脚
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_8,Bit_SET);//设定初始状态为低电平
	
} 


//外部中断初始化函数
void EXTIX_Init(void)
{
 	EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟

	//EC11_Init();//初始化按键对应io模式 A6

    //GPIOA6 中断线以及中断初始化配置
	/*
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource6);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line6;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
	*/
	//GPIOA.8 中断线以及中断初始化配置
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);

  	EXTI_InitStructure.EXTI_Line=EXTI_Line8;
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
		
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;              //使能按键所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;		    //子优先级1
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	                //使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure); 
 

}
extern int encoderVal;
//中断服务函数
void EXTI9_5_IRQHandler(void)
{
	if((EXTI_GetITStatus(EXTI_Line8)!=RESET)&& (EC11_SW))//抬手检测发生了按键按下并已经抬起来
	{
		printf("EC11_SW iS PRESS!\r\n");
		encoderVal = 0; /*按键被按下*/
		printf("%d\r\n",encoderVal);	
		EXTI_ClearITPendingBit(EXTI_Line8);    //清除LINE8上的中断标志位
	}
//	if(EXTI_GetITStatus(EXTI_Line6)!=RESET&&(EC11_CLK))
//	{
//		delay_ms(2);	      //*************很重要*******************
		if(EC11_CLK==1)	
		{
//			if(EC11_DTA == 0)
//			{
//				printf("knob: +1 \r\n");//顺时针
//			}else
//			{
//				printf("knob: -1 \r\n");//逆时针
//			}
//			EXTI_ClearITPendingBit(EXTI_Line6);    //清除LINE6上的中断标志位
		} 
//	}
}

int getEncoderTurn(void)
{
  static int oldA = 1;		/*初始化A波形*/
  static int oldB = 1;		/*初始化B波形*/
  int result = 0;        	/*定义一个结果变量记录顺时针还是逆时针*/
 
  int newB = EC11_DTA_Val;
  int newA = EC11_CLK_Val;
  if(newA != oldA || newB != oldB)/*判断AB波形是否发生变化,有任意一个变化则满足条件,确认旋转*/
  {
    if(oldA == 1 && newA == 0)/*两个条件同时为真,A波形图产生一个下降沿11发生变化01or00*/
    {
      result = (newB*2-1); /*逆时针时返回1*2-1=1,顺时针返回0*2-1=-1*/  /*这个有点怪没有发现问题在哪里*/
    }
  }
  oldA = newA;/*更新A波形值*/
  oldB = newB;/*更新B波形值*/
  return result;
}

  
bmq.h
#ifndef __EC11_H_
#define __EC11_H_

#include "stm32f10x.h"


void EC11_Init(void);
void EXTIX_Init(void);
int getEncoderTurn(void);

#define EC11_CLK PAin(6)
#define EC11_DTA PAin(1)

#define EC11_CLK_Val GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)//读A相的引脚电平
#define EC11_DTA_Val GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)//读B相的引脚电平
#define EC11_SW      GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)//读编码器按键电平
#endif

其实我觉得这两种写法的思想方式完全一样,但是 但是问题来了
在这里插入图片描述
这里直接对change变量加就行,正负号刚好代表顺时针何逆时针

在这里插入图片描述
不知道啥原因这里必须用减号才能实现正加计数 负减计数
(按道理因该不加这个-号的由于结果和我想的刚好相反,我就自作聪明来个负负得正
内心其实困惑为啥返回编码器的状态就不一样了呢???????)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值