Microcontroladores , Open Hardware , Open Software e Tecnologia em Geral
Blog do Je » Page 'Projeto SuperClock - Parte 2'

Projeto SuperClock - Parte 2

Apos o esboço do projeto, avaliei que o ponto mais dificil seria a conexão do DS1302 com o AVR . Este chip usa comunicaçãao serial através de 3 pinos : SCLK , I/O e RST

ds1302.JPG

O RST apesar do nome estar mais para RESET atua como um CHIP ENABLE ( CE) . Os bytes a serem escritos no DS1302 deverão ser serializados e enviados bit a bit , sincronizados por um “clock” enviado do microcontrolador para o DS1302 através do SCLK.

Legal , vamos colocar a mão na massa e fazer isso funcionar … Pera aí­ , já deve ter alguma coisa pronta sobre isso na internet . Pesquisando no google achei uma biblioteca em C e um exemplo no AVRFreaks.net. Este site (em inglês) contem muuuuita coisa sobre AVRs. Contem os datasheets de todos os AVRs já fabricados e tem um comparativo entre chips muito completo.

Lá no AvrFreaks, no link Project “ds1302 library in avr-gcc” archive voce pode fazer o download da biblioteca e do exemplo de como utiliza-la. Baixei , compilei e deu alguns erros. Os erros basicamente referem-se a atualizacao do AVRGcc do ambiente de compilação ( WinAVr). As funções em C sbi e cbi estão obsoletas e precisaram ser mudadas da seguinte forma no exemplo abaixo :

PORTB |= _BV(clk) ; //no lugar de sbi(PORTB,clk);

PORTB &= ~_BV(clk); //no lugar de cbi(PORTB,clk);

Remendo ao texto original em 08/02/2007 :

Verifiquei que o link para a biblioteca original do AvrFreaks.net não estã funcionando. Assim abaixo está o código que estava lá.

// ds1302.c

#include “delay.h”

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>

#define rst 5 //definitions
#define clk 6
#define io 7

#define mon 1
#define tue 2
#define wed 3
#define thu 4
#define fri 5
#define sat 6
#define sun 7

#define sec_w 0×80
#define sec_r 0×81

#define min_r 0×83
#define min_w 0×82

#define hour_r 0×85
#define hour_w 0×84

#define date_r 0×87
#define date_w 0×86

#define month_r 0×89
#define month_w 0×88

#define day_r 0×8b
#define day_w 0×8a

#define year_w 0×8c
#define year_r 0×8d

#define w_protect 0×8e

void reset(void); //define the functions
void write(unsigned char);
unsigned char read(void);
void write_byte(unsigned char,unsigned char);
unsigned char read_byte(unsigned char);
unsigned char get_hours(void);

unsigned char b10;
unsigned char bpm;

unsigned char get_hours(void)
{

unsigned char i;
unsigned char R_Byte;
unsigned char TmpByte;

reset();
write(0×85);

DDRB |= _BV(io) ; //sbi(DDRB,io);

R_Byte = 0×00;
PORTB&= ~_BV(io); // cbi(PORTB,io);

DDRB &= ~_BV(io); //cbi(DDRB,io);

for(i = 0; i < 4; i++) //get the first 4 bits
{
TmpByte = 0;
if(bit_is_set(PINB,io))
TmpByte = 1;
TmpByte <<= 7;
R_Byte >>= 1;
R_Byte |= TmpByte;

PORTB |= _BV(clk) ; //sbi(PORTB,clk);
delay_us(2);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
delay_us(2);
}

b10 = 0;
if(bit_is_set(PINB,io))
b10 = 1;

PORTB |= _BV(clk) ; //sbi(PORTB,clk);
delay_us(2);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
delay_us(2);

bpm = 0;
if(bit_is_set(PINB,io))
bpm = 1;

PORTB |= _BV(clk) ; //sbi(PORTB,clk) ;
delay_us(2);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
delay_us(2);

PORTB &= ~_BV(rst); //cbi(PORTB,rst);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);

R_Byte >>= 4;
return R_Byte;
}

unsigned char read_byte(unsigned char w_byte) //read the byte with register w_byte
{
unsigned char temp;
reset();
write(w_byte);
temp = read();
PORTB &= ~_BV(rst); //cbi(PORTB,rst);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
return temp;
}

void write_byte(unsigned char w_byte, unsigned char w_2_byte) //read the byte with register w_byte
{
reset();
write(w_byte);
write(w_2_byte);
PORTB &= ~_BV(rst); //cbi(PORTB,rst);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
}

void reset(void) //sets the pins to begin and end the ds1302 communication
{
DDRB |= _BV(rst) ; //sbi(DDRB,rst);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
PORTB &= ~_BV(rst); //cbi(PORTB,rst);
PORTB |= _BV(rst) ; //sbi(PORTB,rst);
}

