|
|
View previous topic :: View next topic |
Author |
Message |
ECACE
Joined: 24 Jul 2006 Posts: 94
|
Terrible time getting SPI to work w/16F872 |
Posted: Mon Jul 24, 2006 4:05 pm |
|
|
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
|
|
|
ECACE
Joined: 24 Jul 2006 Posts: 94
|
Getting a bit closer |
Posted: Tue Jul 25, 2006 12:23 pm |
|
|
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
|
|
Posted: Tue Jul 25, 2006 1:16 pm |
|
|
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
|
|
Posted: Tue Jul 25, 2006 2:20 pm |
|
|
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
|
|
Posted: Tue Jul 25, 2006 2:30 pm |
|
|
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
|
|
Posted: Tue Jul 25, 2006 3:48 pm |
|
|
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!!! |
|
|
|
|
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
|