Operácie

Hodinový modul DS1302: Rozdiel medzi revíziami

Z SensorWiki

(Zadanie)
(Analýza a opis riešenia)
 
(Jedna medziľahlá úprava od rovnakého používateľa nie je zobrazená.)
Riadok 10: Riadok 10:
 
'''Literatúra:'''  
 
'''Literatúra:'''  
 
* [https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf Dokumentácia k doske Arduino Uno]
 
* [https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf Dokumentácia k doske Arduino Uno]
* [https://techfun.sk/produkt/hodinovy-modul-ds1302/ Datasheet k RTC DS1302]
+
* [https://www.analog.com/media/en/technical-documentation/data-sheets/ds1302.pdf Datasheet k RTC DS1302]
  
  
Riadok 22: Riadok 22:
 
[[Súbor:zapojenieds1302.png|400px|thumb|center|Schéma zapojenia do arduino dosky.]]
 
[[Súbor:zapojenieds1302.png|400px|thumb|center|Schéma zapojenia do arduino dosky.]]
  
Vnútorná schéma zapojenia RTC hodinového modulu DS1302
 
  
[[Súbor:ds1302vnutro.jpg|400px|thumb|center|Vnútorná schéma zapojenia modulu DS1302.]]
+
[[Súbor:ds1302vnutro.jpg|400px|thumb|center|Vnútorná schéma zapojenia RTC hodinového modulu DS1302.]]
  
  

Aktuálna revízia z 16:38, 11. jún 2024

Záverečný projekt predmetu MIPS / LS2024 - Adam Hano


Zadanie

Hodinový modul DS1302 - napíšte rutiny na nastavenie a prečítanie aktuálneho času a dátumu.
Vývojová doska Arduino Uno.

Literatúra:


Analýza a opis riešenia

Hodinový modul DS1302 je real-time clock (RTC) modul, ktorý poskytuje presný čas a dátum pre systémy s mikrokontrolérmi. Umožňuje sledovať sekundy, minúty, hodiny, deň v týždni, deň v mesiaci, mesiac a rok s automatickou korekciou pre mesiac a počet dní v mesiaci, vrátane priestupných rokov. DS1302 komunikuje s mikrokontrolérom pomocou sériového rozhrania. Do zapojenia som nepridal batériu CR2032, lebo bola v tomto prípade zbytočná. Batéria tu slúži len na udržanie zadaného času a dátumu na hodinovom module, pre naše ukážky nebola potrebná.

Schéma zapojenia do arduino dosky.


Vnútorná schéma zapojenia RTC hodinového modulu DS1302.


Algoritmus a program

Algoritmus programu je....


#define F_CPU 16000000UL  // Definícia frekvencie mikrokontroléra
#define BAUDRATE 9600  // Rýchlosť komunikácie cez UART
#define BAUD_PRESCALE ((F_CPU / (BAUDRATE * 16UL)) - 1)  // Výpočet hodnôt pre nastavenie UART

#define RTC_SCLK_PIN PD6  // Definícia pinov pre komunikáciu s DS1302
#define RTC_IO_PIN PD7
#define RTC_CE_PIN PD8

ds1302RTC myRTC(RTC_SCLK_PIN, RTC_IO_PIN, RTC_CE_PIN);  // Inicializácia objektu pre prácu s DS1302

void ds1302RTC_init() {
    DDRB |= (1 << DS1302_SCLK_PIN) | (1 << DS1302_IO_PIN) | (1 << DS1302_CE_PIN);
}

int main() {
    uart_init(BAUD_PRESCALE);  // Inicializácia UART s vypočítanými hodnotami
    myRTC.initRTC(RTC_SCLK_PIN, RTC_IO_PIN, RTC_CE_PIN);  // Inicializácia RTC modulu

    // NASTAVENIE ČASU: formát > sekundy, minúty, hodiny, deň v týždni, deň v mesiaci, mesiac, rok
    // myRTC.setDS1302Time(20, 04, 11, 2, 4, 6, 2024); 

    while (1) {  // Nekonečná slučka
        myRTC.updateTime();  // Aktualizácia času z RTC modulu

        // Vytvorenie reťazca s aktuálnym dátumom a časom
        char timeString[30];
        sprintf(timeString, "Aktuálny dátum a čas: %d.%d.%d  %02d:%02d:%02d\r\n",
                myRTC.dayofmonth, myRTC.month, myRTC.year, myRTC.hours, myRTC.minutes, myRTC.seconds);

        uart_puts(timeString);  // Poslanie reťazca cez UART
        _delay_ms(1000);  // Oneskorenie 1 sekundu
    }

    return 0; 
}
#ifndef ds1302_H
#define ds1302_H

#include <avr/io.h>
#include <util/delay.h>
#include <string.h>

#define DS1302_ENABLE            0x8E
#define DS1302_TRICKLE           0x90

class ds1302RTC {
public:
    ds1302RTC(uint8_t inSCLK, uint8_t inIO, uint8_t inC_E);

    void initRTC(uint8_t CLK, uint8_t IO, uint8_t ENABLE);
    void DS1302_clock_burst_read(uint8_t *p);
    void DS1302_clock_burst_write(uint8_t *p);
    uint8_t DS1302_read(int address);
    void DS1302_write(int address, uint8_t data);
    void _DS1302_start();
    void _DS1302_stop();
    uint8_t _DS1302_toggleread();
    void _DS1302_togglewrite(uint8_t data, uint8_t release);
    void setDS1302Time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t dayofweek, uint8_t dayofmonth, uint8_t month, int year);
    void updateTime();

private:
    uint8_t SCLK;
    uint8_t IO;
    uint8_t C_E;
    uint8_t seconds;
    uint8_t minutes;
    uint8_t hours;
    uint8_t dayofweek;
    uint8_t dayofmonth;
    uint8_t month;
    int year;
};

#endif
#include <avr/io.h>
#include <util/delay.h>
#include "ds1302.h"

#define DS1302_SCLK_PIN  PD6
#define DS1302_IO_PIN    PD7
#define DS1302_CE_PIN    PD8

void ds1302RTC_init() {
    // Initialize pins as output
    DDRB |= (1 << DS1302_SCLK_PIN) | (1 << DS1302_IO_PIN) | (1 << DS1302_CE_PIN);
}

void DS1302_clock_burst_read(uint8_t *p) {
    int i;
    _DS1302_start();
    _DS1302_togglewrite(DS1302_CLOCK_BURST_READ, true);
    for(i = 0; i < 8; i++) {
        *p++ = _DS1302_toggleread();
    }
    _DS1302_stop();
}

void DS1302_clock_burst_write(uint8_t *p) {
    int i;
    _DS1302_start();
    _DS1302_togglewrite(DS1302_CLOCK_BURST_WRITE, false);
    for(i = 0; i < 8; i++) {
        _DS1302_togglewrite(*p++, false);
    }
    _DS1302_stop();
}

uint8_t DS1302_read(int address) {
    uint8_t data;
    bitSet(address, DS1302_READBIT);
    _DS1302_start();
    _DS1302_togglewrite(address, true);
    data = _DS1302_toggleread();
    _DS1302_stop();
    return data;
}

void DS1302_write(int address, uint8_t data) {
    bitClear(address, DS1302_READBIT);
    _DS1302_start();
    _DS1302_togglewrite(address, false);
    _DS1302_togglewrite(data, false);
    _DS1302_stop();
}

void _DS1302_start(void) {
    digitalWrite(DS1302_CE_PIN, LOW);
    pinMode(DS1302_CE_PIN, OUTPUT);
    digitalWrite(DS1302_SCLK_PIN, LOW);
    pinMode(DS1302_SCLK_PIN, OUTPUT);
    pinMode(DS1302_IO_PIN, OUTPUT);
    digitalWrite(DS1302_CE_PIN, HIGH);
    _delay_us(4);
}

void _DS1302_stop(void) {
    digitalWrite(DS1302_CE_PIN, LOW);
    _delay_us(4);
}

uint8_t _DS1302_toggleread(void) {
    uint8_t i, data = 0;
    for(i = 0; i <= 7; i++) {
        digitalWrite(DS1302_SCLK_PIN, HIGH);
        _delay_us(1);
        digitalWrite(DS1302_SCLK_PIN, LOW);
        _delay_us(1);
        bitWrite(data, i, digitalRead(DS1302_IO_PIN));
    }
    return data;
}

void _DS1302_togglewrite(uint8_t data, uint8_t release) {
    int i;
    for(i = 0; i <= 7; i++) {
        digitalWrite(DS1302_IO_PIN, bitRead(data, i));
        _delay_us(1);
        digitalWrite(DS1302_SCLK_PIN, HIGH);
        _delay_us(1);
        if(release && i == 7) {
            pinMode(DS1302_IO_PIN, INPUT);
        } else {
            digitalWrite(DS1302_SCLK_PIN, LOW);
            _delay_us(1);
        }
    }
}

void ds1302RTC_setDS1302Time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t dayofweek, uint8_t dayofmonth, uint8_t month, int year) {
    struct ds1302_struct rtc;
    seconds = seconds;
    minutes = minutes;
    hours = hours;
    dayofweek = dayofweek;
    dayofmonth = dayofmonth;
    month = month;
    year = year;

    memset((char *)&rtc, 0, sizeof(rtc));

    rtc.Seconds = bin2bcd_l(seconds);
    rtc.Seconds10 = bin2bcd_h(seconds);
    rtc.CH = 0;
    rtc.Minutes = bin2bcd_l(minutes);
    rtc.Minutes10 = bin2bcd_h(minutes);
    rtc.h24.Hour = bin2bcd_l(hours);
    rtc.h24.Hour10 = bin2bcd_h(hours);
    rtc.h24.hour_12_24 = 0;
    rtc.Date = bin2bcd_l(dayofmonth);
    rtc.Date10 = bin2bcd_h(dayofmonth);
    rtc.Month = bin2bcd_l(month);
    rtc.Month10 = bin2bcd_h(month);
    rtc.Day = dayofweek;
    rtc.Year = bin2bcd_l(year - 2000);
    rtc.Year10 = bin2bcd_h(year - 2000);
    rtc.WP = 0;

    DS1302_clock_burst_write((uint8_t *)&rtc);
}

