Перейти к содержанию

Часы на DS3231 & atmega8


Рекомендуемые сообщения

Скрытый текст

#define F_CPU 8000000L

#include <io.h>
#include <interrupt.h>
#include <delay.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <eeprom.h>


// библиотека преобразования двоично-десятичной системы и вывод на LCD
#include "bcd.h"

// библиотеки ЖК
#include "lcd_lib_2.h"

// библиотеки I2C
#include "i2c.h"

// библиотека кнопок
#include "buttons.h"

// дефайны адресов микросхемы
#define RTC_adr_write 0b11010000
#define RTC_adr_read  0b11010001

// переменные времени
unsigned char hour;
unsigned char min;
unsigned char sec;

// переменные даты
unsigned char day;
unsigned char wday;
unsigned char month;
unsigned char year;

// переменные температуры
unsigned int  temp;
unsigned char t1;
unsigned char t2;

// переменные будильника
unsigned char alarm_hour;
unsigned char alarm_min;
unsigned char alarm_on;

// переменные настройки
unsigned char i=0;                  // переменная кнопок
unsigned char al_on;                // переменная состояния будильника (вкл / выкл)
unsigned char al;                   // переменная сработки будильника
unsigned char j=1;                  // подуровни меню


#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED PB0


uint8_t alarm_hour_ee EEMEM = 0;
uint8_t alarm_min_ee EEMEM = 0;
uint8_t alarm_on_ee EEMEM = 0;


// пользовательский символ колокольчика для индикаци будильника
const uint8_t alarm[] PROGMEM   = {0x02,0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x04};

// ========================================================================================================================
// ========================================================================================================================
// DS3231

// функции преобразования чисел (для корректного отображения значений) ====================================================
unsigned char bcd (unsigned char data)
{
    unsigned char bc;

    bc=((((data&(1<<6))|(data&(1<<5))|(data&(1<<4)))*0x0A)>>4)+((data&(1<<3))|(data&(1<<2))|(data&(1<<1))|(data&0x01));

    return bc;
}

unsigned char bin(unsigned char dec){

    char bcd;

    char n, dig, num, count;

    num = dec;
    count = 0;
    bcd = 0;
    for (n=0; n<4; n++) {
        dig = num%10;
        num = num/10;
        bcd = (dig<<count)|bcd;
        count += 4;
    }

    return bcd;
}


// функции с часами =======================================================================================================

// инициализация начальных установок
void RTC_init(void){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x0E);            // передача адреса памяти
    i2c_send_byte(0b00100000);      // запустить преобразование температуры и выход на 1 Гц
    i2c_send_byte(0b00001000);      // разрешить выход 32 кГц
    i2c_stop_cond();                // остановка i2c

}


// получение времени и даты
void RTC_read_time(void){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x00);            // передача адреса памяти
    i2c_stop_cond();                // остановка i2c

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_read);    // передача адреса устройства, режим чтения
    sec = bcd(i2c_get_byte(0));     // чтение секунд, ACK
    min = bcd(i2c_get_byte(0));     // чтение минут, ACK
    hour = bcd(i2c_get_byte(0));    // чтение часов, ACK
    wday = bcd(i2c_get_byte(0));    // чтение день недели, ACK
    day = bcd(i2c_get_byte(0));     // чтение число, ACK
    month = bcd(i2c_get_byte(0));   // чтение месяц, ACK
    year = bcd(i2c_get_byte(1));    // чтение год, NACK
    i2c_stop_cond();                // остановка i2c

}


// установка времени
void RTC_write_time(unsigned char hour1,unsigned char min1, unsigned char sec1){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x00);            // передача адреса памяти
    i2c_send_byte(bin(sec1));       // 0x00 скунды (целесообразно ли задавать еще и секунды?)
    i2c_send_byte(bin(min1));       // 0x01 минуты
    i2c_send_byte(bin(hour1));      // 0x02 часы
    i2c_stop_cond();                // остановка i2c

}


// установка даты
void RTC_write_date(unsigned char wday, unsigned char day, unsigned char month, unsigned char year){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x03);            // передача адреса памяти
    i2c_send_byte(bin(wday));       // 0x03 адень недели (воскресенье - 1, пн 2, вт 3, ср 4, чт 5, пт 6, сб 7)
    i2c_send_byte(bin(day));        // 0x04 день месяц
    i2c_send_byte(bin(month));      // 0x05 месяц
    i2c_send_byte(bin(year));       // 0x06 год
    i2c_stop_cond();                // остановка i2c

}


// чтение температуры
void RTC_read_temper(void){


    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x11);            // передача адреса памяти
    i2c_stop_cond();                // остановка i2c

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_read);    // передача адреса устройства, режим чтения
    t1 = i2c_get_byte(0);           // чтение MSB температуры
    t2 = i2c_get_byte(1);           // чтение LSB температуры
    i2c_stop_cond();                // остановка i2c

    t2=(t2>>7);                     // сдвигаем на 6 - точность 0,25 (2 бита)
                                    // сдвигаем на 7 - точность 0,5 (1 бит)
    t2=t2*5;

}

