Autor Tema: Setear bit específico  (Leído 3314 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Setear bit específico
« en: 10 de Diciembre de 2009, 16:39:08 »
Hola
En algunos dispositivos me e encontrado que hay que setear algún bit en particular dentro de un registro tipo byte.
En ccs se supone que con bit_set y  bit_crear se consigue. perooooo no me funciona el dispositivo no responde al seteo del bit.
Este problema se me presenta ahora que estoy trabajando con el ds1337
Lo que pide la data es setear a 1 o 0 el bit 7 de los registros de hora, minutos etc según como se quiera  la alarma. Yo seteo este bit con las funciones mencionadas pero no me funciona. Lo que ago es esto

seconds_alm1=0;    // segundos vale 0
bit_clear(seconds_alm1,7);bit 7=0 segun data

minutes_alm1=27;    // minutos=27
bit_clear(minutes_alm1,7);bit 7=0 segun data

hours_alm1=22;      // hora=22
bit_clear(hours_alm1,7);// bit 7=0 segun data

day_alm1=2;        // day=2
bit_set(day_alm1,7);  // bit 7=1 segun data
  
ds1337_set_alarma1();//envía a rtc


Mi pregunta es si esta manera de hacerlo es correcta, y si hay otra forma de hacerlo.
Cualquier comentario es bienvenido, e revisado esto asta el hartazgo y ya no se que mas hacer

« Última modificación: 12 de Diciembre de 2009, 12:39:00 por un Moderador, Razón: Se corrige el título. »

Desconectado mariano_pic

  • PIC18
  • ****
  • Mensajes: 498
    • Software Electronica Microncontroladores
Re: Setar bit espesifico
« Respuesta #1 en: 10 de Diciembre de 2009, 17:05:39 »

  Es la manera correpta en ccs. Ademas es la mejor forma, otras usan mascaras que llevan mas instrucciones.
Necesitas ayuda para tu proyecto electronico?
buscame, tal ves pueda colaborarte.
Blog: http://electronicosembebidos.blogspot.com.co/
mail: electronicosembebidos@gmail.com
Mi grupo de facebook: https://www.facebook.com/groups/ProgramandoPics/

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Setar bit espesifico
« Respuesta #2 en: 10 de Diciembre de 2009, 17:32:25 »
En CCS usar bit_set/bit_clear o mascaras es exactamente lo mismo:

Código: [Seleccionar]
....................    bit_set(RByte,0);
027E:  BSF    31.0
....................    RByte=(RByte|0x01);
0280:  BSF    31.0
....................    bit_clear(RByte,7);
0282:  BCF    31.7
....................    RByte=(RByte&0x7F);
0284:  BCF    31.7


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Setar bit espesifico
« Respuesta #3 en: 11 de Diciembre de 2009, 17:36:14 »
Hola agradece sus respuestas,  por lo que me comentan estoy setenado de forma correcta el registro por lo que ahora ya no se que pasa.
Aislando mi programa e detectado que cuando seteo un BIT del registro me modifica el dato completo y no encuentro como resolver esto.
Intentare explicarme.
El registro 0x02h es el registro de la hora , pero también este registro cumple otra función el bit 6 configura la hora en modo 12/24hs  0=24HS  1=12HS  pues bien cuando escribo este registro así: hours=22; no tengo problema leo la hora bien
Pero cuando modifico el bit=6 a 1 para el modo 12hs así: hours=22, bit_set(hours,6), la lectura de la hora es incorrecta en lugar de leer 10pm(22hs) me da 6 hs
Y lo mismo me pasa con todos los registros que operan así  (que tienen doble función.)
Este es el problema por el cual las alarmas no se activan ya que si al setear un bit del registro me modifica el dato de la hora la alarma nunca va a coincidir.
No tengo ni jodida  de por que hace esto  :? :? :? :? :?


Código: [Seleccionar]

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                              ds1337.c                                      //
//                                                                            //
//                        void ds1337_config (void)                           //
//                                                                            //
//             void DS1337_write_byte(int8 address, int8 data)                //
//                                                                            //
//                   int8 DS1337_read_bytes(int8 address)                    //
//                                                                           //
//                      void DS1337_set_datetime()                           //
//                                                                           //
//                     void ds1337_set_alarma1(void)                         //
//                                                                           //
//                     void ds1337_set_alarma2(void)                         //
//                                                                           //
//////////////////////////////////////////////////////////////////////////////









#define DS1337_SDA  PIN_C4
#define DS1337_SCL  PIN_C3
#use i2c(master, sda=DS1337_SDA, scl=DS1337_SCL,fast=400000,force_hw)
// i2c addresses
#define DS1337_I2C_WRITE_ADDR    0xD0
#define DS1337_I2C_READ_ADDR     0xD1

// DS1337 register addresses
#define DS1337_SECONDS_REG       0x00
#define DS1337_MINUTES_REG       0x01
#define DS1337_HOURS_REG         0x02
#define DS1337_DAY_OF_WEEK_REG   0x03
#define DS1337_DATE_REG          0x04
#define DS1337_MONTH_REG         0x05
#define DS1337_YEAR_REG          0x06
//DS1337 Unique Registers
#define DS1337_ALM1_SECONDS_REG  0x07
#define DS1337_ALM1_MINUTES_REG  0x08
#define DS1337_ALM1_HOURS_REG    0x09
#define DS1337_ALM1_DAYDATE_REG  0x0A
#define DS1337_ALM2_MINUTES_REG  0x0B
#define DS1337_ALM2_HOURS_REG    0x0C
#define DS1337_ALM2_DAYDATE_REG  0x0D
#define DS1337_CONTROL_REG       0x0E
#define DS1337_STATUS_REG        0x0F

//opcion1= Enable Oscillator, Disable SQWV, Disable Ints
#define DS1337_CTRL_REG_INIT_VAL 0x04

//opcion2= enable oscillator,disable sqwv,enable ints
#define DS1337_CTRL_REG_INIT_VAL2 0x01 //valor 0x07


//Clear OSF (Oscillator Stop Flag), A2F (Alarm 2 Flag), and A1F (Alarm 1 Flag)
#define DS1337_CLEAR_STATUS_VAL  0x00
//////////////////////       variables clok           ////////////////////////

   int8 seconds;    // 0 to 59
   int8 minutes;    // 0 to 59
   int8 hours;      // 0 to 23  (24-hour time)
   int8 day;        // 0 = Sunday, 1 = Monday, etc.
   int8 date;       // 1 to 31
   int8 month;      // 1 to 12
   int8 year;       // 00 to 99
  
/////////////////////      variables alarma1 ////////////////////////////////

   int8 seconds_alm1;    // 0 to 59
   int8 minutes_alm1;    // 0 to 59
   int8 hours_alm1;      // 0 to 23  (24-hour time)
   int8 day_alm1;        // 1 = Sunday, 2 = Monday, etc.
  
////////////////////      variables alarma2 //////////////////////////////////

 //int8 seconds_alm2;    // 0 to 59
   int8 minutes_alm2;    // 0 to 59
   int8 hours_alm2;      // 0 to 23  (24-hour time)
   int8 day_alm2;        // 0 = Sunday, 1 = Monday, etc.













 //---------------------------------------------------
 //configurar ds1337
 void ds1337_config (void){
 
 
 
 disable_interrupts(GLOBAL);
      i2c_start();
      i2c_write(DS1337_I2C_WRITE_ADDR);
      i2c_write(DS1337_SECONDS_REG);
      i2c_write(0x00);                     //seconds
      i2c_write(0x00);                     //minutes
      i2c_write(0x40);                     //hours & 12/24 hour mode
      i2c_write(0x01);                     //day
      i2c_write(0x01);                     //date
      i2c_write(0x01);                     //month
      i2c_write(0x00);                     //year
      i2c_write(0x00);                     //alm1 seconds
      i2c_write(0x00);                     //alm1 minutes
      i2c_write(0x00);                     //alm1 hours
      i2c_write(0x00);                     //alm1 day/date
      i2c_write(0x00);                     //alm2 minutes
      i2c_write(0x00);                     //alm2 hours
      i2c_write(0x00);                     //alm2 day/date
      i2c_write(DS1337_CTRL_REG_INIT_VAL2); //Turn off the squarewave output pin.
      //i2c_write(DS1337_CLEAR_STATUS_VAL);  //Clear the status registers
      i2c_stop();
      enable_interrupts(GLOBAL);
 
 
      //disable_interrupts(GLOBAL);
      //i2c_start();
      //i2c_write(DS1337_I2C_WRITE_ADDR);
      //i2c_write(DS1337_CONTROL_REG  );  
      //i2c_write(DS1337_CTRL_REG_INIT_VAL2); //                    
      //i2c_write(DS1337_CLEAR_STATUS_VAL); //                    
      //i2c_stop();
      //enable_interrupts(GLOBAL);
 
 
 }
 
  
  
  
   //----------------------------------------------
void DS1337_write_byte(int8 address, int8 data) {

   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();

   enable_interrupts(GLOBAL);

}

//----------------------------------------------
int8 DS1337_read_bytes(int8 address) { //<-----------------------1

  int8 retval;

   disable_interrupts(GLOBAL);
   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(address);
   i2c_start();
   i2c_write(DS1337_I2C_READ_ADDR);
   retval = i2c_read(0);
   i2c_stop();
   enable_interrupts(GLOBAL);

   return(retval);
}



//----------------------------------------------
// 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 DS1337_set_datetime() {

   int8 bcd_sec;
   int8 bcd_min;
   int8 bcd_hrs;
   int8 bcd_day;
   int8 bcd_date;
   int8 bcd_mon;
   int8 bcd_year;

   // Convert the input date/time into BCD values
   // that are formatted for the DS1337 registers.
   bcd_sec  = bin2bcd(seconds);
   bcd_min  = bin2bcd(minutes);
   bcd_hrs  = bin2bcd(hours);    //default to 24 hour mode
   bcd_day  = bin2bcd(day);
   bcd_date = bin2bcd(date);
   bcd_mon  = bin2bcd(month);    //ignore century bit
   bcd_year = bin2bcd(year);

   // Write to the date and time registers.  Disable interrupts
   // so they can't disrupt the i2c operations.
   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(DS1337_SECONDS_REG);   // Start at seconds register
   i2c_write(bcd_sec);
   i2c_write(bcd_min);
   i2c_write(bcd_hrs);
   i2c_write(bcd_day);
   i2c_write(bcd_date);
   i2c_write(bcd_mon);
   i2c_write(bcd_year);
   i2c_stop();
  

   enable_interrupts(GLOBAL);

}

