Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Need help converting some C18 codes to assembly codes

Status
Not open for further replies.

Urahara

Member
Hi All

I have a C18 interrupt routine that I wish to convert to assembly codes in an attempt to reduce latency in some high frequency counting situation (Variable gl_pulse_cnt seems to reach its limit at about 30,000 counts with the C18 codes). Here's snippets of the codes :

Code:
unsigned long int gl_pulse_cnt=0;

#pragma code low_vector=0x18
void low_vector (void)
{   
  _asm GOTO isr_low _endasm    
}

#pragma interruptlow isr_low
void isr_low(void)
{
    gl_pulse_cnt++;
    PIR1bits.CCP1IF=0; //clear interrupt flag
}

What is the assembly code equivalent of the 2-liner C18 codes within the "isr_low" routine? Would also like to insert this assembly code directly into the "low_vector" routine, within the _asm and _endasm block to reduce latency due to function calling. Is this workable?

Thanks!
 
As long as you don't have a high priority interrupt then you can use the fast return stack.
Code:
;this is pure asm - needs converting into C18 equivalent
    movlb high(gl_pulse_cnt)
    incfsz gl_pulse_cnt,f
    goto done
    incfsz gl_pulse_cnt+1,f
    goto done
    incfsz gl_pulse_cnt+2,f
    goto done
    incf gl_pulse_cnt+3,f
done
    bcf PIR1,CCP1IF
    retfie fast

It probably needs a & before the gl_pulse_cnt bits. Read the C18 manual to see how you access C variables in asm.

Mike.
 
Hi Mike

unfortunately I use a hi prority interrupt to stop the counting when 1 second is up.:(

How would that change the assembly code?
 
Luckily, you only have to save the BSR register to still use that code. Plus loose the fast off the return and restore the BSR at the end of the ISR. Check the datasheet.

Alternatively, a 1 second interrupt should not get higher priority - don't use the fast return stack on that interrupt.

Mike.
 
not a very competent assembly language & MCU programmer myself, I tinker with Mike's codes to put them into the _asm _endasm construct that I am slightly more familiar with.

Code:
unsigned long int gl_pulse_cnt;
unsigned char BSR_TEMP;

#pragma code low_vector=0x18
void low_vector (void)
{ 
  _asm GOTO isr_low _endasm  
}


#pragma interruptlow isr_low
void isr_low(void)
{
    _asm
         movff BSR,BSR_TEMP 
         movlb gl_pulse_cnt
         incfsz gl_pulse_cnt,1,1
         goto done
         incfsz gl_pulse_cnt+1,1,1
         goto done
         incfsz gl_pulse_cnt+2,1,1
         goto done
         incf gl_pulse_cnt+3,1,1
     done:
         bcf PIR1,2,1
         movff BSR_TEMP,BSR 
         retfie 0
    _endasm
}

I've gone thru the datasheet and modify the incfsz, bcf and retfie commands based on the syntax expected. Unfortunately it is not working! :banghead:. The codes compiled well but the program does not return anything unlike the pure C18 codes.

Any advise on how I should correct the above? You have to assume I am an absolute newbie in assembly and mixing it with C18. btw, I am using 18f1220.

Thanks!
 
Instead of the piece of code in C (I am not conversant in C), could show here the correct/complete flow diagram of what you want to accomplish? I could be dead wrong but "translating" (whatever that could mean here) seems prone to create an unintended effect.

Edit:

You said converting. My comment stays.

/Edit.
 
Would also like to insert this assembly code directly into the "low_vector" routine, within the _asm and _endasm block to reduce latency due to function calling
WHAT function calling?

Have you taken a look at the asm output of C18 for those two instructions? It's pretty hard to beat... 17 instruction cycles total, including the intr overhead.
 
Also, I meant to point out that not only is the ASM code you've inserted longer than what C18 produces, you can't just do a 'retfie 0' at the end as this skips restoring the intr context that was saved as part of the intr vectoring.

You could leave that instruction out and let the isr_low() perform the proper exit, but you're still better off with the original C code.
 
What you're doing won't speed up anything. I guess the biggest overhead of your interrupt routine is the prolog and epilog inserted by C compiler to save/restore context. You code doesn't remove any of it.

You can look at the listing from C18 which shows its assembly. I suggest you look at it, or, perhaps, post it here.
 
Where can I find the assembly codes? Looked at the output files generated but couldn't find it.

I am using a 4MHz crystal. Looks like if 30KHz is what I can achieve, I'll probably need a faster crystal.
 
If you're building a frequency counter a popular method was using Timer0. You can go beyond the FOSC with that method, Google 16F84 frequency counter for examples.
 
Still lurking around Nigel! :D

Heard of the method. Guess I'll try it should I need higher counting capabilities instead of using a faster crystal.

Thanks!
 
Still lurking around Nigel! :D

Heard of the method. Guess I'll try it should I need higher counting capabilities instead of using a faster crystal.

Thanks!

I posted this as a continuation of another of your threads.

Here's a 50MHz counter using the ancient 16F84. Crystal frequency needs to be accurate but doesn't need to be that fast. A TCXO would get the accuracy up.

If I were doing a frequency counter I'd use a PIC with a "Gated Timer", it can start / stop the timer based on an external input.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top