Часы на Attiny 13 + DS1307

Обсуждаем контроллеры компании Atmel.
Ответить
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

Часы на Attiny 13 + DS1307

Сообщение Jman »

Доброго времени суток. Собираю часы на Attiny 13 + DS1307, которые должны слать набор байт по usart на другой МК к которому прикручен дисплей и прочая переферия. Я написал следующий код:

Библиотека для работы с I2C взята из проекта https://radiokot.ru/circuit/digital/home/239/:
Спойлер

Код: Выделить всё

#define SCL     3
#define SDA     4
#define ACK     1
#define NACK    0
 
#define SCL_HIGH    DDRB&=~(1<<SCL)
#define SCL_LOW     DDRB|=(1<<SCL)
#define SDA_HIGH    DDRB&=~(1<<SDA)
#define SDA_LOW     DDRB|=(1<<SDA)
#include <avr/io.h>
#include "TWI.h"
 
unsigned char k = 0;
 
void i2c_start (void)
{
    SCL_HIGH;
    SDA_HIGH;
    SDA_LOW;
    SCL_LOW;
}
 
void i2c_stop (void)
{
    SDA_LOW;
    SCL_HIGH;
    SDA_HIGH;
}
 
void i2c_send_byte (unsigned char data)
{
    SCL_LOW;
    for(k=8;k>0;k--)
    {
        if(data&(1<<(k-1))) SDA_HIGH;
        else SDA_LOW;
        SCL_HIGH;
        SCL_LOW;
    }
    SCL_HIGH;
    SCL_LOW;
}
 
unsigned char i2c_receive_byte (unsigned char ACK_NACK)
{
    unsigned char out_data=0;
    SCL_LOW;
    for(k=8;k>0;k--)
    {
        SCL_HIGH;
        if(PINB&(1<<SDA)) out_data|=(1<<(k-1));
        else out_data&=~(1<<(k-1));
        SCL_LOW;
    }
    if(ACK_NACK) SDA_LOW;
    else SDA_HIGH;
    SCL_HIGH;
    SCL_LOW;
    SDA_HIGH;
 
    return out_data;
}
Основная программа:
Спойлер

Код: Выделить всё

#ifndef F_CPU
# define F_CPU 1200000UL // 1.2 MHz
#endif  /* !F_CPU */
 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
#include "uart.h"
#include "DS1307.h"
#include "TWI.h"
 
int main(void)
{
    char* time;
    char s;
    
    DDRB  = (0<<PINB5) | (0<<PINB4) | (0<<PINB3) | (0<<PINB2) | (0<<PINB1) | (0<<PINB0);    
    PORTB = (0<<PINB5) | (0<<PINB4) | (0<<PINB3) | (1<<PINB2) | (0<<PINB1) | (0<<PINB0);
    
    GIMSK=(1<<PCIE);    // кнопка
    PCMSK=(1<<PCINT3);  
    
    while (1)
    {
        i2c_start();
        i2c_send_byte(0xD0);        //отправить адрес устройства с 0 = запись
        i2c_send_byte(1);           //отправить № байта, с которого начнём работать
        i2c_start();
        i2c_send_byte(0xD1);        //отправить адрес устройства с 1 = чтение
        time[0] = i2c_receive_byte(1);  //считать минуты
        time[1] = i2c_receive_byte(0);  //считать секунды
        i2c_stop();
              
         uart_putc(time[1]);
        
        _delay_ms(1000);
    }
}
Библиотеку для работы с программным USART -> взял https://github.com/lpodkalicki/attiny13 ... ibraryЛиба вроде рабочая, пробовал передавать и строку и символы в Proteus, в терминал все приходит корректно.
Но если выводить буфер часов минуты или секунды, функция uart_putc в Proteus постоянно выводит в HEX что-то не понятное. Если в uart_putc вставить любой символ -> то HEX код символа передается в терминал верно. Видимо где-то не правильно читаю часики? В чем может быть проблема? по идее мне надо прочитать часы, минуты и каждый элемент массива отправить через uart_putc(аргумент); через определенный квант времени? В либе USART еще есть функция uart_puts(аргумент) которая выводит строку. Какой алгоритм лучше использовать?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение ARV »

во-первых, почему считывается в НУЛЕВОЙ элемент массива ПЕРВЫЙ байт памяти часов, а в ПЕРВЫЙ элемент - НУЛЕВОЙ байт? ну в чем смысл? тут самое то начинать с нулевого байта памяти часов и последовательно, т.е. без указания номера следующего, считывать сколько надо следующих. но это придирки, конечно