// вывод дня недели
void put_wday (void) {
if (wday==1) {LCD_SendStr("Sun");}
if (wday==2) {LCD_SendStr("Mon");}
if (wday==3) {LCD_SendStr("Tue");}
if (wday==4) {LCD_SendStr("Wed");}
if (wday==5) {LCD_SendStr("Thu");}
if (wday==6) {LCD_SendStr("Fri");}
if (wday==7) {LCD_SendStr("Sat");}
}


//
// ========================================================================================================================
// ========================================================================================================================

ISR (TIMER0_OVF_vect)               // вектор прерывания по переполнеинию таймера 0
{

BUT_Debrief ();                     // опрос 4х кнопок

}

int main (void)
{


// инициализации
LCD_Init();
i2c_init();
BUT_Init();
RTC_init();


LED_DDR |= (1<<LED);
LED_PORT &= ~(1<<LED);

// загрузить из eeprom значения будильника
alarm_hour = eeprom_read_byte(&alarm_hour_ee);
alarm_min = eeprom_read_byte(&alarm_min_ee);
alarm_on = eeprom_read_byte(&alarm_on_ee);


LCD_SetUserChar(alarm, 1);      // загружаем пользовательский символ в ОЗУ дисплея


//инициализация таймера 0
TCCR0 |= 0b00000101;            // Включаем предделитель 1/1024
TIMSK |= 0b00000001;            // разрешаем прерывания по переполнению таймера T0.
TCNT0=0;                        // Обнуляем счётный регистр таймера T0

sei();                          // глобально разрешить прерывания

main:
LCD_Clear();

while (1)
{

i=BUT_GetKey();

// вывод времени
RTC_read_time ();

LCD_Goto(0,0);
BCD_2Lcd(hour);
LCD_WriteData(':');
BCD_2Lcd(min);
LCD_WriteData(':');
BCD_2Lcd(sec);

// вывод даты
LCD_Goto(0,1);
BCD_2Lcd(day);
LCD_WriteData('/');
BCD_2Lcd(month);
LCD_WriteData('/');
BCD_2Lcd(year);

// вывод дня недели
LCD_Goto(10,0);
put_wday ();

// вывод температуры
RTC_read_temper();
LCD_Goto(10,1);
LCD_WriteData('+');
BCD_2Lcd(t1);
LCD_WriteData(',');
BCD_1Lcd(t2);

LCD_WriteData('C');

// будильник
if(alarm_on==1)       {
if(alarm_hour==hour)  {
if(alarm_min==min)    {
if(sec==1)            {
al=1;
}
}
}
}


// отображение включенности будильника
if (alarm_on==1) {LCD_Goto(15,0); LCD_WriteData(1);}
else {LCD_Goto(15,0); LCD_WriteData(' ');}


// отключение сигнала будильника (сброс флага при нажатии кнопки 3)
i=BUT_GetKey();

if (i==3)
{ al=0; }


// при сработке будильника совершит действие
if (al==1)
{

LED_PORT |= (1<<LED);

}

else
{

LED_PORT &=~(1<<LED);

}

//_delay_ms(200);


//=== дальше настройки =====================================================================================================
//==========================================================================================================================
// кнопка 1 заходит в меню и перелистывает уровни менюшки
// кнопка 2 увеличивает переменную на 1 (защита от переполнения предусмотрена)
// кнопка 3 немедленно выходит из меню настроек
//


if (i==1)
{

LCD_Clear();

while (3)                           // настрока будильника
 {

    i=BUT_GetKey();

    if (i==1)
    {
      j++;
    }

    if (i==3)                       // отменить и выйти
    {
      i=0;
      j=1;
      goto main;
    }

// индикация настроек будильника
if (j==1) {LCD_Goto(6,1); LCD_SendStr("^^");}
if (j==2) {LCD_Goto(6,1); LCD_SendStr("   ^^");}
if (j==3) {LCD_Goto(9,1); LCD_SendStr("   ^^");}

LCD_Goto(0,0);
LCD_SendStr("Alarm");

LCD_Goto(6,0);
BCD_2Lcd(alarm_hour);
LCD_WriteData(':');
BCD_2Lcd(alarm_min);
LCD_WriteData('-');
if (alarm_on==1)
{ LCD_SendStr("on "); }
else
{ LCD_SendStr("off"); }

    switch (j)
    {
       case (1):
       {
       if (j!=1) {break;}
       if (i==2)
       {

         alarm_hour++;
         if (alarm_hour>23) {alarm_hour=0;}

       }
       }

       case (2):
       {
       if (j!=2) {break;}
       if (i==2)
       {

         alarm_min++;
         if (alarm_min>59) {alarm_min=0;}

       }
       }

       case (3):
       {
       if (j!=3) {break;}
       if (i==2)
       {

         alarm_on++;
         if (alarm_on>1) {alarm_on=0;}

       }
       }

    }


    if (j==4)                       // сохранить настройки и продолжить
    {
    //сохранить значения в eeprom
    eeprom_write_byte(&alarm_hour_ee, alarm_hour);
    eeprom_write_byte(&alarm_min_ee, alarm_min);
    eeprom_write_byte(&alarm_on_ee, alarm_on);
      j=1;
      LCD_Clear();
      break;
    }

 }

while (2)                           // настройка времени
 {

    i=BUT_GetKey();

    if (i==1)
    {
      j++;
    }

    if (i==3)                       // отменить и выйти
    {
      i=0;
      j=1;
      goto main;
    }

// индикация настраевомого времени
if (j==1) {LCD_Goto(6,1); LCD_SendStr("^^");}
if (j==2) {LCD_Goto(6,1); LCD_SendStr("   ^^");}

LCD_Goto(0,0);
LCD_SendStr("Time");

LCD_Goto(6,0);
BCD_2Lcd(hour);
LCD_WriteData(':');
BCD_2Lcd(min);
LCD_WriteData(':');
BCD_2Lcd(0);


    switch (j)
    {
       case (1):
       {
       if (j!=1) {break;}
       if (i==2)
       {

         hour++;
         if (hour>23) {hour=0;}

       }
       }

       case (2):
       {
       if (j!=2) {break;}
       if (i==2)
       {

         min++;
         if (min>59) {min=0;}

       }
       }

    }


    if (j==3)                       // сохранить настройки и продолжить
    {
      RTC_write_time(hour, min, 0);
      j=1;
      LCD_Clear();
      break;
    }


 }

while (2)                           // настрока даты
 {

    i=BUT_GetKey();

    if (i==1)
    {
      j++;
    }

    if (i==3)                       // отменить и выйти
    {
      i=0;
      j=1;
      goto main;
    }

// индикация настраиваемой даты и дня недели
if (j==1) {LCD_Goto(5,1); LCD_SendStr("^^");}
if (j==2) {LCD_Goto(5,1); LCD_SendStr("   ^^");}
if (j==3) {LCD_Goto(8,1); LCD_SendStr("   ^^");}
if (j==4) {LCD_Goto(11,1); LCD_SendStr("   ^^");}

LCD_Goto(0,0);
LCD_SendStr("Date");

LCD_Goto(5,0);
BCD_2Lcd(day);
LCD_WriteData('/');
BCD_2Lcd(month);
LCD_WriteData('/');
BCD_2Lcd(year);
LCD_WriteData(' ');
put_wday();


    switch (j)
    {
       case (1):
       {
       if (j!=1) {break;}
       if (i==2)
       {

         day++;
         if (day>31) {day=1;}

       }
       }

       case (2):
       {
       if (j!=2) {break;}
       if (i==2)
       {

         month++;
         if (month>12) {month=1;}

       }
       }

       case (3):
       {
       if (j!=3) {break;}
       if (i==2)
       {

         year++;
         if (year>40) {year=12;}

       }
       }

       case (4):
       {
       if (j!=4) {break;}
       if (i==2)
       {

         wday++;
         if (wday>6) {wday=0;}

       }
       }

    }


    if (j==5)                       // сохранить настройки и продолжить
    {
      RTC_write_date (wday, day, month, year);
      j=1;
      LCD_Clear();
      break;
    }

 }


}


//=== конец настроек =======================================================================================================
//==========================================================================================================================


} // end while(1)
} // end main
 

