CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PIC16F876A TO PIC16F72 communication problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
bharatwalia



Joined: 04 May 2009
Posts: 35
Location: India

View user's profile Send private message

PIC16F876A TO PIC16F72 communication problem
PostPosted: Thu Jul 01, 2010 2:12 am     Reply with quote

Hi,
I using CCS SPI Library to send data from PIC16f876A to PIC16f72.
My aim is to read voltage from pic16f76a adc and send the same over spi to pic16f72 so that it can then process the data (convert it into 7-segment).

The problem i am facing here is that when i am only using PIC16f876a reading the voltage from ADC converting the 10-bit data into 7-segment everything works fine.

But when i am sending this 10-bit data from PIC16f876A over SPI to PIC16f72 and then converting the same 10-bit adc data into 7-segment, i am not getting the same result.

here is Master's Code(PIC16F876A)

Code:

//master.c

#include <16f876A.h>
#device adc=10
#include <timers.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */
#FUSES XT,NOWDT,NOPROTECT,NOPUT
int32 result=0;

void transmitData(void);
void getVoltage(void);

//-------------------------------------------------------------------
// The rtcc interrupt occurs when the rtcc rolls over from FF to 00.
// I have programmed it to interrupt at a 100 Hz rate.
//
// RTCC interrupt rate = Fosc / (4 * rtcc pre-scaler * rtcc pre-load)
//
//                     = 4 MHz / (4 * 256 * 39)
//
//                     = 100.16 Hz
//
// This gives us a timer tick approx. every 10 ms  (9.98 ms actually).
//-------------------------------------------------------------------
#int_rtcc
void rtcc_isr(void)
{
// Reload the RTCC, so it will keep overflowing every 10 ms.
set_rtcc(RTCC_PRELOAD);

// Decrement any timers that are running.

if(gc_transmit_timer)
   gc_transmit_timer--;



}
//--------------------------------------------------------

void main()
{
   setup_counters(RTCC_INTERNAL,RTCC_DIV_256);    
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);

   setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 );
   setup_adc_ports(AN0_AN1_AN3);
   setup_adc(ADC_CLOCK_DIV_64);

   set_tris_a(0xDB);

   gc_transmit_timer = TRANSMIT_TIMER_TICKS;

   while(1)
   {
      getVoltage();
      transmitData();

      
   }
}

//--------------------------------------------------------
void getVoltage(void)
{

   
         result=0;
         set_adc_channel(0);
         delay_ms(1);
         result=read_adc();
         
         
               
}
//---------------------------------------------------------
void transmitData(void)
{
   if(gc_transmit_timer)                   //refresh rate.
         return;
   else
     gc_transmit_timer = TRANSMIT_TIMER_TICKS;

   spi_write(result);

}


Here is slave code(PIC16f72)

Code:


//slave.c
#include <16f72.h>
#device *=8
#fuses HS,NOWDT,PUT,BROWNOUT,NOPROTECT
#use delay(clock=4000000)

void display(void);
void HTO7S(unsigned int32 Num);


#define  TICKS_BETWEEN_INTERRUPTS      5000 //5000      4/4=1   =1ms
#define  INTERRUPT_OVERHEAD            35   //cycles wasted
#define  TMR1RESET (0xFFFF-(TICKS_BETWEEN_INTERRUPTS-INTERRUPT_OVERHEAD))


#byte port_b=6 /* define the location of register port_b */
#byte port_c=7 /* define the location of register port_c */

byte CONST LED_MAP[11] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xFF};

//                          0    1    2    3    4    5    6    7    8    9   OFF

byte cnt=0,value,i;

byte Column[4]   = {0x80,0x40,0x02,0x10};         //Low bits(right,center,left)
byte Segment[4] = {0x12,0xE3,0xAB,0xAF};      

int32 res,data;

//--------------------------------------------------------
#INT_TIMER1
void Timer1(void)
{   
   

   set_timer1(TMR1RESET);
   display();   
   
}   


void main()
{
   set_tris_b(0); //1 set port_b as outputs
    set_tris_c(0);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //no division
   set_timer1(TMR1RESET);            //65535-4965=60570
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   setup_spi(SPI_SLAVE | SPI_H_TO_L | spi_ss_disabled  );
   
   while(1)
     {
         while(!spi_data_is_in()) ;
         data=spi_read();
               
     HTO7S(data);
   
}
}

//-------------------------------------------------------
void display()
{
   
if(cnt>=4){
cnt=0;}
port_b=Segment[cnt];
//port_b=data;
port_c=Column[cnt];
//port_c=0xFF;
cnt++;
   
}

//--------------------------------------
// Convet HEX 2 byte to 7-Segment code
//--------------------------------------
void HTO7S(unsigned int32 Num)
{
   unsigned int32 res;                     //500ms interrupt to control display


   

   Segment[0]=LED_MAP[30*Num/10230];      //calculating look-up value from LED_MAP array.
   if (Segment[0]==0x40)                //turning off 1st digit if 0
   Segment[0]=0xFF;                  //dividing the three digits
   

   res = 30*Num%10230;
   Segment[1]=LED_MAP[10*res/10230];
   
   res=10*res%10230;
   Segment[2]=LED_MAP[10*res/10230];
   

   res=10*res%10230;
   Segment[3]=LED_MAP[10*res/10230];


}   


I am sending data from master every 400ms.

Can any body help me.

Thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19338

View user's profile Send private message

PostPosted: Thu Jul 01, 2010 3:10 am     Reply with quote

The obvious thing is that you are only sending 8bits of the ADC value.
A single SPI transfer, sends a _byte_ as standard.
Easiest way, use 'make8', and send one byte, then the other.
At your receive end, receive one byte, then the second, and use make16, to put the data back together.

A couple of minor 'comments'. Move your 'timer.h' include to after the fuses and the clock statement. _If_ the code in an include file uses delays, serial I/O etc., then it must be included after the clock and RS232 defintions. It is obviously not causing you a problem in this code, but it is one 'waiting to bite' in the future. get into the habit of structuring the intialisation as :

Processor file
Any #device lines
Fuses
clock statement
RS232, I2C etc., setup lines

Include other stuff

main code.

Long term, if the data gets more complex, you might want to consider implementing a SS line. Problem is, what happens if the slave and master startup slightly 'out of sync', and the slave then starts thinking the first byte it is receiving, is the 'high' byte, when the master has already sent this, and is actually sending the 'low' byte. The code will never re-synchronise....
Two ways of handling this:
1) A 'software' re-sync. Send a pair of FF bytes one after the other, followed by a zero byte. Since the high byte can never be above '3' for real data, you can then use this to work out the synchronisation.
2) Add a SS line.
The latter makes handling SPI multi byte transfers much easier....

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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