|
|
View previous topic :: View next topic |
Author |
Message |
hatanet
Joined: 08 Sep 2003 Posts: 9 Location: South Africa
|
18F452 Rebooting. |
Posted: Mon Nov 10, 2003 7:00 am |
|
|
Hi,
Please help ... I am using RDA interrupt to receive date from a VB.NEt application on a COM port. If I send, lets say a 20 char long string, the PIC just reboots, even though my buffer is 32+1 max.
I have tried a couple of options, but still no luck... my uses & fuses look like this;
#fuses HS,NOPROTECT,NOBROWNOUT,NOWDT,BORV45,NOPUT,CCP2B3,NOSTVREN,NODEBUG,NOLVP
#use rs232(baud=38400,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7,errors)
[b]What am I doing wrong...[/b]
include "C:\Educate\projects\VideoStudio\source\Release\VideoStudio.h"
// [DEFINITIONS]
#define RxBUFFER_SIZE 32
#define TxBUFFER_SIZE 128
// [GLOBAL VARIABLES]
byte rx_buffer[RxBUFFER_SIZE]; // input buffer
byte rx_next_in = 0;
byte rx_next_out = 0;
short RDA_flag=0, TBE_flag=0; // RS-232 Interrupt flags.
byte cmd[RxBUFFER_SIZE+1];
// [INTERRUPT SERVICE ROUTINES]
#int_rda
void rx_serial_isr() {
int store;
RDA_flag=1; // Full buffer flag, Alert Main.
rx_buffer[rx_next_in] = getc(); // Get data.
store = rx_next_in; // store data tracker.
rx_next_in = (rx_next_in + 1) % RxBUFFER_SIZE;
if(rx_next_in == rx_next_out) // if buffer overflow!.
rx_next_in=store; // Load buffer length.
}
// [PROCEDURES & FUNCTIONS]
#define data_present (rx_next_in!=rx_next_out)
byte bgetc()
{
byte input;
while(!data_present); // Wait for data stream flow.
input = rx_buffer[rx_next_out];
rx_next_out = (rx_next_out + 1) % RxBUFFER_SIZE;
return(input);
}
//#separate
void cmdSwitcher(char *cmd)
{
printf("\r\nRex=%S",cmd);
switch (cmd[0]) // get command discriptor.
{
case 'A': cmd_A(cmd); // Get Analogue-to-Digital Converter Results.
break;
case 'C': mux_cmds(cmd); // STV5730A Device command - Set COLOR Registers.
break;
case 'F': mux_cmds(cmd); // STV5730A Device command - Set CFA Registers.
break;
case 'I': mux_cmds(cmd); // STV5730A Device command - Set CFA Registers.
break;
case 'M': mux_cmds(cmd); // STV5730A Device command - Set MODE Registers.
break;
case 'P': mux_cmds(cmd); // STV5730A Device command - Set POSITION Registers.
break;
case 'R': mux_cmds(cmd); // STV5730A Device command - Set RASTER Registers.
break;
case 'T': cmd_T(cmd); // VIDEOSTUDIO Device command - Send overlayed text.
break;
case 'U': cmd_U(cmd); // DS1629 Device command - SET Date & Time.
break;
case 'W': mux_cmds(cmd);
break;
case 'Z': mux_cmds(cmd); // STV5730A Device command - Set ZOOM Registers.
break;
case 'X': cmd_X(cmd); // Microcontroller Software Reset - Set COLOR Registers.
break;
default:
{ //Never to be shown, but then hey..!
error(2); // E02 - Invalid Command Switch!
}
break;
} //end switch(*)
} // void cmdSwitcher(cmd)
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %% VIDEO STUDIO MAIN ROUTINE PROGRAM %%
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
void main()
{
// [VARIABLES]
int cmd_length=0;
// [MICROCONTROLLER]
// setup_adc_ports(RA0_ANALOG);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
// [INTERRUPT SERVICE ROUTINES]
enable_interrupts(INT_RDA);
enable_interrupts(global);
//disable_interrupts(global);
//enable_interrupts(INT_TBE);
//enable_interrupts(ADC_DONE);
// [MAIN LOOP]
while(TRUE)
{
if (RDA_flag == 1) // Data is available on COM Port.
{
delay_ms(5000);
cmd_length=0;
while(data_present)
{
cmd[cmd_length] = bgetc(); // get all characters available!
cmd_length++; // increment count.
}
//printf("\r\nRDA=%S",cmd);
//puts(cmd);
cmdSwitcher(cmd); // command switching/filtering.
//delay_ms(1000);
//stripper(cmd);
//rx_next_in = 0;
//rx_next_out = 0;
RDA_flag=0; // reset RDA flag.
// reset string length count.
//enable_interrupts(int_rda);
}
//scan_port();
if (TBE_flag == 1) // A byte is being sent to COM Port.
TBE_flag=0;
get_date_time();
} // end while
} // end main |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 11, 2003 12:59 am |
|
|
The main problem with your code is that there is too much of it.
Apparently you're using PCWH. PCW & PCWH put in tons and tons
of unnecessary code at the start of the program. For a beginner,
all this extra code hurts you, because it prevents you from looking
closely at the important areas of your program.
You should get rid of all of this stuff:
Code: | setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF); |
The code above is not needed, because all of these hardware
modules are disabled upon power-up. You don't need to put
in code to disable them. (Or, PCWH doesn't need to do it).
Once you get rid of the chaff, you can start to look at your program.
The first thing I notice is that you have based your program on
the CCS example, EX_SISR.C. That's fine, but for some reason,
you have changed it, and added the RDA_flag variable. In your
int_rda function, you describe this flag as meaning "buffer full".
But it doesn't mean that. It just means that one or more characters
is in your buffer. But you don't need the RDA_flag. CCS has
already provided a method of telling if you have chars in the buffer.
It's called bkbhit. You have this macro in your code, but you
have renamed it to data_present. So you should use it.
Get rid of RDA_flag and just test the data_present macro to
see if you have characters in the buffer.
OK. Now let's look at the following section of your code.
Code: | if (RDA_flag == 1) // Data is available on COM Port.
{
delay_ms(5000);
cmd_length=0;
while(data_present)
{
cmd[cmd_length] = bgetc(); // get all characters available!
cmd_length++; // increment count.
} |
In this code, you check to see if you have 1 or more characters
in the buffer, by using testing RDA_flag. You could check this
same thing by testing data_present. You don't need another flag.
Then you wait for 5 seconds. Why ? During 5 seconds, you may
get tons of characters coming into your int_rda function, and your
buffer will overflow, and you'll lose all your messages.
The next thing you do is go into a while() loop, and then remove
characters from the int_rda buffer, and put them into the cmd buffer.
But what if characters are still constantly coming into the int_rda
buffer while you are copying them into the cmd buffer ?
You will overflow the cmd buffer. And, it's not a circular buffer.
So you'll be writing characters into some other part of ram, and
possibly wiping out all your other variables.
So, you need to prevent this by limiting the number of characters
that you copy into the cmd buffer, so they don't exceed the length of
the buffer. Just keep a count of the characters that are copied,
and then exit the loop if the count = the cmd buffer size.
I think you should also test the characters as you copy them
into the cmd buffer, for an "end of messsage" character.
Then stop copying when you reach that character. If your
command protocol does not have an "EOM" character, then
add one to the protocol.
And one final thought --- When you are first trying to make a
program work, you should keep it simple. You should remove
all but 1 or 2 of your commands from the switch() statement.
Make it work with 2 commands, and then add the rest.
Also, what is your version of the compiler ? |
|
|
hatanet
Joined: 08 Sep 2003 Posts: 9 Location: South Africa
|
|
Posted: Tue Nov 11, 2003 8:55 am |
|
|
Ole,
Thanks very much for your response, I am going to try everything that you have mentioned tonight when i get home, and feedback to you tomorrow... so long, my versions are as follows
IDE is 3.11
PCM is 3.088
PCW is 3.088
PCH is 3.088
What bug should I be aware of ?
Regards
Thabang |
|
|
hatanet
Joined: 08 Sep 2003 Posts: 9 Location: South Africa
|
4062221 |
Posted: Wed Nov 12, 2003 1:47 am |
|
|
Lumelang,
I have reworked & optimised most of my code;
#include <input.c>
#define RxBUFFER_SIZE 32
short RDA_flag=0; // RS-232 Interrupt flags.
char cmd[RxBUFFER_SIZE+1];
// [INTERRUPT SERVICE ROUTINES]
#int_rda
void rx_serial_isr()
{
get_string(cmd,RxBUFFER_SIZE+1); // gets the string
RDA_flag=1; // Full buffer flag, Alert Main.
}
In the main program;
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(global);
while(TRUE)
{
if(RDA_flag==1)
{
cmdSwitcher(cmd); // switch received command.
RDA_flag=0;
}
get_date_time();
} // end while
} // end main
I have got rid of all the access baggage as you highlighted, and everything seems to be working....But I am still concerned, what will happen if I'm in the switcher proc & I received some other data while I'm busy processing...? obviously I will loose data, how can I handle this?
Regs
T |
|
|
Guest
|
|
Posted: Wed Nov 12, 2003 3:32 am |
|
|
If you want to be sure no characters get lost, use a circular buffer where you first put in the characters.
I lost the link to the original post, but this link will show you how it works, if you read between the assembly statements:
http://www.ccsinfo.com/forum/viewtopic.php?t=14756&highlight=rxispartfull
Regards,
Ron |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 12, 2003 1:03 pm |
|
|
You did the opposite of some of my suggestions.
I suggested getting rid of the RDA_flag, and using
bkbhit (you called it "data_present") instead.
I did not suggest getting rid of the EX_SISR.C code.
Quote: | But I am still concerned, what will happen if I'm in the switcher proc & I received some other data while I'm busy processing...? obviously I will loose data, how can I handle this? |
Fix that problem by putting the EX_SISR.C code back in.
Then, in main(), you should have a while(1) loop, in which you
check the bkbhit value, and if there is a character, then pass it
to your command checker (the switch-case statement).
In other words, you need to re-work your code a lot. |
|
|
|
|
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
|