Converting a program and I couldn't find exact confirmation but I assume the C instr.
while(1)
would equate to:
Loop:
goto loop ; Waiting for interrupt. ?
Max.
while(1)
would equate to:
Loop:
goto loop ; Waiting for interrupt. ?
Max.
Maybe I misunderstood your question the first time!I will have to ask again. Why do you have to convert it to assembler?
"Much more" is pushing it. "Possibly marginally more for generic code" is more accurate.C is much more portable than assembler even embedded in a PIC.
Converting a program and I couldn't find exact confirmation but I assume the C instr.
while(1)
would equate to:
Loop:
goto loop ; Waiting for interrupt. ?
Max.
In this case the interrupt is constant after every TMR0 roll over so there is no lengthy 'rest' period!Some assemblers even have a handy shortcut for this:
JMP $
on the MSP430 just jumps to the location of itself which saves you a line of code.
It may also be better to go into a low power mode once you have done your configuration and then let the interrupt wake up the device. Saves burning CPU cycles and hence power whizzing round in circles.
Sure there is. At least 256 instruction cycles.In this case the interrupt is constant after every TMR0 roll over so there is no lengthy 'rest' period!
Why?Is the energy used by the PIC going to be significant compared to the current used by the electric motor?
It's up to the compiler to interpret it.Converting a program and I couldn't find exact confirmation but I assume the C instr.
while(1)
would equate to:
Loop:
goto loop ; Waiting for interrupt. ?
Max.
You are missing a semicolon. As written, whatever the next statement after the while(1) is included in the loop.Converting a program and I couldn't find exact confirmation but I assume the C instr.
while(1)
would equate to:
Loop:
goto loop ; Waiting for interrupt. ?
Max.
Semantically they are the same. Implementation wise they may or may not be.I wouldn't have thought it would invoke any ambiguity?
I would assume that in writing the said referenced C program, the authors intention I thought would have been evident?
I have the MikroC manual and it does not exactly show a clear definition.
Max.
/******************************************************************************
DC_motor_xtal.c - run a DC motor at xtal "clockwork" locked speed
PIC16F628A - 20MHz HS xtal (see web page for schematic)
Compiler - MikroC for PIC v8
PIC pins;
RA0 = digital ST input, quad encoder A
RA1 = digital ST input, quad encoder B
RB3 = CCP1 output, PWM to motor, HI = ON
RB0 = echo encoder A output
RB1 = echo encoder A output
PIC configs; MCRLE off, BODEN off, BORES off, WDT off, LVP off, PWRT on
******************************************************************************/
#define MOTOR_PULSE_PERIOD 6944444 // 1 RPS
#define MOTOR_PROP_GAIN 10
// global vars
unsigned char rpos; // reference position of xtal based freq
unsigned char mpos; // actual motor position
unsigned char mlag; // amount the motor lags the reference
unsigned char enc_new; // holds motor's quadrature encoder data for testing
unsigned char enc_last;
unsigned long bres; // bresenham accumulator used to make ref frequency
unsigned char pins; // temporary var for echoing encoder signals
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void interrupt()
{
//-------------------------------------------------------
// This is TMR0 int, prescaled at 2:1 so we get here every 512 instructions.
// This int does the entire closed loop speed control;
// 1. updates encoder to see if motor has moved, records it position
// 2. updates reference freq generator, records its position
// 3. compares the two, sets PWM if motor lags behind reference
// 4. limit both counts, so they never roll, but still retain all error
//-------------------------------------------------------
// clear int flag straight away to give max safe time
INTCON.T0IF = 0;
// 1. updates encoder to see if motor has moved, records it position
enc_new = (PORTA & 0b00000011); // get the 2 encoder bits
if(enc_new != enc_last)
{
if(enc_new.F1 != enc_last.F0) mpos++; // record new motor position
else mpos--;
enc_last = enc_new;
}
// 2. updates reference freq generator, records its position
bres += 102400; // add nS per interrupt period (512 insts * 200nS)
if(bres >= MOTOR_PULSE_PERIOD) // if reached a new reference step
{
bres -= MOTOR_PULSE_PERIOD;
rpos++; // record new xtal-locked reference position
}
// 3. compares the two, set PWM% if motor lags behind reference
if(mpos < rpos) // if motor lagging behind
{
mlag = (rpos - mpos); // find how far it's lagging behind
if(mlag >= (100/MOTOR_PROP_GAIN)) CCPR1L = 100; // full power if is too far behind
else CCPR1L = (mlag * MOTOR_PROP_GAIN); // else adjust PWM if slightly behind
}
else // else if motor is fast, cut all power!
{
CCPR1L = 0;
}
// 4. limit both counts, so they never roll, but still retain all error
if(rpos>250 || mpos>250)
{
rpos -= 50;
mpos -= 50;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//=============================================================================
// MAIN
//=============================================================================
void main()
{
//-------------------------------------------------------
// setup PIC 16F628A
CMCON = 0b00000111; // comparators OFF, all pins digital
PORTA = 0b00000000; //
TRISA = 0b00000011; // RA0,RA1 used for digital ST encoder inputs
PORTB = 0b00000000; //
TRISB = 0b00000000; // RB3 is CCP1 PWM out, RB0,RB1 are encoder echo outputs
// set TMR2 to roll every 100 ticks, PWM freq = 5mil/16/100 = 3125 Hz
T2CON = 0b00000111; // TMR2 ON, 16:1 prescale
PR2 = (100-1); // PWM total period of 100
// set PWM out on CCP1
CCPR1L = 0; // PWM range 0-100% = start with PWM of 0%
CCP1CON = 0b00001100; // CCP1 on, set to PWM mode
// TMR0 used for interrupt, makes interrupt every 512 insts
OPTION_REG = 0b10000000; // PORTB pullups OFF, TMR0 on, 2:1 prescale
//-------------------------------------------------------
// setup before main loop
Delay_mS(200); // allow PSU voltages time to stabilise
// setup vars etc, will be used in interrupt
bres = 0;
rpos = 0;
mpos = 0;
// finally start TMR0 roll interrupt
INTCON = 0b10100000; // GIE=on, TMR0IE=on
//-------------------------------------------------------
// main run loop
while(1)
{
//-------------------------------------------------
// We don't need to do anything in main loop as the motor speed
// control is done entirely in the TMR0 interrupt.
//-------------------------------------------------
// For convenience in setting up the encoder trimpots,
// echo the two encoder pins out two spare PORTB digital outputs!
pins = 0;
if(PORTA.F0) pins.F0 = 1;
if(PORTA.F1) pins.F1 = 1;
PORTB = pins; // output those two pins only (PWM output is not affected)
}
A half way competent compiler will optimize all of those down to the same machine code. Though the last one may not if x is assigned inside the while block or x is declared volatile or external. Though, if those are the only references (plus the declaration), any decent compiler will optimize away x. Heck, GCC does stuff like put variables into registers and completely eliminate the need for storage. Sure makes debugging confusing sometimes.It's up to the compiler to interpret it.
MikroC offers a listing file in assembler. It is not complete but is useful.
For me there is a difference between:
while(1)
and
while(1==1)
and
x=1;
while(x)
The compiler might "observe" that the condition is constant and provide an infinite cycle.