//----------------------------------------------
//setear alarma1_ds1337

void ds1337_set_alarma1(void){


  
   int8 bcd_sec_alm1;
   int8 bcd_min_alm1;
   int8 bcd_hrs_alm1;
   int8 bcd_day_alm1;
 
  

// Convert the input date/time into BCD values
   // that are formatted for the DS1337 registers.
   bcd_sec_alm1  = bin2bcd(seconds_alm1);
   bcd_min_alm1  =  bin2bcd(minutes_alm1);
   bcd_hrs_alm1  =  bin2bcd(hours_alm1);    //default to 24 hour mode
   bcd_day_alm1  =  bin2bcd(day_alm1);
  
  
  
     // Write to the date and time registers.  Disable interrupts
   // so they can't disrupt the i2c operations.
   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(DS1337_ALM1_SECONDS_REG);   // Start at seconds register
   i2c_write(bcd_sec_alm1);
   i2c_write(bcd_min_alm1);
   i2c_write(bcd_hrs_alm1);
   i2c_write(bcd_day_alm1);
   i2c_stop();

   enable_interrupts(GLOBAL);

}
  






// setear alarma2_max6958

void ds1337_set_alarma2(void){



 //int8 bcd_sec_alm2;
   int8 bcd_min_alm2;
   int8 bcd_hrs_alm2;
   int8 bcd_day_alm2;
 
  

// Convert the input date/time into BCD values
   // that are formatted for the DS1337 registers.
 //bcd_sec_alm2  = bin2bcd(seconds_alm2);
   bcd_min_alm2  =  bin2bcd(minutes_alm2);
   bcd_hrs_alm2  =  bin2bcd(hours_alm2);    //default to 24 hour mode
   bcd_day_alm2  =  bin2bcd(day_alm2);
  
  
  
     // Write to the date and time registers.  Disable interrupts
   // so they can't disrupt the i2c operations.
   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(DS1337_ALM2_MINUTES_REG );   // Start at minutes register  
   i2c_write(bcd_min_alm2);
   i2c_write(bcd_hrs_alm2);
   i2c_write(bcd_day_alm2);
   i2c_stop();

   enable_interrupts(GLOBAL);

}










