Страница на этапе разработки
В данном уроке мы с Вами подключим часовую микросхему DS3231 к микроконтроллеру Atmega328P:
В данном уроке мы с Вами рассмотрим базовые возможности работы с данной микросхемой, более специфические функции мы будем рассматривать в других уроках по мере необходимости.
В уроке №42 мы с Вами уже работали с шиной I2C, по этому не будем мы тут на нем останавливаться. Данные будем выводить через UART на монитор порта. Настройка UART аналогична настройке UART Atmega8 с урока №4, с очень маленьким отличием: так как в Atmeg328P, USART0 — то регистры имеют цифру ноль в своих названиях (UCSR0B).
Теперь напишем программный код:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#define BAUD 9600L // Скорость обмена данными
#define UBRRL_value (F_CPU/(BAUD*16))-1 //Согластно заданной скорости подсчитываем значение для регистра UBRR
#define DS3231_ADDRESS 0b11010000 //0x68
unsigned char sec,min,hour,day,date,month,year;
void I2C_init(void);// инициализация
void I2C_Start(void);//Старт
void I2C_Stop(void);//Стоп
void I2C_SendByte(unsigned char c);//отправка данных
void I2C_SendByteAdres(unsigned char c, unsigned char addr );// отправка данных по адресу
char I2C_ReadByte(void);// чтение байта
unsigned char I2C_ReadLastByte(void);
void init_USART();
void send_UART(char value);
unsigned char RTC_ConvertFromDec(unsigned char c); //перевод двоично-десятичного числа в десятичное
unsigned char RTC_ConvertFromBinDec(unsigned char c); //перевод десятичного числа в двоично-десятичное
int main(void)
{
init_USART();
I2C_init();// инициализация
// запись данных
I2C_Start(); // запуск i2c
I2C_SendByte(DS3231_ADDRESS); // передача адреса устройства,
I2C_SendByte(0x00); // передача адреса памяти
I2C_SendByte(RTC_ConvertFromBinDec(0)); //секунды
I2C_SendByte(RTC_ConvertFromBinDec(31)); //минуты
I2C_SendByte(RTC_ConvertFromBinDec(20)); //часы
I2C_SendByte(RTC_ConvertFromBinDec(5)); //день недели
I2C_SendByte(RTC_ConvertFromBinDec(29)); //дата
I2C_SendByte(RTC_ConvertFromBinDec(1)); //месяц
I2C_SendByte(RTC_ConvertFromBinDec(16)); //год
I2C_Stop(); // остановка i2c
while (1)
{
//Читаем время
I2C_SendByteAdres(0,0b11010000); //переходим на адрес 0
_delay_ms(300);
I2C_Start(); //Отправим условие START
I2C_SendByte(0b11010001); //отправим в устройство бит чтения
sec = I2C_ReadByte();
min = I2C_ReadByte();
hour = I2C_ReadByte();
day = I2C_ReadByte();
date = I2C_ReadByte();
month = I2C_ReadByte();
year = I2C_ReadLastByte();
I2C_Stop(); //Отправим условие STOP
sec = RTC_ConvertFromDec(sec); //Преобразуем в десятичный формат
min = RTC_ConvertFromDec(min); //Преобразуем в десятичный формат
hour = RTC_ConvertFromDec(hour); //Преобразуем в десятичный формат
day = RTC_ConvertFromDec(day); //Преобразуем в десятичный формат
year = RTC_ConvertFromDec(year); //Преобразуем в десятичный формат
month = RTC_ConvertFromDec(month); //Преобразуем в десятичный формат
date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат
send_UART(date/10+0x30);//Преобразуем число в код числа
send_UART(date%10+0x30);//Преобразуем число в код числа
send_UART(‘.’);
send_UART(month/10+0x30);//Преобразуем число в код числа
send_UART(month%10+0x30);//Преобразуем число в код числа
send_UART(‘.’);
send_UART(year/10+0x30);//Преобразуем число в код числа
send_UART(year%10+0x30);//Преобразуем число в код числа
send_UART(‘ ‘);
send_UART(‘-‘);
send_UART(day+0x30);//Преобразуем число в код числа
send_UART(‘-‘);
send_UART(‘ ‘);
send_UART(‘ ‘);
send_UART(hour/10+0x30);//Преобразуем число в код числа
send_UART(hour%10+0x30);//Преобразуем число в код числа
send_UART(‘:’);
send_UART(min/10+0x30);//Преобразуем число в код числа
send_UART(min%10+0x30);//Преобразуем число в код числа
send_UART(‘:’);
send_UART(sec/10+0x30);//Преобразуем число в код числа
send_UART(sec%10+0x30);//Преобразуем число в код числа
send_UART(0x0d);//переход в начало строки
send_UART(0x0a);//перевод каретки
}
}
void I2C_init(void){
TWSR=(0<<TWPS1)|(0<<TWPS0);// настройка делителя
TWBR=0x03; // настройка рабочей частоты шины
}
void I2C_Start(void){
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR&(1<<TWINT))){;}
}
void I2C_Stop(void){
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}
void I2C_SendByte(unsigned char c){
TWDR=c;
TWCR=(1<<TWINT)|(1<<TWEN);
while (!(TWCR&(1<<TWINT))){;}
}
void I2C_SendByteAdres(unsigned char c, unsigned char addr )
{
I2C_Start();
I2C_SendByte(addr);
I2C_SendByte(c);
I2C_Stop();
}
char I2C_ReadByte(void){
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
while (!(TWCR&(1<<TWINT))){;}
return TWDR;
}
unsigned char I2C_ReadLastByte(void){
TWCR=(1<<TWINT)|(1<<TWEN);
while (!(TWCR&(1<<TWINT))){;}
return TWDR;
}
unsigned char RTC_ConvertFromBinDec(unsigned char c){
unsigned char ch = ((c/10)<<4)|(c%10);
return ch;
}
unsigned char RTC_ConvertFromDec(unsigned char c){
unsigned char ch = ((c>>4)*10+(0b00001111&c));
return ch;
}
void init_USART() {
UBRR0L = UBRRL_value; //Младшие 8 бит UBRRL_value
UBRR0H = UBRRL_value >> 8; //Старшие 8 бит UBRRL_value
UCSR0B |=(1<<TXEN0); //Бит разрешения передачи
//UCSR0C |=(1<< URSEL|(1<< UCSZ0)|(1<< UCSZ1); //Устанавливем формат 8 бит данных
}
void send_UART(char value) {
while(!( UCSR0A & (1 << UDRE0))); // Ожидаем когда очистится буфер передачи
UDR0 = value; // Помещаем данные в буфер, начинаем передачу
}