|
|
View previous topic :: View next topic |
Author |
Message |
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
#int_rda And RTC int conflict ? |
Posted: Tue Jan 15, 2008 7:38 pm |
|
|
if i have a interrupt for serial receive and one for the real time clock will the serial receive interrupt bother the rtc interrupt ?
By experimenting i see that it does :( anyone have a good idea how to do this without screwing up my RTC ?
Code: | #int_rda
void serial_isr() {
char String[10]; // for user input
int result = 0;
printf("Your Command:");
get_string(String,10);
}
|
also when doing this strcmp(String,"hi"); i always get "bad expression syntax" error ?
// dont read this --------------------------- below here is solved already
I'm new to interrupts. I just wanted a interrupt to tell me when I'm getting message through the rs232. That way my pic can be doing whatever its supposed to do but when i log onto it via the comm port it will greet me with a small menu and take commands. Afterwords i need it to turn off the interrupt.
As it is now it works but it does not stop. If i log onto the com or restart the pic while logged on and then hit a key it keeps looping the interrupt and printing out to my terminal screen (flooding it).
the interrupt function
Code: | ////////////////////////////////////////
// Interrupt on serial RX
////////////////////////////////////////
#int_rda
void serial_isr() {
printf("got serial rx");
} |
In my main
Code: |
// interrupts
enable_interrupts( GLOBAL ); // use the ints
enable_interrupts(int_rda); // int on serial RX |
NEVERMIND, IM DUMB
the interrupt is when there is information available all i needed to do was take the string/char coming in to stop it from interrupting _________________ Smart people know how stupid they are. |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
this is what i did |
Posted: Tue Jan 15, 2008 8:26 pm |
|
|
not sure if this is the best method and i know im loosing a little bit of my RTC every time i log in but this is all i can think of.
As soon as rda is tripped it turns rda int off and sets userconnected to 1 then if you exit it will turn the int back on. Im going to also make it so it logs the time the user last was active and if its been more than 10 minutes log that user out, this will prevent the user (me) from staying logged on forever if i forget or am unable to log out (x).
Code: | ////////////////////////////////////////
// Interupt on serial RX
////////////////////////////////////////
#int_rda
void serial_isr() {
disable_interrupts(int_rda); // stop this int
UserConnected = 1; // make a user
}
|
and in my main inside the while(1) i have
Code: | if(UserConnected)
{
delay_ms(500); // let them open their eyes
printf("\n\r Hello There, You Connected at");
printf("\n\r Time: %d/%d/%d %d:%d.%d",Months,Days,Years,Hours,Minutes,Seconds);
printf("\n\r m=menu s=settime x=dissconnect");
while(UserConnected)
{
delay_ms(200); // so they dont flood me
printf("\n\r Your Choice:"); // prompt for item
get_string(String,10);
if(String[0] == 's'){SetupTime();} // setup time (set clock)
if(string[0] == 'x'){ // disconnect
UserConnected = 0; // set user to 0
enable_interrupts(int_rda); // resetup interrupt
}
}
}
|
You might see now why i want to use the strcmp function !! I want to be able to type in commands and not just letters, any ideas ? _________________ Smart people know how stupid they are. |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Jan 16, 2008 2:58 am |
|
|
strcmp will only take variables and not literals. It says the same for strcpy but that is wrong and a little pointless!
Code: |
#define MAX_MATCH 10
char match[MAX_MATCH];
strcpy(match, "command");
if (strcmp(match, buf) == 0) {
// Execute command
}
|
I have extended this to use an array of commands which I search through to match the input and then use a select on the index of the found command.
Also, I read the input character into a buf within the #INT_RDA and set a flag when '\r' is entered to indicate a command has been entered. Remembering to null terminate the input buf.
Code: |
char rs232_buf[80];
byte count = 0;
int1 command_flag;
#INT_RDA
void serial_isr() {
char c;
while (kbhit()) { // proberbly NOT required
c = getc();
if (c == '\r') {
disable_interrupts(INT_RDA);
rs232_buf[count++] = '\0';
command_flag = true;
printf("\r\n");
} else {
rs232_buf[count++] = c;
putc(c); // echo char
}
}
}
| [/code] |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 16, 2008 4:16 am |
|
|
First key thing, is keep the time spent in any interrupt handler _short_.
The INT_RDA, means that just _one_ charater is waiting to be read. Read that character, and return _quickly_. Your 'demo' code, instead tries to receive a sequence of characters, and will _wait_ till this sequence arrives. As such, it'll interfere with everything else.
Two approaches:
1) _Buffer_ the incoming characters. Look at EX_SISR.
2) Build a 'tree' parser.
For the second, what you do, is receive just _one_ character, and see if it matches the next expected character. If it does, you change 'state' (a 'state machine'), to move to the next search test for the next character. You walk 'down' the branches of the tree, till either you rach the end (with a god match), or something goes wrong, and you have to start searching again. With this, you again return quickly, once the single 'this is a 'good' character, or this is not test has been done.
For your example:
Code: |
const char keyword[]="command";
#INT_RDA
void char_received(void) {
static int8 charno=0; //note _static_
char rcvd;
rcvd=getc();
while (true) {
if (rcvd==keyword[charno++]) {
//here character matches
if (keyword[charno]=='\0) {
//here we have reached the end of the command string
//do what you want....
charno=0; //restart searching
}
break; //exit test
}
else {
if (charno==1) {
//Here have failed on the first character
charno=0;
break;
}
else {
//doesn't match, so start try again
charno=0;
//note this _retries_ the incoming character, against the first
//test character
}
}
}
}
|
Now, this is a rather 'oversimplified' version, looking for just one command, but it shows the approach. The interrupt checks just the single received character, against the next character in the test strng. If the next test character is the 'null' character,then the whole string has been matched.
In common with a lot of things of this sort, the commands look long, but in execution terms, the _time_ involved is short, which is what matters in the interrupt.
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Jan 16, 2008 4:30 am |
|
|
Ttelmah
My code does not wait for a specific sequence of characters and will not WAIT for anything. It reads any and all chars in the input buffer and transfers them to my buffer. it sets a flag when end of line is returned.
You have contradicted yourself.
you said the ISR should retrieve the character and exit. YOU have an infinate loop which scans a (single) keyword. Although this will only ever do 2 iterations it is still a waste of time.
If there are more than 1 keyword then your routine (when modified) will slow down quite quickly as it has to check the first char of each keyword and then if more than one keyword matches on the first char has to somehow check the second char of each of those and so on! |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Wed Jan 16, 2008 8:01 am |
|
|
Wayne_ wrote:
Quote: | Code: | char rs232_buf[80];
byte count = 0;
int1 command_flag;
#INT_RDA
void serial_isr() {
char c;
while (kbhit()) { // proberbly NOT required
c = getc();
if (c == '\r') {
disable_interrupts(INT_RDA);
rs232_buf[count++] = '\0';
command_flag = true;
printf("\r\n");
} else {
rs232_buf[count++] = c;
putc(c); // echo char
}
}
} |
|
Pretty much the approach I use - using kbhit is a good idea for processors that may have FIFO buffering and fast baud rates, so its more portable code. I would probably move the 'printf("\r\n")' out of the ISR though.
The difference between this code and Ttelmah's is that this code looks for CR terminated strings, and then parses them, while Ttelmah's looks for valid start characters, so it parses as chars are received - I think each approach has it's place |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 16, 2008 9:19 am |
|
|
Wayne_ wrote: | Ttelmah
My code does not wait for a specific sequence of characters and will not WAIT for anything. It reads any and all chars in the input buffer and transfers them to my buffer. it sets a flag when end of line is returned.
You have contradicted yourself.
you said the ISR should retrieve the character and exit. YOU have an infinate loop which scans a (single) keyword. Although this will only ever do 2 iterations it is still a waste of time.
If there are more than 1 keyword then your routine (when modified) will slow down quite quickly as it has to check the first char of each keyword and then if more than one keyword matches on the first char has to somehow check the second char of each of those and so on! |
get_string, _waits_ for a terminated string...
No, I say that the ISR should be _quick_. The handler a shown, does one test to see if the character matches the 'current' character in the array. If it does, it then tests if the next array character is zero. Total time about 20 machine instructions. If no match, then it tests again against the first character. As I say, it looks complex, but except for the array accesses, is fast code.
In fact you can make the code very fast for multiple keywords. What you do, is have the keyword array in alphabetic order, and have a row/column index. When a new character arrives, it tests the row/column on the array. If the match succeeds if moves one right (along the row), if the match fails, it moves down one row. If it hits the '\0' when it moves right, the row number is the command number matched. If the test character is lower than the current character, when it moves down, it moves down again.
I have such a system, handling comms at over 500Kbaud, on a system with five other interrupts in use, and some of these have been running reliably for over 8 years, without 'missing a beat' (or a character...).
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Jan 16, 2008 10:24 am |
|
|
SET
I have already moved that printf and I removed the kbhit test as well as it is not required in this context.
Re-examining the code due to this thread sure helps improve things, a bit. |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Wed Jan 16, 2008 10:56 am |
|
|
Quote: | I have already moved that printf and I removed the kbhit test as well as it is not required in this context.
Re-examining the code due to this thread sure helps improve things, a bit. |
I agree, good code is rarely 'write once' |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
|
Posted: Wed Jan 16, 2008 12:10 pm |
|
|
I dont get it. If the object is to keep your interrupts as short as possible than whats wrong with my code. All it does upon the interrupt is disable the interrupts and set a variable (userconnected) to 1 then i can take care of the users input in the main so its not holding up the other interrupts.
Code: |
////////////////////////////////////////
// Interupt on serial RX
////////////////////////////////////////
#int_rda
void serial_isr() {
disable_interrupts(int_rda); // stop this int
UserConnected = 1; // make a user
} |
Wouldnt that be faster than any code to actually get strings from this function ? once user connected is 1 it will catch that in my main
THIS IS IN MAIN()
Code: | if(UserConnected)
{
delay_ms(500); // let them open their eyes
printf("\n\r Hello There, You Connected at");
printf("\n\r Time: %d/%d/%d %d:%d.%d",Months,Days,Years,Hours,Minutes,Seconds);
printf("\n\r m=menu s=settime x=dissconnect");
while(UserConnected)
{
delay_ms(200); // so they dont flood me
printf("\n\r Your Choice:"); // prompt for item
get_string(String,10);
if(String[0] == 's'){SetupTime();} // setup time (set clock)
if(string[0] == 'x'){ // disconnect
UserConnected = 0; // set user to 0
enable_interrupts(int_rda); // resetup interrupt
}
}
} |
so the serial rx interrupt is not enabled again until the user disconnects that way it wont use the interrupt to do anything besides connect/disconnect a user all the string handling or anything else will be done in the main where it will not interfere with my Clock (because i have a interrupt based clock running also)
Note: im not trying to be arrogant or anything im just trying to explain my code to the best of my knowledge so someone can point out whats wrong with it ? Thanks for all your input so far ! _________________ Smart people know how stupid they are. |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Thu Jan 17, 2008 9:52 am |
|
|
Zonemikel, there is nothing wrong with your code, it just does a slightly different job to the other examples. Yours 'wakes up' on a key press, then waits for the user to type a command (terminated by CR). As long as your users are 'well behaved' and only type when they see the prompt then it will work. |
|
|
zonemikel_guest Guest
|
|
Posted: Thu Jan 17, 2008 1:00 pm |
|
|
Ok, yes since it will only be me using it i should be ok. Also if you type the wrong char it wont crap out on you it will just ignore it. It seems to be working pretty well
let me check it . . .
ya just logged on and the time is current, its been running for about two days now.
I need to make it so if the user does not disconnect they will be logged off after a while.
I will print out all the code posted in this thread and look it over with care. Thanks for all your help(s).
mike |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Jan 18, 2008 2:56 am |
|
|
Yes, your code should be fine. My first post to this was to show you where the problem is with using strcmp.
I also through in the code showing how I read the serial port incase you found it usefull. It has been done many ways and will continue to be implimented in different ways. |
|
|
nirayo
Joined: 23 Feb 2009 Posts: 10
|
Re: #int_rda And RTC int conflict ? |
Posted: Wed Aug 19, 2009 2:03 am |
|
|
zonemikel wrote: | if i have a interrupt for serial receive and one for the real time clock will the serial receive interrupt bother the rtc interrupt ?
By experimenting i see that it does :( anyone have a good idea how to do this without screwing up my RTC ?
Code: | #int_rda
void serial_isr() {
char String[10]; // for user input
int result = 0;
printf("Your Command:");
get_string(String,10);
}
|
also when doing this strcmp(String,"hi"); i always get "bad expression syntax" error ?
// dont read this --------------------------- below here is solved already
I'm new to interrupts. I just wanted a interrupt to tell me when I'm getting message through the rs232. That way my pic can be doing whatever its supposed to do but when i log onto it via the comm port it will greet me with a small menu and take commands. Afterwords i need it to turn off the interrupt.
As it is now it works but it does not stop. If i log onto the com or restart the pic while logged on and then hit a key it keeps looping the interrupt and printing out to my terminal screen (flooding it).
the interrupt function
Code: | ////////////////////////////////////////
// Interrupt on serial RX
////////////////////////////////////////
#int_rda
void serial_isr() {
printf("got serial rx");
} |
In my main
Code: |
// interrupts
enable_interrupts( GLOBAL ); // use the ints
enable_interrupts(int_rda); // int on serial RX |
NEVERMIND, IM DUMB
the interrupt is when there is information available all i needed to do was take the string/char coming in to stop it from interrupting |
you can use the #priority dirctive, and set which one will be handled first, if both accure at the same time |
|
|
|
|
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
|