Converting 0-5v analog to a rotary encoder equivalent - c

I'm currently working on a robot as an intern and must choose replacement drivers for the motors. The position information of the axis are given by analog pot. I do have 3 drivers by technosoft that needs a rotary encoder (quadrature) information to do their regulation job.
I was thinking about converting this analog signal into the right quadrature signal to make it work.
The way I designed it is a pic18 sampling the pot value at 150hz, subtracting the previous value to the current one to have an idea (a kind of derivation) of the speed. It generates an absolute value of the speed and a direction signal whose regulate the rate of change of a state machine with the 4 states of the quadrature encoder. I finally send these signals to the 2 outputs.
My questions are the following.
Is it feasible. Or is there a clever way of doing so ? Or even a dedicated chip that can do the job? I searched the web to find someone who would have already done something similar but found nothing.
I've spend my 2 last days to code this solution & debug it without success...
On the scope, the quadrature signal is there but it behaves with no real logic. Changing really fast or slowly whether I move or don't move the pot.
Here's my code
#include <p18f4685.h>
#include <stdlib.h>
#include <stdio.h>
#include <delays.h>
// ----------------------
// Configuration Hardware
// ----------------------
#pragma config OSC = HSPLL
#pragma config MCLRE = ON, PWRT = OFF
#pragma config DEBUG = ON, LVP = OFF
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config BOREN = OFF
#pragma config WDT = OFF
#pragma config XINST = OFF
#pragma code
// Variables
unsigned int position_t0=0;
unsigned int position_t1=0;
signed int speed=0;
unsigned int speed_abs=0;
int direction=0; // si 0 cw, si 1 ccw
unsigned int count_1 = 0;
unsigned int state_out = 0;
//proto fonctions
void setup(void);
void get_pot(void);
void set_out(void);
void low_isr(void);
void high_isr(void);
int abval(int);
void main(void)
{
setup(); //initialisation
get_pot();
LATE = 0b00000000;
while(1)
{
}
}
void setup (void)
{
/*config timers*/
T0CON = 0b11000101; // timer on, 8bits, internal clock, prescaler on + value 1/64 (152 interruptions par seconde)
// data acquisition interrup
T2CON = 0b00111100; // output moditication loop timer 8bits 1/8postscale 1200 interrupt/second
PR2 = 0b00001111;
/*config adc*/
ADCON1 = 0b00001010; // A0->A4 analo + VDD+GND reference
ADCON2 = 0b10111000; // A/D acq time (ADCON2) 20TAD, A/D conversion clock (ADCON2)
// right justified
ADCON0 = 0b00000001; // Turn on A/D module (ADCON0) + channel select
/*config des pins*/
// TRISA = 0b00011111; // 5 entrées analogiques + 3 digitales
// TRISB = 0b01001100; // sorties pour la version finale
TRISE = 0b00000000; // sorties pour la version test
// PORTA = 0b00000000; // Clear A
PORTE = 0b00000000; // clear E
/*config interruptions*/
RCONbits.IPEN = 1; // priority enabled
INTCON = 0b11100000; // enable les interruption hautes et basses, Timer0 interrupt On
INTCON2 = 0b10000100; // Pull up désactivés +timer0 high(acquisition vitesse)
PIE1bits.TMR2IE = 1; // enable interrupt timer2
IPR1bits.TMR2IP = 0; // timer 2 en priorité basse(mise à jour des pins)
}
void get_pot (void) //get the value of the pot and computes the data
{
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS0 = 0;
ADCON0bits.GO = 1;
while(ADCON0bits.GO==1){}
position_t1 = ADRESH*256+ADRESL;
speed = position_t1 - position_t0;
if(speed<0) direction = 1;
else direction = 0;
speed_abs = abval(speed);
position_t0 = position_t1;
}
void set_out (void) //set the output according the speed and direction
{
if(speed_abs>1)
{
count_1++;
if(count_1>=(1023-speed_abs)/4) //counter that makes the output change more or less faster
{
if(direction==1)
{
switch(state_out)
{
case 0:
{
LATE = 0b00000000;
state_out++;
}
break;
case 1:
{
LATE = 0b00000001;
state_out++;
}
break;
case 2:
{
LATE = 0b00000011;
state_out++;
}
break;
case 3:
{
LATE = 0b00000010;
state_out=0;
}
break;
}
}
else if(direction==0)
{
switch(state_out)
{
case 0:
{
LATE = 0b00000000;
state_out=3;
}
break;
case 1:
{
LATE = 0b00000001;
state_out--;
}
break;
case 2:
{
LATE = 0b00000011;
state_out--;
}
break;
case 3:
{
LATE = 0b00000010;
state_out--;
}
break;
}
}
count_1=0;
}
}
}
int abval(int val)
{
return (val<0 ? (-val) : val);
}
#pragma interrupt high_isr
void high_isr (void) //interruption de récupération des adc
{
if(INTCONbits.TMR0IF==1)
{
get_pot();
INTCONbits.TMR0IF=0;
}
}
#pragma interruptlow low_isr
void low_isr (void) //interruption de mise à jour des sorties
{
if(PIR1bits.TMR2IF==1)
{
set_out();
PIR1bits.TMR2IF=0;
}
}
/*
*********************************************************************************************************
* Interupt Vectors
*********************************************************************************************************
*/
#pragma code low_vector=0x18
void interrupt_at_low_vector(void)
{
_asm goto low_isr _endasm
}
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
_asm goto high_isr _endasm
}
Part of the code comments are in french, i translated the important ones.
Do you see any obvious mistakes/wrong ways of coding. Do you have any advices of "where to search" or what to watch ?
Thanks by advance for your help !
Nicolas

