![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
eagerstudent Guest
|
Interrupt problem. |
Posted: Thu Dec 09, 2004 12:15 am |
|
|
Hi,
Can anyone tell me what I am doing wrong in the below code. What happens is, if I transmit just one number say 5 from terminal, f will be displayed only once. If 2 numbers f will be displayed twice and if more than 2 then f is displayed 3 times. Also, can I use strtod just like that and if so, how can I output the double value to terminal. Thank You
#include <16F874.H>
#include <stdlib.h>
//#include <stdio.h>
#use delay(clock=20000000)
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define BUFFER_SIZE 20
#define sizear 5
char buffer[BUFFER_SIZE];
byte next_in = 0;
byte next_out=0;
boolean rec;
char xdist[sizear];
#int_rda
void serial_isr() {
rec=true;
buffer[next_in]=getc();
next_in=(next_in+1) % BUFFER_SIZE; //% gives remainder
if(next_in==next_out)
next_in=0; } // Circular Buffer
int main()
{
double xdistd, ydistd, xtraveld, ytraveld;
disable_interrupts(global);
enable_interrupts(int_rda);
enable_interrupts(global);
rec = false;
do{
if(rec)
{
rec=false;
xdist[0]=buffer[0];
xdist[1]=buffer[1];
xdist[2]=buffer[2];
xdist[3]=buffer[3];
xdist[4]=buffer[4];
xdistd = strtod(xdist, &remst); //converts a string to decimal
putc(102);
}
}while(TRUE);
} |
|
![](templates/subSilver/images/spacer.gif) |
RossJ
Joined: 25 Aug 2004 Posts: 66
|
|
Posted: Thu Dec 09, 2004 1:37 am |
|
|
Next time you post a code/fragment, please select it and press the [Code] button above the editor box. This will allow the formatting to be retained, which makes it easier for everyone to read.
The behavior you describe is consistent with the program you have written. The 'f' is of course the character 102 which you send with putc(). Each time a character is received, the interrupt routine receives the single character and stores it in buffer. The isr also sets the rec flag which causes the if block to be executed. I think the conversion to a float probably works, and an 'f' is transmitted back to the terminal.
Some observations...
1. Do you really need to use doubles? Note that strtod() returns a float, and that most (if not all) standard C support is for floats not doubles. Also, on processors like the PIC, it is often more appropriate to use fixed point arithmetic instead. This allows you to work with integers (just show the fractional part for display etc.).
I also see that under the 'data definitions/data types' chapter of the CCS reference manual, double is defined as a reserved word but NOT a supported data type. I have no idea why the compiler would accept your program with variables declared as double. They would certainly not be handled by the compiler as doubles.
2. Make sure the string you pass to strtod is null (0) terminated. Otherwise the function may continue past the end of your buffer.
3. Probably just a typo, but I don't see the remst declaration. It should be a char* (or similar), and it is probably not correct to be passing its address with the & operator.
4. You have decided to reset your circular buffer pointers to zero when empty (or overflowed). But you probably need to reset the next_out also.
5. When you initialise rec outside the do loop, you are creating a short timing window for a bug (not serious in this case). It is good practice to initialise such variables BEFORE enabling the interrupt which will use it.
6. I suspect you should be receiving several characters before converting it to a float/double. Now you repeat the process with one, the two, then three etc. characters.
7. The easiest way to convert a float to ascii and sending it to the RS232 output is (once again) using printf(). For example, printf("%f", float_value).
8. Depending on what you are doing, it might not be necessary to exchange data over the RS232 link in text form at all. You could consider keeping them in binary form (i.e. the 4 bytes of a float). Of course you could not just view them in a terminal program or type them on the keyboard.
I hope this gives you some ideas. In order to be able to help explain why the program is not working, it would be necessary for you to indicate (briefly and at a high level), what you are trying to achieve. |
|
![](templates/subSilver/images/spacer.gif) |
eagerstudent Guest
|
|
Posted: Thu Dec 09, 2004 4:00 am |
|
|
I am sending decimal values as string to the pic which reads data coming in as char. To convert the value from char to decimal, i am using strtod function. I used float, but it does not give the same values as expected. For example, 12.34 sent as string, pic reads them as 5 bit chars. When used strtod, the float returned some value that is not right. I made the changes that was suggested. |
|
![](templates/subSilver/images/spacer.gif) |
RossJ
Joined: 25 Aug 2004 Posts: 66
|
|
Posted: Thu Dec 09, 2004 5:32 pm |
|
|
It seems to me that floats and strtod should do what you want.
When you say the float value returned was not what you expected, what wereyou expecting? According to the numeric converter tool in the PCW tools menu, 12.34 expressed as a float is the 32 bit number 824570A4 (in hex). Did you get something else?
Also, what do you mean by Quote: | pic reads them as 5 bit chars | ? The PIC will read your string in 8 bit (typically ascii) characters. In the case of 12.34, thats five characters. Before calling strtod, make sure the sixth buffer position is zero (null).
You can verify the result by using printf("%f", float_value * 2) to send back the received value multiplied by two ('* 2' is just to ensure you are not just seeing the characters echoed back). |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|