//----------------------------------------------
// Read the Date and Time from the hardware registers
// in the DS1337.
void DS1337_read_datetime() {

   int8 bcd_sec;
   int8 bcd_min;
   int8 bcd_hrs;
   int8 bcd_day;
   int8 bcd_date;
   int8 bcd_mon;
   int8 bcd_year;

   // Disable interrupts so the i2c process is not disrupted.
   disable_interrupts(GLOBAL);

   // Read the date/time registers from the DS1337.
   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(DS1337_SECONDS_REG);   // Start at seconds register
   i2c_start();
   i2c_write(DS1337_I2C_READ_ADDR);

   bcd_sec  = i2c_read();
   bcd_min  = i2c_read();
   bcd_hrs  = i2c_read();
   bcd_day  = i2c_read();
   bcd_date = i2c_read();
   bcd_mon  = i2c_read();
   bcd_year = i2c_read(0);
   i2c_stop();

   enable_interrupts(GLOBAL);

   // Convert the date/time values from BCD to
   // unsigned 8-bit integers. Unpack bits in
   // DS1337 registers where required.
   seconds = bcd2bin(bcd_sec  & 0x7F);
   minutes = bcd2bin(bcd_min  & 0x7F);
   hours   = bcd2bin(bcd_hrs  & 0x3F);
   day     = bcd2bin(bcd_day  & 0x07);
   date    = bcd2bin(bcd_date & 0x3F);
   month   = bcd2bin(bcd_mon  & 0x1F);
   year    = bcd2bin(bcd_year);

}