во-вторых, вам нужно время именно в BCD-формате или в "человеческом"? считываете вы BCD, а для человека надо символы, т.е. надо преобразовывать полученное число в строку хотя бы при помощи itoa, а уж потом выводить строку.

в-третьих, если у вас нет каких-то хитрых целей, вычитывать время из часов непрерывно в цикле нет никакой нужды. я всегда использую режим часов, когда они на своем выходе формируют меандр с частотой 1 Гц - опрашивая (или по прерываниям) этот пин можно точно знать, что прошла секунда и надо обновить время - это логично.

не знаю, помогут ли мои советы решить вашу проблему... но я бы советовал к ним прислушаться.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение Jman »

[uquote="ARV",url="/forum/viewtopic.php?p=4203474#p4203474"]не знаю, помогут ли мои советы решить вашу проблему... но я бы советовал к ним прислушаться.[/uquote]
Благодарю! Да, советы действительно полезные!
во-вторых, вам нужно время именно в BCD-формате или в "человеческом"? считываете вы BCD, а для человека надо символы, т.е. надо преобразовывать полученное число в строку хотя бы при помощи itoa, а уж потом выводить строку.
Я вообще думаю, перевести из BCD сформировать строку и отправлять по UART.
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение GoldenAndy »

ARV, а смысл считать время вручную?
Код чтения времени из часов уже есть. Он нужен для стартового чтения.
Зачем еще придумывать код своих часов? А если с календарем, то еще и счёт календаря?
Неужто чтение раз в секунду времени из МС часов так сильно изнашивает их?
В 99% домашних поделок МК не загружен настолько сильно, что бы не уделить несколько миллисекунд для чтения данных по и2ц...
На скорости 100 кГц чтение байта по и2ц - порядка 100 мкс. 10 байт - миллисекунда.... На 400 кГц - еще быстрее...
Зачем дулбировать программно уже реализованный в железе функционал?
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение ARV »

GoldenAndy писал(а):а смысл считать время вручную?
то ли я сказал непонятно, то ли вы о своём думаете...
GoldenAndy писал(а):На скорости 100 кГц чтение байта по и2ц - порядка 100 мкс. 10 байт - миллисекунда.... На 400 кГц - еще быстрее...
по-вашему разумным выходит делать примерно 1000 чтений абсолютно одинакового результата в секунду, чем спокойно дождаться, когда значение обновится и считать 1 раз новое?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение GoldenAndy »

ARV, зачем 1000????
Или по 1 сек с вашего вывда 1 гц - это если есть желание заводить этот 1 гц в мк.
Или по своим внутренним алгоритмам, тоже раз в секунду...
Основная программа ж крутится в каком то цикле... И этот цикл, теоретически, привязан ко времени выполнения. Вот там, раз в секунду читать время.
А если это тупо первичные часы, у которых никакой другой работы нет, кроме как читать время - то тут пофиг.
Или ждать импульс 1 Гц на каком то входе, или тупо в цикле читать данные из часов, запомнив показания секунд из прошлого чтения.
Как только секунды поменялись - выплюнуть в УАРТ.
Тут же еще фишка - для программного счета времени нужно стабильное тактирование. Т.е. еще и кварц лепить.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение ARV »

GoldenAndy писал(а):Вот там, раз в секунду читать время.
прошу прощения: а нафига тогда внешний RTC? если программно считать секунды, то и внешний RTC не нужен. как правило, главный цикл, если его специально не тормозить, прокручивается за миллисекунды даже при большой нагрузке... 1 секунда - слишком много даже для дохленького AVR. поэтому, раз уж тормозить, почему бы не тормозить по сигналу от часов? часы сказали "у меня есть новое время!" - отреагировать на это, часы молчат - делать свои темные дела... ну, или, если делать нечего - спать или ждать...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
GoldenAndy
Поставщик валерьянки для Кота
Сообщения: 1925
Зарегистрирован: Чт июл 28, 2016 07:58:37
Откуда: Kyiv, UA
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение GoldenAndy »

Всё зависит от задачи. Если это батарейка - то да - проснуться от RTC, прочитать время, віплюнуть его и спать дальше.
Если питание нормальное - то тут пофиг, ждать 1 Гц, отсчитівать 1000мс delay-ами или постоянно опрашивать RTC.
Это пофиг.

А вот в дополнение к RTC считать своё время и календарь средствами МК, как на форуме некоторые советуют - лишнее.