void ds1302RTC_updateTime() {
    struct ds1302_struct rtc;
    DS1302_clock_burst_read((uint8_t *)&rtc);

    seconds = (rtc.Seconds10 * 10) + rtc.Seconds;
    minutes = (rtc.Minutes10 * 10) + rtc.Minutes;
    hours = (rtc.h24.Hour10 * 10) + rtc.h24.Hour;
    dayofweek = rtc.Day;
    dayofmonth = (rtc.Date10 * 10) + rtc.Date;
    month = (rtc.Month10 * 10) + rtc.Month;
    year = (rtc.Year10 * 10) + rtc.Year + 2000;
}
/* ************************************************************************* */
/* FileName:             uart.h                                              */
/* ************************************************************************* */

#define LED PB5  // internal on-board LED 

 /* na testovanie su uz zadefinovane */
 // bit_is_set(PINB, SW1)
 // bit_is_clear(PINB, SW1)

 /* na cakanie su preddefinovane slucky */
 // loop_until_bit_is_set(PINB, SW1);    // cakanie na uvolnenie tlacitka
 // loop_until_bit_is_clear(PINB, SW1);  // cakanie na stlacenie tlacitka


#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))

#ifndef UART_H_
#define UART_H_

#include <stdio.h>

#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)  // vzor?ek z datasheetu

