两个端口提供方波,但时序略有不同。因此,如果我们接受输出为1和0,则只能有四个状态,0 0,1 0,1 1,0 1.二进制输出的序列决定顺时针转动或逆时针转动。例如,如果旋转编码器在空闲状态下提供1 0并在此之后提供1 1,则意味着编码器将其位置向顺时针方向改变一步,但如果在空闲1 0之后提供0 0,则意味着轴一步一步地沿逆时针方向转动其位置。
所需组件
现在是确定我们需要什么接口旋转编码器与 pic 微控制器的时候了,
PIC16F877A
电阻器
1k电阻器
10k
4.7k电容器33pF陶瓷圆盘电容器 - 2个
20Mhz晶体
16x2显示
旋转编码器
5V适配器。
面包板
连接线。
PIC16F877A旋转编码器接口电路图
下面是根据电路图连接组件后的最终设置图:
我们使用单个1K电阻来代替LCD的对比度,而不是使用电位计。
代码说明
完整的PIC代码 在本项目的最后给出了 演示视频,这里我们将解释代码的一些重要部分。如果您是PIC微控制器的就遵循我们的 新手,请PIC教程 从一开始。
正如我们之前讨论的那样,我们需要 检查输出并区分DT和CLK的二进制输出,因此我们创建了一个 if-else为操作部分。
if (Encoder_CLK != position){
if (Encoder_DT != position){
// lcd_com (0x01);
counter++; // Increase the counter which will be printed on the lcd
lcd_com (0xC0);
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
}
else{
// lcd_com (0x01);
lcd_com (0xC0);
counter--; // decrease the counter
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
//lcd_puts("Left");
}
}
我们还需要在每一步上存储位置。为此, 我们使用了一个存储当前位置的变量 “position”。
position = Encoder_CLK; // It is to store the encoder clock position on the variable. Can be 0 or 1
除此之外,还提供了一个选项,用于 通知开关按压LCD上的。
if (Encoder_SW == 0)
{
sw_delayms(20); //debounce delay
if (Encoder_SW == 0)
{ //lcd_com(1);
//lcd_com(0xC0);
lcd_puts ("switch pressed");
// itoa(counter, value, 10);
// lcd_puts(value);
}
}
系统 _ init 函数用于初始化引脚 ito 操作、lcd 和存储旋转编码器位置。
void system_init()
{
TRISB = 0x00; // PORT B as output, This port is used for LCD
TRISDbits.TRISD2 = 1;
TRISDbits.TRISD3 = 1;
TRISCbits.TRISC4 = 1;
lcd_init(); // This will Initialize the LCD
position = Encoder_CLK;// Sotred the CLK position on system init, before the while loop start.
}
lcd 功能写在 lcd. h 库上, 其中声明了 lcd _ put ()、lcd _ cmd ()。
完整代码:
/*
* File: main.c
* Author: Sourav Gupta
*
* Created on 18 Dec 2018, 18:57
*/
/*
* Configuration Related settings. Specific for microcontroller unit.
*/
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 20000000
/*
* System Header files inclusions
*/
#include
//#include
#include
#include "supporting c files/lcd.h"
#define Encoder_SW PORTDbits.RD2
#define Encoder_DT PORTDbits.RD3
#define Encoder_CLK PORTCbits.RC4
/*
* Program flow related functions
*/
int counter; // It will hold the count of rotary encoder.
int position; // It will store the rotary encoder position.
void sw_delayms(unsigned int d);
int value[7];
/*
* System Init Function
*/
void system_init ();
/* Main function single Thread*/
void main(void) {
system_init();
lcd_puts ("Circuit Digest");
lcd_com(0xC0);
counter = 0;
while(1){
lcd_com(0xC0);
if (Encoder_SW == 0){
sw_delayms(20);
if (Encoder_SW == 0){
//lcd_com(1);
//lcd_com(0xC0);
lcd_puts ("switch pressed");
// itoa(counter, value, 10);
// lcd_puts(value);
}
}
if (Encoder_CLK != position){
if (Encoder_DT != position){
// lcd_com (0x01);
counter++;
lcd_com (0xC0);
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
}
else{
// lcd_com (0x01);
lcd_com (0xC0);
counter--;
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
//lcd_puts("Left");
}
}
position = Encoder_CLK;
}
return;
}
void sw_delayms(unsigned int d){
int x, y;
for(x=0;x