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

Terrible time getting SPI to work w/16F872

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



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

Terrible time getting SPI to work w/16F872
PostPosted: Mon Jul 24, 2006 4:05 pm     Reply with quote

I have been spending the last two days trying to get SPI to work on my project to no avail. I am using a 16F872 running a cutter module, connecting to a printer that will communicate with this board. When the printer powers up, it checks each of the SPI ports and expects the board to reply with its HW ID byte.
When I run the code with the printer, I have a logic analyser connected, so I can see what is happening on all the lines. I see the point where the CS goes low and it is clocked 8 times, but SDI and SDO are silent. I have followed the circuit from them printer MLB to this new module and all the HW seems to be working fine, but SPI is not happy.
Is there somthing stupid simple I am missing here??? Using PCWH 3.227
I have stripped the code down to just the SPI section trying to get it to work. Mind you, I am a HW engineer trying to learn C, so pardon my messy code! Here it is:

#include <16F872>
#device ICD=TRUE
#device adc=8
#include <stdio>
#ZERO_RAM

#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES DEBUG //Debug mode for use with ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected

#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)

#define PORTA = 5
#define PORTB = 6
#define PORTC = 7

#INT_SSP
void SPIInterupt()
{
printf("You are in the SPI Interupt!"); //Never gets here
}

void main()
{
////////////////////////////////////////////////////////////////////////////////
// Variables and Constants //
////////////////////////////////////////////////////////////////////////////////

int spi_data_in, spi_data_out, spi_id=3;
//spi_data_in == data from the mlb to cutter
//spi_data_out == data from the cutter to mlb
//spi_id == hardware id of the cutter module

////////////////////////////////////////////////////////////////////////////////
// Configure pin direction //
////////////////////////////////////////////////////////////////////////////////

set_tris_a(0b11111111); //7-0-All inputs
set_tris_c(0b01011000); //7-out,6-in,5-out,4-in,3-in,2-out,1-out,0-out

////////////////////////////////////////////////////////////////////////////////
// Periferal Setup //
////////////////////////////////////////////////////////////////////////////////

setup_adc_ports(NO_ANALOGS);

setup_spi(SPI_SLAVE|SPI_L_TO_H);

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_4,24,1);

setup_ccp1(CCP_PWM);

enable_interrupts(GLOBAL);

////////////////////////////////////////////////////////////////////////////////
// Simple Spi Test //
////////////////////////////////////////////////////////////////////////////////

printf("Out of reset and sending ID\n\n"); //Works!
spi_write(spi_id); //Never sends it out but will pass and go to printf
// spi_data_in = spi_read(spi_id); //Never sends it out but will pass and go to printf
printf("ID has been sent!!!");

while(1)
{
printf("sitting in main loop\n\f");
}
}
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 24, 2006 4:26 pm     Reply with quote

Change the LVP fuse to NOLVP and look at this sample code:
http://www.ccsinfo.com/forum/viewtopic.php?t=26888
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

Getting a bit closer
PostPosted: Tue Jul 25, 2006 12:23 pm     Reply with quote

Ok, I made a couple changes and can get SPI to communicate, as long as I don't mess with any other pins of PORTC. I can run SPI communications fine, as long as I don't mess with the CCP or RS-232 BEFORE I try to do my SPI comms. If I enable the CCP and/or try to send anything with RS-232, then the SPI port seems to get messed up.
What am I missing here??? Thanks for the help so far, and any other help given.

#include <16F872>
#device ICD=TRUE
#device adc=8

#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES DEBUG //Debug mode for use with ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected

#use delay(clock=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)

#define PORTA = 5
#define PORTB = 6
#define PORTC = 7
#define SPI_SS PIN_A5
#define SPI_CLK PIN_C3
#define SPI_DI PIN_C4
#define SPI_DO PIN_C5

#ZERO_RAM


void main()
{
////////////////////////////////////////////////////////////////////////////////
// Variables and Constants //
////////////////////////////////////////////////////////////////////////////////

int spi_data_in, spi_data_out, spi_id=3;
//spi_data_in == data from the mlb to cutter
//spi_data_out == data from the cutter to mlb
//spi_id == hardware id of the cutter module

////////////////////////////////////////////////////////////////////////////////
// Configure pin direction //
////////////////////////////////////////////////////////////////////////////////

set_tris_a(0b11111111); //7-0-All inputs
set_tris_c(0b01011000); //7-out,6-in,5-out,4-in,3-in,2-out,1-out,0-out

////////////////////////////////////////////////////////////////////////////////
// Periferal Setup //
////////////////////////////////////////////////////////////////////////////////

setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);