ЗЫ. Я не совсем внимательно прочел вашу фразу про использование прерывания и почему то подумал, что вы предлагаете по этим 1 Гц считать время средствами МК. Сорри.
ИзображениеИзображение
Изображение
 
Telegram               Лучшая благодарность ->
[+]
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение Jman »

Так как нет свободных ног, решил примерно раз в 5 сек опрашивать часы и передавать в UART.

Код: Выделить всё

#ifndef F_CPU
# define F_CPU 1200000UL // 1.2 MHz
#endif  /* !F_CPU */

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#include "uart.h"
#include "DS1307.h"
#include "TWI.h"

const uint8_t WORK_TIME = 25;    //  1200000/1024/256=3.8  (0.026 сек)    12/0.26=46,15 = 10 сек, для 1 секунды = 4-5
volatile uint8_t tick = 0;
volatile unsigned char hour, minute, second;

volatile unsigned char* time;
volatile unsigned char* buffer;

ISR(TIM0_OVF_vect)
{
	tick++;

	if(tick >= WORK_TIME){
		time = rtc_read();

		second = (((time[0] & 0xF0) >> 4)*10)+(time[0] & 0x0F);
		minute = (((time[1] & 0xF0) >> 4)*10)+(time[1] & 0x0F);
		
		itoa(minute, buffer, 10); // ???? хз....
		uart_puts(buffer);
		tick = 0;
	}
}

int main(void)
{
	DDRB  = (0<<PINB5) | (0<<PINB4) | (0<<PINB3) | (0<<PINB2) | (0<<PINB1) | (0<<PINB0);	
	PORTB = (0<<PINB5) | (0<<PINB4) | (0<<PINB3) | (1<<PINB2) | (0<<PINB1) | (0<<PINB0);
			
	GIMSK=(1<<PCIE);	//Захват кнопки
	PCMSK=(1<<PCINT3);	//по прерыванию
	
	TCCR0B |= (1<<CS02) | (1<<CS00); // предделитель на 1024 (CLK=1200000Hz/1024/256=4Hz, 0.25s)
	TIMSK0 |= (1<<TOIE0); // переполнение по таймеру
	sei();
			
	while (1){
		
	}
}
Гоняю в протеусе, железа нет. Прерывание отрабатывает, читаются часики, но как понять, визуально в терминале Protes понять, правильное ли время. Сейчас выводиться какая-то дичь...
Вот код чтения:

Код: Выделить всё

#define	ACK		1
#define	NACK	0
volatile char time[2];
char* rtc_read (void){
	i2c_start();
	i2c_send_byte(0xD0);		//отправить адрес устройства с 0 = запись
	i2c_send_byte(1);			//отправить № байта, с которого начнём работать
	i2c_start();
	i2c_send_byte(0xD1);		//отправить адрес устройства с 1 = чтение
	time[0] = i2c_receive_byte(ACK);	//считать минуты
	time[1] = i2c_receive_byte(NACK);	//считать часы
	i2c_stop();
	
	return time;
}
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение ARV »

у вас beffer - это указатель, а где память, на которую он указывает? объявите так char buffer[7]; хотя бы...

Добавлено after 1 minute 34 seconds:
ну и вообще: из обработчика прерываний вызывать "долгоиграющие" функции - не комильфо... ставьте в обработчике прерываний флаг, а в главном цикле читайте часы, выводите и сбрасывайте флаг... собственно, флагом может быть прямо флаг запроса прерывания, тогда обработчик вообще не нужен...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение Jman »

А само чтение часов же вроде верно организовано?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение Jman »

Сделал так. Передает часы и минуты в уарт. Готов получить порцию рациональной критики:

Код: Выделить всё

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

#include "uart.h"
#include "DS1307.h"
#include "TWI.h"

#define TIME_SIZE 2
#define BUFFER_SIZE 7
#define TRUE 1
#define FALSE 0


const uint8_t WORK_TIME = 25;    //  1200000/1024/256=3.8  (0.026 сек)    12/0.26=46,15 = 10 сек, для 1 секунды = 4-5
volatile uint8_t tick = 0;
volatile unsigned char hour, minute, second;

unsigned char data[TIME_SIZE];
volatile unsigned char buffer[BUFFER_SIZE];
volatile uint8_t isRead = FALSE;

void mcu_int(void);
int main(void);

ISR(TIM0_OVF_vect)
{
	tick++;

	if(tick >= WORK_TIME){
		isRead = TRUE;
		tick = 0;
	}
}

