奇怪的是什么,同样的元器件,同样的逻辑(我觉得是同样的逻辑,可能理解的不完全正确,结果缺截然相反)
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变量加就行,正负号刚好代表顺时针何逆时针
不知道啥原因这里必须用减号才能实现正加计数 负减计数
(按道理因该不加这个-号的由于结果和我想的刚好相反,我就自作聪明来个负负得正
内心其实困惑为啥返回编码器的状态就不一样了呢???????)