|
|
View previous topic :: View next topic |
Author |
Message |
HGHK
Joined: 29 Jun 2010 Posts: 33
|
problem with sleep and wake up PIC16F876A |
Posted: Wed Oct 13, 2010 3:38 pm |
|
|
I use PIC16F876A and PCF8563 for RTC. PCF8563 make an external interrupt for alarm. For testing I connect a LED to RA3 by resistor to indicate state of test program. It must be turn on 3 time to sleep but it turn 6 or 7 time after any reset. I use ccs pcwhd compiler ver. 4.084.
I send source here. Please help me!
debug.c:
Code: | #include "C:\Documents and Settings\HGhK\Desktop\CRP\temp project\debprg.h"
#include "C:\Documents and Settings\HGhK\Desktop\CRP\temp project\PCF8583.c"
// command set definition
#define Test_Temperature 0x00
#define Read_Temperature_Limits 0x01
#define Set_Temperature_Limits 0x03
#define Read_Time_And_Report 0x07
#define Set_Time_from_Recive 0x0F
#define Read_Sleep_Period 0x1F
#define Set_Sleep_Period 0x3F
#define Reset_Temp_counter 0x7F
#define Controler_Connected 0xFF
#define Report_Temp_counter 0xFE
// -------------------------------------------------
// EEPROM Data Address
#define Temperature_In_Reng_Count 0x01
#define Hi_Temperature_Limit 0x04
#define Lo_Temperature_Limit 0x06
#define Period_Time_reg 0x09
#define Time_Period_defult 2
// -------------------------------------------------
date_time_t Time,*t;
PCF8563_Alarm AlarmTime,*ALT;
float Temprature;
int8 counter=0,command=0x00,Time_Period=Time_Period_defult;
signed int8 Lo_limit_Temp,Hi_limit_Temp;
int8 cnt;
#int_EXT
void EXT_isr(void)
{
command = Test_Temperature;
}
// #include "C:\Documents and Settings\HGhK\Desktop\CRP\temp project\functions.c"
void main()
{
Time=&t;
AlarmTime=&ALT;
enable_interrupts(INT_EXT);ext_int_edge(H_TO_L);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
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);
disable_interrupts(INT_RB);
enable_interrupts(INT_EXT);ext_int_edge(H_TO_L);
disable_interrupts(INT_AD);
disable_interrupts(INT_TBE);
disable_interrupts(INT_RDA);
disable_interrupts(INT_SSP);
disable_interrupts(INT_EEPROM);
enable_interrupts(GLOBAL);
// TODO: USER CODE!!
PCF8563_init();
Time.day = 1;
Time.hours = 1;
Time.minutes = 1;
Time.month = 1;
Time.seconds = 1;
Time.weekday = 1;
Time.year = 1;
PCF8563_set_datetime(*t);
set_tris_a (0x01);
output_high(PIN_A3); // *
delay_ms( 1000 );
output_low(PIN_A3);
delay_ms( 1000 );
while(1){
PCF8563_read_datetime(*t);
output_high(PIN_A3); // *
delay_ms( 1000 );
Time.minutes = Time.minutes + Time_Period_defult;
if ( Time.minutes > 59 ){ Time.hours++;Time.minutes=Time.minutes-60;}
if ( Time.hours > 23 ){ Time.hours = Time.hours - 24 ; }
AlarmTime.minutes = Time.minutes ;
AlarmTime.hours = Time.hours ;
Set_Alarm(PCF8563_MH_Mode,ALT);
config_PCF8563_Interrupt(Alarm_Interrupt_Enable,Timer_INT_Pulse_off);
enable_interrupts(GLOBAL);
output_low(PIN_A3);
delay_ms( 10 );
output_high(PIN_A3); // *
delay_ms( 1000 );
output_low(PIN_A3);
delay_ms( 1000 );
enable_interrupts(GLOBAL);
sleep();
output_high(PIN_A3); // *
delay_ms( 10 );
output_low(PIN_A3);
}
} |
debug.h:
Code: | #include <16F876A.h>
#device ICD=TRUE
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES LP //Low power osc < 200 khz
#FUSES NOPUT //No 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=32768)
#use rs232(baud=256,parity=O,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,Slow=100000,sda=PIN_C4,scl=PIN_C3,force_hw)
|
pcf8563:
Code: | // PCF8563.C
// Command Set:
// PCF8563_init(void)
// PCF8563_write_byte(int8 address, int8 data)
// PCF8563_read_byte(int8 address)
// bin2bcd(int8 value)
// bcd2bin(char bcd_value)
// PCF8563_set_datetime(date_time_t *dt)
// PCF8563_read_datetime(date_time_t *dt)
// Set_Alarm(int8 AMode,PCF8563_Alarm *AT)
// config_CLKOUT()
// config_PCF8563_Timer()
// config_PCF8563_Interrupt()
#ifndef PCF8563_SDA
#define PCF8563_SDA PIN_C4
#define PCF8563_SCL PIN_C3
#endif
#use i2c(master, sda=PCF8563_SDA, scl=PCF8563_SCL)
#ifndef PCF8563_WRITE_ADDRESS
#define PCF8563_WRITE_ADDRESS 0xA2
#define PCF8563_READ_ADDRESS 0xA3
#endif
// Register addresses
#define PCF8563_CTRL_STATUS_REG1 0x00
#define PCF8563_CTRL_STATUS_REG2 0x01
#define PCF8563_SECONDS_REG 0x02
#define PCF8563_MINUTES_REG 0x03
#define PCF8563_HOURS_REG 0x04
#define PCF8563_DAY_REG 0x05
#define PCF8563_WEEK_REG 0x06
#define PCF8563_MONTH_REG 0x07
#define PCF8563_YEAR_REG 0x08
#define PCF8563_ALARM_MINS_REG 0x09
#define PCF8563_ALARM_HOURS_REG 0x0A
#define PCF8563_ALARM_DAY_REG 0x0B
#define PCF8563_ALARM_WEEKDAY_REG 0x0C
#define PCF8563_CTRL_CLKOUT_REG 0x0D
#define PCF8563_CTRL_TIMER_REG 0x0E
#define PCF8563_TIMER_REG 0x0F
int8 CTRL_STATUS_REG1,CTRL_STATUS_REG2,LV_sec,MINUTES_REG;
int8 HOURS_REG,DAY_REG,WEEK_REG,C_Mon,YEAR_REG;
int8 CTRL_TIMER_REG,TIMER_REG,CTRL_CLKOUT_REG;
#bit LowVoltage = LV_sec.7
#bit Century = C_Mon.7
#define bcd_min MINUTES_REG
#define bcd_hrs HOURS_REG
#define bcd_day DAY_REG
#define bcd_yer YEAR_REG
#define wek WEEK_REG
// Commands for the Control/Status register.
#define PCF8563_START_COUNTING 0x08
#define PCF8563_STOP_COUNTING 0x28
//************************************* for Set_Alarm()
#define PCF8563_Alarm_off 0x00
#define PCF8563_M_Mode 0x01
#define PCF8563_MH_Mode 0x04
#define PCF8563_MHW_Mode 0x07
#define PCF8563_MHD_Mode 0x0B
//************************************* for config_CLKOUT()
#define PCF8563_CLKOUT_off 0x00
#define PCF8563_CLKOUT_32KHz 0x80
#define PCF8563_CLKOUT_1KHz 0x81
#define PCF8563_CLKOUT_32Hz 0x82
#define PCF8563_CLKOUT_1Hz 0x83
//************************************* for config_PCF8563_Timer()
#define PCF8563_Timer_off 0x00
#define PCF8563_Timer_4KHz 0x80
#define PCF8563_Timer_64Hz 0x81
#define PCF8563_Timer_1Hz 0x82
#define PCF8563_Timer_1_60Hz 0x83
//************************************* for config_PCF8563_Interrupt()
#define Alarm_Interrupt_Enable 0x01
#define Timer_Interrupt_Enable 0x02
#define A_T_Interrupt_Enable 0x03
#define Timer_INT_Pulse_on 0x10
#define Timer_INT_Pulse_off 0x00
char const weekday_names[7][10] =
{
{"Sunday"},
{"Monday"},
{"Tuesday"},
{"Wednesday"},
{"Thursday"},
{"Friday"},
{"Saturday"}
};
// This structure defines the user's date and time data.
// The values are stored as unsigned integers. The user
// should declare a structure of this type in the application
// program. Then the address of the structure should be
// passed to the PCF8563 read/write functions in this
// driver, whenever you want to talk to the chip.
typedef struct
{
int8 seconds; // 0 to 59
int8 minutes; // 0 to 59
int8 hours; // 0 to 23 (24-hour time)
int8 day; // 1 to 31
int8 weekday; // 0 = Sunday, 1 = Monday, etc.
int8 month; // 1 to 12
int8 year; // 00 to 99
}date_time_t;
typedef struct
{
int8 minutes; // 0 to 59
int8 hours; // 0 to 23 (24-hour time)
int8 day; // 1 to 31
int8 weekday; // 0 = Sunday, 1 = Monday, etc.
}PCF8563_Alarm;
//----------------------------------------------
void PCF8563_write_byte(int8 address, int8 data)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(address);
i2c_write(data);
i2c_stop();
enable_interrupts(GLOBAL);
}
//----------------------------------------------
int8 PCF8563_read_byte(int8 address)
{
int8 retval;
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(address);
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
retval = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
return(retval);
}
//----------------------------------------------
// PCF8563 Initial // //
void PCF8563_init(void)
{
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_START_COUNTING);
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
CTRL_STATUS_REG1 = i2c_read();
CTRL_STATUS_REG2 = i2c_read();
LV_sec = i2c_read();
MINUTES_REG = i2c_read();
HOURS_REG = i2c_read();
DAY_REG = i2c_read();
WEEK_REG = i2c_read();
C_Mon = i2c_read();
YEAR_REG = i2c_read();
i2c_read();
i2c_read();
i2c_read();
i2c_read();
CTRL_CLKOUT_REG = i2c_read();
CTRL_TIMER_REG = i2c_read();
TIMER_REG = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
}
//----------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.
int8 bin2bcd(int8 value)
{
char retval;
retval = 0;
while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(value >= 10)
{
value -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += value;
break;
}
}
return(retval);
}
//----------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.
char bcd2bin(char bcd_value)
{
char temp;
temp = bcd_value;
// Shifting the upper digit right by 1 is
// the same as multiplying it by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;
// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
//----------------------------------------------
//----------------------------------------------
void PCF8563_set_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_mon;
// Convert the input date/time into BCD values
// that are formatted for the PCF8563 registers.
bcd_sec = bin2bcd(dt->seconds);
bcd_min = bin2bcd(dt->minutes);
bcd_hrs = bin2bcd(dt->hours);
bcd_day = bin2bcd(dt->day) | (dt->year << 6);
bcd_mon = bin2bcd(dt->month) | (dt->weekday << 5);
bcd_yer = bin2bcd(dt->year);
wek = dt->weekday;
// Stop the RTC from counting, before we write to
// the date and time registers.
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_STOP_COUNTING);
// Write to the date and time registers. Disable interrupts
// so they can't disrupt the i2c operations.
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_SECONDS_REG); // Start at seconds reg.
i2c_write(bcd_sec);
i2c_write(bcd_min);
i2c_write(bcd_hrs);
i2c_write(bcd_day);
i2c_write(wek);
i2c_write(bcd_mon);
i2c_write(bcd_yer);
i2c_stop();
enable_interrupts(GLOBAL);
// Now allow the PCF8563 to start counting again.
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_START_COUNTING);
}
//----------------------------------------------
//----------------------------------------------
// Read the Date and Time from the hardware registers
// in the PCF8563. We don't have to disable counting
// during read operations, because according to the data
// sheet, if any of the lower registers (1 to 7) is read,
// all of them are loaded into "capture" registers.
// All further reading within that cycle is done from
// those registers.
void PCF8563_read_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 wek;
int8 bcd_mon;
int8 bcd_yer;
// LowVoltage = VL_sec.7
// Century = C_Mon.7
// Disable interrupts so the i2c process is not disrupted.
disable_interrupts(GLOBAL);
// Read the date/time registers inside the PCF8563.
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_SECONDS_REG); // Start at seconds reg.
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
LV_sec = i2c_read();
bcd_min = i2c_read();
bcd_hrs = i2c_read();
bcd_day = i2c_read();
wek = i2c_read();
C_Mon = i2c_read();
bcd_yer = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
// Convert the date/time values from BCD to
// unsigned 8-bit integers. Unpack the bits
// in the PCF8563 registers where required.
bcd_sec = LV_sec & 0x7F;
bcd_mon = C_Mon & 0x7F;
dt->seconds = bcd2bin(bcd_sec);
dt->minutes = bcd2bin(bcd_min);
dt->hours = bcd2bin(bcd_hrs & 0x3F);
dt->day = bcd2bin(bcd_day & 0x3F);
dt->month = bcd2bin(bcd_mon & 0x1F);
dt->weekday = wek & 0x07;
dt->year = bcd2bin(bcd_yer);
}
//----------------------------------------------
void Set_Alarm(int8 AMode)
{
if (AMode == 0x00)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_ALARM_MINS_REG); // Start at alarm min reg.
i2c_write(0x80);
i2c_write(0x80);
i2c_write(0x80);
i2c_write(0x80);
i2c_stop();
enable_interrupts(GLOBAL);
}
}
void Set_Alarm(int8 AMode,PCF8563_Alarm *AT)
{
int8 min = 0x80;
int8 hrs = 0x80;
int8 day = 0x80;
int8 wek = 0x80;
switch (AMode){
case 0x01: min = bin2bcd(AT->minutes);
break;
case 0x04: min = bin2bcd(AT->minutes);
hrs = bin2bcd(AT->hours);
break;
case 0x07: min = bin2bcd(AT->minutes);
hrs = bin2bcd(AT->hours);
wek = AT->weekday;
break;
case 0x0B: min = bin2bcd(AT->minutes);
hrs = bin2bcd(AT->hours);
day = bin2bcd(AT->day);
break;
}
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_ALARM_MINS_REG); // Start at alarm min reg.
i2c_write(min);
i2c_write(hrs);
i2c_write(day);
i2c_write(wek);
i2c_stop();
enable_interrupts(GLOBAL);
}
//----------------------------------------------
void config_CLKOUT(int8 mode)
{
PCF8563_write_byte(PCF8563_CTRL_CLKOUT_REG, mode);
}
//----------------------------------------------
void config_PCF8563_Timer(int8 mode)
{
PCF8563_write_byte(PCF8563_CTRL_TIMER_REG, mode);
}
//----------------------------------------------
void config_PCF8563_Interrupt(int8 mode,ti_tp)
{
mode = mode | ti_tp;
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG2, mode);
}
//----------------------------------------------
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 14, 2010 1:24 pm |
|
|
Quote: |
void main()
{
Time=&t;
AlarmTime=&ALT;
|
These two lines are the opposite of what you want. You created an
instance of a structure. You also created a pointer to the structure.
You should initialize the pointer so it points to the structure. But you're
doing the opposite of that above (in both lines).
Quote: | #use delay(clock=32768)
#use i2c(Master,Slow=100000,sda=PIN_C4,scl=PIN_C3,force_hw) |
This part here is incredibly wishful thinking. If your PIC's oscillator is
only 32.768 KHz, how can your hardware i2c baud rate generator
(which runs from Fosc/4 = 8192 Hz) ever be 100 KHz ?
Are you using a Low Voltage programmer ? These are only available
as home-built hobby projects, such as the TLVP programmer.
99.9 % of all PIC users don't use LVP mode. They use ICD2, PicStart-
Plus, ICD-U40, PicKit 2 or 3, etc. All of these are High Voltage
programmers. They require NOLVP as the fuse.
Quote: | // PCF8563.C
#ifndef PCF8563_SDA
#define PCF8563_SDA PIN_C4
#define PCF8563_SCL PIN_C3
#endif
#use i2c(master, sda=PCF8563_SDA, scl=PCF8563_SCL) |
Here you have a 2nd instance of #use i2c(), at the top of the pcf8563
driver file. This line (not the first one with Force_hw) is actually used for
the pcf8583.c file. In CCS, the latest #use i2c() statement in the file
is in control, and all lines in the file that come after it will be compiled for
the parameters given in that #use i2c() line. |
|
|
HGHK
Joined: 29 Jun 2010 Posts: 33
|
I2C in Lower speed than standard |
Posted: Sat Oct 16, 2010 5:06 am |
|
|
Dear PCM programmer, thanks for your attention.
Now, do you know, can I use I2C in 8192Hz speed? and if it possible I must set SSPADD as 00H. How can I do it? How can write to this register?
Is it true if I write : Code: | #use i2c(Master,Slow=8190,sda=PIN_C4,scl=PIN_C3,force_hw)
|
I Use ICD2 for programming. but it can't run in debug mode and failed, help me please.
For that pointer I must write:
Code: |
*t=Time;
*ALT=AlarmTime;
| is it true? |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
Re: I2C in Lower speed than standard |
Posted: Sat Oct 16, 2010 7:57 am |
|
|
HGHK wrote: | Dear PCM programmer, thanks for your attention.
Now,do you know, can I use I2C in 8192Hz speed? and if it possible I must set SSPADD as 00H. how can I do it? How can write to this register?
Is it true if I write : Code: | #use i2c(Master,Slow=8190,sda=PIN_C4,scl=PIN_C3,force_hw)
|
|
The SSPADD is only useful in SLAVE mode. Not master.
(EDIT: Allow me to better qualify that "usefullness" concept in master mode. In Master mode, the SSPADD holds the I2C bit rate, so unless you're fiddling with it regularly, there's no reason to be editing it in master mode. I have an app that changes the speed of the CPU around, so I need to adjust any speeds based off Fosc. Unless you're doing that, SSPADD is sort of set once and forget in Master mode. At least in my experience. The datasheet says:
SSPADD register holds the slave device address when
the SSP is configured in I2C Slave mode. When the
SSP is configured in Master mode, the lower seven bits
of SSPADD act as the Baud Rate Generator reload
value. )
Is your PIC supposed to be a slave or master I2C device?
Quote: |
I Use ICD2 for programming. but it can't run in debug mode and failed |
Then something else is wrong. change LVP to NOLVP and post your ICSP circuit for us. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 16, 2010 4:09 pm |
|
|
To see the value that the compiler is loading into the SSPADD register,
go to the Project / Build Options menu in MPLAB. Then go to the tab for
the CCS compiler. Then in the List File section, select "Symbolic Format".
Now re-compile the program and look at the .LST file. It's in the project
directory after you successfully compile the program. Look for the
line where the SSPADD register is loaded.
If it's loading a number into SSPADD, the number will be "xx" (in hex)
and the code will look like this:
Code: | MOVLW xx
MOVWF SSPADD
|
or if it's setting the SSPADD register to 0x00, the code will look like this:
|
|
|
HGHK
Joined: 29 Jun 2010 Posts: 33
|
correction aplied but not worked |
Posted: Sat Oct 16, 2010 4:25 pm |
|
|
I correct my program as :
test1.c: Code: | #include "C:\Documents and Settings\HGhK\Desktop\CRP\temp project\test1.h"
#include "C:\Documents and Settings\HGhK\Desktop\CRP\temp project\PCF8583.c"
#define Time_Period_defult 2
date_time_t Time,*t;
PCF8563_Alarm AlarmTime,*ALT;
int8 SSPADD,counter=0,command=0x00,Time_Period=Time_Period_defult;
#locate SSPADD=0x93
#int_EXT
void EXT_isr(void)
{
}
void main()
{
SSPADD=0x00;
t=&Time;
ALT=&AlarmTime;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
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);
enable_interrupts(INT_EXT);ext_int_edge(H_TO_L);
enable_interrupts(GLOBAL);
set_tris_a (0x08);
PCF8563_init();
Time.day = 1;
Time.hours = 1;
Time.minutes = 1;
Time.month = 1;
Time.seconds = 1;
Time.weekday = 1;
Time.year = 1;
PCF8563_set_datetime(*t);
output_high(PIN_A3); // *
delay_ms( 1000 );
output_low(PIN_A3);
delay_ms( 1000 );
while(1){
PCF8563_read_datetime(*t);
Time.minutes = Time.minutes + Time_Period_defult;
Set_Alarm(PCF8563_M_Mode,*ALT);
config_PCF8563_Interrupt(Alarm_Interrupt_Enable,Timer_INT_Pulse_off);
enable_interrupts(GLOBAL);
output_high(PIN_A3); // *
delay_ms( 1000 );
output_low(PIN_A3);
delay_ms( 1000 );
sleep();
delay_ms( 200 );
config_PCF8563_Interrupt(Alarm_Interrupt_Enable,Timer_INT_Pulse_off);
clear_interrupt(INT_EXT);
}
} |
and test1.h: Code: | #include <16F876A.h>
#device ICD=TRUE
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES LP //Low power osc < 200 khz
#FUSES NOPUT //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 prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=32768)
#define I2C_SCL PIN_C3
#define I2C_SDA PIN_C4
#use rs232(baud=256,parity=O,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,Slow=8192,sda=PIN_C4,scl=PIN_C3,force_hw) |
and PCF8563.c : Code: | #ifndef PCF8563_WRITE_ADDRESS
#define PCF8563_WRITE_ADDRESS 0xA2
#define PCF8563_READ_ADDRESS 0xA3
#endif
// Register addresses
#define PCF8563_CTRL_STATUS_REG1 0x00
#define PCF8563_CTRL_STATUS_REG2 0x01
#define PCF8563_SECONDS_REG 0x02
#define PCF8563_MINUTES_REG 0x03
#define PCF8563_HOURS_REG 0x04
#define PCF8563_DAY_REG 0x05
#define PCF8563_WEEK_REG 0x06
#define PCF8563_MONTH_REG 0x07
#define PCF8563_YEAR_REG 0x08
#define PCF8563_ALARM_MINS_REG 0x09
#define PCF8563_ALARM_HOURS_REG 0x0A
#define PCF8563_ALARM_DAY_REG 0x0B
#define PCF8563_ALARM_WEEKDAY_REG 0x0C
#define PCF8563_CTRL_CLKOUT_REG 0x0D
#define PCF8563_CTRL_TIMER_REG 0x0E
#define PCF8563_TIMER_REG 0x0F
int8 CTRL_STATUS_REG1,CTRL_STATUS_REG2,LV_sec,MINUTES_REG;
int8 HOURS_REG,DAY_REG,WEEK_REG,C_Mon,YEAR_REG;
int8 CTRL_TIMER_REG,TIMER_REG,CTRL_CLKOUT_REG;
#bit LowVoltage = LV_sec.7
#bit Century = C_Mon.7
#define bcd_min MINUTES_REG
#define bcd_hrs HOURS_REG
#define bcd_day DAY_REG
#define bcd_yer YEAR_REG
#define wek WEEK_REG
// Commands for the Control/Status register.
#define PCF8563_START_COUNTING 0x08
#define PCF8563_STOP_COUNTING 0x28
//************************************* for Set_Alarm()
#define PCF8563_Alarm_off 0x00
#define PCF8563_M_Mode 0x01
#define PCF8563_MH_Mode 0x04
#define PCF8563_MHW_Mode 0x07
#define PCF8563_MHD_Mode 0x0B
//************************************* for config_CLKOUT()
#define PCF8563_CLKOUT_off 0x00
#define PCF8563_CLKOUT_32KHz 0x80
#define PCF8563_CLKOUT_1KHz 0x81
#define PCF8563_CLKOUT_32Hz 0x82
#define PCF8563_CLKOUT_1Hz 0x83
//************************************* for config_PCF8563_Timer()
#define PCF8563_Timer_off 0x00
#define PCF8563_Timer_4KHz 0x80
#define PCF8563_Timer_64Hz 0x81
#define PCF8563_Timer_1Hz 0x82
#define PCF8563_Timer_1_60Hz 0x83
//************************************* for config_PCF8563_Interrupt()
#define Alarm_Interrupt_Enable 0x01
#define Timer_Interrupt_Enable 0x02
#define A_T_Interrupt_Enable 0x03
#define Timer_INT_Pulse_on 0x10
#define Timer_INT_Pulse_off 0x00
char const weekday_names[7][10] =
{
{"Sunday"},
{"Monday"},
{"Tuesday"},
{"Wednesday"},
{"Thursday"},
{"Friday"},
{"Saturday"}
};
// This structure defines the user's date and time data.
// The values are stored as unsigned integers. The user
// should declare a structure of this type in the application
// program. Then the address of the structure should be
// passed to the PCF8563 read/write functions in this
// driver, whenever you want to talk to the chip.
typedef struct
{
int8 seconds; // 0 to 59
int8 minutes; // 0 to 59
int8 hours; // 0 to 23 (24-hour time)
int8 day; // 1 to 31
int8 weekday; // 0 = Sunday, 1 = Monday, etc.
int8 month; // 1 to 12
int8 year; // 00 to 99
}date_time_t;
typedef struct
{
int8 minutes; // 0 to 59
int8 hours; // 0 to 23 (24-hour time)
int8 day; // 1 to 31
int8 weekday; // 0 = Sunday, 1 = Monday, etc.
}PCF8563_Alarm;
//----------------------------------------------
void PCF8563_write_byte(int8 address, int8 data)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(address);
i2c_write(data);
i2c_stop();
enable_interrupts(GLOBAL);
}
//----------------------------------------------
int8 PCF8563_read_byte(int8 address)
{
int8 retval;
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(address);
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
retval = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
return(retval);
}
//----------------------------------------------
// PCF8563 Initial // //
void PCF8563_init(void)
{
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_START_COUNTING);
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
CTRL_STATUS_REG1 = i2c_read();
CTRL_STATUS_REG2 = i2c_read();
LV_sec = i2c_read();
MINUTES_REG = i2c_read();
HOURS_REG = i2c_read();
DAY_REG = i2c_read();
WEEK_REG = i2c_read();
C_Mon = i2c_read();
YEAR_REG = i2c_read();
i2c_read();
i2c_read();
i2c_read();
i2c_read();
CTRL_CLKOUT_REG = i2c_read();
CTRL_TIMER_REG = i2c_read();
TIMER_REG = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
}
//----------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.
int8 bin2bcd(int8 value)
{
char retval;
retval = 0;
while(1)
{
// Get the tens digit by doing multiple subtraction
// of 10 from the binary value.
if(value >= 10)
{
value -= 10;
retval += 0x10;
}
else // Get the ones digit by adding the remainder.
{
retval += value;
break;
}
}
return(retval);
}
//----------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.
char bcd2bin(char bcd_value)
{
char temp;
temp = bcd_value;
// Shifting the upper digit right by 1 is
// the same as multiplying it by 8.
temp >>= 1;
// Isolate the bits for the upper digit.
temp &= 0x78;
// Now return: (Tens * 8) + (Tens * 2) + Ones
return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
//----------------------------------------------
//----------------------------------------------
void PCF8563_set_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_mon;
// Convert the input date/time into BCD values
// that are formatted for the PCF8563 registers.
bcd_sec = bin2bcd(dt->seconds);
bcd_min = bin2bcd(dt->minutes);
bcd_hrs = bin2bcd(dt->hours);
bcd_day = bin2bcd(dt->day) | (dt->year << 6);
bcd_mon = bin2bcd(dt->month) | (dt->weekday << 5);
bcd_yer = bin2bcd(dt->year);
wek = dt->weekday;
// Stop the RTC from counting, before we write to
// the date and time registers.
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_STOP_COUNTING);
// Write to the date and time registers. Disable interrupts
// so they can't disrupt the i2c operations.
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_SECONDS_REG); // Start at seconds reg.
i2c_write(bcd_sec);
i2c_write(bcd_min);
i2c_write(bcd_hrs);
i2c_write(bcd_day);
i2c_write(wek);
i2c_write(bcd_mon);
i2c_write(bcd_yer);
i2c_stop();
enable_interrupts(GLOBAL);
// Now allow the PCF8563 to start counting again.
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG1,PCF8563_START_COUNTING);
}
//----------------------------------------------
//----------------------------------------------
// Read the Date and Time from the hardware registers
// in the PCF8563. We don't have to disable counting
// during read operations, because according to the data
// sheet, if any of the lower registers (1 to 7) is read,
// all of them are loaded into "capture" registers.
// All further reading within that cycle is done from
// those registers.
void PCF8563_read_datetime(date_time_t *dt)
{
int8 bcd_sec;
int8 bcd_min;
int8 bcd_hrs;
int8 bcd_day;
int8 wek;
int8 bcd_mon;
int8 bcd_yer;
// LowVoltage = VL_sec.7
// Century = C_Mon.7
// Disable interrupts so the i2c process is not disrupted.
disable_interrupts(GLOBAL);
// Read the date/time registers inside the PCF8563.
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_SECONDS_REG); // Start at seconds reg.
i2c_start();
i2c_write(PCF8563_READ_ADDRESS);
LV_sec = i2c_read();
bcd_min = i2c_read();
bcd_hrs = i2c_read();
bcd_day = i2c_read();
wek = i2c_read();
C_Mon = i2c_read();
bcd_yer = i2c_read(0);
i2c_stop();
enable_interrupts(GLOBAL);
// Convert the date/time values from BCD to
// unsigned 8-bit integers. Unpack the bits
// in the PCF8563 registers where required.
bcd_sec = LV_sec & 0x7F;
bcd_mon = C_Mon & 0x7F;
dt->seconds = bcd2bin(bcd_sec);
dt->minutes = bcd2bin(bcd_min);
dt->hours = bcd2bin(bcd_hrs & 0x3F);
dt->day = bcd2bin(bcd_day & 0x3F);
dt->month = bcd2bin(bcd_mon & 0x1F);
dt->weekday = wek & 0x07;
dt->year = bcd2bin(bcd_yer);
}
//----------------------------------------------
void Set_Alarm(int8 AMode)
{
if (AMode == 0x00)
{
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_ALARM_MINS_REG); // Start at alarm min reg.
i2c_write(0x80);
i2c_write(0x80);
i2c_write(0x80);
i2c_write(0x80);
i2c_stop();
enable_interrupts(GLOBAL);
}
}
void Set_Alarm(int8 AMode,PCF8563_Alarm *AT)
{
int8 min = 0x80;
int8 hrs = 0x80;
int8 day = 0x80;
int8 wek = 0x80;
switch (AMode){
case 0x01: min = bin2bcd(AT->minutes);
break;
case 0x04: min = bin2bcd(AT->minutes);
hrs = bin2bcd(AT->hours);
break;
case 0x07: min = bin2bcd(AT->minutes);
hrs = bin2bcd(AT->hours);
wek = AT->weekday;
break;
case 0x0B: min = bin2bcd(AT->minutes);
hrs = bin2bcd(AT->hours);
day = bin2bcd(AT->day);
break;
}
disable_interrupts(GLOBAL);
i2c_start();
i2c_write(PCF8563_WRITE_ADDRESS);
i2c_write(PCF8563_ALARM_MINS_REG); // Start at alarm min reg.
i2c_write(min);
i2c_write(hrs);
i2c_write(day);
i2c_write(wek);
i2c_stop();
enable_interrupts(GLOBAL);
}
//----------------------------------------------
void config_CLKOUT(int8 mode)
{
PCF8563_write_byte(PCF8563_CTRL_CLKOUT_REG, mode);
}
//----------------------------------------------
void config_PCF8563_Timer(int8 mode)
{
PCF8563_write_byte(PCF8563_CTRL_TIMER_REG, mode);
}
//----------------------------------------------
void config_PCF8563_Interrupt(int8 mode,ti_tp)
{
mode = mode | ti_tp;
PCF8563_write_byte(PCF8563_CTRL_STATUS_REG2, mode);
}
//----------------------------------------------
|
It not work.
LED that connected to RA3 turn on 6 or 7 time and then not work!
When I use debug in ICD, error ICD0083, ICD0069 are happened. I connect VPP by Pull up resistor and Vdd, GND and PGD, PGC directly to corresponding pin.
Please Help me! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 16, 2010 4:42 pm |
|
|
I don't want to fix your ICD2 problem. Post a question on the Microchip
ICD2 forum, or search their forum archives for the answer. Here is the link:
http://www.microchip.com/forums/f49.aspx |
|
|
HGHK
Joined: 29 Jun 2010 Posts: 33
|
I need help in my code |
Posted: Sat Oct 16, 2010 11:31 pm |
|
|
Dear PCM programmer,
I need your help in my program Not to ICD2 and i say it for Know and my uC programed successfully and run with out debugging.
for example is this method true?:
Code: | int8 SSPADD;
#locate SSPADD=0x93 | and then in main Program
Thanks! |
|
|
|
|
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
|