View previous topic :: View next topic |
Author |
Message |
mtsoule
Joined: 19 Oct 2011 Posts: 31
|
Putting ASM in to C |
Posted: Fri Oct 14, 2016 10:51 am |
|
|
Device: PIC18F87K22
Compiler: 4.125
I am trying to put a few, time critical, statements into my program, so I am using ASM.
A few statements are not compiling, just wondering the proper syntax of these statements.
For example, I have the same pin, but I have to define it twice, once for C and once for ASM. I should (theoretically) only have to define it once:
Code: |
#define DATA_PIN pin_E3
#define DATA_PINa PORTE,3
#define Be_ONE(pinPtr) {#asm BSF DATA_PINa NOP NOP BCF DATA_PINa NOP #endasm }
#define Be_ZERO(pinPtr) {#asm BSF DATA_PINa NOP BCF DATA_PINa NOP NOP #endasm }
|
And, on the Be_ONE and BeZero defines, the above works, but this does not, just seems more readable on separate lines:
Code: |
#define Be_ZERO(pinPtr)
{
#asm
BSF DATA_PINa
NOP
BCF DATA_PINa
NOP
NOP
#endasm
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 14, 2016 12:14 pm |
|
|
When you write a #define statement on multiple lines, you have to put
continuation marks (backslash) at the end of all lines except the last one.
Example:
Code: |
#define Be_ZERO(pinPtr) \
{ \
#asm \
BSF DATA_PINa \
NOP \
BCF DATA_PINa \
NOP \
NOP \
#endasm \
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Fri Oct 14, 2016 1:51 pm |
|
|
Let me add one thing. It technically has to be " \". There must be a space in front of the backslash. PCM_programmer has typed all his like this, but unless you realise this, you can find it doesn't work as expected!... |
|
|
mtsoule
Joined: 19 Oct 2011 Posts: 31
|
|
Posted: Fri Oct 14, 2016 2:14 pm |
|
|
AWESOME!! Learn something new every day!!
any ideas on the multiple defines?
for example, I have to define "PORTE,3" for ASM, because otherwise, it expects a comma.
the unlimate goal would be to define my data_pin and use it in C or ASM as such:
Code: |
#define DATA_PIN pin_E3
#define Be_ONE(pinPtr) {#asm BSF DATA_PIN NOP NOP BCF DATA_PIN NOP #endasm }
#define Be_ZERO(pinPtr) {#asm BSF DATA_PIN NOP BCF DATA_PIN NOP NOP #endasm }
void main()
{
while(True) {
output_toggle(DATA_PIN);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Sat Oct 15, 2016 12:44 am |
|
|
Just as a comment, you don't actually need assembler!....
The compiler can generate the same code for you. The only thing is that you have to generate a #bit definition for the pin:
Code: |
#byte PORTE=getenv("SFR:PORTE")
#bit DATA_PIN=PORTE.3
#define NOP delay_cycles(1);
#define Be_ONE(x) {x=TRUE;NOP;NOP;x=FALSE;NOP;}
#define Be_ZERO(x) {x=TRUE;NOP;x=FALSE;NOP;NOP;}
|
Then this called as:
Be_ONE(DATA_PIN);
will work for any #bit defined pin bit.
This is why it is so rare now to actually have to use assembler, since you can directly access a bit/byte like this (and delay_cycles(1) codes as a nop). Delay_cycles(2) will code as the smallest sequence to give two machine cycles of delay (a local jump forward), so you could even use this:
Code: |
#define Be_ONE(x) {x=TRUE;delay_cycles(2);x=FALSE;delay_cycles(1);}
#define Be_ZERO(x) {x=TRUE;delay_cycles(2);x=FALSE;delay_cycles(2);}
|
Now in fact you can just use a standard pin reference, but then you have to be selecting #USE FAST_IO on the port. So:
Code: |
#use fast_io(e)
#define Be_ONE(x) {output_high(x);delay_cycles(2); \
output_low(x);delay_cycles(1);}
#define Be_ZERO(x) {output_high(x);delay_cycles(2); \
output_low(x);delay_cycles(2);}
|
Will then work with:
Be_ONE(PIN_E3);
etc..
However then remember that you now have to set the TRIS. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9240 Location: Greensville,Ontario
|
|
Posted: Sat Oct 15, 2016 4:58 am |
|
|
comment..
Since this is a 'time critical' application, remember that timing is based on the CPU clock speed.
In the 'good old days', micros could only run at ONE speed, today you can change it, some even while running.
Do that (change the CPU speed) and your 'time critical' function will not be running at the speed it requires....
Just something to remember...
Jay |
|
|
|