Доброго здоровья всем форумчанам. В общем сделал я часы как в этой теме http://cxem.net/mc/mc316.php, всё хорошо, они работают, но захотелось внести в программу некоторые изменения. Когда пытаюсь компилировать в Аtmel Studio то сразу вылетает 88 ероров (скрин экрана прилагается). А когда пытаюсь то же скомпилировать в CVAVR то вылазит всего два ерора:

Error: C: declaration 'unsigned char' is incompatible with the previous one: 'int' from file: 'D:\...\math.h', line: 22
Error: D:\...\(67): missing ';'

Проверял, тчк. с запятой стоят правильно. Библиотеки есть все и подключены. 

Без імені.png

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

17 часов назад, Lihey.german сказал:

Библиотеки есть все и подключены.

Значит не подключены, если Студия не желает видеть функции для работы с LCD. CVAVR же ругается на декларацию какой-то переменной, как unsigned char, хотя в файле math.h эта переменная требуется как int

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

5 часов назад, солар сказал:

#include <avr/io.h>

Это AVRStudio. Версия?
 

Да, версия Atmel Studio 7.0

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Вроде разобрался в CVAVR с  Error: C: declaration 'unsigned char' is incompatible with the previous one: 'int' from file: 'D:\...\math.h', line: 22

В файле math.h я удалил строчки:

int min(int a,int b);
long lmin(long a,long b);
float fmin(float a,float b);

незнаю правильно ли поступил.. Но остался еще один ерор, он кричит что пропущена точка-запятая, но всё на месте.

A-Studio всё так же ругается.

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

1. Зачем вы залезли в библиотечный файл? Оставьте его в покое. Поменяйте вашу переменную min на MIN или minits и компилятор успокоится.

2. CVAVR этого не понимает и справедливо ругается, что "need array size"

const uint8_t alarm[] PROGMEM   = {0x02,0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x04};

Для CVAVR надо

flash unit8_t alarm[] = {0x02,0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x04};

 

Изменено пользователем Sergey-Ufa
Ссылка на комментарий
Поделиться на другие сайты