setup_spi(SPI_SLAVE|SPI_L_TO_H);

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_4,24,1);
// setup_ccp1(CCP_PWM); //If left in, SPI won't work!
// enable_interrupts(GLOBAL);

// printf("Waiting to send ID Byte...\n\f"); //If left in, SPI won't work!
spi_write(spi_id);
printf("\n\fID Byte 1 & 2 have been sent...now sitting idle!");

while(1)
{

}
}
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jul 25, 2006 1:16 pm     Reply with quote

Quote:
I can get SPI to communicate, as long as I don't mess with any
other pins of PORTC.

There is a bug with the 16F872 in vs. 3.249 of the PCM compiler.
The data sheet says to avoid using Read-Modify-Write instructions
on the TRISC register, when peripherals on PortC are in use.
Normally, CCS solves this problem by using a shadow register for
TRISC. They make all modifications to the shadow register (just a
ram location) and then write it out as a complete byte to TRISC.
They don't ever have to do a RMW operation on TRISC.

Problem:
This feature is not enabled for the 16F872 in vs. 3.249.

Here is a short test program I made, to investigate this problem.
Code:
#include <16F872.h>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

//=================================
main()
{
setup_ccp1(CCP_PWM);

while(1);
}


I first compiled it for the 16F877. Here is the generated code.
Note the use of the shadow register, called "@TRISC".
Code:
... setup_ccp1(CCP_PWM);
000C:  MOVLW  FF          // Init shadow reg. to all inputs
000D:  BCF    STATUS.5    // Bank 0
000E:  MOVWF  @TRIS_C

000F:  BCF    @TRIS_C.2 // Set C2 as output in shadow reg.
0010:  MOVF   @TRIS_C,W  // Read shadow reg.
0011:  BSF    STATUS.5  // Bank 1
0012:  MOVWF  TRISC  // Write shadow reg. to physical reg.
0013:  BCF    STATUS.5  // Bank
0014:  BCF    PORTC.2   // Set PortC.2 = 0
0015:  MOVLW  0C        // Set CCP1CON = 0x0C
0016:  MOVWF  CCP1CON


Here is the code for the 16F872. Notice there is no shadow register used.
This is the cause of the problem.
Code:

... setup_ccp1(CCP_PWM);
000C:  BCF    TRISC.2
000D:  BCF    STATUS.5
000E:  BCF    PORTC.2
000F:  MOVLW  0C
0010:  MOVWF  CCP1CON


Possible solutions:
1. If you have PCW or PCWH, you may be able to use the
Device Editor to enable the shadow register for TRISC.
Here's a screen-shot of the Device Editor:
http://www.ccsinfo.com/images/content/device_editor.gif
Notice on the right side it say "Errata", and there is a box for
"Don't use RMW on TRISC". I don't have PCWH, so I can't
confirm this, but I think if you edit the 16F872 and enable that
box and save the updated file, then it might correct the problem.

2. If only have the plain PCM compiler, and thus don't have the
Device Editor, you could email CCS support and ask them to
edit the Devices.dat file for you (as described above) and email
the updated file back to you.

3. You could write your own versions of the CCS functions that
affect Port C and add the shadow register. This would be a pain.
I suggest you do item 1 or 2 above.
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Tue Jul 25, 2006 2:20 pm     Reply with quote

I did #1 and it worked!!! Thank you so much for your help. Why would that box hav not been checked? Can that cause other problems? Also, how can I find more information about the device editor and what some of the other boxes meant? Thanks again for your help.
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jul 25, 2006 2:30 pm     Reply with quote

I think it's been that way for years. I checked vs. 3.191 and it has the
bug. Probably, very few people use the 16F872 and so it was never
noticed until now. I think it was just an accident (an oversight) that
occurred when the chip data was initially entered.

Historically, CCS doesn't really check things very well when they add
support for a new PIC. Quite often the start-up code is incorrect and
the A/D functions or comparator functions may have errors. Lately
they've increased the size of their company, so hopefully they've added
more staff to check these kinds of things.

Since I don't have PCW or PCWH (I only have PCM and PCH), I can't
offer much help on the Device Editor. (Only what I can see on the
screen-shot).
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Tue Jul 25, 2006 3:48 pm     Reply with quote

OK. Well, it sure is a good thing there is this forum. I was about to loose hair a couple of hours ago. 8-0
Hopefully this project will go smoother from this point on. Thanks again guys/gals for all your help.
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
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