int main(void)
{
	mcu_int();
	
	while (1){
		if(isRead){
			
			cli();
			rtc_read(&data); 
			second = (((data[1] & 0xF0) >> 4)*10)+(data[1] & 0x0F);
			minute = (((data[0] & 0xF0) >> 4)*10)+(data[0] & 0x0F);
			itoa(second, buffer, 10);
			uart_puts(buffer);
			itoa(minute, buffer, 10);
			uart_puts(buffer);
			
			isRead = FALSE;
			sei();
		}
	}
}

void mcu_int(void){
	DDRB  = (0<<PINB5) | (0<<PINB4) | (0<<PINB3) | (0<<PINB2) | (0<<PINB1) | (0<<PINB0);
	PORTB = (0<<PINB5) | (0<<PINB4) | (0<<PINB3) | (1<<PINB2) | (0<<PINB1) | (0<<PINB0);
	
	GIMSK=(1<<PCIE);	//Захват кнопки
	PCMSK=(1<<PCINT3);	//по прерыванию
	
	TCCR0B |= (1<<CS02) | (1<<CS00); // предделитель на 1024 (CLK=1200000Hz/1024/256=4Hz, 0.25s)
	TIMSK0 |= (1<<TOIE0); // переполнение по таймеру
	sei();
}
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение ARV »

sei() один раз перед главным циклом, а cli() вообще не нужно. а в остальном - работает? ну и чудно! видно, что кое-что у вас уже по полочкам улеглось.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Jman
Мучитель микросхем
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря
Контактная информация:

Re: Часы на Attiny 13 + DS1307

Сообщение Jman »

[uquote="ARV",url="/forum/viewtopic.php?p=4206022#p4206022"]sei() один раз перед главным циклом, а cli() вообще не нужно.[/uquote]
Да, но почему-то в Протеусе без запрета глобальных прерываний не фурычит. Уже в железе буду проверять.
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Аватара пользователя
Карбофос
Опытный кот
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Re: Часы на Attiny 13 + DS1307

Сообщение Карбофос »

rtc_read(&data); - data и так есть указатель на область данных, ошибка?
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Часы на Attiny 13 + DS1307

Сообщение Dimon456 »

Jman писал(а):Да, но почему-то в Протеусе без запрета глобальных прерываний не фурычит.
Но если вы вот это используете[uquote="Jman",url="/forum/viewtopic.php?p=4203469#p4203469"]Библиотека для работы с I2C взята из проекта https://radiokot.ru/circuit/digital/home/239/:

Код: Выделить всё

#define SCL     3
#define SDA     4
#define ACK     1
#define NACK    0
 
#define SCL_HIGH    DDRB&=~(1<<SCL)
#define SCL_LOW     DDRB|=(1<<SCL)
#define SDA_HIGH    DDRB&=~(1<<SDA)
#define SDA_LOW     DDRB|=(1<<SDA)
#include <avr/io.h>
#include "TWI.h"
 
void i2c_start (void)
{
    SCL_HIGH;
    SDA_HIGH;
    SDA_LOW;
    SCL_LOW;
} 
[/uquote]то ни чего удивительного.
Аватара пользователя
Карбофос
Опытный кот
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Re: Часы на Attiny 13 + DS1307

Сообщение Карбофос »

Мне кажется, ничего страшного в этом фрагменте кода нет.
Возможно, передавая неправильную ссылку, что-то в SREG или хз куда пишется.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Часы на Attiny 13 + DS1307

Сообщение Dimon456 »

Не стал полностью код цитировать, но раз в Attiny13 нет аппаратного i2c, значит используется "ногодрыг", которому прерывание и как раз мешает. Лучше бы Attiny25 поставил.
Аватара пользователя
Карбофос
Опытный кот
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Re: Часы на Attiny 13 + DS1307

Сообщение Карбофос »

[uquote="Jman",url="/forum/viewtopic.php?p=4205527#p4205527"]Так как нет свободных ног[/uquote]
Вы ведь ничего по уарту не получаете? Вот и нога свободная появилась.

Код: Выделить всё

#define DS3231_REG_CONTROL      0x0E    // Control register

I2C_write(DS3231_REG_CONTROL);
I2C_write(0);   // SQUARE-WAVE OUTPUT FREQUENCY 1 Hz
Записываем в Control Register (0Eh) 0, получаем 1 Гц на ножке 32kHz, по заднему фронту считываем текущее время.
Ответить

Вернуться в «AVR»