Так, переименовал переменную, как Вы @Sergey-Ufa  и говорили. Действительно, компилятор по ней молчит, но вот почему он просит ";", не ясно. Везде всё стоит. Странно...

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

После устранения ошибки с min мой CVAVR снова выдает 2 ошибки. Первая "need array size", вторая ";". После того, как переделываем определение массива обе эти ошибки исчезают и появляется та же куча ошибок, что и у вас в Студии.
 

// библиотека преобразования двоично-десятичной системы и вывод на LCD
#include "bcd.h"

// библиотеки ЖК
#include "lcd_lib_2.h"

// библиотеки I2C
#include "i2c.h"

// библиотека кнопок
#include "buttons.h"

Эти файлы должны быть размещены в той же директории, что и ваш проект. Подозреваю, что их там у вас нет.

Ссылка на комментарий
Поделиться на другие сайты

@Sergey-Ufa  Т.е. они должны быть в папке с проэктом? И при изменении массива ошибка с ";" не исчезает. Бум пробовать 

В общем перенес я 

.#include "bcd.h"

#include "lcd_lib_2.h"

#include "i2c.h"

#include "buttons.h"

прямо в папку с проэктом, массив изменил, но остается все та же ошибка...

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

Вы сейчас используете CVAVR? Если да, то ему не нравится такое объявление переменных в EEPROM. Вместо

unsigned char alarm_hour_ee EEMEM = 0;
unsigned char alarm_min_ee EEMEM = 0;
unsigned char alarm_on_ee EEMEM = 0;

нужно

eeprom unsigned char alarm_hour_ee = 0;
eeprom unsigned char alarm_min_ee = 0;
eeprom unsigned char alarm_on_ee = 0;

У меня после этого ";" исчезла.

Ссылка на комментарий
Поделиться на другие сайты

@Sergey-Ufa да, именно cvavr.  После всех манипуляций ошибка уже просит "(" после 

flash unit8_t alarm[] = {0x02,0x04,0x04,0x0E,0x0E,0x1F,0x1F,0x04};

Error: C:\cvavr\proj\1.c(71): '(' expected

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

Вы не могли бы выложить эти ваши 4 h-файла bcd.h, lcd_lib_2.h,  i2c.h, buttons.h, чтобы я смог попробовать запустить всю программу целиком. Откровенно говоря уже самому стало интересно. А вообще, с учетом того, что вы перенесли файлы в папку с проектом и изменили название переменной min, может быть есть смысл вернуться в Студию с первоначальным кодом. Адаптация под CVAVR может потребовать еще приличное количество изменений.

Ссылка на комментарий
Поделиться на другие сайты

В общем разобрался с этими часами. Там библиотеки были авторские, а не стандартные, вот оно и матюкалось. Но вот возник другой вопрос, как в будильник вписать мелодию! Программу написал отдельно от часов, а от совместить их не выходит.

Скрытый текст

#include <avr/io.h>
#define F_CPU 1000000UL //1MHz
#include <util/delay.h>
#define H3 494
#define G4 392
#define E4 329
#define F4 349
#define A4 440
#define E5 659
#define F5 740
#define C5 523
#define G5 783
#define D5 587
#define D5S 622
#define A5S 932
#define LOOPS_PAUSE 100 //between loops, ms
#define R 10 //between notes, ms
#define  NOTES_PAUSE 1
#define SEQU_SIZE 51 //notes quantity
#define TEMPO 122 //quarter in minute
#define WHOLE_NOTE_DUR 240000/TEMPO //ms
int notes[51] = {   H3, R,  F5, R,  H3, R,  G5, R, F5, R,  E5, R,  F5, R, E5, R,  F5, R,  G5, R,  G5, R,  F5, R,  E5, R, H3, R,  F5, R,  H3, R,  G5, R, F5, R, E5, R, D5,
R, E5, R, D5, R, C5, R, C5, R, D5, R, C5    };
int beats[51]  = {26, 35, 26, 20, 26, 20, 20, 40, 20, 20, 20, 20, 20, 40, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 40, 20, 20, 20, 20,  20, 40, 20, 20, 20, 20, 20,
40,    20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 40};
uint16_t note_duration[SEQU_SIZE];
uint32_t signal_period[SEQU_SIZE];
uint32_t elapsed_time;
uint8_t i;

void VarDelay_us(uint32_t takt) {
    while(takt--) {
        _delay_us(1);
    }
}

int main(void) {
    DDRB  |= 1<<5;
    PORTB &= ~1<<5;
    //converting notes to signal period, us
    for (i = 0; i < SEQU_SIZE; i++) {
        signal_period = 1000000 / notes;
    }
    //converting beats to notes duration, ms
    for (i = 0; i < SEQU_SIZE; i++) {
        note_duration = (WHOLE_NOTE_DUR*beats)/255;
    }
    while(1) {
        for (i = 0; i < SEQU_SIZE; i++) {
            elapsed_time = 0;
            while (elapsed_time < 1000*((uint32_t)note_duration)) {
                PORTB |= 1<<5;
                VarDelay_us(signal_period/2);
                PORTB &= ~(1<<5);
                VarDelay_us(signal_period/2);
                elapsed_time += signal_period;
            }
            _delay_ms(NOTES_PAUSE);
        }
        _delay_ms(LOOPS_PAUSE);
    }
}

 

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