Related

uart between atmega328p (C) and Feather m0 (Arduino) receive

I want to send data from my ac/gy via atmega328p to a feather m0 module. The atmega is programmed in C using the following github code: https://github.com/YifanJiangPolyU/MPU6050
And the Arduino code for receiving data within the LoRa module is shown below:
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
byte strArray[30];
int i = 0;
if(Serial1.available()>0) {
while (Serial1.available()>0){
strArray[i] = Serial1.read();
i++;
}
// send the 6 bytes payload to LoRaWAN port 7 --> now port 1
LMIC_setTxData2(1, strArray, sizeof(strArray), 1);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage HIGH //optional: for confirmation
}
}
}
// Next TX is scheduled after TX_COMPLETE event.
//delay(60000);
void loop() {
os_runloop_once();
}
However, I can't seem to receive anything and can't send a "char array" to the gateway using the LMIC function apparently, so trying to receiving data within a byte array instead. Any help or tips regarding this is greatly appreciated. I'll also include the main.c code for the atmega328P down here below:
#define F_CPU 16000000UL
#define BAUD 9600
#include <inttypes.h>
#include <avr/sfr_defs.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/setbaud.h>
#include <avr/interrupt.h>
#include <math.h>
#include "mpu6050.h"
#include "mpu6050_reg.h"
#include "i2c.h"
#include "uart.h"
void timer_setup();
void get_time(double* dt);
volatile double count;
const double unit_t = 8/16000000;
int main(void){
sei();
uart_init();
i2c_init();
DDRB |= _BV(5);
uint8_t ret;
int16_t accel_buff[3], gyro_buff[3];
double accelX, accelY, accelZ;
double gyroX, gyroY, gyroZ;
double biasX, biasY;
double phi_accel, theta_accel;
double phi_innov, theta_innov;
double phi_est, theta_est;
double phi_prev, theta_prev;
double dt;
char s[30];
// initialize & test MPU5060 availability
ret = i2c_start(MPU6050_ADDRESS+I2C_WRITE);
if(~ret){
PORTB |= _BV(5);
_delay_ms(200);
PORTB &= ~(_BV(5));
}
mpu6050_init();
timer_setup();
// find gyro bias
biasX = 0;
biasY = 0;
uint8_t i;
for(i=0; i<20; i++){
mpu6050_read_gyro_ALL(gyro_buff);
biasX += gyro_buff[0];
biasY += gyro_buff[1];
}
biasX = biasX/20*(3.14159/180)/1000/32768;
biasY = biasY/20*(3.14159/180)/1000/32768;
// initialization for Kalman filter
double P = 0.0;
double Q = 0.001;
double R = 0.03;
double Pp, K;
mpu6050_read_accel_ALL(accel_buff);
phi_prev = atan2(accelY, accelZ); // row
theta_prev = atan2(-accelX, sqrt(accelY*accelY+accelZ*accelZ)); // pitch
for(;;){
get_time(&dt);
mpu6050_read_accel_ALL(accel_buff);
mpu6050_read_gyro_ALL(gyro_buff);
// acceleration (m/s^2)
accelX = accel_buff[0]*9.8*2/32768;
accelY = accel_buff[1]*9.8*2/32768;
accelZ = accel_buff[2]*9.8*2/32768;
// gyro rate (rad/s)
gyroX = gyro_buff[0]*(3.14159/180)/1000/32768;
gyroY = gyro_buff[1]*(3.14159/180)/1000/32768;
gyroZ = gyro_buff[2]*(3.14159/180)/1000/32768;
// estimation
phi_est = phi_prev + dt*(gyroX - biasX);
theta_est = theta_prev + dt*(gyroY - biasY);
Pp = P+Q;
// innovation
phi_accel = atan2(accelY, accelZ); // row
phi_innov = phi_accel - phi_est;
theta_accel = atan2(-accelX, sqrt(accelY*accelY+accelZ*accelZ)); // pitch
theta_innov = theta_accel - theta_est;
// Kalman gain
K = Pp/(Pp+R);
// correction
phi_prev = phi_prev + K*phi_innov;
theta_prev = theta_prev + K*theta_innov;
P = (1-K)*Pp;
uart_putchar('\n');
_delay_ms(10);
uart_putdouble(phi_prev); //phi, row
uart_putdouble(theta_prev); //theta, pitch
uart_putdouble(dt);
//_delay_ms(10);
}
}//end of main
void timer_setup(){
TCCR1A = 0x00;
TIMSK1 |= _BV(TOIE1);
TCCR1B |= _BV(CS11);
TCCR1B &= ~( _BV(CS12) | _BV(CS10)); // prescaler=8
}
void get_time(double * dt){
cli();
uint8_t l = TCNT1L;
uint8_t h = TCNT1H;
uint16_t step = h<<8 | l;
*dt = (double)step*5e-7 + count*0.032768;
count = 0;
sei();
}
// timer 1 overflow interrupt handler
SIGNAL(TIMER1_OVF_vect){
count += 1;
}
Connect the board to the PC and check in the Arduino IDE Serial Monitor if you can get or send data.
If your serial communication doesn't work, you can check if you are past a point in execution by turning on the led on the board. Most development boards have at least 1, and with Arduino is just a matter of setting the pin as output and digitalWrite(LED_BUILTIN, 0) in setup, then digitalWrite(LED_BUILTIN, 1) at the point you want to check.
If your atmega328p is on an arduino board (e.g. uno, nano etc) you should check in the same way for it, too. Both the serial and past-the-point verification.
I'd to that, then rely on the serial for debugging for a while.
I'm curious, do you think the condition "if(Serial1.available()>0)" is true?

Issue in interfacing SPI e-ink display with PIC 18F46K22

I am using a PIC 18F46K22 in SPI master mode to communicate with a Waveshare 1.54" ePaper Module. The FOSC frequency is 8Mhz internal and SPI configuration is FOSC/4. So when I check the output on logic-analyzer some output bits are differ from expected. And there is some deviation in SCL.
#include <xc.h>
#include "config.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "main.h"
//#define _XTAL_FREQ 8000000
#define SPI1_DUMMY_DATA 0x0
#define SPI_RX_IN_PROGRESS 0x0
#define MY_BUFFER_SIZE 25
extern UBYTE EPD_Init(const unsigned char* lut);
unsigned char myWriteBuffer[100]="Hi I'm master..";
uint8_t myReadBuffer[100];
uint8_t total;
uint8_t temp;
uint8_t my_data = 0x58;
void UART_Init(void)
{
//69
SPBRG2 = 69;
TXSTA2bits.BRGH = 1;
BAUDCON2bits.BRG16 = 1; // Divisor at 8 bit
TRISDbits.TRISD6 = 0;
TRISDbits.TRISD7 = 1;
RCSTA2bits.SPEN = 1; // Enable serial port
TXSTA2bits.SYNC = 0; // Async operation
TXSTA2bits.TX9 = 0; // No tx of 9th bit
RCSTA2bits.RX9 = 0; // No rx of 9th bit
TXSTA2bits.TXEN = 1; // Enable transmitter
RCSTA2bits.CREN = 1; // Enable receiver
}
void UART_Putch(unsigned char bt)
{
while (!PIR3bits.TX2IF); // hold the program till TX buffer is free
TXREG2 = bt; //Load the transmitter buffer with the received value
}
void UART_Print(unsigned const char *ptr)
{
while (*ptr != 0)
{
UART_Putch(*ptr++);
}
}
unsigned char UART_getch() {
unsigned char temp;
if (RCSTA2bits.OERR) // check for Error
{
RCSTA2bits.CREN = 0; //If error -> Reset
//__delay_ms(10);
RCSTA2bits.CREN = 1; //If error -> Reset
}
while (!PIR3bits.RC2IF); // hold the program till RX buffer is free
temp = RCREG2;
return temp; //receive the value and send it to main function
}
void main()
{
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
ANSELD = 0;
TRISBbits.TRISB0 = 0; //RST Pin OUTPUT
TRISBbits.TRISB1 = 0; //DC Pin OUTPUT
TRISBbits.TRISB2 = 0; //CS Pin OUTPUT
TRISBbits.RB3 = 1; //BUSY Pin INPUT
// int i;
TRISD =0;/* PORT initialize as output */
EPD_RST_PIN = 0;
EPD_DC_PIN = 0;
//OSCCON = 0x72; /* Use internal osc. frequency 16 MHz */
OSCCONbits.SCS = 0b10; //Frequency & PLL SETUP
OSCCONbits.IRCF = 0b110; //8 MHz
while (!OSCCONbits.HFIOFS);
OSCTUNEbits.PLLEN = 0; //PLL disable
UART_Init();
SPI_Init_Master(); /* Initialize SPI communication as a master */
if(EPD_Init(lut_full_update) != 0) {
UART_Print("e-Paper init failed\r\n");
while(1);
}
UART_Print("e-Paper init\r\n");
for(uint8_t i = 0; i < 10; i++){
__delay_ms(10);
}
EPD_Clear();
UART_Print("e-Paper cleared\r\n");
for(uint8_t i = 0; i < 10; i++){
__delay_ms(50);
}
while(1)
{
// total = 0;
// //do
// //{
// LATAbits.LATA5=0;
// //total = SPI1_Exchange8bitBuffer(SPI1_DUMMY_DATA, MY_BUFFER_SIZE, &myReadBuffer[total]);
// total = SPI1_Exchange8bit(my_data);
//
// LATAbits.LATA5=1;
// __delay_ms(500);
// __delay_ms(500);
// // Do something else...
//
// //} while(total < MY_BUFFER_SIZE);
// //while(1);
//
// EPD_Clear();
//
// __delay_ms(500);
}
}
void SPI_Init_Master()
{
/* PORT definition for SPI pins*/
TRISCbits.TRISC4 = 1; /* RB0 as input(SDI) */
TRISCbits.TRISC3 = 0; /* RB1 as output(SCK) */
// TRISBbits.TRISB2 = 0; /* RA5 as a output(SS') */
TRISCbits.TRISC5 = 0; /* RC7 as output(SDO) */
/* To initialize SPI Communication configure following Register*/
EPD_CS_PIN = 1;
SSP1STAT=0x00; /* Data change on rising edge of clk , BF=0*/
SSP1CON1=0x20; /* Slave mode,Serial enable, idle state high for clk */
PIR1bits.SSP1IF=0;
/* Disable the ADC channel which are on for multiplexed pin
when used as an input */
ADCON0=0; /* This is for de-multiplexed the SCL
and SDI from analog pins*/
ADCON1=0x0F; /* This makes all pins as digital I/O */
}
uint8_t SPI1_Exchange8bit(uint8_t data)
{
// Clear the Write Collision flag, to allow writing
SSP1CON1bits.WCOL = 0;
SSP1BUF = data;
while(SSP1STATbits.BF == SPI_RX_IN_PROGRESS)
{
}
return (SSP1BUF);
}
uint8_t SPI1_Exchange8bitBuffer(uint8_t *dataIn, uint8_t bufLen, uint8_t *dataOut)
{
uint8_t bytesWritten = 0;
if(bufLen != 0)
{
if(dataIn != NULL)
{
while(bytesWritten < bufLen)
{
if(dataOut == NULL)
{
SPI1_Exchange8bit(dataIn[bytesWritten]);
}
else
{
dataOut[bytesWritten] = SPI1_Exchange8bit(dataIn[bytesWritten]);
}
bytesWritten++;
}
}
else
{
if(dataOut != NULL)
{
while(bytesWritten < bufLen )
{
temp = SPI1_Exchange8bit(SPI1_DUMMY_DATA);
if(temp!=SPI1_DUMMY_DATA)
{
UART_Putch(temp); //uart print
dataOut[bytesWritten] = temp;
bytesWritten++;
}
__delay_ms(5);
}
}
}
}
return bytesWritten;
}
Compare your logic analyser SCK and MOSI timing with that specified for the part at https://www.waveshare.com/wiki/1.54inch_e-Paper_Module:
Note that the MOSI (SDIN) state must be stable on the rising edge of SCK (SCLK). In your case the MOSI transitions are synchronous with the rising edge, and you have a clock transition before the MOSI has the correct D7=0 state. SPI timing is defined by both clock polarity and clock phase - giving four possible clock modes. Compare the Waveshare timing diagram with the 18F46K22 datasheet:
The Waveshare diagram suggests that either CKP=1/CKE=0, or CKP=0/CKE=1 may be used, you have:
SSP1STAT=0x00 ;
SSP1CON1=0x20 ;
Which is CKP=0/CKE=0 (which correlates with your logic analyser trace).
You need on of either:
SSP1STAT=0x20 ; // CKE=1
SSP1CON1=0x20 ; // CKP=0
or
SSP1STAT=0x00 ; // CKE=0
SSP1CON1=0x30 ; // CKP=1
Since idle state (controlled by CKP) of SCK is a don't-care, I suggest leaving that as-is and using the first suggestion - that seems more intuitive somehow.
Note also that your logic analyser must also be set to the same phase/polarity clock mode in order for its presentation of the data to be correct.

