The language itself has few instruction, maybe as few as one dozen (never counted).
Mike.
I think the idea was to make C easy to compile. It tends to mimic machine language constructs, so a=a+ translates to INC A
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
The language itself has few instruction, maybe as few as one dozen (never counted).
Mike.
Time to read a book on basic C
If that was the idea, it does a very poor job in that regard.It tends to mimic machine language constructs, so a=a+ translates to INC A
#include <xc.h>
#include <stdint.h>
#include "config.c"
#define LED1 LATC3
#define LED2 LATC4
#define LED3 LATC5
#define SW1 RC6
#define SW2 RC7
#define TRISLED1 TRISC3
#define TRISLED2 TRISC4
#define TRISLED3 TRISC5
#define TRISSW1 TRISC6
#define TRISSW2 TRISC7
#define LED1ON LED1=0
#define LED1OFF LED1=1
#define LED2ON LED2=0
#define LED2OFF LED2=1
#define LED3ON LED3=0
#define LED3OFF LED3=1
#define _XTAL_FREQ 32000000
int8_t readEncoder(void);
int8_t encoder,delayLED=0;
void main(void){
OSCCON1 = 0x60; //HF int osc
OSCFRQ = 0x07; //32MHz clock
BORCON = 0x00;
// WDTPS 1:65536; SWDTEN OFF;
WDTCON = 0x16; //WDT off
ANSELC=0;
TRISLED1 = 0; //only need to set
TRISLED2 = 0; //output pins to zero
TRISLED3 = 0; //as default is input
WPUC=0b11000000; //Week pullups on switch inputs
//setup timer2 to generate 1mS ticks
//clocking at 8MHz (32/4), divide by 64 gives 125kHz, postscaler = 1 and PR2 = 124
T2CON=0b00000011;
TMR2ON=1;
PR2=124;
LED1OFF; //LED1 off
LED2OFF; //LED2 off
LED3OFF; //LED3 off
while(1){
while(!TMR2IF); //ensure a ms has passed
TMR2IF=0; //reset flag
encoder=readEncoder();
if(encoder==0){ //encoder not moved
if(delayLED>0){ //has the (100mS) delay finished
delayLED--; //no, so count down
}else{
LED1OFF; //yes, turn off LEDs
LED3OFF;
}
}else if(encoder==1){ //increment?
LED3ON; //turn on LED
delayLED=100; //keep it on for 100mS
}else if(encoder==-1){
LED1ON; //as above
delayLED=100;
}
}
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const signed char table[] = {0,-1,+1,0,+1,0,0,-1,-1,0,0,+1, 0,+1,-1, 0};
int8_t readEncoder(void){
static uint8_t previous;
uint8_t one=0,two=0;
if(SW1) //preread switches
two|=1;
if(SW2)
two|=2;
do{
__delay_us(250); //short delay
one=two; //keep old value
if(SW1) //get new value
two|=1;
if(SW2)
two|=2;
}while(one!=two); //repeat until bouncing stops
previous<<=2; //make room for new bits
previous|=one; //OR in new bits
previous&=15; //get rid of higher bits
return(table[previous]);//return value from table
}
I've had a play with this and found that contact bounce is a real problem.
The Jaycar encoder is the Ebay one, at 4+ times the price (and green instead of blue).Yes, contact bounce is a real problem with encoders, particularly cheap ones - so the Jaycar one 'might' work, but the Ebay one not.
#include <xc.h>
#include <stdint.h>
#include "config.c"
#define LED1 LATC3
#define LED2 LATC4
#define LED3 LATC5
#define SW1 RC6
#define SW2 RC7
#define TRISLED1 TRISC3
#define TRISLED2 TRISC4
#define TRISLED3 TRISC5
#define TRISSW1 TRISC6
#define TRISSW2 TRISC7
#define LED1ON LED1=0
#define LED1OFF LED1=1
#define LED2ON LED2=0
#define LED2OFF LED2=1
#define LED3ON LED3=0
#define LED3OFF LED3=1
#define _XTAL_FREQ 32000000
int8_t encoder,delayLED=0,encoderCount=0;
void main(void){
OSCCON1 = 0x60; //HF int osc
OSCFRQ = 0x07; //32MHz clock
BORCON = 0x00;
// WDTPS 1:65536; SWDTEN OFF;
WDTCON = 0x16; //WDT off
ANSELC=0;
TRISLED1 = 0; //only need to set
TRISLED2 = 0; //output pins to zero
TRISLED3 = 0; //as default is input
WPUC=0b11000000; //Week pullups on switch inputs
//setup timer2 to generate 250uS interrupts
//clocking at 8MHz (32/4), divide by 64 gives 125kHz, postscaler = 1 and PR2 = 31
T2CON=0b00000011;
TMR2ON=1;
PR2=31;
LED1OFF; //LED1 off
LED2OFF; //LED2 off
LED3OFF; //LED3 off
TMR2IE=1;
PEIE=1;
GIE=1;
while(1){
__delay_ms(1); //stop it running too fast
GIE=0; //no interrupts
encoder=encoderCount; //get the count
encoderCount=0; //and zero the interrupt variable
GIE=1; //let interrupts happen again
if(encoder==0){ //encoder not moved
if(delayLED>0){ //has the (100mS) delay finished
delayLED--; //no, so count down
}else{
LED1OFF; //yes, turn off LEDs
LED3OFF;
}
}else if(encoder>0){ //increment?
LED1ON; //turn on LED
delayLED=100; //keep it on for 100mS
}else if(encoder<0){
LED3ON; //as above
delayLED=100;
}
}
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const signed char table[] = {0,-1,+1,0,+1,0,0,-1,-1,0,0,+1, 0,+1,-1, 0};
void __interrupt() inter(void){
volatile static uint8_t previous;
static uint8_t one,two;
TMR2IF=0; //must be timer2 or we have a huge problem
one=two; //copy previous value
two=0; //and zero current
if(SW1) //update current from switches
two|=1;
if(SW2)
two|=2;
if(two==one){ //if bouncing stopped
previous<<=2; //make room for new bits
previous|=two; //OR in new bits
previous&=15; //discard higher bits
encoderCount+=table[previous]; //get value from table - note added so encoderCount can be more than ±1
}
}
if(SW1) //update current from switches
two|=1;
if(SW2)
two|=2;
while();
while(1){
}
while(1){}
while(1)
{
}
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = SWDTEN // Watchdog Timer Enable->WDT controlled by the SWDTEN bit in the WDTCON register
#pragma config PWRTE = ON // Power-up Timer Enable->PWRT enabled
#pragma config MCLRE = OFF // MCLR Pin Function Select->MCLR/VPP pin function is INPUT
#pragma config CP = OFF // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = OFF // Brown-out Reset Enable->Brown-out Reset disabled
#pragma config CLKOUTEN = OFF // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = ON // Internal/External Switchover->Internal/External Switchover mode is enabled
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is enabled
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = ON // PLL Enable->4x PLL enabled
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF // Low-Voltage Programming Enable->High-voltage on MCLR/VPP must be used for programming
#include <xc.h>
#include <stdint.h>
#define LED1 LATA0
#define LED2 LATA1
#define LED3 LATA2
#define SW1 RA3
#define SW2 RA4
#define TRISLED1 TRISA0
#define TRISLED2 TRISA1
#define TRISLED3 TRISA2
#define TRISSW1 TRISA3
#define TRISSW2 TRISA4
#define LED1ON LED1=0
#define LED1OFF LED1=1
#define LED2ON LED2=0
#define LED2OFF LED2=1
#define LED3ON LED3=0
#define LED3OFF LED3=1
#define _XTAL_FREQ 32000000
int8_t readEncoder(void);
int8_t encoder,delayLED=0;
void main(void){
OSCCON = 0x70; // set osc to 32MHz
BORCON = 0x00;
// WDTPS 1:65536; SWDTEN OFF;
WDTCON = 0x16; //WDT off
ANSELA=0;
TRISLED1 = 0; //only need to set
TRISLED2 = 0; //output pins to zero
TRISLED3 = 0; //as default is input
OPTION_REGbits.nWPUEN = 1;
//setup timer2 to generate 1mS ticks
//clocking at 8MHz (32/4), divide by 64 gives 125kHz, postscaler = 1 and PR2 = 124
T2CON=0b00000011;
TMR2ON=1;
PR2=124;
LED1OFF; //LED1 off
LED2OFF; //LED2 off
LED3OFF; //LED3 off
while(1){
while(!TMR2IF); //ensure a ms has passed
TMR2IF=0; //reset flag
encoder=readEncoder();
if(encoder==0){ //encoder not moved
if(delayLED>0){ //has the (100mS) delay finished
delayLED--; //no, so count down
}else{
LED1OFF; //yes, turn off LEDs
LED3OFF;
}
}else if(encoder==1){ //increment?
LED3ON; //turn on LED
delayLED=100; //keep it on for 100mS
}else if(encoder==-1){
LED1ON; //as above
delayLED=100;
}
}
}
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const signed char table[] = {0,-1,+1,0,+1,0,0,-1,-1,0,0,+1, 0,+1,-1, 0};
int8_t readEncoder(void){
static uint8_t previous;
uint8_t one=0,two=0;
if(SW1) //preread switches
two|=1;
if(SW2)
two|=2;
do{
__delay_us(250); //short delay
one=two; //keep old value
if(SW1) //get new value
two|=1;
if(SW2)
two|=2;
}while(one!=two); //repeat until bouncing stops
previous<<=2; //make room for new bits
previous|=one; //OR in new bits
previous&=15; //get rid of higher bits
return(table[previous]);//return value from table
}
...Academia recommends the last version.
Mike.
You will definitely get both LEDs lit if you reverse direction due to the delay being re-triggered every move. I can't get both lit when spinning in one direction - maybe you can spin faster than me!!!I can trick it in to lighting both direction LEDs at high speed rotation of the encoder or by judicious reversing direction half way through the 4 step sequence, but I was deliberatly trying things to see if I could upset it
I'm using your code in post #92, just dropping my config and definitions over the top of yours.Are you up to trying the interrupt version? It seems to work very well for me and doesn't miss anything - so far.
Any bits of the code that you're not following or needs to be better explained?
Mike.
encoderCount=0; //and zero the interrupt variable
Can you elaborate on that? Why won't it work? It simply returns a value that is ± a number which you add to a larger variable and then check the larger variable is in range. The larger variable can be uses as is or divided by four to account for the detent count.As it currently stands, that encoder function isn't going to work for what I want to do.