6 часов назад, Lihey.german сказал:

while (elapsed_time < 1000*((uint32_t)note_duration)) {

Со знанием таких конструкций и вдобавок

 

6 часов назад, Lihey.german сказал:

Программу написал

вы не может вписать мелодию в будильник? Не верю.

Я не раздаю удочки. Я продаю рыбу.

Ссылка на комментарий
Поделиться на другие сайты

7 часов назад, солар сказал:

Со знанием таких конструкций и вдобавок

 

вы не может вписать мелодию в будильник? Не верю.

Ну как написал, содрал с польского сайта и переписал саму мелодию))

Я так понимаю не работает по той причине, что uint8 i присутствует в обеих кодах.

Изменено пользователем Lihey.german
Ссылка на комментарий
Поделиться на другие сайты

Так, в принципе получилось, но с другим уском кода, правда пришлось поизвращаться дабы оно работало. Но вот заметил странность, после сработки будильника\мелодии перестают считываться время\дата\температура и не отключается будило т.е. дисплей молчит, только после reset все востанавливается. Сначала думал что таймеры мешают друг-другу, но нет. Вот теперь думаю что всё дело в delay, или самом коде мелодии.

Скрытый текст


#define F_CPU 8000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <avr/eeprom.h>

 
 
 #define A2      9008 // Ля (2 октава)
 #define Ais2    8580 // Ля диез
 #define B2      8098 // Си
 #define C3      7644 // До (3 октава)
 #define Cis3    7214 // До диез
 #define D3      6810 // Ре
 #define Dis3    6427 // Ре диез
 #define E3      6066 // Ми
 #define F3      5726 // Фа
 #define Fis3    5404 // Фа диез
 #define G3      5101 // Соль
 #define Gis3    4815 // Соль диез
 #define A3      4544 // Ля
 #define Ais3    4289 // Ля диез
 #define B3      4049 // Си
 #define C4      3821 // До (4 октава)
 #define Cis4    3607 // До диез
 #define D4      3404 // Ре
 #define Dis4    3213 // Ре диез
 #define E4      3033 // Ми
 #define F4      2862 // Фа
 #define Fis4    2702 // Фа диез
 #define G4      2550 // Соль
 #define Gis4    2407 // Соль диез
 #define A4      2272 // Ля
 #define Ais4    2144 // Ля диез
 #define B4      2024 // Си
 #define C5      1910 // До (5 октава)
 #define Cis5    1803 // До диез
 #define D5      1702 // Ре
 #define Dis5    1606 // Ре диез
 #define E5      1516 // Ми
 #define F5      1431 // Фа
 #define Fis5    1350 // Фа диез
 #define G5      1275 // Соль
 #define Gis5    1203 // Соль диез
 #define A5      1135 // Ля
 #define Ais5    1072 // Ля диез
 #define B5      1011 // Си
 #define C6      955 // До (6 октава)
 #define Cis6    901 // До диез
 #define D6      850 // Ре
 #define Dis6    803 // Ре диез
 #define E6      757 // Ми
 
 #define LE32    1*3 // 1/32 Длительность тона
 #define LE16    2*3 // 1/16
 #define LE16D   3*3
 #define LE16T   2*2
 #define LE8     4*3 // 1/8
 #define LE8D    6*3
 #define LE8T    4*2
 #define LE4     8*3 // 1/4
 #define LE4D    12*3
 #define LE4T    8*2
 #define LE2     16*3 // 1/2
 #define LE2D    24*3
 #define LE1     32*3 // 1
 void Delay_us(unsigned char time_us) // функция задержки в us
 { register unsigned char a;
     
     for(a = 0; a < time_us; a++)   // 4 цикла
     { asm (" PUSH  R0 ");       // 2 цикла
         asm (" POP   R0 ");       // 2 цикла
         // 8 циклов = 1 us для 8MHz
     }
 }
 
 void Delay_ms(unsigned int time_ms) // функция задержки в ms
 { register unsigned int a;
     
     for(a = 0; a < time_ms; a++)
     { Delay_us(250);
         Delay_us(250);
         Delay_us(250);
         Delay_us(250);
     }
 }
 
 unsigned char TEMP;
 
 void Set_TEMP(unsigned char number)   // функция установки темпа и паузы
 {
     TEMP = number;                      // установка темпа
     TCCR1B = (1 << COM1A0);                // CTC режим, использование OC1A
     TCCR1B = (1 << WGM13)|(1 << WGM12);     // звук выключен
 }
 void Play_LE(unsigned int sound, unsigned int LE) // функция проигрывания ноты
 {
     ICR1 = sound;                      // установка ICR1
     TCNT1 = 0x0000;                     // очистка Timer/Counter1
     TCCR1B |= (1 << WGM13)|(1 << WGM12)     // CTC режим
     |(1 << CS10);    // предделитель = 8
     
     Delay_ms(LE*TEMP*7);               // длительность ноты
     
     TCCR1B = (1 << WGM13)|(1 << WGM12); // звук выключен
 }
     
