|
|
View previous topic :: View next topic |
Author |
Message |
hayee
Joined: 05 Sep 2007 Posts: 252
|
sending 2 adc values through spi |
Posted: Sat Apr 19, 2008 4:52 am |
|
|
Hi everyone;
I am reading 2 adc values from 1 microcontroller(PIC16f877a) and want to send these both values to another microcontroller(PIC16f877a) through spi.i have written a code which send only 1 adc value.here is the code
code for slave
Code: |
#define first(x, offset)\
*((int8 )&x +offset) //function for breaking floating number into 4 bytes.
/*#define MakeDWord(x, b3, b2, b1, b0) \
*(int8 *)&x = b0; \
*((int8 *)&x +1) = b1; \
*((int8 *)&x +2) = b2; \
*((int8 *)&x +3) = b3*/
void main()
{
float value,adc1,adc2;
int8 b0, b1, b2, b3;
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL );
setup_psp(PSP_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_4);
while(1)
{
if(input(PIN_A5)==0)
{
set_adc_channel(0);
delay_us(10);
adc1=read_adc();
adc2=(adc1*5)/1024;
value =adc2;
printf("first no is = %2.2f \n\r", value);
// Break the float into 4 bytes.
b0 = first(value, 0);
b1 = first(value, 1);
b2 = first(value, 2);
b3 = first(value, 3);
//send 4 bytes one by one through spi
spi_write(b0);
spi_write(b1);
spi_write(b2);
spi_write(b3);
}
else
{
delay_cycles(100);
}
}
} |
code for master
Code: |
#define MakeDWord(x, b3, b2, b1, b0) \
*(int8 )&x = b0; \
*((int8 )&x +1) = b1; \
*((int8 )&x +2) = b2; \
*((int8 )&x +3) = b3 //fuction for joining 4 bytes and give result in
//floating number.
float readnum(void);
void main()
{
float num;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
// TODO: USER CODE!!
output_high(PIN_A5);
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4);
while(1)
{
num=readnum();
printf("no is:%2.2f \n\r",num);
delay_ms(100);
}
}
float readnum(void)
{
int8 b0,b1,b2,b3;
float result;
output_low(PIN_A5);
delay_us(100);
b0=spi_read(0);
b1=spi_read(0);
b2=spi_read(0);
b3=spi_read(0);
MakeDWord(result, b3, b2, b1, b0);
output_high(PIN_A5);
return result;
}
|
Now the question is that how i send 2nd value(which is from channel 1) through spi and what will be the timings of sending and reciving of these 2 values.
Thankx in Advance. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Apr 19, 2008 8:42 am |
|
|
Code: | setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_4); | An SPI slave never generates a clock signal, so using an SPI_CLK_DIV_x is a bug. You are lucky it works because SPI_CLK_DIV_4 is defined as zero and has no effect in your code. Remove this define to prevent difficult to find future errors.
Code: | #define first(x, offset)\
*((int8 )&x +offset) //function for breaking floating number into 4 bytes.
/*#define MakeDWord(x, b3, b2, b1, b0) \
*(int8 *)&x = b0; \
*((int8 *)&x +1) = b1; \
*((int8 *)&x +2) = b2; \
*((int8 *)&x +3) = b3*/ | For your info: The CCS compiler functions make8() and make32() do exactly the same thing but because they are internal to the compiler are way more efficient.
Code: | float value,adc1,adc2;
...
adc1=read_adc(); | You are wasting memory as the function read_adc() returns returns an 8- or 16-bit integer value (1 or 2 bytes, depending on settings) and a float takes 4 bytes.
A design tip: Do the conversion from the integer A/D-value to a float not in the slave but in the master. This way you have less data to transmit and a higher accuracy (because of rounding errors an integer is more accurate than a float). Do the conversion to float as late as possible, preferably only when showing the calculated result to the user.
Quote: | Now the question is that how i send 2nd value(which is from channel 1) through spi and what will be the timings of sending and receiving of these 2 values. | Communications between master and slave over SPI have been discussed many times on this forum, try searching this forum.
A universal system which is easy to extend for future expansions would be to implement some kind of message system where the master sends a command to the slave and the slave responds with an answer. For example:
- Master says 'Give me the data of channel 1'
- Slave keeps telling 'I'm busy, please wait'
- When data is present the slave says 'Great master, here is your requested data'.
Adding new channels is easy and you will not get the timing problems you are afraid of. |
|
|
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Mon May 12, 2008 5:16 am |
|
|
Thanks ckielstra for lot of ur suggestions as i was busy in my other project that's why i am replying late.
i am using ccs compiler version 4.020
as u say that i can use make32 function instead of my own function.
when i use make32 function the floating value is converted into 32 bit integer and when i use make8 function the value is converted into an 8 bit integer but how i convert this value into float again.how i do this?
for example
i have an floating number that is 4.52.
now tell me that how i convert it into 32 bit and send it through spi
and again convert it into floating number.
thanks in advance. |
|
|
Ttelmah Guest
|
|
Posted: Mon May 12, 2008 7:46 am |
|
|
Personally even 'better', use a union:
Code: |
union convert {
int8 b[4];
float fpval;
} val;
|
val.b[0] to val.b[3], are the four bytes making up the floating point value 'val.fpval'. You can use this to go both ways,and it generates similar code to the make8/make32 version.
You can (obviously) use the same 'trick' with make32, so:
Code: |
union intfp {
int32 word;
float fpval;
} val2;
|
You then just put the result of the make32, into val2.word, and can read the float value as val2.fpval.
Best Wishes |
|
|
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Tue May 27, 2008 1:21 am |
|
|
Ttelmah thanks for ur reply.
But i am not getting the point that how i convert floating number into 32 bit int and again convert the 32 bit int into floating number using union method.Kindly give me a proper example so that i run the program and check its functionality.plz.
I am at a begineer level and not know much.
Thanks in advance. |
|
|
Ttelmah Guest
|
|
Posted: Tue May 27, 2008 3:26 am |
|
|
The 'point' about a union, is it allows multiple variables to 'share' the same memory area. So, if you have a union:
Code: |
union demo {
int32 32bitval;
float fpval;
int8 b[4];
} shared;
|
Then you have a floating point variable 'shared.fpval', and a int32 variable 'shared.32bitval', and also an array of four 8bit values 'shared.b[0]' to 'shared.b[3]', _all of which are stored in exactly the same memory locations_.
Now, you can take a floating point number, and put it into the floating variable, say:
shared.fpval=1.2345;
and then if you print the int32 number, with:
printf("%8x",shared.int32);
you will get the eight hex characters '19041E7F', corresponding to the four bytes used to represent the float in memory. You can also access the bytes individually using the byte array.
Think of it a bit like a tape measure, that has got both inches, and mm, written on it's face. You can move 'along' to 4", and just read off the other edge, that this is 101.6mm, or move along to 600mm, and read the other way, that this is 23.62". Just like with the tape measure, no actual 'maths' is involved, it just allows you to see the two different representations at the same time.
You can write or read in either direction (or three ways with the int8/int32/float example given above), and no actual 'work' is involved from the compiler, since it just 'looks' at the same data using the different representations selected. This makes the union fast, and a very powerful way of accessing the values stored in one form, using a different representation.
Best Wishes |
|
|
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Wed May 28, 2008 1:26 am |
|
|
Thanks again Ttelmah. I am doing the same thing as u said, but I got the result like that 0000007f but not '19041E7F'. What's wrong in my code ?
Code: |
void main()
{
while(1)
{
union demo
{
int32 bitval;
float fpval;
}
val;
val.fpval=1.2345;
printf("%8x",val.bitval);
delay_ms(500);
}
} |
|
|
|
Ttelmah Guest
|
|
Posted: Wed May 28, 2008 2:32 am |
|
|
My error. I missed out the 'L', in the format specifier when I typed it. %8x, only treats the source as an integer (8bit). You need %8Lx to print the 32bit value.
Best Wishes |
|
|
hayee
Joined: 05 Sep 2007 Posts: 252
|
|
Posted: Wed May 28, 2008 3:47 am |
|
|
Thanks Ttelmah.It is working now.One more question can i send this int32 bit value through spi or first i have to break it into 4 8bit integer.
Best Wshes. |
|
|
|
|
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
|