//////////////////////////////////////////////////////////////////////////
//// DS1302.C ////
//// Driver for Real Time Clock ////
//// ////
//// rtc_init() Call after power up////
//// ////
//// rtc_set_datetime(day,mth,year,dow,hour,min) Set the date/time ////
//// ////
//// rtc_get_date(day,mth,year,dow) Get the date ////
//// ////
//// rtc_get_time(hr,min,sec) Get the time ////
//// ////
//// rtc_write_nvr(address,data) Write to NVR ////
//// ////
//// data = rtc_read_nvr(address) Read from NVR ////
//// ////
//// get_bcd(data) Convert data to BCD ////
//// ////
//// rm_bcd(data) Convert data to int ////
//// ////
//////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
//////////////////////////////////////////////////////////////////////////
#ifndef RTC_SCLK
#define RTC_SCLK PIN_E1
#define RTC_IO PIN_E0
#define RTC_RST PIN_E2
#endif
void write_ds1302_byte(BYTE cmd) {
BYTE i;
for(i=0;i<=7;++i) {
output_bit(RTC_IO, shift_right(&cmd,1,0) );
output_high(RTC_SCLK);
output_low(RTC_SCLK);
}
}
void write_ds1302(BYTE cmd, BYTE data) {
output_high(RTC_RST);
write_ds1302_byte(cmd);
write_ds1302_byte(data);
output_low(RTC_RST);
}
BYTE read_ds1302(BYTE cmd) {
BYTE i,data;
output_high(RTC_RST);
write_ds1302_byte(cmd);
input(RTC_IO);
delay_us(1);
for(i=0;i<=7;++i) {
shift_right(&data,1,input(RTC_IO));
output_high(RTC_SCLK);
delay_us(2);
output_low(RTC_SCLK);
delay_us(2);
}
output_low(RTC_RST);
return(data);
}
void rtc_init() {
BYTE x;
output_low(RTC_RST);
delay_us(2);
output_low(RTC_SCLK);
write_ds1302(0x8e,0);
write_ds1302(0x90,0xa4);
x=read_ds1302(0x81);
if((x & 0x80)!=0)
write_ds1302(0x80,0);
}
void rtc_set_datetime(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min) {
write_ds1302(0x86,day);
write_ds1302(0x88,mth);
write_ds1302(0x8c,year);
write_ds1302(0x8a,dow);
write_ds1302(0x84,hr);
write_ds1302(0x82,min);
write_ds1302(0x80,(0));
}
void rtc_get_date(BYTE& day, BYTE& mth, BYTE& year, BYTE& dow) {
day = read_ds1302(0x87);
mth = read_ds1302(0x89);
year = read_ds1302(0x8d);
dow = read_ds1302(0x8b);
}
void rtc_get_time(BYTE& hr, BYTE& min, BYTE& sec) {
hr = read_ds1302(0x85);
min = read_ds1302(0x83);
sec = read_ds1302(0x81);
}
void rtc_write_nvr(BYTE address, BYTE data) {
write_ds1302(address|0xc0,data);
}
BYTE rtc_read_nvr(BYTE address) {
return(read_ds1302(address|0xc1));
}//-----------------------------------------------------------------------------
void lcd_print_2num_bcd_lcd1(int num_bcd)
{
lcd_putc1((num_bcd >> 4) + 0x30); //DECENAS
lcd_putc1((num_bcd & 0x0F) + 0x30); //UNIDADES
}
//----------------------------------------------------------------------------- //PANTALLA DE CONFIGURACION
case 1:
switch (config_cursor_actual)
{
//CURSOR EN DIA DE LA SEMANA
case 0:
if (puls_up_fs && comprobar_datos_config())
{
if (++config_dia_actual == 8) config_dia_actual = 1;
}
if (puls_down_fs && comprobar_datos_config())
{
if (--config_dia_actual == 0) config_dia_actual = 7;
}
//-------------------------
break;
//CURSOR EN DECENAS HORA INICIO
case 1:
if (puls_up_fs)
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 1);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 1);
}
//-------------------------
break;
//CURSOR EN UNIDADES HORA INICIO
case 2:
if (puls_up_fs)
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
//-------------------------
break;
//CURSOR EN DECENAS MINUTOS INICIO
case 3:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_INC, 1))
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_DEC, 1))
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//CURSOR EN UNIDADES MINUTOS INICIO
case 4:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_INC, 0))
{
inc_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_inicio[config_dia_actual],
LIMIT_MINS_DEC, 0))
{
dec_2bcd(&config_hora_inicio[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//CURSOR EN DECENAS HORA FIN
case 5:
if (puls_up_fs)
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 1);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 1);
}
//-------------------------
break;
//CURSOR EN UNIDADES HORA FIN
case 6:
if (puls_up_fs)
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
if (puls_down_fs)
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
//-------------------------
break;
//CURSOR EN DECENAS MINUTOS FIN
case 7:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_INC, 1))
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_DEC, 1))
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//CURSOR EN UNIDADES MINUTOS FIN
case 8:
if (puls_up_fs){
if (inc_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_INC, 0))
{
inc_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_INC, 0);
}
}
if (puls_down_fs){
if (dec_2bcd(&config_minuto_fin[config_dia_actual],
LIMIT_MINS_DEC, 0))
{
dec_2bcd(&config_hora_fin[config_dia_actual],
LIMIT_HORAS_DEC, 0);
}
}
//-------------------------
break;
//PANTALLA DE CONFIGURACION
case 1:
//ENCABEZADO
lcd_gotoxy (1,1);
printf (lcd_putc1 "< PANTALLA PARA PROGRAMAR EL ENCENDIDO >");
//DIA
lcd_gotoxy(1,2);
printf(lcd_putc1,"Encender el ");
lcd_gotoxy(13,2);
lcd_print_nom_dia_sem(config_dia_actual);
lcd_gotoxy(16,2);
printf(lcd_putc1," de ");
//INICIO
lcd_gotoxy(20,2);
lcd_print_2num_bcd_lcd1(config_hora_inicio[config_dia_actual]);
lcd_gotoxy(22,2);
printf(lcd_putc1,":");
lcd_gotoxy(23,2);
lcd_print_2num_bcd_lcd1(config_minuto_inicio[config_dia_actual]);
lcd_gotoxy(25,2);
printf(lcd_putc1," a ");
//FIN
lcd_gotoxy(28,2);
lcd_print_2num_bcd_lcd1(config_hora_fin[config_dia_actual]);
lcd_gotoxy(30,2);
printf(lcd_putc1,":");
lcd_gotoxy(31,2);
lcd_print_2num_bcd_lcd1(config_minuto_fin[config_dia_actual]);
lcd_gotoxy(33,2);
printf(lcd_putc1," ");
break;//-----------------------------------------------------------------------------
short inc_2bcd(int* num_bcd, int bcd_limite = 0x9A, short digito = 0)
//Significado de los parametros:
// num_bcd: numero de 2 cifras en BCD que queremos incrementar
// bcd_limite: valor una vez incrementado el numero BCD que se considera que
// ha habido un desbordamiento, volviendo al valor 0. Los unicos
// valores no BCD aceptables son desde 0x9A hasta 0xA0 que
// equivalen a 100 BCD.
// digito: especifica si se ha de incrementar la cifra de las unidades(0)
// o la de las decenas (1)
//
//Devuelve 1 si desborda por el limite
{
switch (digito)
{
//Incrementar unidades
case 0:
*num_bcd +=1; //Unidades + 1
if ((*num_bcd & 0x0F) > 9) //Unidades > 9?
{
*num_bcd &= 0xF0; //Unidades = 0
*num_bcd += 0x10; //Decenas + 1
}
if (*num_bcd >= bcd_limite)//Desbordamiento?
{
*num_bcd = 0x00; //Numero BCD = 00
return 1; //Devolver desbordamiento
}
break;
//Incrementar decenas
case 1:
*num_bcd += 0x10; //Decenas + 1
if (*num_bcd >= bcd_limite)//Desbordamiento?
{
*num_bcd &= 0x0F; //Decenas = 0
return 1; //Devolver desbordamiento
}
break;
}
return 0;
}
//-----------------------------------------------------------------------------
short dec_2bcd(int* num_bcd, int bcd_limite = 0x99, short digito = 0)
//Significado de los parametros:
// num_bcd: numero de 2 cifras en BCD que queremos decrementar
// bcd_limite: valor que tomará el numero BCD si se ha llegado a numeros
// negativos (desbordamiento).
// digito: especifica si se ha de decrementar la cifra de las unidades(0)
// o la de las decenas (1)
//
//Devuelve 1 si desborda por debajo de 0
{
switch (digito)
{
//Decrementar unidades
case 0:
*num_bcd -= 1; //Unidades - 1
if (*num_bcd == 0xFF) //Desbordamiento?
{
*num_bcd = bcd_limite; //Numero BCD = limite
return 1; //Devolver desbordamiento
}
if ((*num_bcd & 0x0F) == 0x0F)//Desbordamiento de Unidades?
{ //Automaticamente -> Decenas - 1
*num_bcd &= 0xF9;//0b11111001;//Unidades = 9
}
break;
//Decrementar decenas
case 1:
*num_bcd -= 0x10; //Decenas - 1
if ((*num_bcd & 0xF0) == 0xF0)//Desbordamiento?
{
*num_bcd = (*num_bcd & 0x0F) | (bcd_limite & 0xF0); //Decenas = Decenas de limite
if (*num_bcd > bcd_limite){ //Al restaurar las decenas, el numBCD es > limite?
*num_bcd -= 0x10; //Decenas - 1
}
return 1; //Devolver desbordamiento
}
break;
}
return 0;
}//-----------------------------------------------------------------------------
short cargar_eeprom() //Devuelve 0 si todo correcto / 1 si ha ocurrido algun error
{
short temp_return;
int *array;
int i;
int checksum_calc, checksum_leido;
checksum_calc = 0x4A; //Valor de inicio de la suma de comprobación de errores.
for (i = 0; i < 4; i++){
switch(i)
{
case 0: array = &config_hora_inicio[0]; break;
case 1: array = &config_minuto_inicio[0]; break;
case 2: array = &config_hora_fin[0]; break;
case 3: array = &config_minuto_fin[0]; break;
}
for (temp = 0; temp < 7; temp++){
array[temp] = read_eeprom((i*7) + temp);
if (array[temp] > 0x59) temp_return = 1;
checksum_calc += array[temp];
}
}
//Comprobación de errores
checksum_leido = read_eeprom(0x1C /* =4*7 */);
if (checksum_calc != checksum_leido){
//Reset Data
for (temp = 0; temp < 7; temp++){
config_hora_inicio[temp] = config_minuto_inicio[temp] = 0x00;
config_hora_fin[temp] = config_minuto_fin[temp] = 0x00;
}
return 1;
}else return 0;
}
//-----------------------------------------------------------------------------
void guardar_eeprom()
{
int *array;
int i;
int checksum;
checksum = 0x4A; //Valor de inicio de la suma de comprobación de errores.
for (i = 0; i < 4; i++){
switch(i)
{
case 0: array = &config_hora_inicio[0]; break;
case 1: array = &config_minuto_inicio[0]; break;
case 2: array = &config_hora_fin[0]; break;
case 3: array = &config_minuto_fin[0]; break;
}
for (temp = 0; temp < 7; temp++){
write_eeprom((i*7) + temp, array[temp]);
checksum += array[temp];
}
}
write_eeprom((0x1C /* =4*7 */), checksum);
}
//-----------------------------------------------------------------------------;Nunca he hecho un codigo PWM para PIC, asi que por eso pdio ayuda.
aqui creo que es donde se podria hacer eso
setup_timer_2(T2_DIV_BY_16, 255, 1);
Si yo queiro que la subida de 0 a 100% (0 a 255) sean 5 segundos como deberia hacerlo?
#include <18F8722.h>
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=4000000)
void pwm();
int i,j,k;
//========================
void main()
{
setup_timer_2(T2_DIV_BY_16, 255, 1);
setup_ccp3(CCP_PWM);
setup_ccp4(CCP_PWM);
setup_ccp5(CCP_PWM);
WHILE(1){
//de 0 a 10 segundos
i=255;
j=0;
k=0;
set_pwm3_duty(i);
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(10000);
//de 10 a 20 segundos
j=0;
k=0;
set_pwm4_duty(j);
set_pwm5_duty(k);
for(i=255; i > 0; i--)
{
set_pwm3_duty(i);
delay_ms(39);// sale de -> (10segundos)-[(1/frecuencia reloj)*256 ciclos] /256 ciclos
}
//de 20 a 30 segundos
i=0;
set_pwm3_duty(0);
for(j=0; j< 255; j++)
{
set_pwm4_duty(j);
k=(j-178)*0.662338;
if(j<178)
{
k=0;
set_pwm5_duty(k);
}
else
set_pwm5_duty(k);
delay_ms(39);// sale de -> (10segundos)-[(1/frecuencia reloj)*256 ciclos] /256 ciclos
}
//de 30 a 40 segundos
i=0;
j=255;
k=51;
set_pwm3_duty(i);
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(10000);
//de 40 segundos a 43 segundos
i=0;
set_pwm3_duty(i);
for(j=255; j> 204; j--)
{
k=51+(255-j)*1.5098039;
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(58);// sale de -> (3segundos)-[(1/frecuencia reloj)*51 ciclos] /51 ciclos
}
//de 43 a 60 segundos
i=0;
j=204;
k=128;
set_pwm3_duty(i);
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(17000);
//de 60 a 63 segundos
i=0;
set_pwm3_duty(i);
for(j=204; j> 51; j--)
{
k=128+(204-j)*0.830065;
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(20);// sale de -> (3segundos)-[(1/frecuencia reloj)*153 ciclos] /153 ciclos
}
//de 63 a 97 segundos
i=0;
j=51;
k=255;
set_pwm3_duty(0);
set_pwm4_duty(51);
set_pwm5_duty(255);
delay_ms(34000);
// de 97 a 100 segundos
i=0;
set_pwm3_duty(i);
for(k=255; k> 128; k--)
{
j=51+(255-k)*1.204724;
set_pwm5_duty(k);
set_pwm4_duty(j);
delay_ms(24);// sale de -> (3segundos)-[(1/frecuencia reloj)*127 ciclos] /127 ciclos
}
//de 100 a 117 segundos
i=0;
j=204;
k=128;
set_pwm3_duty(i);
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(17000);
// de 117 a 120
i=0;
set_pwm3_duty(i);
for(k=128; k> 51; k--)
{
j=204+(128-k)*0.662338;
set_pwm5_duty(k);
set_pwm4_duty(j);
delay_ms(39);// sale de -> (3segundos)-[(1/frecuencia reloj)*77 ciclos] /77 ciclos
}
//de 120 a 130 segundos
i=0;
j=255;
k=51;
set_pwm3_duty(i);
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(10000);
// de 130 a 140
i=0;
set_pwm3_duty(i);
for(j=255; j> 0; j--)
{
k=51-(255-j)*0.662338;
set_pwm4_duty(j);
if(j>178)
set_pwm5_duty(k);
else
{
k=0;
set_pwm5_duty(k);
}
delay_ms(39);// sale de -> (10segundos)-[(1/frecuencia reloj)*256 ciclos] /256 ciclos
}
//de 140 a 150 segundos
j=0;
k=0;
set_pwm4_duty(j);
set_pwm5_duty(k);
for(i=0; i <255; i++)
{
set_pwm3_duty(i);
delay_ms(39);// sale de -> (10segundos)-[(1/frecuencia reloj)*256 ciclos] /256 ciclos
}
//de 150 a 160 segundos
i=255;
j=0;
k=0;
set_pwm3_duty(i);
set_pwm4_duty(j);
set_pwm5_duty(k);
delay_ms(10000);
}
}