void write(unsigned char W_Byte) //writes the W_Byte to the DS1302
{
unsigned char i;
DDRB = 0xFF;

for(i = 0; i < 8; i++)
{
PORTB &= ~_BV(io); // cbi(PORTB,io);
if(W_Byte &0×01)
{
PORTB |= _BV(io) ; //sbi(PORTB,io);
}
PORTB |= _BV(clk) ; //sbi(PORTB,clk);
delay_us(2);
PORTB &= ~_BV(clk); // cbi(PORTB,clk);
delay_us(2);
W_Byte >>=1;
}
}

unsigned char read(void) //reads the ds1302 reply
{
unsigned char i;
unsigned char R_Byte, R_Byte2, TmpByte;

DDRB |= _BV(io) ; //sbi(DDRB,io);

R_Byte = 0×00;
R_Byte2 = 0×00;
PORTB &= ~_BV(io); //cbi(PORTB,io);

DDRB &= ~_BV(io); //cbi(DDRB,io);

for(i = 0; i < 4; i++) //get the first 4 bits
{
TmpByte = 0;
if(bit_is_set(PINB,io))
TmpByte = 1;
TmpByte <<= 7;
R_Byte >>= 1;
R_Byte |= TmpByte;

PORTB |= _BV(clk) ; //sbi(PORTB,clk);
delay_us(2);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
delay_us(2);
}
for(i = 0; i < 4; i++) //get the next 3 bits
{
TmpByte = 0;
if(bit_is_set(PINB,io))
TmpByte = 1;
TmpByte <<= 7;
R_Byte2 >>= 1;
R_Byte2 |= TmpByte;

PORTB |= _BV(clk) ; //sbi(PORTB,clk);
delay_us(2);
PORTB &= ~_BV(clk); //cbi(PORTB,clk);
delay_us(2);
}
R_Byte >>= 4;
R_Byte2 >>= 4;
R_Byte = (R_Byte2 * 10) + R_Byte;
return R_Byte;
}

_______________________________________________________________

//delay.h
/****************************************************************************
Title : Header file for the DELAY FUNCTIONS library (delay.h)
Author: Chris efstathiou hendrix@otenet.gr
Date: 26/Oct/2002
Software: AVR-GCC with AVR-AS
Target: any AVR device
Comments: This software is FREE.

*****************************************************************************/

#ifndef DELAY_H
#define DELAY_H 1

/*######################################################################################################*/
/* START OF CONFIGURATION BLOCK */
/*######################################################################################################*/
#ifndef F_CPU
//#define F_CPU 3686400 /* The cpu clock frequency in Hertz */
#define F_CPU 8000000 /* The cpu clock frequency in Hertz */
#endif
#define USE_DELAY_MACROS 1 /* 1=enable macros, 0=no macros are defined */
#define USE_DELAY_FUNCTIONS 1 /* 1=enable functions, 0=no functions are included */

/*######################################################################################################*/
/* END OF CONFIGURATION BLOCK */
/*######################################################################################################*/

#if USE_DELAY_MACROS == 1

#define TIME_L1_MS ( 1*(F_CPU/6000) ) /* MUST USE A LONG FOR COUNTING TO BE ACCURATE */
#define TIME_S1_MS ( 1*(F_CPU/4000) )

#define DELAY_MS(ms) DELAY_LONG((TIME_L1_MS*ms))
#define delay_ms(ms) delay_long((TIME_L1_MS*ms))

#define DELAY_US(us) DELAY_SHORT( ((TIME_S1_MS*us)/1000) )
#define delay_us(us) delay_short( ((TIME_S1_MS*us)/1000) )

/*
IF YOU USE THE ACCURATE DELAY MACROS MAKE SURE THAT THE VALUE PASSED IS NOT ZERO
OTHERWISE BAD THINGS WILL HAPPEN TO YOU.
*/

/* 3 cpu cycles per loop when a constant is passed.*/
#define DELAY_C_ACCURATE(x) ({ __asm__ volatile ( “ldi r25,%0 \n\t” \
“L_%=: \n\t” \
“dec r25 \n\t” \
“brne L_%= \n\t” \
: /* NO OUTPUT */ \
: “g” ((unsigned char)(x)) \
: “r25″ \
); \
})

/* 4 cpu cycles per loop + 1 overhead when a constant is passed. */
#define DELAY_S_ACCURATE(x) ({ unsigned short number_of_loops=(unsigned short)x; \
__asm__ volatile ( “L_%=: \n\t” \
“sbiw %A0,1 \n\t” \
“brne L_%= \n\t” \
: /* NO OUTPUT */ \
: “w” (number_of_loops) \
); \
})

/* 6 cpu cycles per loop + 3 overhead when a constant is passed. */
#define DELAY_L_ACCURATE(x) ({ unsigned long number_of_loops=(unsigned long)x; \
__asm__ volatile ( “L_%=: \n\t” \
“subi %A0,lo8(-(-1)) \n\t” \
“sbci %B0,hi8(-(-1)) \n\t” \
“sbci %C0,hlo8(-(-1)) \n\t” \
“sbci %D0,hhi8(-(-1)) \n\t” \
“brne L_%= \n\t” \
: /* NO OUTPUT */ \
: “w” (number_of_loops) \
); \
})

/* 3 cpu cycles per loop + 2 overhead when a constant is passed. */
#define DELAY_CHAR(x) ({ unsigned char number_of_loops=(unsigned char)x; \
__asm__ volatile ( “cp %A0,__zero_reg__ \n\t” \
“breq L_EXIT_%= \n\t” \
“L_%=: \n\t” \
“dec %A0 \n\t” \
“brne L_%= \n\t” \
“L_EXIT_%=: \n\t” \
: /* NO OUTPUT */ \
: “r” (number_of_loops) \
); \
})

/* 4 cpu cycles per loop +4 overhead when a constant is passed. */
#define DELAY_SHORT(x) ({ unsigned short number_of_loops=(unsigned short)x; \
__asm__ volatile ( “cp %A0,__zero_reg__ \n\t” \
“cpc %B0,__zero_reg__ \n\t” \
“breq L_EXIT_%= \n\t” \
“L_%=: \n\t” \
“sbiw r24,1 \n\t” \
“brne L_%= \n\t” \
“L_EXIT_%=: \n\t” \
: /* NO OUTPUT */ \
: “w” (number_of_loops) \
); \
})

/* 6 cpu cycles per loop +12 overhead when a constant is passed. */
#define DELAY_LONG(x) ({ unsigned long number_of_loops=(unsigned long)x; \
__asm__ volatile ( “cp %A0,__zero_reg__ \n\t” \
“cpc %B0,__zero_reg__ \n\t” \
“cpc %C0,__zero_reg__ \n\t” \
“cpc %D0,__zero_reg__ \n\t” \
“breq L_EXIT_%= \n\t” \
“L_%=: \n\t” \
“subi %A0,lo8(-(-1)) \n\t” \
“sbci %B0,hi8(-(-1)) \n\t” \
“sbci %C0,hlo8(-(-1)) \n\t” \
“sbci %D0,hhi8(-(-1)) \n\t” \
“brne L_%= \n\t” \
“L_EXIT_%=: \n\t” \
: /* NO OUTPUT */ \
: “w” (number_of_loops) \
); \
})

#endif /* #if USE_DELAY_MACROS == 1 */

#if USE_DELAY_FUNCTIONS == 1
void delay_char(unsigned char number_of_loops)
{
/* 3 cpu cycles per loop + 10 cycles overhead when a constant is passed. */
__asm__ volatile ( “cp %A0,__zero_reg__ \n\t” \
“breq L_EXIT_%= \n\t” \
“L_%=: \n\t” \
“dec %A0 \n\t” \
“brne L_%= \n\t” \
“L_EXIT_%=: \n\t” \
: /* NO OUTPUT */ \
: “r” (number_of_loops) \
);

return;
}

void delay_short(unsigned short number_of_loops)
{
/* 4 cpu cycles per loop + 12 cycles overhead when a constant is passed. */
__asm__ volatile ( “cp %A0,__zero_reg__ \n\t” \
“cpc %B0,__zero_reg__ \n\t” \
“breq L_EXIT_%= \n\t” \
“L_%=: \n\t” \
“sbiw r24,1 \n\t” \
“brne L_%= \n\t” \
“L_EXIT_%=: \n\t” \
: /* NO OUTPUT */ \
: “w” (number_of_loops) \
);

return;
}

void delay_long(unsigned long number_of_loops)
{
/* 6 cpu cycles per loop + 20 cycles overhead when a constant is passed. */
__asm__ volatile ( “cp %A0,__zero_reg__ \n\t” \
“cpc %B0,__zero_reg__ \n\t” \
“cpc %C0,__zero_reg__ \n\t” \
“cpc %D0,__zero_reg__ \n\t” \
“breq L_EXIT_%= \n\t” \
“L_%=: \n\t” \
“subi %A0,lo8(-(-1)) \n\t” \
“sbci %B0,hi8(-(-1)) \n\t” \
“sbci %C0,hlo8(-(-1)) \n\t” \
“sbci %D0,hhi8(-(-1)) \n\t” \
“brne L_%= \n\t” \
“L_EXIT_%=: \n\t” \
: /* NO OUTPUT */ \
: “w” (number_of_loops) \
); \

return;
}
#endif /* #if USE_DELAY_FUNCTIONS == 1 */

#endif

Gostou deste post ? Divulgue !
delicious digg google
stumbleupon technorati Yahoo!

Um comentário to “Projeto SuperClock - Parte 2”

  1. Oi, Je, muito legal teu blog.
    Sera que nao tem a parte 3 deste artigo? estou procurando em varios lugares algo sobre arduino e ds1302, encontrei mais com 1307 e cada lugar fala uma coisa “diferente”.
    Abraços

Deixe um comentario

XHTML - Voce pode usar:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Topo da página / Assinar para receber novos Posts (RSS)