This only applies to Timers, CCP values don't increment. If by some rare coincidence writing the low byte first causes a match then it will be cleared lower down before exiting the ISR. I don't know if Oshonsoft will write a 16 bit register or if it will need splitting, depends on the compiler.The only things I can see with his version are:
When reading 16 bit registers one byte at a time, you must read LOW byte first.
When writing them, you must read HIGH byte first.
(The high byte is transferred via a latch to synchronise the two halves).
'T1CON=0b00000001; 'timer 1 clocks at
T1CON.7 = 0 '7=RD16 0 = Enables register read/write of Timer1 in two 8-bit operations
T1CON.6 = 1 'T1RUN 1 = Device clock is derived from Timer1 oscillator
T1CON.5 = 1 'T1CKPS.5-4 10 = 1:4 Prescale value
T1CON.4 = 0
T1CON.3 = 1 'T1OSCEN 1 = Timer1 oscillator is enabled
T1CON.2 = 0 'T1SYNC This bit is ignored. Timer1 uses the internal clock when TMR1CS = 0.
T1CON.1 = 0 'TMR1CS 0 = Internal clock (FOSC/4)
T1CON.0 = 1 'TMR1ON 1 = Enables Timer1
INTCON.PEIE = 1 '[6]PEIE/GIEL: Peripheral Interrupt Enable bit: When IPEN = 1: 1 = Enables all low-priority peripheral interrupts
INTCON.GIE = 1 '[7]GIE/GIEH: Global Interrupt Enable bit: When IPEN = 1:1 = Enables all low-priority peripheral interrupts
Enable High 'This is set for SERVOS
Enable Low 'This is set for GPS later
In 28-pin devices, the two standard CCP modules
(CCP1 and CCP2) operate as described in this
chapter. In 40/44-pin devices, CCP1 is implemented
as an Enhanced CCP module with standard Capture
and Compare modes and Enhanced PWM modes.
Hi M,This only applies to Timers, CCP values don't increment. If by some rare coincidence writing the low byte first causes a match then it will be cleared lower down before exiting the ISR. I don't know if Oshonsoft will write a 16 bit register or if it will need splitting, depends on the compiler.
The conversion (?) has some strange bits like,
This converts T1CON=1 to T1CON=105. Also, it's running from Timer1 oscillator which I assume doesn't exist.Code:'T1CON=0b00000001; 'timer 1 clocks at T1CON.7 = 0 '7=RD16 0 = Enables register read/write of Timer1 in two 8-bit operations T1CON.6 = 1 'T1RUN 1 = Device clock is derived from Timer1 oscillator T1CON.5 = 1 'T1CKPS.5-4 10 = 1:4 Prescale value T1CON.4 = 0 T1CON.3 = 1 'T1OSCEN 1 = Timer1 oscillator is enabled T1CON.2 = 0 'T1SYNC This bit is ignored. Timer1 uses the internal clock when TMR1CS = 0. T1CON.1 = 0 'TMR1CS 0 = Internal clock (FOSC/4) T1CON.0 = 1 'TMR1ON 1 = Enables Timer1
and,
Aren't these doing the same thing?Code:INTCON.PEIE = 1 '[6]PEIE/GIEL: Peripheral Interrupt Enable bit: When IPEN = 1: 1 = Enables all low-priority peripheral interrupts INTCON.GIE = 1 '[7]GIE/GIEH: Global Interrupt Enable bit: When IPEN = 1:1 = Enables all low-priority peripheral interrupts Enable High 'This is set for SERVOS Enable Low 'This is set for GPS later
I also note that your code enables interrupt priority.
Mike.
Edit, the CCP1CON value is wrong too.
Hi m,Luckily, your chip doesn't have the ECCP modules or this may apply,
From the 2620 datasheet,
I'm using a 28 pin device so it's pretty much identical to yours where the CCP module is concerned.Code:In 28-pin devices, the two standard CCP modules (CCP1 and CCP2) operate as described in this chapter. In 40/44-pin devices, CCP1 is implemented as an Enhanced CCP module with standard Capture and Compare modes and Enhanced PWM modes.
Mike.
CCP1CON=0b10001010; //generate interrupt only
Hi M,Can you run the above code through your A.I. and post the results. The Basic posted above seems to be a mix of things.
CCP1CON should be as in the C program above,
Actually, I see you have that but I read the comment instead of the code.Code:CCP1CON=0b10001010; //generate interrupt only
Bit 7 isn't implemented on the 2620 either.
Mike.
Hi M,#188
Mike.
'Include OSHONSOFT Basic Library
#include <xc.bas>
#include "config.bas"
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 8
#define FRAME 16000L 'how long each frame is
Dim servoPos(NUM_SERVOS) As Word
Dim servoCount As Byte
Dim servoTemp As Byte
'Main Program
Sub Main()
OSCCON = &B01110000 '8MHz
PLLEN = 1 'x4=32MHz
T1CON = &B00000001 'timer 1 clocks at
CCP1CON = &B10001010 'generate interrupt only
CCP1IE = 1 'enable CCP1 interrupts
For i = 0 To NUM_SERVOS - 1
servoPos(i) = i * 1000 + 8000 '1ms(8000) to 1.875(7/8ths - 15000)ms in 1/8th mS steps
Next
TRISB = 0 'all output
LATB = 0
servoTemp = 0
PEIE = 1
GIE = 1
Do
'adjust servo positions here
Loop
End Sub
'Interrupt Routine
Sub inter()
PORTB = servoTemp 'output as soon as possible to minimise jitter.
If CCP1IE And CCP1IF Then
If servoTemp = 0 Then 'which phase of the output are we in? True=just cleared output pin and started output gap
'outputting the gap
CCPR1 = CCPR1 + FRAME - servoPos(servoCount) 'add gap time
servoTemp = 1 << servoCount 'make up what is required on port B NEXT TIME
If servoCount = 7 Then
servoCount = 0
Else
servoCount = servoCount + 1
End If
Else
'outputting the pulse
CCPR1 = CCPR1 + servoPos(servoCount) 'add on time to
servoTemp = 0 'next time clear port B
End If
CCP1IF = 0
End If
End Sub
OK, if the CCPs don't use the high byte latch, then order is irrelevant.This only applies to Timers, CCP values don't increment.
void __interrupt() inter(void){
PORTB=servoTemp; //output as soon as possible to minimise jitter.
if(CCP1IE && CCP1IF){
if(servoTemp==0){ //which phase of the output are we in? True=just cleared output pin and started output gap
//outputting the gap
CCPR1=CCPR1+FRAME-servoPos[servoCount]; //add gap time
servoTemp=1<<servoCount; //make up what is required on port B NEXT TIME
if(servoCount==7) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
servoCount=0;
else
servoCount=servoCount+1;
}else{
//outputting the pulse
CCPR1=CCPR1+servoPos[servoCount]; //add on time to
servoTemp=0; //next time clear port B <<<<<<<<<<<<<<<<<<<<<<<<<<<
}
CCP1IF=0;
}
}
void __interrupt() inter(void){
PORTB = servoTemp; //output as soon as possible to minimise jitter.
if(CCP1IE && CCP1IF){
if(servoTemp==0){ //which phase of the output are we in?
// servoTemp == 0 means outputs havr just been cleared.
// Output the frame gap and reset the sequence.
// outputting the frame gap. roughly 20 - (number of servos * 1.5) in mS
CCPR1 = CCPR1 + FRAME; // add gap time
servoCount = 0; // Reset counter
servoTemp = 1; // And initialise output bit
}
else {
// Servotemp was not zero; Above output was a pulse start, keep sequencing
// Setting the pulse duration
CCPR1=CCPR1+servoPos[servoCount]; // Add time for this channel
servoCount = servoCount + 1; // Increment channel number and
servoTemp = servoTemp << 1; // Shift output bit ready for next pass
}
CCP1IF=0;
}
}
Hi R,OK, if the CCPs don't use the high byte latch, then order is irrelevant.
However your code from post #188 is still messed up so the "AI" translation is not going to produce working BASIC.
C:void __interrupt() inter(void){ PORTB=servoTemp; //output as soon as possible to minimise jitter. if(CCP1IE && CCP1IF){ if(servoTemp==0){ //which phase of the output are we in? True=just cleared output pin and started output gap //outputting the gap CCPR1=CCPR1+FRAME-servoPos[servoCount]; //add gap time servoTemp=1<<servoCount; //make up what is required on port B NEXT TIME if(servoCount==7) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< servoCount=0; else servoCount=servoCount+1; }else{ //outputting the pulse CCPR1=CCPR1+servoPos[servoCount]; //add on time to servoTemp=0; //next time clear port B <<<<<<<<<<<<<<<<<<<<<<<<<<< } CCP1IF=0; } }
"servoTemp" can never be zero as you are constraining the left shift to 0-7 rather than letting it shift endlessly after initialisation.
servoCount is being incremented during initialisation rather than the pulse sequence.
servoTemp is being forced to zero every time it hits the "}else{" section.
An attempted fix:
C:void __interrupt() inter(void){ PORTB = servoTemp; //output as soon as possible to minimise jitter. if(CCP1IE && CCP1IF){ if(servoTemp==0){ //which phase of the output are we in? // servoTemp == 0 means outputs havr just been cleared. // Output the frame gap and reset the sequence. // outputting the frame gap. roughly 20 - (number of servos * 1.5) in mS CCPR1 = CCPR1 + FRAME; // add gap time servoCount = 0; // Reset counter servoTemp = 1; // And initialise output bit } else { // Servotemp was not zero; Above output was a pulse start, keep sequencing // Setting the pulse duration CCPR1=CCPR1+servoPos[servoCount]; // Add time for this channel servoCount = servoCount + 1; // Increment channel number and servoTemp = servoTemp << 1; // Shift output bit ready for next pass } CCP1IF=0; } }
On High Interrupt
Save System
'RCODE
'void __interrupt() inter(void){
PORTB = servotemp 'output as soon as possible to minimise jitter.
'If(CCP1IE && CCP1IF){
If PIE1.CCP1IE And PIR1.CCP1IF Then
'If(servotemp == 0) 'which phase of the output are we in?
If servotemp = 0 Then 'which phase of the output are we in?
'servotemp == 0 means outputs havr just been cleared.
'Output the frame gap And reset the sequence.
'outputting the frame gap. roughly 20 - (number of servos * 1.5) in ms
CCPR1 = CCPR1 + frame 'add gap time
servocount = 0 'Reset counter
servotemp = 1 'And initialise output bit
'Endif
Else
'servotemp was Not zero; above Output was A pulse start, keep sequencing
'setting the pulse duration
' CCPR1 = CCPR1 + servopos[servocount] 'Add time for this channel [[COMMENTED OUT ]]<<<<<<<<<<<<
servocount = servocount + 1 'Increment channel number and
servotemp = servotemp << 1 'Shift output bit ready for next pass
'Endif
PIR1.CCP1IF = 0
Endif
Endif
Resume
Hi R,The end of the routine has the interrupt clear in the wrong place, it should be like
Endif
PIR1.CCP1IF = 0
Endif
Resume
In that other line, try
CCPR1 = CCPR1 + servopos(servocount)
I think BASIC does not use the [] square brackets?
Also, I forgot, when you dimension the servopos array in the start of the program, make it two more than the number of servos you are actually using; eg. 10 for the 8 servo count in these tests.
I can't see how it's messed up. My code is outputting a pulse of 1 to 2 mS every 2.5mS to give a total time of 20mS. The servoTemp=0; is required to output the gap between pulses. I did it this way as some (mainly analogue) servos depend on the overall frame-rate being 20mS. Or rather, don't like it to vary.However your code from post #188 is still messed up so the "AI" translation is not going to produce working BASIC.
}else{
//outputting the pulse
CCPR1=CCPR1+servoPos[servoCount]; //add on time to
servoTemp=0; //next time clear port B <<<<<<<<<<<<<<<<<<<<<<<<<<<
}
The order isn't actually irrelevant. If the low byte is written first then a match could happen before the high byte is written which could cause a very nasty bug. However, it will result in the (already set) CCP1IF being set which will be cleared later. If CCP1IF was cleared at the beginning of the code then it could be a big problem.OK, if the CCPs don't use the high byte latch, then order is irrelevant.
Hi M,I can't see how it's messed up. My code is outputting a pulse of 1 to 2 mS every 2.5mS to give a total time of 20mS. The servoTemp=0; is required to output the gap between pulses. I did it this way as some (mainly analogue) servos depend on the overall frame-rate being 20mS. Or rather, don't like it to vary.
Look at the code again with the fact that servoTemp is written in the next interrupt. It can definitely be zero.
This bitis executed if servoTemp wasn't zero so it delays for the required time (servoPos[servoCount]) and ensures that a zero is outputted the next interrupt to create the gap. You talk of initialization in the ISR but there isn't any, that's done before interrupts are enabled.Code:}else{ //outputting the pulse CCPR1=CCPR1+servoPos[servoCount]; //add on time to servoTemp=0; //next time clear port B <<<<<<<<<<<<<<<<<<<<<<<<<<< }
The order isn't actually irrelevant. If the low byte is written first then a match could happen before the high byte is written which could cause a very nasty bug. However, it will result in the (already set) CCP1IF being set which will be cleared later. If CCP1IF was cleared at the beginning of the code then it could be a big problem.
Mike.
Edit, not sure how the PIR1.CCP1IF = 0 instruction got moved but it would have resulted in all the gaps being very short.
'Include OSHONSOFT Basic Library
#include <xc.bas>
#include "config.bas"
#define _XTAL_FREQ 32000000
#define NUM_SERVOS 8
#define FRAME 20000L 'how long each frame is
Dim servoPos(NUM_SERVOS) As Word
Dim servoCount As Byte
Dim servoTemp As Byte
'Main Program
Sub Main()
OSCCON = &B01110000 '8MHz
PLLEN = 1 'x4=32MHz
T1CON = &B00000001 'timer 1 clocks at
CCP1CON = &B10001010 'generate interrupt only
CCP1IE = 1 'enable CCP1 interrupts
For i = 0 To NUM_SERVOS - 1
servoPos(i) = i * 1000 + 8000 '1ms(8000) to 1.875(7/8ths - 15000)ms in 1/8th mS steps
Next
TRISB = 0 'all output
LATB = 0
servoTemp = 0
PEIE = 1
GIE = 1
Do
'adjust servo positions here
Loop
End Sub
'Interrupt Routine
Sub inter()
PORTB = servoTemp 'output as soon as possible to minimise jitter.
If CCP1IE And CCP1IF Then
If servoTemp = 0 Then 'which phase of the output are we in? True=just cleared output pin and started output gap
'outputting the gap
CCPR1 = CCPR1 + FRAME - servoPos(servoCount) 'add gap time
servoTemp = 1 << servoCount 'make up what is required on port B NEXT TIME
If servoCount = 7 Then
servoCount = 0
Else
servoCount = servoCount + 1
End If
Else
'outputting the pulse
CCPR1 = CCPR1 + servoPos(servoCount) 'add on time to
servoTemp = 0 'next time clear port B
End If
End If
CCP1IF = 0
End Sub
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?