// библиотека преобразования двоично-десятичной системы и вывод на LCD
#include "bcd.h"

// библиотеки ЖК
#include "lcd_lib_2.h"

// библиотеки I2C
#include "i2c.h"

// библиотека кнопок
#include "buttons.h"

// дефайны адресов микросхемы
#define RTC_adr_write 0b11010000
#define RTC_adr_read  0b11010001

// переменные времени
unsigned char hour;
unsigned char min;
unsigned char sec;

// переменные даты
unsigned char day;
unsigned char wday;
unsigned char month;
unsigned char year;

// переменные температуры
unsigned int  temp;
unsigned char t1;
unsigned char t2;

// переменные будильника
unsigned char alarm_hour;
unsigned char alarm_min;
unsigned char alarm_on;

// переменные настройки
unsigned char i=0;                  // переменная кнопок
unsigned char al_on;                // переменная состояния будильника (вкл / выкл)
unsigned char al;                   // переменная сработки будильника
unsigned char j=1;                  // подуровни меню

uint8_t alarm_hour_ee EEMEM = 0;
uint8_t alarm_min_ee EEMEM = 0;
uint8_t alarm_on_ee EEMEM = 0;


// пользовательский символ колокольчика для индикаци будильника
const uint8_t alarm[] PROGMEM   = {0x00,0x04,0x0E,0x0E,0x0E,0x1F,0x04,0x00};

// ========================================================================================================================
// ========================================================================================================================
// DS3231

// функции преобразования чисел (для корректного отображения значений) ====================================================
unsigned char bcd (unsigned char data)
{
    unsigned char bc;

    bc=((((data&(1<<6))|(data&(1<<5))|(data&(1<<4)))*0x0A)>>4)+((data&(1<<3))|(data&(1<<2))|(data&(1<<1))|(data&0x01));

    return bc;
}

unsigned char bin(unsigned char dec){

    char bcd;

    char n, dig, num, count;

    num = dec;
    count = 0;
    bcd = 0;
    for (n=0; n<4; n++) {
        dig = num%10;
        num = num/10;
        bcd = (dig<<count)|bcd;
        count += 4;
    }

    return bcd;
}


// функции с часами =======================================================================================================

// инициализация начальных установок
void RTC_init(void){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x0E);            // передача адреса памяти
    i2c_send_byte(0b00100000);      // запустить преобразование температуры и выход на 1 Гц
    i2c_send_byte(0b00001000);      // разрешить выход 32 кГц
    i2c_stop_cond();                // остановка i2c

}


// получение времени и даты
void RTC_read_time(void){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x00);            // передача адреса памяти
    i2c_stop_cond();                // остановка i2c

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_read);    // передача адреса устройства, режим чтения
    sec = bcd(i2c_get_byte(0));     // чтение секунд, ACK
    min = bcd(i2c_get_byte(0));     // чтение минут, ACK
    hour = bcd(i2c_get_byte(0));    // чтение часов, ACK
    wday = bcd(i2c_get_byte(0));    // чтение день недели, ACK
    day = bcd(i2c_get_byte(0));     // чтение число, ACK
    month = bcd(i2c_get_byte(0));   // чтение месяц, ACK
    year = bcd(i2c_get_byte(1));    // чтение год, NACK
    i2c_stop_cond();                // остановка i2c

}


// установка времени
void RTC_write_time(unsigned char hour1,unsigned char min1, unsigned char sec1){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x00);            // передача адреса памяти
    i2c_send_byte(bin(sec1));       // 0x00 скунды (целесообразно ли задавать еще и секунды?)
    i2c_send_byte(bin(min1));       // 0x01 минуты
    i2c_send_byte(bin(hour1));      // 0x02 часы
    i2c_stop_cond();                // остановка i2c

}


// установка даты
void RTC_write_date(unsigned char wday, unsigned char day, unsigned char month, unsigned char year){

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x03);            // передача адреса памяти
    i2c_send_byte(bin(wday));       // 0x03 адень недели (воскресенье - 1, пн 2, вт 3, ср 4, чт 5, пт 6, сб 7)
    i2c_send_byte(bin(day));        // 0x04 день месяц
    i2c_send_byte(bin(month));      // 0x05 месяц
    i2c_send_byte(bin(year));       // 0x06 год
    i2c_stop_cond();                // остановка i2c

}

// чтение температуры
void RTC_read_temp(void){


    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_write);   // передача адреса устройства, режим записи
    i2c_send_byte(0x11);            // передача адреса памяти
    i2c_stop_cond();                // остановка i2c

    i2c_start_cond();               // запуск i2c
    i2c_send_byte(RTC_adr_read);    // передача адреса устройства, режим чтения
    t1 = i2c_get_byte(0);           // чтение MSB температуры
    t2 = i2c_get_byte(1);           // чтение LSB температуры
    i2c_stop_cond();                // остановка i2c

    t2=(t2>>7);                     // сдвигаем на 6 - точность 0,25 (2 бита)
    // сдвигаем на 7 - точность 0,5 (1 бит)
    t2=t2*5;

}


// вывод дня недели
void put_wday (void) {
    if (wday==1) {LCD_SendStr("Sun");}
    if (wday==2) {LCD_SendStr("Mon");}
    if (wday==3) {LCD_SendStr("Tue");}
    if (wday==4) {LCD_SendStr("Wed");}
    if (wday==5) {LCD_SendStr("Thu");}
    if (wday==6) {LCD_SendStr("Fri");}
    if (wday==7) {LCD_SendStr("Sat");}
}


//
// ========================================================================================================================
// ========================================================================================================================

ISR (TIMER0_OVF_vect)               // вектор прерывания по переполнеинию таймера 0
{

    BUT_Debrief ();                     // опрос 4х кнопок

}

int main (void)
{

    // инициализации
    LCD_Init();
    i2c_init();
    BUT_Init();
    RTC_init();


    // загрузить из eeprom значения будильника
    alarm_hour = eeprom_read_byte(&alarm_hour_ee);
    alarm_min = eeprom_read_byte(&alarm_min_ee);
    alarm_on = eeprom_read_byte(&alarm_on_ee);


    LCD_SetUserChar(alarm, 1);      // загружаем пользовательский символ в ОЗУ дисплея


    //инициализация таймера 0
    TCCR0 |= 0b00000101;            // Включаем предделитель 1/1024
    TIMSK |= 0b00000001;            // разрешаем прерывания по переполнению таймера T0.
    TCNT0=0;                        // Обнуляем счётный регистр таймера T0

    sei();                          // глобально разрешить прерывания

    main:
    LCD_Clear();


    while (1)
    {

        i=BUT_GetKey();

        // вывод времени
        RTC_read_time ();

        LCD_Goto(0,0);
        BCD_2Lcd(hour);
        LCD_WriteData(':');
        BCD_2Lcd(min);
        LCD_WriteData(':');
        BCD_2Lcd(sec);

        // вывод даты
        LCD_Goto(0,1);
        BCD_2Lcd(day);
        LCD_WriteData(',');
        BCD_2Lcd(month);
        LCD_WriteData(',');
        BCD_2Lcd(year);

        // вывод дня недели
        LCD_Goto(9,0);
        put_wday ();

        // вывод температуры
        RTC_read_temp();
        LCD_Goto(11,1);
        LCD_WriteData('+');
        BCD_2Lcd(t1);
        LCD_WriteData(',');
        BCD_1Lcd(t2);


        LCD_WriteData('*');

        // будильник
        if(alarm_on==1)      
 {
            if(alarm_hour==hour) 
 {
                if(alarm_min==min)   
 {
                    if(sec==1)          
  {
                        al=1;
                    }
                }
            }
        }


        // отображение включенности будильника
        if (alarm_on==1) {LCD_Goto(9,1); LCD_WriteData(1);}
        else {LCD_Goto(9,1); LCD_WriteData(' ');}


        // отключение сигнала будильника (сброс флага при нажатии кнопки 3)
        i=BUT_GetKey();

        if (i==3)
        { al=0; }


        // при сработке будильника совершит действие
        
 
            
                if (al==1)
                {
                    
                    DDRB |= (1 << PB1);
                    PORTB = 0x00;
                Delay_ms(50);
                
                Set_TEMP(3);       // установка темпа
                Play_LE(Dis4,LE8);
                Play_LE(Cis4,LE8);
                Play_LE(Fis3,LE4);
                Play_LE(Fis4,LE4);
                Play_LE(Fis4,LE4);
                Play_LE(Dis4,LE8);
                Play_LE(Cis4,LE8);
                Play_LE(Fis3,LE4);
                Play_LE(Fis4,LE4);
                Play_LE(Fis4,LE4);
                Play_LE(Dis4,LE8);
                Play_LE(Cis4,LE8);
                Play_LE(Fis3,LE4);
                Play_LE(Fis4,LE4);
                Play_LE(Dis3,LE4);
                Play_LE(Fis4,LE4);
                Play_LE(Cis3,LE4);
                Play_LE(F4,LE4);
                Play_LE(F4,LE4);
                _delay_ms(1000);
            }

        
        
        else
        {

             PORTB=0x00;
        }

        
        

        //=== дальше настройки =====================================================================================================
        //==========================================================================================================================
        // кнопка 1 заходит в меню и перелистывает уровни менюшки
        // кнопка 2 увеличивает переменную на 1 (защита от переполнения предусмотрена)
        // кнопка 3 немедленно выходит из меню настроек
        //


        if (i==1)
        {

            LCD_Clear();

            while (3)                           // настрока будильника
            {

                i=BUT_GetKey();

                if (i==1)
                {
                    j++;
                }

                if (i==3)                       // отменить и выйти
                {
                    i=0;
                    j=1;
                    goto main;
                }

                // индикация настроек будильника
                if (j==1) {LCD_Goto(6,1); LCD_SendStr("^^");}
                if (j==2) {LCD_Goto(6,1); LCD_SendStr("   ^^");}
                if (j==3) {LCD_Goto(9,1); LCD_SendStr("    ^^");}

                LCD_Goto(0,0);
                LCD_SendStr("Alarm");

                LCD_Goto(6,0);
                BCD_2Lcd(alarm_hour);
                LCD_WriteData(':');
                BCD_2Lcd(alarm_min);
                LCD_WriteData('-');
                if (alarm_on==1)
                { LCD_SendStr("on "); }
                else
                { LCD_SendStr("off"); }

                switch (j)
                {
                    case (1):
                    {
                        if (j!=1) {break;}
                        if (i==2)
                        {
                            
                            alarm_hour++;
                            if (alarm_hour>23) {alarm_hour=0;}
                            
                        }
                    }

                    case (2):
                    {
                        if (j!=2) {break;}
                        if (i==2)
                        {
                            
                            alarm_min++;
                            if (alarm_min>59) {alarm_min=0;}
                            
                        }
                    }

                    case (3):
                    {
                        if (j!=3) {break;}
                        if (i==2)
                        {
                            
                            alarm_on++;
                            if (alarm_on>1) {alarm_on=0;}
                            
                        }
                    }

                }


                if (j==4)                       // сохранить настройки и продолжить
                {
                    //сохранить значения в eeprom
                    eeprom_write_byte(&alarm_hour_ee, alarm_hour);
                    eeprom_write_byte(&alarm_min_ee, alarm_min);
                    eeprom_write_byte(&alarm_on_ee, alarm_on);
                    j=1;
                    LCD_Clear();
                    break;
                }

            }

            while (2)                           // настройка времени
            {

                i=BUT_GetKey();

                if (i==1)
                {
                    j++;
                }

                if (i==3)                       // отменить и выйти
                {
                    i=0;
                    j=1;
                    goto main;
                }

                // индикация настраевомого времени
                if (j==1) {LCD_Goto(6,1); LCD_SendStr("^^");}
                if (j==2) {LCD_Goto(6,1); LCD_SendStr("   ^^");}
                if (j==3) {LCD_Goto(8,1); LCD_SendStr("    ^^");}
                LCD_Goto(0,0);
                LCD_SendStr("Time");

                LCD_Goto(6,0);
                BCD_2Lcd(hour);
                LCD_WriteData(':');
                BCD_2Lcd(min);
                LCD_WriteData(':');
                BCD_2Lcd(sec);
                
                


                switch (j)
                {
                    case (1):
                    {
                        if (j!=1) {break;}
                        if (i==2)
                        {
                            
                            hour++;
                            if (hour>23) {hour=0;}
                            
                        }
                    }

                    case (2):
                    {
                        if (j!=2) {break;}
                        if (i==2)
                        {
                            
                            min++;
                            if (min>59) {min=0;}
                            
                        }
                    }
case (3):
{
    if (j!=3) {break;}
    if (i==2)
    {
        
        sec++;
        if (sec>59) {sec=0;}
        
    }
}
                }


                if (j==4)                       // сохранить настройки и продолжить
                {
                    RTC_write_time(hour, min, sec);
                    j=1;
                    LCD_Clear();
                    break;
                }


            }

            while (2)                           // настрока даты
            {

                i=BUT_GetKey();

                if (i==1)
                {
                    j++;
                }

                if (i==3)                       // отменить и выйти
                {
                    i=0;
                    j=1;
                    goto main;
                }

                // индикация настраиваемой даты и дня недели
                if (j==1) {LCD_Goto(5,1); LCD_SendStr("^^");}
                if (j==2) {LCD_Goto(5,1); LCD_SendStr("   ^^");}
                if (j==3) {LCD_Goto(8,1); LCD_SendStr("   ^^");}
                if (j==4) {LCD_Goto(11,1); LCD_SendStr("   ^^");}

                LCD_Goto(0,0);
                LCD_SendStr("Date");

                LCD_Goto(5,0);
                BCD_2Lcd(day);
                LCD_WriteData(',');
                BCD_2Lcd(month);
                LCD_WriteData(',');
                BCD_2Lcd(year);
                LCD_WriteData(' ');
                put_wday();


                switch (j)
                {
                    case (1):
                    {
                        if (j!=1) {break;}
                        if (i==2)
                        {
                            
                            day++;
                            if (day>31) {day=1;}
                            
                        }
                    }

                    case (2):
                    {
                        if (j!=2) {break;}
                        if (i==2)
                        {
                            
                            month++;
                            if (month>12) {month=1;}
                            
                        }
                    }

                    case (3):
                    {
                        if (j!=3) {break;}
                        if (i==2)
                        {
                            
                            year++;
                            if (year>40) {year=12;}
                            
                        }
                    }

                    case (4):
                    {
                        if (j!=4) {break;}
                        if (i==2)
                        {
                            
                            wday++;
                            if (wday>6) {wday=0;}
                            
                        }
                    }

                }


                if (j==5)                       // сохранить настройки и продолжить
                {
                    RTC_write_date (wday, day, month, year);
                    j=1;
                    LCD_Clear();
                    break;
                }

            }


        
                        

    }    //=== конец настроек =======================================================================================================
        //==========================================================================================================================


                    

    } // end while(1)
} // end main

                    

 

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...