Zbernica i2c: hodiny reálneho času s PCF8583P
Zo stránky SensorWiki
Záverečný projekt predmetu MIPS / LS2025 - Filip Boco
Zadanie
Zadaním tohto projektu bolo navrhnúť a realizovať hodiny reálneho času s RTC modulu PCF8583P komunikujúcim cez zbernicu I2C. Systém s mikroprocesorom ATmega328P, ktorý zobrazuje aktuálny čas pomocou UART (PuTTY) alebo LCD displeja.
Súbor:DS138833.jpg RTC čip DS1388.
Literatúra:
Analýza a opis riešenia
V zadaní špecifikovaný RTC modul PCF8583P som pri vypracovaní nepoužil. Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami... Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.

Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.

Algoritmus a program
Algoritmus programu obsahuje hlavičkovú časť programu s použitými knižnicami, definíciu pomocných funkcií a hlavnú funkčnú časť.
Použité knižnice
- uart - knižnica na komunikáciu cez UART
- i2cmaster - knižnica pre I2C komunikáciu
Vlastné funkcie
- bcd2hex(uint8_t val) - prevod BCD (Binary-Coded Decimal) na HEX, využívaná pri čítaní aktuálneho času z RTC modulu
- hex2bcd(uint8_t val) - prevod HEX na BCD, využívaná pri zápise aktuálneho času do RTC modulu
- i2c_scanner(void) - funkcia vypíše do sériovej linky I2C adresu pripojeného zariadenia
- set_time_date(...) - nastaví aktuálny čas a dátum do RTC modulu DS1388
- read_time_date(...) - číta aktuálny čas a dátum z RTC modulu DS1388
Hlavný program
Main začína inicializáciou uart a i2c. Ďalej mám dve pomocné testovanie funkcie. Prvá uart_puts(...) testuje správnu funkcionalitu sériovej linky. Druhá i2c_scenner() overuje adresu RTC DS1388 modulu. Pokračuje definícia premenných a ich typu. Nakoniec samotný zápis času a čítanie s výpisom času vo while cykle. Knižnice i2cmaster.h a i2cmaster.c som nevkladal, pretože som na nich neurobil žiadne zmeny.
/*
uPrijekt MIPS
Filip Boco
Téma: Zbernica i2c: hodiny reálneho času
Poznámka: Namiesto čipu PCF8583P som použil čip DS1388 I2C RTC.
*/
#define F_CPU 16000000UL
#define BAUD 9600
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "i2cmaster.h"
#include "uart.h"
#define DS1388_ADDR 0x68
/*--------------------/ Funkcie na prevod BCD na HEX a HEX na BCD /--------------------*/
static uint8_t bcd2hex(uint8_t val) {
return ((val>>4)*10)+(val&0x0F);
}
static uint8_t hex2bcd(uint8_t val) {
return ((val/10)<<4)|(val % 10);
}
/*--------------------/ I2C scenner na zistenie I2C adresy /--------------------*/
void i2c_scanner(void) {
uart_puts("I2C scanner start...\r\n");
for (uint8_t address = 1; address < 127; address++) {
i2c_start(address << 1); // Shift adresa na zápis (write)
if (i2c_write(0) == 0) {
uart_puts("Device found at 0x");
uart_put_hex(address);
uart_puts("\r\n");
}
i2c_stop();
_delay_ms(10);
}
}
/*--------------------/ Funkcie pre zápis a čítanie času na RTC module /--------------------*/
void set_time_date(uint8_t h, uint8_t m, uint8_t s, uint8_t day, uint8_t date, uint8_t month, uint8_t year) {
i2c_start_wait(DS1388_ADDR<<1 | I2C_WRITE);
i2c_write(0x01); // 0x01 register sekúnd, 0x00 sú desatiny sekundy
i2c_write(hex2bcd(s));
i2c_write(hex2bcd(m));
i2c_write(hex2bcd(h));
i2c_write(hex2bcd(day));
i2c_write(hex2bcd(date));
i2c_write(hex2bcd(month));
i2c_write(hex2bcd(year));
i2c_stop();
}
void read_time_date(uint8_t *h, uint8_t *m, uint8_t *s, uint8_t *day, uint8_t *date, uint8_t *month, uint8_t *year) {
i2c_start_wait(DS1388_ADDR<<1 | I2C_WRITE);
i2c_write(0x01); // 0x01 register sekúnd
i2c_rep_start(DS1388_ADDR<<1 | I2C_READ);
uint8_t sec = i2c_readAck();
uint8_t min = i2c_readAck();
uint8_t hour = i2c_readAck();
uint8_t d = i2c_readAck(); // d - day
uint8_t dt = i2c_readAck(); // dt - date
uint8_t mo = i2c_readAck(); // mo - month
uint8_t yr = i2c_readNak(); // yr - year
i2c_stop();
*s = bcd2hex(sec & 0x7F);
*m = bcd2hex(min);
*h = bcd2hex(hour & 0x3F);
*day = bcd2hex(d);
*date = bcd2hex(dt);
*month = bcd2hex(mo & 0x1F);
*year = bcd2hex(yr);
}
/*--------------------/ Hlavný program /--------------------*/
int main(void) {
i2c_init();
uart_init();
/*uart_puts("DS1388 RTC Test\r\n");*/
/*i2c_scanner();*/
char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
uint8_t h,m,s,day,date,month,year;
char buf[48];
// Nastavenie času a dátumu
/*set_time_date(6, 39, 0, 5, 13, 6, 25);*/ // 1 = Monday, ...
while (1) {
read_time_date(&h, &m, &s, &day, &date, &month, &year);
sprintf(buf, "%s %02u.%02u.20%02u %02u:%02u:%02u\r", days[day-1], date, month, year, h, m, s);
uart_puts(buf);
_delay_ms(1000);
}
}
/* FileName: uart.c */
#include "uart.h"
#include <avr/io.h>
#include <util/setbaud.h>
#define F_CPU 16000000UL
#define BAUDRATE 9600
//#define BAUD_PRESCALE (((F_CPU / (BAUDRATE * 16UL))) - 1) // vzorček z datasheetu
void uart_init( void )
{
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
//UBRR0 = (unsigned char)BAUD_PRESCALE; // Set baud rate: Load the UBRR register
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); // Set format: 8data, 1stop bit
UCSR0B = (1 << RXEN0) | (1 << TXEN0); // Enable receiver and transmitter
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
}
void uart_putc(char c)
{
if (c == '\n')
{
uart_putc('\r');
}
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
UDR0 = c;
}
void uart_puts(const char *s)
{
while(*s!='\0'){
uart_putc(*s);
s++;
}
}
char uart_getc(void)
{
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
return UDR0;
}
void uart_put_hex(uint8_t num) {
const char hex[] = "0123456789ABCDEF";
uart_putc(hex[(num >> 4) & 0x0F]); // vyššia štvorica bitov
uart_putc(hex[num & 0x0F]); // nižšia štvorica bitov
}
/* FileName: uart.h */
#ifndef UART_H_
#define UART_H_
#define F_CPU 16000000UL
#define BAUD 9600
#define BAUD_PRESCALE (((F_CPU / (BAUD * 16UL))) - 1) // vzor?ek z datasheetu
void uart_init( void );
void uart_putc( char c );
void uart_puts( const char *s );
char uart_getc( void );
#endif /* UART_H_ */
Zdrojový kód: Boco_Projekt_i2c_RTC.zip
Overenie
Funkčnosť som overil porovnaním reálneho času a času vypísaného do PuTTY sériovej linky.

Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.