Pages: [1]   Go Down
Author Topic: [Solved] using a mask bit dallas rtc  (Read 524 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 2
Posts: 148
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all,
if i have a byte, say dec17 , B00010001, but bit 6 is a mask bit so if i set bit6 high i get B01010001(dec83), which totally changes my original 17. im thinking im to use |= to change bit 6, but im not having any luck doing it. this is for an rtc which uses bcd. i have my bcd code in place
Code:
writeRegister(MINUTES_REG,decToBcd(17));
void writeRegister(byte thisRegister, char thisValue)
{
  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister+DS1305_ADDRESS_OFFSET);
  SPI.transfer(thisValue);
  digitalWrite(SLAVESELECT, LOW);
}
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
and the clock is set and running fine, to enable alarms bit 6 in hours,days, and minutes register has to be "1". im not using a library for the device (ds1305)http://datasheets.maximintegrated.com/en/ds/DS1305.pdf but am looking at the ds1302 library to see how the bits are handled but im not understanding it. thank you.
« Last Edit: May 03, 2013, 11:00:37 am by grendle » Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Untested but something along the line of -

Code:
#define setBit(VALUE, BIT)       ((VALUE) |=  (1 << BIT))
#define clearBit(VALUE, BIT)     ((VALUE) &= ~(1 << BIT))
« Last Edit: April 25, 2013, 12:44:13 am by lloyddean » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 596
Posts: 33271
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but bit 6 is a mask bit so if i set bit6 high i get B01010001(dec83), which totally changes my original 17.
Yes it will. The number 17 is only one way of interpreting what is after all only a pattern of bits. But if you set bit 6 then all the other bits remain the same and that is what matters if I understand your context correctly.
Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 148
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but bit 6 is a mask bit so if i set bit6 high i get B01010001(dec83), which totally changes my original 17.
Yes it will. The number 17 is only one way of interpreting what is after all only a pattern of bits. But if you set bit 6 then all the other bits remain the same and that is what matters if I understand your context correctly.

ya but the clock then runs with "83" (or whatever 83 converts to from bcd).

Untested but something along the line of -

Code:
#define setBit(VALUE, BIT)       ((VALUE) |=  (1 << BIT))
#define clearBit(VALUE, BIT)     ((VALUE) &= ~(1 << BIT))

im gonna give this a shot. thank you.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 285
Posts: 25630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
(or whatever 83 converts to from bcd).
Woah!
Don't confuse hex with BCD or decimal.

0b10000011 is 0x83 and BCD 83, but 131 decimal.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 512
Posts: 26219
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I like using a more direct approach:

value = value | B01000000;  // set bit 6
value = vaue & B10111111; // clear bit 6

I often do this to clear/set a PORTx pin for SPI transfers, vs doing a digitalWrite of a pin.
PORTD = PORTD & B11111011; // using PD2 for SS pin
SPI.transfer(someValue);        // transfer the data
PORTD = PORTD | B00000100;  // SS pin high
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Full Member
***
Karma: 2
Posts: 148
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
(or whatever 83 converts to from bcd).
Woah!
Don't confuse hex with BCD or decimal.

0b10000011 is 0x83 and BCD 83, but 131 decimal.


yes, and it is confusing for someone just learning (my lesson is getting an spi device to work from reading the datasheet and not using a library) but im careful with the numbers and constantly using the debug window to see whats coming out. also mike, im gonna post the full code, but at this point its just writing and reading a couple registers. the bcd conversion function is by someone else i cant take credit for that, and some of the code is by others also.

Code:
#include <SPI.h>
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

#define CONTROL_REG 0x0F
#define DS1305_ADDRESS_OFFSET 0x80
#define SECONDS_REG 0x00
#define MINUTES_REG 0x01
#define HOURS_REG 0x02

SPI.begin();
digitalWrite(SLAVESELECT,LOW);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1);
  // initialize SPI:

Serial.begin(9600);
  digitalWrite(SLAVESELECT, HIGH);
   writeRegister(CONTROL_REG,0x07);
  unsigned int r = readRegister(CONTROL_REG);
  Serial.println("CONTROL = ");
  Serial.println(r,BIN);
  writeRegister(SECONDS_REG,0);
  writeRegister(MINUTES_REG,decToBcd(17));
  char hn = B00010001;                                    //next few lines is me experimenting, this didnt work so needs to be rewritten
  char mask = B01010001;
writeRegister(HOURS_REG,decToBcd(hn));
  hn|=mask;
  writeRegister(HOURS_REG,decToBcd(hn));
}

void loop(){
  
  delay(1000);

  

  byte seconds = bcdToDec(readRegister(SECONDS_REG));
  byte minutes = bcdToDec(readRegister(MINUTES_REG));
  byte hours = bcdToDec(readRegister(HOURS_REG));
  Serial.print(hours,DEC);
  Serial.print(":");
  Serial.print(minutes,DEC);
  Serial.print(":");
  Serial.println(seconds,DEC);

  
}

unsigned int readRegister(byte thisRegister)
{
  byte inByte = 0;
  unsigned int result = 0;

  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister);
  result = SPI.transfer(0x00);
  digitalWrite(SLAVESELECT, LOW);
  return(result);
}

void writeRegister(byte thisRegister, char thisValue)
{
  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister+DS1305_ADDRESS_OFFSET);
  SPI.transfer(thisValue);
  digitalWrite(SLAVESELECT, LOW);
}
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}



Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 148
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I like using a more direct approach:

value = value | B01000000;  // set bit 6
value = vaue & B10111111; // clear bit 6

I often do this to clear/set a PORTx pin for SPI transfers, vs doing a digitalWrite of a pin.
PORTD = PORTD & B11111011; // using PD2 for SS pin
SPI.transfer(someValue);        // transfer the data
PORTD = PORTD | B00000100;  // SS pin high

hmm, interesting. very. im gonna toy around with this especially since ive seen your work before and like it alot. thx crossroads.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 285
Posts: 25630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
value = value | B01000000;  // set bit 6
value = vaue & B10111111; // clear bit 6

C has the _BV (Bit Value) macros to handle this sort of stuff, without having to resort to writing numbers out in binary.
Code:
value |= _BV(6); //no need for a comment, the operation is obvious
value &= ~_BV(6); // clear bit 6, similarly clear without comment

Want to set bits six and 4?
Code:
value |= _BV(6) | _BV(4);
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 512
Posts: 26219
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I'm gonna admit to not really being a programmer or having indepth knowledge of C macros & classes & things like

value |= _BV(6) | _BV(4);

without having to look them up somewhere every time.  I'll stick with my more expanded form and let the compiler deal with it smiley-cool
Drives my wife nuts - I tell her I've never written a function or macro or class or a library - she'll counter that I use them all the time. Yes, but I've  never written one!
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Full Member
***
Karma: 2
Posts: 148
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

wow great replies, i thank you all, awol & crossroads also, thanks so much great information. i have a feeling from my simple lesson im going to learn much more than i anticipated, this is great, good stuff to work with. cheers all

and dont let crossroads fool ya lol, some awesome boards the man has
Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 148
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

finally figured this out, all the posts were correct, clearing the mask bits when reading was the key. sorry this stuff was hard for me but i learned alot.
setting the clock for 8pm

Code:
writeRegister(HOURS_REG,B01101000);
lowbyte 1000 is bcd for 8, bits 6 is 12 hour mode, bit 5 is am/pm..
to read..
Code:
byte hours = readRegister(HOURS_REG);
  byte ampm=bitRead(hours,5);
  if (ampm==1){
    meridian=1;
  }
  else{
    meridian=0;
  }
  hours=hours &B10011111; // CLEAR THE MASK BITS HERE
  byte days = readRegister(0x10);
  Serial.print(bcdToDec(hours),DEC);

still working on it, alarm registers etc, there is a library for this particular clock (ds1305) but i wont learn how to deal with the chip directly by using it all the time. and ill never be able to write my own libraries without being able to talk to the chip. next up when im done with 1305 is ds1615 and ds2404. thanks again to all the posters here who helped me.

entire sloppy test code, im just testing and its not optimized, just fyi.
Code:
#include <avr/interrupt.h>
#include <SPI.h>
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss
#define control 240 //READ
#define CONTROL_REG 0x0F
#define DS1305_ADDRESS_OFFSET 0x80
#define SECONDS_REG 0x00
#define MINUTES_REG 0x01
#define HOURS_REG 0x02
#define DAY_REG 0x03
#define DAY_ALARM 0x0A
#define SECONDS_ALARM 0x07
#define MINUTES_ALARM 0x08
#define HOURS_ALARM 0x09
#define DS1305_SR 0x10
#define DS1305_SR_IRQF1 1
#define DS1305_SR_IRQF0 0
boolean meridian;
void setup() {
  // set the slaveSelectPin as an output:

  unsigned int data;
  unsigned int address = 0xF0;
  SPI.begin();
  digitalWrite(SLAVESELECT,LOW);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1);
  // initialize SPI:
  pinMode(2, INPUT);
  digitalWrite(2,HIGH);
  attachInterrupt(0, alarmTriggered, FALLING);
  interrupts();
  Serial.begin(9600);
  digitalWrite(SLAVESELECT, HIGH);
  writeRegister(CONTROL_REG,0x03);
  //  unsigned int r = readRegister(CONTROL_REG);
  //  Serial.println("CONTROL = ");
  //  Serial.println(r,BIN);
  //  writeRegister(SECONDS_REG,decToBcd(30));
  //  writeRegister(MINUTES_REG,decToBcd(40));
  // 
  //   
  //   
  //writeRegister(HOURS_REG,B01101000);

  writeRegister(DAY_REG,1);
  writeRegister(HOURS_ALARM,B10010010);
  writeRegister(MINUTES_ALARM,B10010010);
  writeRegister(DAY_ALARM,B10010010);
  writeRegister(SECONDS_ALARM,B1110000);

}

void loop(){

  delay(1000);



  byte seconds = bcdToDec(readRegister(SECONDS_REG));
  byte minutes = bcdToDec(readRegister(MINUTES_REG));
  //  byte hours = bcdToDec(readRegister(HOURS_REG));
  byte hours = readRegister(HOURS_REG);
  byte ampm=bitRead(hours,5);
  if (ampm==1){
    meridian=1;
  }
  else{
    meridian=0;
  }
  hours=hours &B10011111;
  byte days = readRegister(0x10);
  Serial.print(bcdToDec(hours),DEC);
  Serial.print(":");
  Serial.print(minutes,DEC);
  Serial.print(":");
  Serial.print(seconds);
  if (meridian==1){
    Serial.println(" PM");
  }
  else{
    Serial.println(" AM");
  }


  //  writeRegister(0x20,0x30);
  //  r = readRegister(0x20);
  //  Serial.println("0x20 = ");
  //  Serial.println(r,HEX);
}

unsigned int readRegister(byte thisRegister)
{
  byte inByte = 0;
  unsigned int result = 0;

  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister);
  result = SPI.transfer(0x00);
  digitalWrite(SLAVESELECT, LOW);
  return(result);
}

void writeRegister(byte thisRegister, char thisValue)
{
  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister+DS1305_ADDRESS_OFFSET);
  SPI.transfer(thisValue);
  digitalWrite(SLAVESELECT, LOW);
}
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

void alarmTriggered()
{
  Serial.println("** ALARM WENT OFF! **");
  writeRegister(DS1305_SR,0);
}
« Last Edit: May 03, 2013, 11:16:11 am by grendle » Logged

Pages: [1]   Go Up
Jump to: