|
|
View previous topic :: View next topic |
Author |
Message |
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
is it necessary to get value from int_rda? |
Posted: Fri Jan 19, 2018 3:51 am |
|
|
Hello everyone,
I want to use the int_rda interrupt to get the code out from an endless loop. So i just want to change a value. is this ok?
Code: |
byte surekli=1;
#int_RDA
void RDA_isr()
{
disable_interrupts(INT_RDA);
surekli = 0;
} |
as i heard, the value that triggers interrupt is in buffer. should i use it? does it have any disadvantage?
thank you so much! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri Jan 19, 2018 6:00 am |
|
|
It should work fine, with two small changes
1) you can delete the
disable_interrupts(INT_RDA);
line of code as the CCS compiler already does that !
2) you need to actually read the UART data. this will clear the buffer.
3) also add 'errors' to the use rs232(...options...)
There may be a problem though. EVERY character coming into the PIC will trigger the ISR,so your variable will be reset EVERY time. It would be better to have a specific character(say 'P') to trigger the variable reset. That way you have control of the process.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Jan 19, 2018 9:16 am |
|
|
The point about reading the byte, is that the interrupt cannot be cleared until it has been read. So you _must_ read the byte, otherwise if you ever re-enable INT_RDA, the chip will immediately interrupt...
Code: |
byte surekli=1;
#int_RDA
void RDA_isr()
{
int8 dummy;
dummy=getc(); //now allows the interrupt to be cleared
//Do you really want to disable the interrupt?.
//Why?.
//Chip won't respond to another character if it is disabled.
disable_interrupts(INT_RDA);
surekli = 0;
} //The compiler will automatically clear the interrupt, but can't do so
//unless the character has been read.
|
|
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Fri Jan 19, 2018 10:39 am |
|
|
Hello everyone,
Thank you for your answers.
temtronic
1) you can delete the
disable_interrupts(INT_RDA);
line of code as the CCS compiler already does that ! (thank you, read this from an old book about ccs, updated it the way you said it)
2) you need to actually read the UART data. this will clear the buffer.
I added a variable for this.
3) also add 'errors' to the use rs232(...options...) i dont know what this does but i saw it on this forum so i am using it
"There may be a problem though. EVERY character coming into the PIC will trigger the ISR,so your variable will be reset EVERY time. It would be better to have a specific character(say 'P') to trigger the variable reset. That way you have control of the process. "
I did not do that because i have read that using "if else" or loops in an interrupt routine is not good. as you suggested that i am assuming it is not that bad?
Ttelmah
Quote: | //Do you really want to disable the interrupt?. //Why?. |
I use the code for a stepper motor driver module. Slave pic is 16f628 and master is 18f2550. The problem is i have to use 1 pin to communicate those 2 pics.
I want to be able to send a specific step number and also do a infinite go. But when the motor moves the infinite go function, i cannot stop it. I tried to use the interrupt to be able to stop the motors.
Why i want to disable? I dont want code to go isr on every comm attempt. Sorry for my english.
Thank you both for your answers |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri Jan 19, 2018 11:15 am |
|
|
You should rethink your program 'flow'.
try this idea
main()
loopforever...
check for incoming serial data() function
step motor one pulse() function
...loopforever
end of main
the time it take check for an incoming character will not affect the stepping motors performance
there are several ways to accomplish this.
jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 19, 2018 4:29 pm |
|
|
temtronic wrote: |
1) you can delete the
disable_interrupts(INT_RDA);
line of code as the CCS compiler already does that !
|
This is not correct. The compiler does not disable RDA interrupts.
The 18F2550 data sheet says:
Quote: |
9.0 INTERRUPTS
When an interrupt is responded to, the global interrupt
enable bit is cleared to disable further interrupts.
|
This is done in hardware in the PIC's silicon. This affects the global
interrupt, not the RDA interrupt.
Below is the .LST file for the #int_rda routine. Notice that the compiler
does not clear the RCIE flag. The RCIE flag is the one that is disabled
when you use the line: disable_interrupts(INT_RDA).
Code: |
.................... #int_rda
.................... void rda_isr(void)
.................... {
.................... char c;
....................
.................... c = getc();
00C6: BRA 00AE
00C8: MOVFF 01,c
00CC: BCF PIR1.RCIF
00CE: GOTO 0060
.................... }
|
I'm not saying you need the disable_interrupts(INT_RDA) line.
Normally you don't need it. But I am saying that the compiler
doesn't automatically put that line in. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri Jan 19, 2018 4:53 pm |
|
|
hmm.. I was always under the impression the compiler did the 'housework'...to keep ISR 'neat and tidy'....
sigh, too many PICs, too little time |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Jan 20, 2018 1:59 am |
|
|
Yes, it does do the housework.
However 'since when' would disabling a receive data interrupt be part of this?. You want to receive data....
The hardware disables the global interrupt, when you enter the ISR, and re-enables it when you leave. The compiler clears the receive interrupt (if it can - the caveat about not reading the data). Only thing left is to read the data.
To doguhanpala
The point about 'ERRORS', is that the PIC USART has the 'feature', that if it overflows, it goes to a 'stalled' state, with 'overrun error' flagged. This stops further reception till cleared. 'ERRORS' adds the housekeeping, to automatically clear this if it happens. |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Sat Jan 20, 2018 5:02 am |
|
|
Thank you all for your answers. I have another question.
This is the transmit code from 18f2550. It sends an 16 bit integer in 2 parts. After sending the bytes, the pin waits for high to understand if the process completed.
Code: | include <18F2550.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,MCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,CPUDIV1,VREGEN
#use delay(clock=8000000)
#use rs232(baud=9600, UART1, ERRORS,stream = bt)
#use rs232(baud=9600, xmit=PIN_B1,stream = motormodul)
int16 step_sayisi=200;
int step_sayisi_l=0;
int step_sayisi_h=0;
int begin=0;
void main()
{
while(true)
{
while(!kbhit(bt))
delay_us(100);
if(kbhit(bt))
{
begin=getc(bt);
putc('b',bt);
}
while(begin=='a')
{
putc('c',bt);
putc(1,motormodul);
delay_ms(1);
step_sayisi_l = make8(step_sayisi,0);
step_sayisi_h = make8(step_sayisi,1);
putc(step_sayisi_h,motormodul);
delay_ms(1);
putc(step_sayisi_l,motormodul);
while(input_state(PIN_B1)!=0)
delay_us(100);
putc('d',bt);
break;
}
}
} |
This is the receive code. I am not adding all functions they are very similiar. The code waits for step number high and low. It makes them 16 bit. After that i use that integer on for loops. When the loop is done, the code calls "bitir()" in order to inform 18f2550.
Code: | #include <16F628.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,NOMCLR,NOPROTECT,NOLVP,NOBROWNOUT,
#use delay(clock=4000000)
#use rs232(baud=9600, rcv=PIN_B1)
#define motor1_pin1 PIN_A0
#define motor1_pin2 PIN_A1
#define motor1_pin3 PIN_A2
#define motor1_pin4 PIN_A3
#define motor2_pin1 PIN_B7
#define motor2_pin2 PIN_B6
#define motor2_pin3 PIN_B5
#define motor2_pin4 PIN_B4
void motor1_s1();
void motor1_s2();
void motor1_s3();
void motor1_s4();
void motor1_s5();
void motor1_s6();
void motor1_s7();
void motor1_s8();
void motor2_s1();
void motor2_s2();
void motor2_s3();
void motor2_s4();
void motor2_s5();
void motor2_s6();
void motor2_s7();
void motor2_s8();
void robot_ileri();
void robot_geri();
void robot_sol();
void robot_sag();
void motor1_ileri();
void motor1_geri();
void motor2_ileri();
void motor2_geri();
void durdur();
void bitir();
void komutal();
int16 step_sayisi = 0;
int8 step_sayisi_l=0;
int8 step_sayisi_h=0;
int16 sayac=0;
void main()
{
durdur();
while(true)
komutal();
}
void bitir()
{
output_high(PIN_B1);
delay_ms(2);
output_low(PIN_B1);
delay_ms(2);
}
void komutal()
{
int komut=0;
while(!kbhit())
delay_us(10);
if(kbhit())
{
komut = getc();
step_sayisi_h=getc();
step_sayisi_l=getc();
step_sayisi = make16(step_sayisi_h,step_sayisi_l);
switch(komut)
{
case 1:
robot_ileri();
durdur();
bitir();
break;
case 2:
robot_sol();
durdur();
bitir();
break;
case 3:
robot_sag();
durdur();
bitir();
break;
case 4:
robot_geri();
durdur();
bitir();
break;
case 5:
motor1_ileri();
durdur();
bitir();
break;
case 6:
motor2_ileri();
durdur();
bitir();
break;
case 7:
motor1_geri();
durdur();
bitir();
break;
case 8:
motor2_geri();
durdur();
bitir();
break;
}
}
}
void robot_ileri()
{
for(sayac=0;sayac<step_sayisi;sayac++)
{
motor1_s1();
motor2_s1();
delay_us(1000);
motor1_s2();
motor2_s2();
delay_us(1000);
motor1_s3();
motor2_s3();
delay_us(1000);
motor1_s4();
motor2_s4();
delay_us(1000);
motor1_s5();
motor2_s5();
delay_us(1000);
motor1_s6();
motor2_s6();
delay_us(1000);
motor1_s7();
motor2_s7();
delay_us(1000);
motor1_s8();
motor2_s8();
delay_us(1000);
}
} |
My question is, when i change the line
Code: | #use rs232(baud=9600, rcv=PIN_B1) |
to this
Code: | #use rs232(baud=9600, UART1, ERRORS) |
the 18f can't get the 2 ms high voltage, so it gets stuck at here
Code: |
while(input_state(PIN_B1)!=0)
delay_us(100);
putc('d',bt);
break; |
I don't see the char 'd'. Is there a way to make hardware uart pins act like IOs even if they are used as uart? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sat Jan 20, 2018 11:46 am |
|
|
TTL serial, idles high. The line is permanently going to be high when the UART (soft or hard), is sitting not sending. You can't use this as an identifier.
Pulling the line low for 2mSec, sends two characters of 0.
Your approach is fundamentally flawed.
Simply send a character that is identified as a 'header' Something like a line feed or a '$' sign.
Follow this with your byte for 'what you want to do'. Now you seen to be relying on this being 1, 2, 3 etc.. You do understand the difference between a value of 1, and the character '1'. Which are you sending?.
Then send the value as hex, rather than as direct binary. Problem with direct binary is it makes it hard to identify other values. |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Sun Jan 21, 2018 6:20 am |
|
|
Ttelmah wrote: | TTL serial, idles high. The line is permanently going to be high when the UART (soft or hard), is sitting not sending. You can't use this as an identifier.
Pulling the line low for 2mSec, sends two characters of 0.
Your approach is fundamentally flawed.
|
Interestingly, the code works when i use software uart. When the motors do their job 16f sends low, and 18f gets it. after that i see the 'd' on screen. When i use hardware uart. It gets stuck on while loop.
Ttelmah wrote: | Simply send a character that is identified as a 'header' Something like a line feed or a '$' sign. |
My problem is, i cannot understand the process on 16f is complete or not. I want to block the comm, if the process is not complete and motors are still moving. So i need to do something after the process.
Ttelmah wrote: | Follow this with your byte for 'what you want to do'. Now you seen to be relying on this being 1, 2, 3 etc.. You do understand the difference between a value of 1, and the character '1'. Which are you sending?.
Then send the value as hex, rather than as direct binary. Problem with direct binary is it makes it hard to identify other values. |
I know the difference between value 1 and char '1'(this is 50 as i recall?). I chose to send value but not for a specific reason. I said, well send value man. Actually which one i send is not important to me, i can edit the code both sides(rcv and xmit) and send char. unfortunately it still does not solve my problem.
My guess, when i use software uart and call the function input state, the port starts to behave like io port? Sounds idiotic but my only guess
Thank you for your aswer and explanation. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Sun Jan 21, 2018 9:41 am |
|
|
The problem is that because you rely on detecting values like 1, 2, 3. These can happen inside the data you are sending, since by sending 'raw' values any value is possible. The hardware UART will still be receiving the low as a character. Just because you have the interrupt disabled, does _not_ stop the UART from receiving. So it will have received a zero at this point, and will in fact have set it's error flags, since it will see a malformed character, and this has not been read, resulting in both a framing error and an overrun. The soft UART will not, since you are not actually calling it till after the line goes high again, and it does not have error checking.
If you just want to ignore data till a task is complete, then just set a flag.
Have your INT_RDA, simply throw any character received if the 'busy' flag is set. Once this goes off, start listening to the data again.
If you must use your current approach, then disable the UART (setup_uart(FALSE);), rather than disabling the interrupt. |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Mon Jan 22, 2018 7:36 am |
|
|
Ttelmah wrote: | The problem is that because you rely on detecting values like 1, 2, 3. These can happen inside the data you are sending, since by sending 'raw' values any value is possible. The hardware UART will still be receiving the low as a character. Just because you have the interrupt disabled, does _not_ stop the UART from receiving. So it will have received a zero at this point, and will in fact have set it's error flags, since it will see a malformed character, and this has not been read, resulting in both a framing error and an overrun. The soft UART will not, since you are not actually calling it till after the line goes high again, and it does not have error checking.
|
Thank you for suggestions Ttelmah. I edited the code to this. Used char instead of vaue itself.
Code: | #include <16F628.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,NOMCLR,NOPROTECT,NOLVP,NOBROWNOUT,
#use delay(clock=4000000)
#use rs232(baud=9600, UART1, ERRORS)
#define motor1_pin1 PIN_A0
#define motor1_pin2 PIN_A1
#define motor1_pin3 PIN_A2
#define motor1_pin4 PIN_A3
#define motor2_pin1 PIN_B7
#define motor2_pin2 PIN_B6
#define motor2_pin3 PIN_B5
#define motor2_pin4 PIN_B4
void motor1_s1();
void motor1_s2();
void motor1_s3();
void motor1_s4();
void motor1_s5();
void motor1_s6();
void motor1_s7();
void motor1_s8();
void motor2_s1();
void motor2_s2();
void motor2_s3();
void motor2_s4();
void motor2_s5();
void motor2_s6();
void motor2_s7();
void motor2_s8();
void robot_ileri();
void robot_geri();
void robot_sol();
void robot_sag();
void motor1_ileri();
void motor1_geri();
void motor2_ileri();
void motor2_geri();
void durdur();
void bitir();
void komutal();
int16 step_sayisi = 0;
int8 step_sayisi_l=0;
int8 step_sayisi_h=0;
int16 sayac=0;
void main()
{
durdur();
while(true)
komutal();
}
void bitir()
{
output_high(PIN_B1);
delay_ms(2);
output_low(PIN_B1);
delay_ms(2);
}
void komutal()
{
setup_uart(true);
int komut=0;
while(!kbhit())
delay_us(10);
if(kbhit())
{
komut = getc();
step_sayisi_h=getc();
step_sayisi_l=getc();
step_sayisi = make16(step_sayisi_h,step_sayisi_l);
delay_ms(1);
setup_uart(FALSE);
switch(komut)
{
case '1':
robot_ileri();
durdur();
bitir();
break;
case '2':
robot_sol();
durdur();
bitir();
break;
case '3':
robot_sag();
durdur();
bitir();
break;
case '4':
robot_geri();
durdur();
bitir();
break;
case '5':
motor1_ileri();
durdur();
bitir();
break;
case '6':
motor2_ileri();
durdur();
bitir();
break;
case '7':
motor1_geri();
durdur();
bitir();
break;
case '8':
motor2_geri();
durdur();
bitir();
break;
}
}
}
void robot_ileri()
{
for(sayac=0;sayac<step_sayisi;sayac++)
{
motor1_s1();
motor2_s1();
delay_us(1000);
motor1_s2();
motor2_s2();
delay_us(1000);
motor1_s3();
motor2_s3();
delay_us(1000);
motor1_s4();
motor2_s4();
delay_us(1000);
motor1_s5();
motor2_s5();
delay_us(1000);
motor1_s6();
motor2_s6();
delay_us(1000);
motor1_s7();
motor2_s7();
delay_us(1000);
motor1_s8();
motor2_s8();
delay_us(1000);
}
} |
Transmit code
Code: | #include <18F2550.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,MCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,CPUDIV1,VREGEN
#use delay(clock=8000000)
#use rs232(baud=9600, UART1, ERRORS,stream = bt)
#use rs232(baud=9600, xmit=PIN_B1,stream = motormodul)
int16 step_sayisi=200;
int step_sayisi_l=0;
int step_sayisi_h=0;
int begin=0;
int yonler[8]={'1','2','3','4','5','6','7','8'};
void main()
{
while(true)
{
while(!kbhit(bt))
delay_us(100);
if(kbhit(bt))
{
begin=getc(bt);
putc('b',bt);
}
while(begin=='a')
{
putc('c',bt);
putc(yonler[0],motormodul);
delay_ms(1);
step_sayisi_l = make8(step_sayisi,0);
step_sayisi_h = make8(step_sayisi,1);
putc(step_sayisi_h,motormodul);
delay_ms(1);
putc(step_sayisi_l,motormodul);
while(input_state(PIN_B1)!=0)
delay_us(100);
putc('d',bt);
break;
}
}
}
|
this time the code works correctly '1' time. i send the values,see the 'abc' on screen. motors go, the transmit code waits for low and prints the 'd'. if i press 'a' again, i see the abcd on screen. the setup_uart(FALSE) does not work on second time.
Quote: |
If you just want to ignore data till a task is complete, then just set a flag.
Have your INT_RDA, simply throw any character received if the 'busy' flag is set. Once this goes off, start listening to the data again. |
I can block the receiver side from getting any data. The real problem is i want to block the transmit side from sending any data till the task is complete. so i tried the setup_uart approach. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jan 22, 2018 8:02 am |
|
|
Code: |
delay_ms(1);
setup_uart(FALSE)
|
What is going to happen if a character has already arrived in this mSec?.
You stop the UART which can already holding a character.
Then at the transmit, 'putc' for a hardware UART, returns as soon as a character is loader _to_ transmit. It hasn't actually been sent yet.
So, when sending, you need to wait for the transmit buffer to empty. On the receive switch off the UART as soon as you have read the characters you want. |
|
|
doguhanpala
Joined: 05 Oct 2016 Posts: 120
|
|
Posted: Thu Jan 25, 2018 5:57 am |
|
|
Ttelmah wrote: | Code: |
delay_ms(1);
setup_uart(FALSE)
|
What is going to happen if a character has already arrived in this mSec?.
You stop the UART which can already holding a character.
Then at the transmit, 'putc' for a hardware UART, returns as soon as a character is loader _to_ transmit. It hasn't actually been sent yet.
So, when sending, you need to wait for the transmit buffer to empty. On the receive switch off the UART as soon as you have read the characters you want. |
Hello Ttelmah
I tried to edit the code like this
Code: | void komutal()
{
int komut=0;
setup_uart(TRUE);
while(!kbhit())
delay_us(10);
if(kbhit())
{
komut = getc();
step_sayisi_h=getc();
step_sayisi_l=getc();
setup_uart(FALSE);
step_sayisi = make16(step_sayisi_h,step_sayisi_l);
|
The problem still contuniues unfortunately. I thought maybe i can disable the rs232 from both sides.
So i changed the xmit code to this version.
Code: | while(true)
{
setup_uart(TRUE,motormodul);
while(!kbhit(bt))
delay_us(100);
if(kbhit(bt))
{
begin=getc(bt);
putc('b',bt);
}
while(begin=='a')
{
putc('c',bt);
putc(yonler[0],motormodul);
delay_ms(1);
step_sayisi_l = make8(step_sayisi,0);
step_sayisi_h = make8(step_sayisi,1);
putc(step_sayisi_h,motormodul);
delay_ms(1);
putc(step_sayisi_l,motormodul);
delay_ms(1);
setup_UART(FALSE,motormodul);
while(input_state(PIN_B1)!=0)
delay_us(100);
putc('d',bt);
break;
}
} |
This time problem got more interesting. I cannot see the 'd'. Also the pin B1 is still high. I disabled the comm from both sides, but could not solve the problem. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|