Porting the procedures from PIC16 to series 18
The theory already is described in the before mentioned article, so not much to discuss, so straight to the code:
#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); }
A small test:
Works well, the 1ms period still good enough for all my Chinese encoders.