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.
Is CCPR1= 2000 valid statement or should CCPR1H and CCPR1L be used?This is code I think will work with a 164. RC0 should go to the data input (pins 1&2) and RC1 to clock (pin 8). The servos go to Qa to Qe.
Not tested as no hardware, comments welcome.
It (I hope) outputs a 0.5mS pulse every servoTime.Code:#include <xc.h> #include "config.c" #include <stdint.h> #define _XTAL_FREQ 32000000 #define NUM_SERVOS 10 uint16_t servoPos[NUM_SERVOS]; uint32_t ms; uint8_t count=0,servoCount; void main(void) { OSCCON=0b01110000; //8MHz PLLEN=1; //x4=32MHz //setup 1mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=49 = 50,000/50 = 1000 = 1mS T2CON=0b01001110; //pre=16 post=10 PR2=49; TMR2IE=1; //timer 2 interrupts enable T1CON=0; //timer 1 stopped for(uint8_t i=0;i<NUM_SERVOS;i++){ servoPos[i]=i*1000+8000; //1ms(8000) to 1.875(7/8ths - 15000)ms in 1/8th mS steps } TRISC=0b11111100; //CCP0 & 1 output PEIE=1; GIE=1; while(1){ //adjust servo positions here } } void __interrupt() inter(void){ if(TMR2IE && TMR2IF){ ms++; count++; if(count>=20){ //start every 20mS TMR1=0; //zero timer 1 T1CON=1; //start timer 1 count=0; CCP1CON=0b1000; //CCP1 pin low and high on match - will be first pulse CCPR1=2000; //start pulse in 0.25mS (2000 clock cycles) CCP1IE=1; //enable CCP1 interrupts CCP1IF=0; //ensure interrupt flag is clear servoCount=0; //reset servoCount LATC0=1; //connected to data in of shift register will clock in a high when CCP1 goes high } TMR2IF=0; } if(CCP1IE && CCP1IF){ LATC0=0; //clear the data in pin if(servoCount==9) //have we done all servos? CCP1IE=0; //yes so no more CCP1 interrupts if(CCP1CON==0b1000){ //have we started the 4000 cycle pulse CCP1CON=0b1001; //yes so end the pulse after 0.5mS CCPR1=CCPR1+4000; //4000 cycles=0.5mS }else{ CCP1CON=0b1000; //No so output the timed gap CCPR1=CCPR1+servoPos[servoCount++]-4000; //will generate an interrupt when servo time is up } CCP1IF=0; } }
Mike.
Edit, added a millisecond interrupt as it's useful.
Hi S,jjw, if one looks at the system variables in Oshonsoft, CCPR1 is defined as a byte, location same as CCPR1L. CCPR1H is also defined as a byte, at the next higher address. Since CCPR1 is defined as a byte in Oshonsoft by default, one can only do byte operations against it and have to use CCPR1H and CCPR1L to used word values...
CCPR1 = 2000 is an invalid operation.
I checked this with PIC18 IDE.
View attachment 140158
PIE1.TMR2IF = 0 'Variable argument expected here??????????????
If PIE1.TMR2IE And PIR1.TMR2IF Then
CCPR1 = 2000
Will need to be,
CCPR1L=0xD0
CCPR1H=0x07
Hi M,Been away for the last few days and writing this reply on my phone would have been painful.
Theconversion is weird as it (the A.I.) got it right earlier,Code:PIE1.TMR2IF = 0 'Variable argument expected here??????????????
So, yes it should be PIR1.TMR2IF.Code:If PIE1.TMR2IE And PIR1.TMR2IF Then
All the references to CCPR1 will need to be double writes so,
Code:CCPR1 = 2000 Will need to be, CCPR1L=0xD0 CCPR1H=0x07
And the other write to CCPR1 changed as posted previously.
Mike.
edit, 2000 decimal is 0x07D0 hex.
edit2, the code uses timer 2 for the 1mS interrupt and timer 1 for the servo timing via CCP1 in compare mode.
edit3, can you post your current code that you're currently working with - preferably as a text file.
edit4, no idea what is set/clear in the config values but one of those bits moves CCP1 to port B so it won't appear on PortC.1
no idea what is set/clear in the config values but one of those bits moves CCP1 to port B so it won't appear on PortC.1
Hi M,The chip is executing 8,000,000 instructions per second so in 1mS it executes 8,000 instructions. As long as the GPS (usart) interrupt doesn't wait for the whole sentence then it'll all be fine. All the above interrupts are very short, it spends most of the time in the while loop.
Mike.
Then it shouldn't. That's almost as bad as having a huge delay with interrupts disabled.The GPS waits for a whole sentence.
Hi M,Then it shouldn't. That's almost as bad as having a huge delay with interrupts disabled.
Mike.
Hi M,Assuming the GPS is at 9600 baud then you get a character approximately every mS. Read the character (using an interrupt), put it in a buffer, if a complete sentence has been received then deal with it, otherwise, return from the interrupt and don't block the rest of the program.
I can now see why you need multiple chips.
Mike.
/*
* File: rj_ringbuffer.h
* Author: Robert Jenkins
*
* Created on 22 October 2018, 16:45
*/
#ifndef RJ_RINGBUFFER_H
#define RJ_RINGBUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
// This must be a power-of-2 value
// The mask is the bit size of this value
// eg. 32 size, 0x1F mask; five bits set, 2^5 = 32.
// 256 size, mask 0xff
// 64 size, mask 0x3f
// 8 size, mask 0x07 etc.
#define RING_BUFFER_SIZE 256
#define RING_BUFFER_MASK 0xff
/* In the main program, declare each required buffer
* with its own name, like
rs232_buffer serial_rx;
or
rs232_buffer terminal_tx;
etc.
*/
// Limit value to prevent possible buffer wrap.
#define RING_BUFFER_LIMIT RING_BUFFER_SIZE - 2
typedef struct rs_bf
{
unsigned int16 buf_inp;
unsigned int16 buf_out;
unsigned int8 * inp_ptr;
unsigned int8 * out_ptr;
unsigned int16 bcount;
unsigned int8 buf_dat[RING_BUFFER_SIZE];
} rs232_buffer;
//
// In each of these, "rs232_buffer *" is replaced by the
// name of buffer as declared above, eg.
//
// buf_put(terminal_tx, c);
// i = buf_count(serial_rx);
//
void buf_clear(rs232_buffer *);
int buf_put(rs232_buffer *, char);
char buf_get(rs232_buffer *);
int buf_count(rs232_buffer *);
int buf_put_string(rs232_buffer *, char *);
#ifdef __cplusplus
}
#endif
#endif /* RJ_RINGBUFFER_H */
#include "rj_ringbuffer.h"
/* For reference:
typedef struct rs_bf
{
unsigned int16 buf_inp;
unsigned int16 buf_out;
unsigned int8 * inp_ptr;
unsigned int8 * out_ptr;
unsigned int16 bcount;
unsigned int8 buf_dat[RING_BUFFER_SIZE];
} rs232_buffer;
*/
void buf_clear(rs232_buffer *b)
{
b->buf_inp = b->buf_out = b->bcount = 0;
b->inp_ptr = b->out_ptr = &(b->buf_dat[0]);
}
int buf_put(rs232_buffer *b, char c)
{
if(b->bcount < RING_BUFFER_LIMIT)
{
b->buf_dat[b->buf_inp++] = c;
b->bcount++;
b->buf_inp &= RING_BUFFER_MASK;
}
return b->bcount;
}
char buf_get(rs232_buffer *b)
{
char c;
if(b->bcount > 0)
{
c = b->buf_dat[b->buf_out++];
b->bcount--;
b->buf_out &= RING_BUFFER_MASK;
if(b->buf_inp == b->buf_out)
b->bcount = 0;
return c;
}
else
return '\0';
}
int buf_count(rs232_buffer *b)
{
return b->bcount;
}
int buf_put_string(rs232_buffer *b, char *c)
{
char *p;
char l;
int i = 0;
p = c;
while(*p)
{
l = *p++;
buf_put(b, l);
i++;
}
return i;
}