Pic18 Lab. Experiment #4. Энкодер.

Статья эксперимент про порт кода обработки энкодера из пиков 16 серии.

encoder_8901

Все описано в вышеупомянутой статье, здесь всего лишь адаптированный под 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);
}

И небольшой тест:

encoder_term_out

Все четко срабатывает, периода проверки в 1мс также достаточно для моих китайских энкодеров.

Исходники.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.