Pic Lab, PIC18, Experiment #4, Encoder

Porting the procedures from PIC16 to series 18

an encoder

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.

The source

Leave a Reply

Your email address will not be published.