//----------------------------------------------
//If there has been an oscillator failure since last
//init, then init DS1337. A default time and date is set as well.
void DS1337_init(void) {

    int8 temp = 0;

    //Read the status register to see if the oscillator has failed.
    temp = DS1337_read_bytes(DS1337_STATUS_REG);//<-------------------2
    //Unpack OSF bit
    temp = temp >> 7;

    //If oscillator has failed then init DS1337
    if(temp) {
      disable_interrupts(GLOBAL);
      i2c_start();
      i2c_write(DS1337_I2C_WRITE_ADDR);
      i2c_write(DS1337_SECONDS_REG);
      i2c_write(0x00);                     //seconds
      i2c_write(0x00);                     //minutes
      i2c_write(0x40);                     //hours & 12/24 hour mode
      i2c_write(0x00);                     //day
      i2c_write(0x01);                     //date
      i2c_write(0x01);                     //month
      i2c_write(0x06);                     //year
      i2c_write(0x00);                     //alm1 seconds
      i2c_write(0x00);                     //alm1 minutes
      i2c_write(0x00);                     //alm1 hours
      i2c_write(0x00);                     //alm1 day/date
      i2c_write(0x00);                     //alm2 minutes
      i2c_write(0x00);                     //alm2 hours
      i2c_write(0x00);                     //alm2 day/date
      i2c_write(DS1337_CTRL_REG_INIT_VAL); //Turn off the squarewave output pin.
      i2c_write(DS1337_CLEAR_STATUS_VAL);  //Clear the status registers
      i2c_stop();
      enable_interrupts(GLOBAL);
   }
}










