|
|
View previous topic :: View next topic |
Author |
Message |
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
problem with DS1305 and PIC18F6722 |
Posted: Tue Feb 13, 2007 1:59 am |
|
|
Hi
I have a problem with communication between a PIC18F6722 and a DS1305 via the second SPI port. I am using compiler version 3.222 so I don't have access to ds1305.c nor to the standard fuction for the second SPI port.
I have already searched this forum and the internet for possible slutions but couldn't find a solution...
I think my clocksignal is wrong, because I have CKE on 1 and when I compare the datasheets I conclude CKE needs to be 0.
But when I put CKE on 0 the PIC stalls in the rtc_init() function.
When I put CKE on 1 the ossiclator from the RTC doesn't seem to work (not initialized I guess?)
I have a battery connected to the DS1305 and have a 6 MHz ossilator on my PIC.
I have 2 LEDs on pin G3 and pin G4.
here is the code I use:
Code: | #include <18F6722.h>
#device adc=8
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use delay(clock=6000000)
#use rs232(baud=9600, xmit=PIN_G1, rcv=PIN_G2, stream=USB)
//========================= DEFINES ============================================
#define CS_RTC PIN_E4
#byte SSP2BUF = 0xF66
#byte SSP2CON = 0xF63
#byte SSP2STAT = 0xF64
#byte TRISD = 0xF95
#bit TRISD4 = TRISD.4
#bit TRISD6 = TRISD.6
#bit TRISD7 = TRISD.7
#bit CKP = SSP2CON.4
#bit CKE = SSP2STAT.6
#bit SMP = SSP2STAT.7
#bit BF = SSP2STAT.0
//========================= GLOBALS ============================================
char c;
int sec, min, hour, day, date, month, year;
//========================= SPI METHODS ========================================
void spi2_send(char data)
{
char temp;
temp = SSP2BUF;
SSP2BUF = data;
while(!BF);
}
//========================= RTC METHODS ========================================
char rtc_receive_byte()
{
char data;
spi2_send(0);
delay_us(5);
data = SSP2BUF;
return data;
}
void rtc_init()
{
//setup SPI
SMP = 1;
CKE = 1;
CKP = 0;
delay_ms(20);
//start RTC
output_high(CS_RTC);
delay_us(10);
//set control register
spi2_send(0x8F);
spi2_send(0);
//stop RTC
delay_us(10);
output_low(CS_RTC);
}
void rtc_setTime(int newsec, int newmin, int newhour, int newday, int newdate,
int newmonth, int newyear)
//POST: sets RTC in 24-hour mode!
{
//setup SPI
SMP = 1;
CKE = 1;
CKP = 0;
delay_ms(20);
//start RTC
output_high(CS_RTC);
delay_us(10);
//read raw values
spi2_send(0x80);
spi2_send(newsec);
spi2_send(newmin);
spi2_send(newhour);
spi2_send(newday);
spi2_send(newdate);
spi2_send(newmonth);
spi2_send(newyear);
//stop RTC
delay_us(10);
output_low(CS_RTC);
}
void rtc_getTime()
//PRE: works only if RTC is in 24-hour mode!
{
//setup SPI
SMP = 1;
CKE = 1;
CKP = 0;
delay_ms(20);
//start RTC
output_high(CS_RTC);
delay_us(10);
//read raw values
spi2_send(0x00);
sec = rtc_receive_byte();
min = rtc_receive_byte();
hour = rtc_receive_byte();
date = rtc_receive_byte();
date = rtc_receive_byte();
month = rtc_receive_byte();
year = rtc_receive_byte();
//stop RTC
delay_us(10);
output_low(CS_RTC);
}
//========================== INIT ==============================================
void init()
{
output_low(CS_RTC);
TRISD4 = 0;
TRISD6 = 0;
TRISD7 = 1;
SSP2CON = 0b00100011;
fprintf(USB, "\n\rFirst Contact!\n\r\n\r");
setup_timer_2(T2_DIV_BY_16,250,16);
enable_interrupts(GLOBAL);
delay_ms(20);
output_high(PIN_G3);
rtc_init();
output_low(PIN_G3);
}
// ========================= MAIN ==============================================
void main()
{
init();
delay_ms(10);
//rtc_setTime(0,30,14,1,1,2,7); //set time to: 14:30:00 1-2-07
//fprintf(USB, "\n\rRTC clock set\n\r");
while(1)
{
output_high(PIN_G4);
delay_ms(1);
rtc_getTime();
output_low(PIN_G4);
delay_ms(1);
}
} |
If you can have a look at it and give me some hints it would be very appreciated.
Cheers,
Jos |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 13, 2007 12:34 pm |
|
|
The CCS file ds1305.c uses software SPI. You want to use hardware SPI.
If you own the compiler, you can email CCS support, give them your
CCS user number to prove that you own the compiler, and ask them
to email you the file. They'll probably do it.
For an example of a hardware SPI driver, just Google for "ds1305.c".
You'll find .c and .h files for download from Seattle Robotics. These
are for a different compiler, but they will give you a good example.
With regard to the SPI mode, read my post in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=29656
I explain how to determine the SPI mode and how to setup the CCS
compiler to use the correct mode. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Feb 13, 2007 1:18 pm |
|
|
The DS1305 works in both SPI-mode_0_1 and SPI-mode_1_1, this means:
CKE=0
CKP=don't care
SMP=0
There is also an error in your rtc_init(). On power up the Write Protect bit (WP) in the Control Register is undefined, this means you will have to write twice to this register; once for clearing the Write Protection bit, than a second time for the value you want to set. Code: | // Remove possible write protect (undefined on initial power-on.
// Can not write to other bits in this register when active, so those bits must be set later.
spi2_send(0x8F);
spi2_send(0);
//set control register
spi2_send(0x8F);
spi2_send(0);
|
|
|
|
Foppie
Joined: 16 Sep 2005 Posts: 138 Location: The Netherlands
|
|
Posted: Wed Feb 14, 2007 5:12 am |
|
|
Thanks for the help. I want to use the hardware SPI indeed so I'll try later to get my hands on a d21305.c file from CCS. I studied the example of Seattle Robotics and it indeed gave me a good example, but not the solution.
I have indeed overlooked the write protection bit, but I cannot clear it. My PIC stalls in the function that should read that byte. See the code below.
I have altered the clock so that it matches CKielstras discription.
Code: | #include <18F6722.h>
#device adc=8
#fuses HS, NOWDT, NOPROTECT, NOLVP
#use delay(clock=6000000)
#use rs232(baud=9600, xmit=PIN_G1, rcv=PIN_G2, stream=USB)
//========================= DEFINES ============================================
#define CS_FLASH PIN_E3
#define CS_RTC PIN_E4
#define CS_DAC PIN_E2
#byte SSP2BUF = 0xF66
#byte SSP2CON = 0xF63
#byte SSP2STAT = 0xF64
#byte TRISD = 0xF95
#bit TRISD4 = TRISD.4
#bit TRISD6 = TRISD.6
#bit TRISD7 = TRISD.7
#bit CKP = SSP2CON.4
#bit CKE = SSP2STAT.6
#bit SMP = SSP2STAT.7
#bit BF = SSP2STAT.0
#define RTCSMP 0
#define RTCCKE 0
#define RTCCKP 0
//========================= SPI METHODS ========================================
void spi2_send(char data)
{
char temp;
temp = SSP2BUF;
SSP2BUF = data;
while(!BF);
}
char spi2_receive()
{
char data;
spi2_send(0);
delay_us(5);
data = SSP2BUF;
return data;
}
//========================= RTC METHODS ========================================
void rtc_init()
{
int controlState;
//setup SPI
SMP = RTCSMP;
CKE = RTCCKE;
CKP = RTCCKP;
delay_ms(20);
//start RTC
output_high(CS_RTC);
delay_us(10);
//read control register
spi2_send(0x0F);
output_high(PIN_G4);
controlState = spi2_receive(); // <- HERE THE PIC STALLS
output_low(PIN_G4);
//stop RTC
delay_us(10);
output_low(CS_RTC);
//delay between transmissions
delay_ms(10);
//start RTC
output_high(CS_RTC);
delay_us(10);
//disable write protection
spi2_send(0x8F);
spi2_send(controlState & 0xBF);
//stop RTC
delay_us(10);
output_low(CS_RTC);
//delay between transmissions
delay_ms(10);
//start RTC
output_high(CS_RTC);
delay_us(10);
//set control register
spi2_send(0x8F);
spi2_send(0);
//stop RTC
delay_us(10);
output_low(CS_RTC);
}
void init()
{
output_high(CS_FLASH);
output_low(CS_RTC);
output_high(CS_DAC);
setup_adc_ports(AN0_TO_AN6|VSS_VREF);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);
TRISD4 = 0;
TRISD6 = 0;
TRISD7 = 1;
SSP2CON = 0b00100011;
setup_timer_2(T2_DIV_BY_16,250,16);
delay_ms(20);
rtc_init();
}
void main()
{
init();
delay_ms(10);
fprintf(USB, "\n\rRTC clock set\n\r");
while(1)
{
}
} |
Does anyone knows why my PIC stalls?
The PIC ceases to stall when CKE = 1, but as CKielstra said, that is not the correct setting for this device...
Cheers,
Jos |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 14, 2007 12:43 pm |
|
|
You're trying to do two things at one time.
1. You're trying to create your own routines to support the 2nd hardware
SPI module, presumably because you have an older version of the
compiler, which lacks support for the 2nd module.
2. You're trying to create a hardware SPI driver for the DS1305.
My advice would be to do one thing at a time. First make a hardware
SPI driver for the DS1305 that runs on the first SPI module, and use
the built-in CCS functions to do this.
Also, when you write your routines for the 2nd SPI module, you should
look at the ASM code in the .LST file that CCS generates for the 1st SPI
module. Use that code as a guide in writing your own routines.
You could just convert it to C and change the register addresses.
That would be the safest method. |
|
|
|
|
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
|