void hw_init( void );
void uart_init( void );
     
/* Following definition is compatible with STDIO.H, for more
 * information see https://www.appelsiini.net/2011/simple-usart-with-avr-libc/
 */
	 
int uart_putc( char c, FILE *stream );
void uart_puts( const char *s );

char uart_getc( void );

void delay(int delay); 

#endif /* UART_H_ */
/* ************************************************************************* */
/* FileName:             uart.c                                              */
/* ************************************************************************* */

#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"

void hw_init( void )
{ 
  DDRB |= (1<<LED);    // PORTB.5 kde je LED ma byt OUTPUT
  /* sem si mozete dopisat svoje vlastne inicializacne prikazy */ 	
}

void uart_init( void ) 
{
//  for different BAUD rate change the project settings, or uncomment 
//  following two lines:	
//	#undef  BAUD           // avoid compiler warning
//  #define BAUD 115200
	
   #include <util/setbaud.h>  // requires defined BAUD
   
   UBRR0H = UBRRH_VALUE;
   UBRR0L = UBRRL_VALUE;
   #if USE_2X                 // defined in setbaud.h 
    UCSR0A |= (1 << U2X0);
   #else
    UCSR0A &= ~(1 << U2X0);
   #endif


    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */	
}


int uart_putc( char c, FILE *stream )
{
   if (c == '\n') 
      uart_putc('\r',stream);
   
   loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
   UDR0 = c;
   return 0;
}


void uart_puts(const char *s)
{
  /* toto je vasa uloha */
}

char uart_getc(void) 
{
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    return UDR0;
}

void delay(int delay)      // vlastna funkcia pre dlhsie casy 
{
  for (int i=1; i<=delay; i++)
  _delay_ms(1);
}


Zdrojový kód: zdrojaky.zip


Overenie

Na overenie môjho projektu som použil Serial(Putty), kedy sa náš aktuálny čas každú sekundu vypíše v našom zadanom formáte kvôli prehľadnosti.

Aplikácia.

Video: