اطلاعیه

Collapse
No announcement yet.

ساخت ساعت دقیق با کریستال 32.768KHZ

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    ساخت ساعت دقیق با کریستال 32.768KHZ

    سلام
    وقت بخیر دوستان
    میخوام یه ساعت دقیق با کریستال 32.768KHZ متصل به TOSC1 و TOSC2 با استفاده از تایمر 2 میکرو AVR 2560 بسازم
    از تقسیم کلاک 128 استفاده کردم
    باید این تایمر آسنکرون باشه تا CPU میکرو درگیر اون نباشه
    نیاز به OCR و اینتراپت OCR ندارم
    پاییه های OC هم نمیخوام خروجی بدن
    فقط میخوام از اینتراپت OVER FLOW استفاده کنم برای شمارش ثانیه ها
    تو رجیستراش اشکال عمده دارم اخه خیلی وارد نیستم
    تشکر


    اضافه شده در تاریخ :
    // Timer/Counter 2 initialization
    // Clock source: Crystal on TOSC1 pin
    // Clock value: PCK2/128
    // Mode: Normal top=0xFF
    // OC2A output: Disconnected
    // OC2B output: Disconnected
    GTCCR=0x00;
    ASSR=0x60; //(0<<EXCLK) | (1<<AS2) | (0<<TCN2UB);
    TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
    TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (1<<CS20);
    TIFR2=0x01;
    TCNT2=0x00;
    OCR2A=0x00;
    OCR2B=0x00;

    اضافه شده در تاریخ :
    // Timer/Counter 2 Interrupt(s) initialization
    TIMSK2=(0<<OCIE2B) | (0<<OCIE2A) | (1<<TOIE2);

    اضافه شده در تاریخ :

    {
    //while(ASSR & 0x1F);

    char lcd_buff[32];
    //delay_ms(10);
    if(Second == 59)
    {
    Second = 0;
    if(Minute == 59)
    {
    Minute = 0;
    if(Hour == 24)
    {
    Hour = 0;
    }
    else
    {
    Hour++;
    }
    }
    else
    {
    Minute++;
    }
    }
    else
    {
    Second++;
    }
    sprintf(lcd_buff, "%d : %d : %d", Hour, Minute, Second);
    lcd_gotoxy(0, 3);
    lcd_puts(" "
    lcd_gotoxy(0, 3);
    lcd_puts(lcd_buff);
    }

    #2
    پاسخ : ساخت ساعت دقیق با کریستال 32.768KHZ

    سلام.
    من اینکارو قبلا کردم ولی نه دقیقا اونی که میخای.کدشو میذارم سوال داشتی بپرس.اگه خواستی بگو تا پروتئوسش هم برات ایمیل کنم.
    کد:
    /*
     * DS1307.c
     *
     * Created: 2014-07-11 19:45:15
     * Author: Astronomer
     */ 
    
    // ---------------------------------------------------------------------------
    // GLOBAL DEFINES
    #define F_CPU    8000000UL      // run CPU at 1 MHz
    #define F_TIM0   8000000UL     // Clock value of timer0 = 8000.000 KHZ
    #define ONESEC   F_TIM0/256
    #define UPDATETIME ONESEC/10
    #define LED     5          // Boarduino LED on PB5
    // ---------------------------------------------------------------------------
    // INCLUDES
    #include <avr/io.h> 
    #include <avr/interrupt.h>          // deal with port registers
    #include <util/delay.h>         // used for _delay_ms function
    #include <string.h>           // string manipulation routines
    #include <stdio.h> // sprintf()
    #include <stdlib.h>// itoa ()
    #include "alcd.h"
    //#include "I2C_Master.h"
    #include "DS1307.h"
    
    // ---------------------------------------------------------------------------
    // TYPEDEFS
    typedef uint8_t byte;          // I just like byte & sbyte better
    typedef int8_t sbyte;
    // ---------------------------------------------------------------------------
    void ShowDevices();
    void SetRegisters();
    
    byte hours, minutes, seconds;
    byte curSec = 0;
    byte preSec = 0;
    byte months, days, years;
    int TIMER0_CNT = 0; // Timer0 counter
    
    int main(void)
    {	
    	SetRegisters();
     // ShowDevices();   // show that I2C is working OK	
    	lcd_gotoxy(0,1);
    	lcd_puts("DS1307 I2C");
    	_delay_ms(2000);	
    	while(1)
      {        
      }
    }
    
    ISR(TIMER0_OVF_vect)
    {
    	TIMER0_CNT++;
    		
    	if(TIMER0_CNT > UPDATETIME)	
    	{
    		TIMER0_CNT = 0;
    		DS1307_GetTime(&hours,&minutes,&seconds);
    		DS1307_GetDate(&months,&days,&years);
    		
    		if(seconds != preSec)
    		{
    			preSec = seconds;
    			
    			char date[16] = "";
    			char time[16] = "";
    			sprintf(time,"%02d : %02d : %02d  ",hours,minutes,seconds);
    			sprintf(date,"20%02d / %02d / %02d ",years,months,days);
    			
    			lcd_gotoxy(0,0);lcd_puts(time);
    			lcd_gotoxy(0,1);lcd_puts(date);
    		}
    	}
    }
    
    void ShowDevices() // Scan I2C addresses and display addresses of all devices found
    {
    	lcd_gotoxy(0,0);
    	lcd_puts("Found:");
    	
    	byte addr = 1;
    	
    	while (addr>0)
    	{		
    		lcd_puts(" , ");
    		addr = I2C_FindFirstDevice(addr);
    		if (addr>0) 
    		{
    			 // save enough space for result
    			 char str[8] = "";
    			itoa(addr,str,16);
    			lcd_puts(str);
    			addr++;
    		}
    	}
    }
    
    void SetRegisters()
    {
    	// Timer/Counter 0 initialization
    	// Clock source: System Clock
    	// Clock value: 8000.000 kHz
    	TCCR0=0x01;
    	TCNT0=0x00;
    	// Timer(s)/Counter(s) Interrupt(s) initialization
    	TIMSK=0x01;
    	
    	I2C_Init();     // set I2C clock frequency
    	lcd_init();
    	sei();
    }
    کد:
    /*
     * DS1307.h
     *
     * Created: 2014-07-11 19:52:46
     * Author: Astronomer
     */ 
    
    
    // ---------------------------------------------------------------------------
    // DS1307 RTC ROUTINES
    #include "bcd.h"
    #include "I2C_Master.h"
    
    #define DS1307       0xD0     // I2C bus address of DS1307 RTC
    #define SECONDS_REGISTER  0x00
    #define MINUTES_REGISTER  0x01
    #define HOURS_REGISTER   0x02
    #define DAYOFWK_REGISTER  0x03
    #define DAYS_REGISTER   0x04
    #define MONTHS_REGISTER  0x05
    #define YEARS_REGISTER   0x06
    #define CONTROL_REGISTER  0x07
    #define RAM_BEGIN     0x08
    #define RAM_END      0x3F
    
    /** returns hours, minutes, and seconds in decimal format **/
    void DS1307_GetTime(unsigned char *hours, unsigned char *minutes, unsigned char *seconds)
    {
    	*hours = I2C_ReadRegisterNack(DS1307,HOURS_REGISTER);
    	*minutes = I2C_ReadRegisterNack(DS1307,MINUTES_REGISTER);
    	*seconds = I2C_ReadRegisterNack(DS1307,SECONDS_REGISTER);
    	
    	if (*hours & 0x40)  // 12hr mode:        
    		{
    			*hours &= 0x1F;// use bottom 5 bits (pm bit = temp & 0x20)
    			
    		}
    		else           
    		{
    			*hours &= 0x3F; // 24hr mode: use bottom 6 bits			
    		}   
    		     
    	// BCD2DEC
    	*hours = Bcd2Dec(*hours);
    	*minutes = Bcd2Dec(*minutes);
    	*seconds = Bcd2Dec(*seconds);
    }
    
    void DS1307_SetTime(unsigned char hour,unsigned char min,unsigned char sec)
    {
    	I2C_WriteRegister(DS1307,HOURS_REGISTER,  Dec2Bcd(hour)+0x40); // add 0x40 for PM
    	I2C_WriteRegister(DS1307,MINUTES_REGISTER, Dec2Bcd(min));
    	I2C_WriteRegister(DS1307,SECONDS_REGISTER, Dec2Bcd(sec));
    }
    
    /** returns months, days, and years in decimal format **/
    void DS1307_GetDate(unsigned char *months, unsigned char *days, unsigned char *years)
    {
    	*months = I2C_ReadRegisterNack(DS1307,MONTHS_REGISTER);
    	*days = I2C_ReadRegisterNack(DS1307,DAYS_REGISTER);
    	*years = I2C_ReadRegisterNack(DS1307,YEARS_REGISTER);
    	
    	*months = Bcd2Dec(*months);
    	*days = Bcd2Dec(*days);
    	*years = Bcd2Dec(*years);
    }
    
    void DS1307_SetDate(unsigned char year,unsigned char month,unsigned char day) //
    {
    	I2C_WriteRegister(DS1307,MONTHS_REGISTER, Dec2Bcd (month));
    	I2C_WriteRegister(DS1307,DAYS_REGISTER,  Dec2Bcd (day));
    	I2C_WriteRegister(DS1307,YEARS_REGISTER, Dec2Bcd (year));
    }
    
    
    
    ///** simple, hard-coded way to set the date. **/
    //void SetTimeDate() // 
    //{
    	//I2C_WriteRegister(DS1307,MONTHS_REGISTER, 0x08);
    	//I2C_WriteRegister(DS1307,DAYS_REGISTER,  0x31);
    	//I2C_WriteRegister(DS1307,YEARS_REGISTER,  0x13);
    	//I2C_WriteRegister(DS1307,HOURS_REGISTER,  0x08+0x40); // add 0x40 for PM
    	//I2C_WriteRegister(DS1307,MINUTES_REGISTER, 0x51);
    	//I2C_WriteRegister(DS1307,SECONDS_REGISTER, 0x00);
    //}

    کد:
    /**
    *	BCD.h
    *	Author: Astronomer
    **/
     
    #ifndef _BCD_H
    #define _BCD_H
     
    #define Bcd2Bin(val)  ((val&0x0f)+(val>>4)*10)
    #define Bin2Bcd(val)  (((val/10)<<4)+val%10)
    #define Bcd2Dec(val)  (val-6*(val>>4))
    #define Dec2Bcd(val)  (val+6*(val/10))
    
    #endif /* _BCD_H */
    کد:
    /*
     * I2C_Master.h
     *
     * Created: 2014-07-15 17:05:33
     * Author: Astronomer
     */ 
    
    #ifndef _I2CMASTER_H
    #define _I2CMASTER_H  1
    
    /************************************************************************* 
    * Title:  C include file for the I2C master interface 
    *      (i2cmaster.S or twimaster.c)
    * Author:  Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
    * File:   $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
    * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
    * Target:  any AVR device
    * Usage:  see Doxygen manual
    **************************************************************************/
    
    /* define CPU frequency in Mhz here if not defined in Makefile */
    #ifndef F_CPU
    #define F_CPU 1000000UL
    #endif
    /* I2C clock in Hz */
    #ifndef SCL_CLOCK
    #define SCL_CLOCK 100000UL
    #endif
    
    #define TW_SEND    0x84       // send data (TWINT,TWEN)
    #define TW_READY   (TWCR & 0x80)   // ready when TWINT returns to logic 1.
    
    #include <avr/io.h>
    #include <inttypes.h>
    #include <compat/twi.h>
    
    
    /** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
    #define I2C_READ  1
    
    /** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
    #define I2C_WRITE  0
    
    
    void I2C_Init(void);
    void I2C_Stop(void);
    unsigned char I2C_Start(unsigned char address);
    unsigned char I2C_Read(unsigned char ack);
    unsigned char I2C_Rep_Start(unsigned char address);
    void I2C_Start_Wait(unsigned char address);
    unsigned char I2C_Write( unsigned char data );
    void I2C_WriteRegister(unsigned char busAddr, unsigned char deviceRegister, unsigned char data);
    unsigned char I2C_ReadAck(void);
    unsigned char I2C_ReadNack(void);
    unsigned char I2C_ReadRegisterAck(unsigned char busAddr, unsigned char deviceRegister);
    unsigned char I2C_ReadRegisterNack(unsigned char busAddr, unsigned char deviceRegister);
    unsigned char I2C_Detect(unsigned char addr);
    unsigned char I2C_FindFirstDevice(unsigned char start);
    unsigned char * I2C_FindAllDevice(unsigned char start,unsigned char * deviceAddr,int maxDeviceNum);
    void I2C_Init(void)
    {
     /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
     
     TWSR = 0;             /* no prescaler */
     TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
    
    }
    
    void I2C_Stop(void)
    {
      /* send stop condition */
    	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
    	
    	// wait until stop condition is executed and bus released
    	while(TWCR & (1<<TWSTO));
    
    }
    
    
    /** 
     @brief Issues a start condition and sends address and transfer direction 
     
     @param  addr address and transfer direction of I2C device
     @retval  0  device accessible 
     @retval  1  failed to access device 
     */
    unsigned char I2C_Start(unsigned char address)
    {
      uint8_t  twst;
    
    	// send START condition
    	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
    	// wait until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
    
    	// send device address
    	TWDR = address;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    
    	// wail until transmission completed and ACK/NACK has been received
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits.
    	twst = TW_STATUS & 0xF8;
    	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
    
    	return 0;
    
    }
    
    
    /**
     @brief Issues a repeated start condition and sends address and transfer direction 
    
     @param  addr address and transfer direction of I2C device
     @retval 0 device accessible
     @retval 1 failed to access device
     */
    unsigned char I2C_Rep_Start(unsigned char address)
    {
      return I2C_Start( address );
    
    }
    
    
    /**
     @brief Issues a start condition and sends address and transfer direction 
      
     If device is busy, use ack polling to wait until device ready 
     @param  addr address and transfer direction of I2C device
     @return  none
     */
    void I2C_Start_Wait(unsigned char address)
    {
      uint8_t  twst;
    
    
      while ( 1 )
      {
    	  // send START condition
    	  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
      
      	// wait until transmission completed
      	while(!(TWCR & (1<<TWINT)));
      
      	// check value of TWI Status Register. Mask prescaler bits.
      	twst = TW_STATUS & 0xF8;
      	if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
      
      	// send device address
      	TWDR = address;
      	TWCR = (1<<TWINT) | (1<<TWEN);
      
      	// wail until transmission completed
      	while(!(TWCR & (1<<TWINT)));
      
      	// check value of TWI Status Register. Mask prescaler bits.
      	twst = TW_STATUS & 0xF8;
      	if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
      	{  	  
      	  /* device busy, send stop condition to terminate write operation */
    	    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
    	    
    	    // wait until stop condition is executed and bus released
    	    while(TWCR & (1<<TWSTO));
    	    
      	  continue;
      	}
      	//if( twst != TW_MT_SLA_ACK) return 1;
      	break;
       }
    
    }
    
     
    /**
     @brief Send one byte to I2C device
     @param  data byte to be transfered
     @retval  0 write successful
     @retval  1 write failed
     */
    unsigned char I2C_Write( unsigned char data )
    {	
      uint8_t  twst;
      
    	// send data to the previously addressed device
    	TWDR = data;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    
    	// wait until transmission completed
    	while(!(TWCR & (1<<TWINT)));
    
    	// check value of TWI Status Register. Mask prescaler bits
    	twst = TW_STATUS & 0xF8;
    	if( twst != TW_MT_DATA_ACK) return 1;
    	return 0;
    
    }
    
    unsigned char I2C_ReadRegisterAck(unsigned char busAddr, unsigned char deviceRegister)
    {
    	
    	unsigned char data = 0;
    	I2C_Start(busAddr);         // send device address
    	I2C_Write(deviceRegister);     // set register pointer
    	I2C_Start(busAddr+I2C_READ);      // restart as a read operation
    	data = I2C_ReadAck();       // read the register data
    	I2C_Stop();             // stop
    	return data;
    }
    
    unsigned char I2C_ReadRegisterNack(unsigned char busAddr, unsigned char deviceRegister)
    {
    	unsigned char data = 0;
    	I2C_Start(busAddr);         // send device address
    	I2C_Write(deviceRegister);     // set register pointer
    	I2C_Start(busAddr+I2C_READ);      // restart as a read operation
    	data = I2C_ReadNack();       // read the register data
    	I2C_Stop();             // stop
    	return data;
    }
    
    void I2C_WriteRegister(unsigned char busAddr, unsigned char deviceRegister, unsigned char data)
    {
    	I2C_Start(busAddr);  // send bus address
    	I2C_Write(deviceRegister);     // first byte = device register address
    	I2C_Write(data);          // second byte = data for device register
    	I2C_Stop();
    }
    
    /**
     @brief  read one byte from the I2C device, request more data from device 
     @return  byte read from I2C device
     */
    unsigned char I2C_ReadAck(void)
    {
    	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
    	while(!(TWCR & (1<<TWINT)));  
    
      return TWDR;
    
    }
    
    /**
     @brief  read one byte from the I2C device, read is followed by a stop condition 
     @return  byte read from I2C device
     */
    unsigned char I2C_ReadNack(void)
    {
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	while(!(TWCR & (1<<TWINT)));
    	
      return TWDR;
    
    }
    
    unsigned char I2C_Detect(unsigned char addr){ // look for device at specified address; return 1=found, 0=not found
    
    	TWCR = TW_START;           // send start condition
    	while (!TW_READY);          // wait
    	TWDR = addr;             // load device's bus address
    	TWCR = TW_SEND;           // and send it
    	while (!TW_READY);          // wait
    	return (TW_STATUS==0x18);      // return 1 if found; 0 otherwise
    }
    
    unsigned char I2C_FindFirstDevice(unsigned char start) // returns with address of first device found; 0=not found
    {
    	for (unsigned char addr=start;addr<0xFF;addr++) // search all 256 addresses
    	{     if (I2C_Detect(addr))      // I2C detected?
    		return addr;        // leave as soon as one is found
    	}
    	return 0;              // none detected, so return 0.
    }
    unsigned char * I2C_FindAllDevice(unsigned char start,unsigned char * deviceAddr,int maxDeviceNum)
    {
    	int index = 0;
    //	unsigned char deviceAddr[maxDeviceNum];
    	for(int i=0;i<maxDeviceNum;i++) {deviceAddr[i]=0x00;}
    	
    	unsigned char addr = start;
    	while (addr>0)
    	{
    		addr = I2C_FindFirstDevice(addr);
    		if (addr>0 && index<maxDeviceNum)
    		{
    			// save enough space for result
    			deviceAddr[index] = addr;
    			index++;
    			addr++;
    		}
    	}
    	return deviceAddr;
    }
    
    
    
    
    /** 
     @brief  read one byte from the I2C device
     
     Implemented as a macro, which calls either i2c_readAck or i2c_readNak
     
     @param  ack 1 send ack, request more data from device<br>
            0 send nak, read is followed by a stop condition 
     @return  byte read from I2C device
     */
    #define I2C_Read(ack) (ack) ? I2C_ReadAck() : I2C_ReadNack(); 
    
    
    /**@}*/
    #endif
    اول هدرفایل هایی رو که قرار دادم رو به پروژت اضاف کن بعد فایل DS1307.C رو اجرا کن. هدر فایل تابع LCD رو هم خودت به پروژه اضاف کن. سوال داشتی بپرس.
    اللهم صل علي محمد و ال محمد و عجل فرجهم
    >>> www.DMF313.ir <<<
    اگر ژرف یابی و پژوهش نباشد; نتیجه اش یک جا ایستادن،
    در جا زدن و با دنیای پیرامون خود به تدریج بیگانه تر شدن
    است.

    دیدگاه


      #3
      پاسخ : ساخت ساعت دقیق با کریستال 32.768KHZ

      سلام
      تشکر بابت راهنمایی هات ولی همونطور که عرض کردم میخوام با خود تایمر 2 و فقط یه کریستال خارجی 32.768KHZ بسازمش
      مرسی
      دوستان چیزی به ذهنشون نمیرسه ؟

      دیدگاه

      لطفا صبر کنید...
      X