Timer based interrupt in PIC microcontroller using mikroC for PIC

I am facing a problem while implementing a timer based interrupt in mikroC for PIC.
I want to toggle a port pin for 8 times if there is a keypress at PORTC.F0 and there should be a delay of say 100ms between the toggles.
Normally this would be very easy using a delay function
for (i=0;i<=8;i++)
{
PORTB.F0=~PORTB.F0;
Delay_ms(100);
}
But during the period, any other keypresses are missed by the system. So I thought of implementing the solution using interrupts.
#define SW PORTC.F0
char ttime,i;
volatile flag;
void Inittimer()
{
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0x06;
TMR1L = 0x00;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
void Interrupt()
{
if (TMR1IF_bit)
{
TMR1IF_bit = 0;
TMR1H = 0x06;
TMR1L = 0x00;
ttime--;
if (ttime==0)
{
flag=1;
}
}
}
void main()
{
Inittimer1();
TRISB = 0;
TRISC.F0 = 1;
PORTB = 0x00;
while(1)
{
if (SW==0)
{
ttime=3;
}
if (flag==1)
{
for (i=0;i<=8;i++)
{
PORTB=~PORTB;
flag=0;
}
}
}
}
Nothing is working. Can somebody please help me to correct the code?
Well this doesn't look right:
if (flag==1)
{
for (i=0;i<=8;i++)
{
PORTB=~PORTB;
flag=0;
}
}
When you first see that flag is set, you immediately loop and toggle the output 8 times, without waiting for flag to turn back to 1. That's not right, it's overly simplified.
You need to look for the flag, then toggle the output and clear the flag, and wait for it to to get set again, maintaining the counter in parallel. The for loop is not the proper structure for this, since it will "lock out" the rest of the program and might cause keypresses to be missed.
When you initialize your timer:
void Inittimer()
{
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0x06; // No prescaler? I doubt your clock speed is 40-some KHz!
TMR1L = 0x00;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
Why don't you control the LED directly from the ISR ?
if (ttime)
PORTB.F0 = (--ttime & 1); // ttime is not decremented when led is not blinking.
else
PORTB.F0 = 0; // ensures the LED is off.
To start blinking 8 times:
if (SW==0)
{
PORTB.F0 = 1;
ttime = 16;
}
Note that with a 100ms clock interrupt, the first 'blink' of the LED may last up to 200ms... This is why many like to work with a faster timer interrupt (this has usually other uses as well), controlling the led would require adding a soft post-scaler
if (blinking)
{
if (--blinkTimer == 0)
{
blinkTimer = BLINK_DELAY; // whatever number it takes for 100ms.
PORTB.F0 = (--blinking & 1);
}
}
else
{
PORTB.F0 = 0
}
To start blinking:
if (SW==0)
{
blinking = (2 * BLINKS) - 1;
blinkTimer = BLINK_DELAY;
PORTB.F0 = 1;
}
This should get you a more even first blink.

Why isn't Timer2 Interrupt firing up?

I am trying to enable timer2 interrupt to use it for PWM purposes. In this case, I just turn on an LED and when timer 2 interrupt occurs I turn it off but the timer interrupt never occurs. Everything looks good to me so I don't understand why Timer2 is not firing up. I am using PIC18F87J11, here is the datasheet.
/*
File: main.c
Date: 2011-SEP-4
Target: PIC18F87J11
IDE: MPLAB 8.76
Compiler: C18 3.40
*/
#include <p18cxxx.h>
#include<usart.h>
#include <pwm.h>
#include <delays.h>
#pragma config FOSC = INTOSC, WDTEN = OFF, XINST = OFF
#pragma interrupt HighISR
void main(void) {
unsigned int i;
/* set FOSC clock to 8MHZ */
OSCCON = 0b01110000;
/* turn off 4x PLL */
OSCTUNE = 0x00;
/* make all ADC inputs digital I/O */
ANCON0 = 0xFF;
ANCON1 = 0xFF;
PR2 = 124; // Period
TMR2=0;
// 1/16 prescalar
T2CONbits.T2CKPS0 = 1;
T2CONbits.T2CKPS1 = 0;
PIE1bits.TMR2IE == 1; // Enables the TMR2 to PR2 match interrupt
// Enable Timer 2
T2CONbits.TMR2ON = 1;
INTCONbits.PEIE = 1; // Enable Perpherial Interrupt
INTCONbits.GIE = 1; // Enable Global Interrupt
TRISDbits.TRISD6 = 0; // Turn on LED
LATDbits.LATD6 = 1;
while (1);
}
#pragma code highVector=0x08
void HighVector(void) {
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
// Timer Interrupt
void HighISR(void) {
if (PIR1bits.TMR2IF == 1) {
LATDbits.LATD6 = 0; // Turn off LED to indicate it came thru
PIR1bits.TMR2IF = 0;
}
}
Thanks!
Found my mistake
PIE1bits.TMR2IE == 1;
It should be PIE1bits.TMR2IE = 1;

How to simulate Interrupts in debug mode with PIC18?

I tried to debug timer 1 interrupt with MPLAB Simulator, but it seems like the debugger never goes to the interrupt service routine.
The settings for timer 1 seem correct to me , not sure if I missed something else. Here is the datasheet
/*
File: main.c
Date: 2011-SEP-4
Target: PIC18F87J11
IDE: MPLAB 8.76
Compiler: C18 3.40
*/
#include <p18cxxx.h>
#pragma config FOSC = INTOSC, WDTEN = OFF, XINST = OFF
#pragma code HighISR = 0x08 // high priority 0x18
#pragma interrupt HighISR
int time = 0;
void main(void) {
/* set FOSC clock to 8MHZ */
OSCCON = 0b01110000;
/* turn off 4x PLL */
OSCTUNE = 0x00;
/* make all ADC inputs digital I/O */
ANCON0 = 0xFF;
ANCON1 = 0xFF;
// 1/1 prescalar
T1CONbits.T1CKPS1 = 0;
T1CONbits.T1CKPS0 = 0;
// Use Internal Clock
T1CONbits.TMR1CS = 0;
// Timer1 overflow interrupt
PIE1bits.TMR1IE = 1;
// Enable Timer 1
T1CONbits.TMR1ON = 1;
INTCONbits.PEIE = 1; // Enable Perpherial Interrupt
INTCONbits.GIE = 1; // Enable Global Interrupt
while (1);
}
// Timer Interrupt
void HighISR(void) {
if (PIR1bits.TMR1IF == 1) {
time++;
PIR1bits.TMR1IF = 0;
}
}
Just found out what I was missing ...
#pragma code highVector=0x08
void HighVector (void)
{
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
Now the whole program looks like this
/*
File: main.c
Date: 2011-SEP-4
Target: PIC18F87J11
IDE: MPLAB 8.76
Compiler: C18 3.40
*/
#include <p18cxxx.h>
#pragma config FOSC = INTOSC, WDTEN = OFF, XINST = OFF
#pragma interrupt HighISR
int time = 0;
void main(void) {
/* set FOSC clock to 8MHZ */
OSCCON = 0b01110000;
/* turn off 4x PLL */
OSCTUNE = 0x00;
/* make all ADC inputs digital I/O */
ANCON0 = 0xFF;
ANCON1 = 0xFF;
// 1/1 prescalar
T1CONbits.T1CKPS1 = 0;
T1CONbits.T1CKPS0 = 0;
// Use Internal Clock
T1CONbits.TMR1CS = 0;
// Timer1 overflow interrupt
PIE1bits.TMR1IE = 1;
// Enable Timer 1
T1CONbits.TMR1ON = 1;
INTCONbits.PEIE = 1; // Enable Perpherial Interrupt
INTCONbits.GIE = 1; // Enable Global Interrupt
while (1);
}
#pragma code highVector=0x08
void HighVector (void)
{
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
// Timer Interrupt
void HighISR(void) {
if (PIR1bits.TMR1IF == 1) {
time++;
PIR1bits.TMR1IF = 0;
}
}

Resources