The .w bit was to mimic the oshonsoft .HB and .LB. .w is not legal in oshonsoft (I think) it's only in C as a union. The later version uses a word variable instead and loads CCPR1L and H into it, does some maths and moves it back.
The use of 2000 and 4000 are just constants that represent 0.25mS and 0.5mS and are definitely required. They can easily be split up into two 8 bit variables to load into the registers - or in the 4000 case added to the word variable.
Why doesn't 'Define num_servos = 10 'not compile?? compile?
You have constants defined above I.E. Define CLOCK_FREQUENCY = 32
What is the difference?
Why does one compile and not the other?
Here's a version that does not use a union and writes the two 8 bit values and makes i a global variable,
Code:
#include <xc.h>
#include "config.c"
#include <stdint.h>
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 10
#define BUFFER 80
uint8_t buff[BUFFER],strCount=0,done=0;
uint16_t wordTemp;
uint32_t ms;
uint8_t count=0,servoCount,i;
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(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
CCPR1L=0x0d;
CCPR2H=0x07;
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
wordTemp=CCPR1H*256+CCPR1L;
wordTemp=wordTemp+4000;
CCPR1L=wordTemp & 255;
CCPR1H=wordTemp/256;
}else{
CCP1CON=0b1000; //No so output the timed gap
//CCPR1=CCPR1+servoPos[servoCount++]-4000; //will generate an interrupt when servo time is up
wordTemp=CCPR1H*256+CCPR1L;
wordTemp=wordTemp-4000+servoPos[servoCount];
CCPR1L=wordTemp&255;
CCPR1H=wordTemp/256;
servoCount=servoCount+1;
}
CCP1IF=0;
}
if(RCIE & RCIF){
uint8_t chr=RCREG; //get the received character
if(OERR || FERR){ //neither of these should ever occur.
CREN=0; //this is kinda wishful thinking
CREN=1; //as any data received is corrupt
strCount=0; //however, reset everything
done=0; //and hope for the best
}else{ //no errors so use the data
if(strCount==0 && done==0){ //are we already receiving
//waiting for $ //no so wait
if(chr=='$'){ //for $ to appear
buff[strCount]=chr; //start receiving
strCount++;
}else if(done==0){ //have we collected a full string?
buff[strCount]=chr; //no so carry on storing
strCount++;
if(chr=='W'){ //have we got the "endOfString" character
done=1; //yes, so set done true
}
}
}
}
}
}
Mike.
Edit, you can of course replace,
CCPR1L=wordTemp&255;
CCPR1H=wordTemp/256;
with
CCPR1L=wordTemp.LB
CCPR1H=wordTemp.HB
Edit2, seems constants aren't defined with Define but Const so
Const NUM_SERVOS=10
and
Const BUFFER=80
should be fine.
Edit3, looks like multiple definition on one line are not allowed so
uint8_t buff[BUFFER],strCount=0,done=0;
will become
Dim buff(BUFFER) as byte
Dim strCount as byte
Dim done as byte
and initialise them prior to enabling interrupts,
strCount=0
done=0
before the line
PEIE=1
Edit4, TRISC will also need to be changed