Статья эксперимент про порт кода обработки энкодера из пиков 16 серии.
Все описано в вышеупомянутой статье, здесь всего лишь адаптированный под pic18f14k50 код.
#include <xc.h>
#include <plib/usart.h>
#include <plib/delays.h>
#define _XTAL_FREQ 12000000 //The speed of your internal(or)external oscillator
#pragma config WDTEN = OFF, LVP = OFF, FOSC = HS
unsigned char UARTConfig = 0;
unsigned char baud = 0;
volatile unsigned char EncData = 3;
void NumToUart(unsigned int Num);
void InitTimer0();
void Delay1us(); //1us delay for 12MHz xtall
void DelayUs(unsigned char Us);
void DelayMs(unsigned int Ms);
void main()
{
unsigned char OldEncData = 3; //сохраням старое значение линий, инициализируем с 3
unsigned char upcount = 0;
unsigned char downcount = 0;
ANSEL = 0; //Отключаем аналоговые буфера
ANSELH = 0;
TRISB7 = 0; //TX pin set as output
TRISB5 = 1; //RX pin set as input
TRISB6 = 1; //RX pin set as input
TRISC2 = 0;
TRISC0 = 1;
TRISC1 = 1;
PORTCbits.RC2 = 1;
UARTConfig = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ; //прерывания выключены, асинхронный режим, 8 бит, высокоскоростной режим
baud = 77; //Focs/(9600*16) - 1
OpenUSART(UARTConfig,baud);
putsUSART( (char *) "Welcome to Diymicro.ru!!!\r\n" );
InitTimer0();
GIE = 1;
PEIE = 1;
TMR0IE = 1;
while(1)
{
if (OldEncData != EncData) { //если новое значение отличается от старого
switch (OldEncData) {
case 0 : if (EncData == 1) {upcount++; downcount=0; }
if (EncData == 2) {downcount++; upcount = 0; }
break;
case 1 : if (EncData == 3) {upcount++; downcount=0; }
if (EncData == 0) {downcount++; upcount = 0; }
break;
case 2 : if (EncData == 0) {upcount++; downcount=0; }
if (EncData == 3) {downcount++; upcount = 0; }
break;
case 3 : if (EncData == 2) {upcount++; downcount=0; }
if (EncData == 1) {downcount++; upcount = 0; }
break;
}
OldEncData = EncData; //текущее значение = старое значение
}
if (upcount >= 4) { //флаг поворота направо
putsUSART( (char *)"\r\n UP");
upcount = 0;
}
if (downcount >= 4 ) { //флаг поворота налево
putsUSART( (char *)"\r\n Down");
downcount = 0;
}
}
}//main
void interrupt isr()
{
if (TMR0IF)
{
EncData = PORTCbits.RC0 | (PORTCbits.RC1 << 1);
InitTimer0();
TMR0IF = 0;
}
}
void NumToUart(unsigned int Num) //Number to uart
{
unsigned int bignum = 10000;
unsigned char numtemp = 5;
if (!Num)
{
WriteUSART('0'); //Выталкиеваем все разряды - от старшего к младшему
while(BusyUSART()); //Ждем пока освободится модуль иначе будут прострелы
}
else
{
while(numtemp>0) //Определяем сколько разрядов имеет наше число
{
if (Num/bignum)
break;
numtemp--;
bignum = bignum / 10;
}
for (unsigned char i = numtemp; i>0; i--)
{
WriteUSART( (Num - (Num/(bignum*10))*bignum*10 )/bignum + '0'); //Выталкиеваем все разряды - от старшего к младшему
while(BusyUSART()); //Ждем пока освободится модуль иначе будут прострелы
bignum = bignum/10;
}
}
}
void InitTimer0() //Timer0 initialization, 8bit mode, prescaler = 16 - period 1ms
{
TMR0 = 67; //188*16*333.33ns approx 1ms
T0CON = 0b11010011;
}
void Delay1us() //delay approx 1 us
{
Delay1TCY();
Delay1TCY();
Delay1TCY();
}
void DelayUs(unsigned char Us) //delay for a given number of microseconds
{
for (unsigned char i = 0; i<Us; i++)
Delay1us();
}
void DelayMs(unsigned int Ms) //approx delay for a given number of miliseconds
{
for (unsigned int i=0; i<Ms; i++)
Delay1KTCYx(3);
}
И небольшой тест:
Все четко срабатывает, периода проверки в 1мс также достаточно для моих китайских энкодеров.