Código: [Seleccionar]
#include <16f877a.h>
#fuses HS,NOWDT,NOLVP,NOPROTECT,NOPUT,NOBROWNOUT,NODEBUG              
#use delay(clock=20000000)
#org 0x1eaf, 0x1FFF void loader16F877A(void) {} //protect bootloader code for the 8k 16F876/7



#include <ds1337.c>

////////////////////////////////////////////////////////////////////////////////
// Canal de Comunicación : usart
////////////////////////////////////////////////////////////////////////////////
 
#define TTL_TX PIN_C6
#define TTL_RX PIN_C7
#use rs232(baud=9600, xmit=TTL_TX, rcv=TTL_RX)


VOID MAIN (VOID){

int8 data,dia_s;


set_tris_b(0b11111111);
set_tris_a(0b00000000);
setup_adc_ports(NO_ANALOGS);


ds1337_config();

year=9;
month=12;
date=10;
day=3;
hours=22;
bit_set(hours,6); // Setea bit 6 del registro 02h para cambiar a modo 12hs
seconds=40;
minutes=30;
DS1337_set_datetime();

hours_alm1=22;                                            
minutes_alm1=31;
seconds_alm1=50;
day_alm1=3;
ds1337_set_alarma1();



                                          



 while(1){
DS1337_read_datetime();   //   leer rtc
data=hours*1000;          //Convertir a long hora y minutos
data=data/10;
data=data+minutes;
dia_s=day;
printf("HS:%u",hours);
printf(" MIN:%u",minutes);
printf(" SEC:%u",seconds);
printf(" day:%u",day);
printf(" fecha:%u",date);                                  
printf(" mes:%u",month);
printf(" ano:%u\n\r",year);
                                              

printf("HS_A1:%u", hours_alm1);
printf(" MIN_A1:%u", minutes_alm1);
printf(" SEC_A1:%u",seconds_alm1 );
printf(" DAY_A1:%u \n\r",day_alm1 );
delay_ms(1000);
 }

}
« Última modificación: 11 de Diciembre de 2009, 17:38:24 por septiembre_negro »

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Setar bit espesifico
« Respuesta #4 en: 12 de Diciembre de 2009, 02:23:12 »
Eso no es culpa del seteo de los bits, lo que ocurre es que el DS1307 trabaja en BCD

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Setear bit específico
« Respuesta #5 en: 12 de Diciembre de 2009, 16:04:23 »
Pues si  también lo estuve pensando, que el problema esta en la conversión a bcd,  lo que me desconcierta es que las rutinas de conversión bcd -decimal, decimal-bcd aparentemente funcionan bien. puedo escribir y leer la hora sin  problema siempre y cuando no setie algun bit del reguistro.
Pues no queda mas que analizar a fondo estas rutinas
Te agradezco el comentario.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Setear bit específico
« Respuesta #6 en: 14 de Diciembre de 2009, 22:27:47 »
Hola
Pues este asunto del seteo de bit sigo sin conseguir resolverlo, la rutina bcd trabaja bien es lógico que al setear algún bit cambie el valor del registro así que no tengo ni las mas jodida  idea que como resolver esto. :5] :5] :5] :5] :5] :5] :5]
Alguien conoce algún ejemplo para el ds1307 donde este configurado para trabajar en modo 12hs??
Saludos.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Setear bit específico
« Respuesta #7 en: 15 de Diciembre de 2009, 15:13:40 »
Nadie ha configurado un ds1307 en modo 12hs???? :shock: :shock: :shock: :shock: :shock: :shock:

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Setear bit específico
« Respuesta #8 en: 15 de Diciembre de 2009, 22:12:46 »
Tengo que tomar esto como un no  :?  :D :D :D :D :D :D :D :D


 

anything