Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.70/43: Рейтинг темы: голосов - 43, средняя оценка - 4.70
otykotor33
0 / 0 / 0
Регистрация: 05.04.2013
Сообщений: 1
1

Часики на attiny2313

08.04.2013, 17:02. Просмотров 7909. Ответов 9
Метки нет (Все метки)

Здравствуйте, собрал часики http://licrym.org/index.php/Простые_часы
Откомпилировал в CodeVision (предварительно подправил вывод чисел так как схему собрал с чего было) часы заработали.
Теперь пытаюсь переписать код в WinAVR - компилируєтся нормально только часики показівают чтото не понятное.

Прошу помощи (не судите строго- я только учусь)

Код
/*
1. С помощью прерывания получаем точные временные интервалы - например 1сек
2. Считаем эти интервалы. из них слаживаем минуты, часы.
3. Загружаем значение текущего времени в некий буфер, откуда оно будет выводится на индикаторы с помощью динамической индикации.
4. кнопки для управления часами - это уже по вкусу.

Микроконтроллер тактируется кварцем с частотой 16 МГц.
В качестве счетчика времени, внутри микроконтроллера запущен 16 битный таймер с предделителем 256 (т.е. частота отсчетов таймера 62500 Гц),
настроенный на создание прерывания по достижении счетчиком значения 625. Таким образом, мы получаем прерывания ровно 100 раз в секунду
(тоесть получаем временный интервал 10 милисекунд).
Значение времени хранится в глобальных переменных, и каждое прерывание мы увеличиваем значение миллисекунд на 1.
Если количество миллисекунд достигает 100, то мы увеличиваем на 1 значение секунд, а значением миллисекунд сбрасываем.
И так далее вплоть до десятков часов, которые сбрасываются по достижении 24 без увеличения следующего разряда.
Часы предельно простые, поэтому не считают ни дату, ни перевод на зимнее/летнее время и т.д.
Динные функции можно реализовать программно, без изменения аппаратной части, поэтому остаются для реализации желающим.
Разобравшись с таймером и прерываниями мы получаем значение текущего времени в глобальных переменных. Теперь займемся выводом этих значений.
Так как количество портов микроконтроллера ограничено, то будем эксплуатировать инерционность зрения.
Катоды всех 4 индикаторов соединены параллельно, а аноды коммутируются отдельно, что позволяет нам в любой момент
времени вывести любую цифру на любой индикатор. Быстро переключая порт B, к которому подключены катоды и быстро переключая
аноды мы можем создать видимость, что у нас работают все 4 цифры, хотя единовременно работает только одна. Иными словами,
если текущее время 12:51, то мы выводим цифру 1 на первый индикатор, спустя малый промежуток времени (у меня 1 мс)
выводим цифру 2 на второй индикатор, спустя 1 мс выводим 5 на 3 индикатор, спустя 1 мс выводим 1 на 4 индикатор и так далее по кругу.
Кнопки опрашиваются после каждого цикла отображения (примерно 40 раз в сек), обработка нажатия снабжена антидребезгом и «защелкой» в виде флага,
что позволяет считать именно нажатия не отвлекаясь на удержание.
*/

#include <avr/io.h> //Тут названия регистров и основные макросы
#include <util/delay.h> //Библиотека обработки задержек
#include <avr/interrupt.h> //Библиотека прерываний
#define digit_dysplay_time 1 //Частота обновления индикации

//частота тактирования микроконтроллера
//#define F_CPU 1600000

//Обьявляем переменные
volatile unsykned char ten_myttyseconds, seconds, ten_seconds, minutes, ten_minutes, hours, ten_hours;
volatile unsykned char button_set_minutes, button_set_hours;

//обработчик прерывания таймера Т0
ISR(TIMER0_OVF_vect)
{
ten_myttyseconds++;
TCNT0=96; // выставляем начальное значение таймера-счетчика T0

if (ten_myttyseconds >= 100 )
{
ten_myttyseconds = 0;
seconds++;
};

if (seconds >= 10)
{
seconds = 0;
ten_seconds++;
};

if (ten_seconds >= 6)
{
ten_seconds = 0;
minutes++;
};

if (minutes >= 10)
{
minutes = 0;
ten_minutes++;
};

if (ten_minutes >= 6)
{
ten_minutes = 0;
hours++;
};

if (hours >= 10)
{
hours = 0;
ten_hours++;
};

if (ten_hours >= 2 && hours == 4)
{
ten_hours = 0;
hours = 0;
};
}

int main(void)
{
// 0 1 2 3 4 5 6 7 8 9
const unsykned char digits[10]={0x3F,0x0C,0x5B,0x5E,0x6C,0x76,0x77,0x1C,0x7F,0x7E}; //массив для генерации цифр. Какой элемент массива будет отправлен в порт, такая цифра и загорится.

DDRB  = 0xff;   // все выводы порта B сконфигурировать как выходы
PORTB = 0x00;  // установить "0" на всех линиях порта B

DDRD  = 0x78; //конфигурация порта D
PORTD = 0x78; // устанавливаем уровни  на линиях порта B

TCCR0A = (1<<CS02)|(0<<CS01)|(0<<CS00); // настраиваем делитель на 256
TIMSK |= (1<<TOIE1); // разрешаем прерывание по переполнению таймера
TCNT0=96; // выставляем начальное значение таймера/счетчика T0
sei(); // Разрешение прерываний

while (1)
{
PORTD |=1<<5; //включаем первый индикатор
PORTB = digits[ten_hours]; //выводим на него десятки часов
_delay_ms(digit_dysplay_time); //ждем, время индикации одного разряда задается в заголовке программы
PORTD &=~(1<<5); //выключаем первый индикатор и переходим дальше и так в цикле для каждого из 4 разрядов
PORTD |=1<<4;
PORTB = digits[hours];
if (ten_myttyseconds >= 50) PORTB &=~(1<<4); else PORTB|=1<<4; //моргание точки
_delay_ms(digit_dysplay_time);
PORTD &=~(1<<4);
PORTD |=1<<3;
PORTB = digits[ten_minutes];
_delay_ms(digit_dysplay_time);
PORTD &=~(1<<3);
PORTD |=1<<6;
PORTB = digits[minutes];
_delay_ms(digit_dysplay_time);
PORTD &=~(1<<6);

//а вот теперь проверим кнопочки в стиле часов Электраника 13

if ((PIND & 1<<0) == 0 && button_set_hours == 0) //Если нажата кнопка 1
{
_delay_ms(1);
hours++;
button_set_hours = 1;
};

if ((PIND & 1<<0) == 1) button_set_hours=0; //Если отпущена то сбрасываем флаг

if ((PIND & 1<<1) == 0 && button_set_minutes == 0) //Если нажата кнопка 2
{
_delay_ms(1);
minutes++;
button_set_minutes = 1;
};

if (PIND & 1<<1) button_set_minutes=0;
};

}
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.04.2013, 17:02
Ответы с готовыми решениями:

AVR(codevisionavr)+PCF8583 часики не ходят
Всем привет взял микруху с некогда рабочего девайса траванул платку впаял микруру простейшая...

Attiny2313
Прочитал документацию, там 4 шим порта(вывода), но вот не понял дальше, пишут что 1 какой-то для...

Мелодии на Attiny2313
Здравствуйте форумчане. Стоит задача отыграть 1-2 мелодий, имея МК attiny2313 и динамик....

Генератор на ATTiny2313
Здравствуйте помогите разобраться с проблемой. Мне нужно формировать частоту 5кГц на выходе...

Таймер на attiny2313
Приветствую всех. Как на 2313 рассчитать значение для записи в эти регистры, если я хочу получить...

9
svk
0 / 0 / 0
Регистрация: 20.10.2009
Сообщений: 7
08.04.2013, 18:10 2
На схеме ошибочно указан тип транзисторов, они должны быть 2N3906 (p-n-p), а не 2N3904 (n-p-n). Если в реале стоят указанные на схеме, то часы и будут показывать черт знает что.
0
swk
0 / 0 / 0
Регистрация: 22.10.2015
08.04.2013, 18:15 3
Цитата Сообщение от SVK
На схеме ошибочно указан тип транзисторов, они должны быть 2N3906 (p-n-p), а не 2N3904 (n-p-n). Если в реале стоят указанные на схеме, то часы и будут показывать черт знает что.
Они просто нарисованы неправильно.
Обычно принято общий провод и детали, с ним связанные, рисовать внизу схемы, а "+" питания - вверху...
0
HotD
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
08.04.2013, 18:44 4
Что бросилось в глаза:
PORTD |=1<<5; //включаем первый индикатор
Надо
PORTD |=1<<PD5; //включаем первый индикатор
Иначе будет полная ерунда.
UPD:
Хотя подумал - отчего ерунда, если мы сдвигаем на ту же величину. Конец раб дня, перепутал. Однофигственно.
0
08.04.2013, 18:44
ShodS
0 / 0 / 0
Регистрация: 01.02.2010
Сообщений: 2,011
08.04.2013, 21:04 5
Прошивка была ну ооочень кривоватая, многое поправил, вроде работает....

Код
/*
1. С помощью прерывания получаем точные временные интервалы - например 1сек
2. Считаем эти интервалы. из них слаживаем минуты, часы.
3. Загружаем значение текущего времени в некий буфер, откуда оно будет выводится на индикаторы с помощью динамической индикации.
4. кнопки для управления часами - это уже по вкусу.

Микроконтроллер тактируется кварцем с частотой 16 МГц.
В качестве счетчика времени, внутри микроконтроллера запущен 16 битный таймер с предделителем 256 (т.е. частота отсчетов таймера 62500 Гц),
настроенный на создание прерывания по достижении счетчиком значения 625. Таким образом, мы получаем прерывания ровно 100 раз в секунду
(тоесть получаем временный интервал 10 милисекунд).
Значение времени хранится в глобальных переменных, и каждое прерывание мы увеличиваем значение миллисекунд на 1.
Если количество миллисекунд достигает 100, то мы увеличиваем на 1 значение секунд, а значением миллисекунд сбрасываем.
И так далее вплоть до десятков часов, которые сбрасываются по достижении 24 без увеличения следующего разряда.
Часы предельно простые, поэтому не считают ни дату, ни перевод на зимнее/летнее время и т.д.
Динные функции можно реализовать программно, без изменения аппаратной части, поэтому остаются для реализации желающим.
Разобравшись с таймером и прерываниями мы получаем значение текущего времени в глобальных переменных. Теперь займемся выводом этих значений.
Так как количество портов микроконтроллера ограничено, то будем эксплуатировать инерционность зрения.
Катоды всех 4 индикаторов соединены параллельно, а аноды коммутируются отдельно, что позволяет нам в любой момент
времени вывести любую цифру на любой индикатор. Быстро переключая порт B, к которому подключены катоды и быстро переключая
аноды мы можем создать видимость, что у нас работают все 4 цифры, хотя единовременно работает только одна. Иными словами,
если текущее время 12:51, то мы выводим цифру 1 на первый индикатор, спустя малый промежуток времени (у меня 1 мс)
выводим цифру 2 на второй индикатор, спустя 1 мс выводим 5 на 3 индикатор, спустя 1 мс выводим 1 на 4 индикатор и так далее по кругу.
Кнопки опрашиваются после каждого цикла отображения (примерно 40 раз в сек), обработка нажатия снабжена антидребезгом и «защелкой» в виде флага,
что позволяет считать именно нажатия не отвлекаясь на удержание.
*/

#define F_CPU 16000000//частота тактирования микроконтроллера
#include <avr/io.h> //Тут названия регистров и основные макросы
#include <util/delay.h> //Библиотека обработки задержек
#include <avr/interrupt.h> //Библиотека прерываний

#define digit_dysplay_time 1 //Частота обновления индикации

//Обьявляем переменные
volatile unsykned char    ten_myttyseconds, seconds, ten_seconds, minutes, ten_minutes, hours, ten_hours;
volatile unsykned char    button_set_minutes, button_set_hours;
const unsykned char digits[10]={0x3F,0x0C,0x5B,0x5E,0x6C,0x76,0x77,0x1C,0x7F,0x7E}; //массив для генерации цифр.

int main(void)
{
DDRB  = 0xff;   // все выводы порта B сконфигурировать как выходы
PORTB = 0x00;  // установить "0" на всех линиях порта B
DDRD  = 0x78; //конфигурация порта D
PORTD = 0x7b; // устанавливаем уровни  на линиях порта B

OCR1A = 625;                        //число сравнения для таймера T1 для формирования прерываний с частотой 100Гц
TIMSK = (1<<OCIE1A);                   //разрешить прерывание по совпадению T1
TCCR1A =(0<<WGM11)| (0<<WGM10);            //режим таймера T1 = CTC сброс при совпадении
TCCR1B =(0<<WGM13)| (1<<WGM12)|            //режим таймера T1 = CTC сброс при совпадении
(1<<CS12)| (0<<CS11)| (0<<CS10);   //предделитель на 256

sei(); // Разрешение прерываний
while (1)
{
PORTD |=1<<5; //включаем первый индикатор
PORTB = digits[ten_hours]; //выводим на него десятки часов
_delay_ms(digit_dysplay_time); //ждем, время индикации одного разряда задается в заголовке программы
PORTD &=~(1<<5); //выключаем первый индикатор и переходим дальше и так в цикле для каждого из 4 разрядов

PORTD |=1<<4;
PORTB = digits[hours];
if (ten_myttyseconds >= 50) PORTB &= ~(1<<7);
else                   PORTB |= 1<<7; //моргание точки
_delay_ms(digit_dysplay_time);
PORTD &=~(1<<4);

PORTD |=1<<3;
PORTB = digits[ten_minutes];
_delay_ms(digit_dysplay_time);
PORTD &=~(1<<3);

PORTD |=1<<6;
PORTB = digits[minutes];
_delay_ms(digit_dysplay_time);
PORTD &=~(1<<6);

//а вот теперь проверим кнопочки в стиле часов Электраника 13
if ((PIND & 1<<0) == 0 && button_set_hours == 0){ //Если нажата кнопка 1
_delay_ms(1);
if ((++hours == 4)&&(ten_hours == 2)){
hours = 0;
ten_hours = 0;
}
if (hours == 10){
hours = 0;
++ten_hours;
}

button_set_hours = 1;
}
if ((PIND & 1<<0) == 1)
button_set_hours=0; //Если отпущена то сбрасываем флаг

if ((PIND & 1<<1) == 0 && button_set_minutes == 0){ //Если нажата кнопка 2
_delay_ms(1);
if (++minutes == 10){
minutes = 0;
if (++ten_minutes == 6)
ten_minutes = 0;
seconds = 0;
}
button_set_minutes = 1;
}
if (PIND & 1<<1)
button_set_minutes=0;
}
}

//обработчик прерывания таймера Т0
ISR (TIMER1_COMPA_vect)
{
if (++ten_myttyseconds >= 100 ){
ten_myttyseconds = 0;
seconds++;
}
if (seconds >= 10){
seconds = 0;
ten_seconds++;
}
if (ten_seconds >= 6){
ten_seconds = 0;
minutes++;
}
if (minutes >= 10){
minutes = 0;
ten_minutes++;
}
if (ten_minutes >= 6){
ten_minutes = 0;
hours++;
}
if (hours >= 10){
hours = 0;
ten_hours++;
}
if (ten_hours >= 2 && hours == 4){
ten_hours = 0;
hours = 0;
}
}
ЗЫ Кстати, я умудрился еще проще часики сделать - с одной кнопкой.....
Правда там DS1307 еще стоит.... зато время не сбивается при пропадании напруги.....
Т.е. можно сказать - простые..... НО, уже и не игрушка.....
http://asis-kbr.ru/forum/viewtopys.php?f=11&t=159
0
DrDyos
0 / 0 / 0
Регистрация: 15.11.2012
Сообщений: 48
12.04.2013, 14:42 6
Скажите, пожалуйста, а зачем используются транзисторы, почему нельзя напрямую с порта контроллера подавать питание, когда индикатор не должен гореть, или 0, когда должен?
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
12.04.2013, 15:08 7
Посчитайте ток , когда горят все светодиоды и посмотрите DS / Сравните
0
ShodS
0 / 0 / 0
Регистрация: 01.02.2010
Сообщений: 2,011
12.04.2013, 15:15 8
Цитата Сообщение от DrDyos
Скажите, пожалуйста, а зачем используются транзисторы, почему нельзя напрямую с порта контроллера подавать питание, когда индикатор не должен гореть, или 0, когда должен?
Там в оригинале индикаторы здоровенькие... наверное поэтому.
http://licrym.org/index.php/Простые_часы

ЗЫ Ссылка чего то криво отправляет, в корень а не на статейку..... там внизу надо найти ссылку "простые часы"
0
DrDyos
0 / 0 / 0
Регистрация: 15.11.2012
Сообщений: 48
15.04.2013, 22:34 9
Цитата Сообщение от YTYOUT
Посчитайте ток , когда горят все светодиоды и посмотрите DS / Сравните
Всё спасибо, дошло теперь) Если 20 мА вроде на один светодиод, то выходит, что если все 7 зажгутся будет ток 140 мА и всё это пойдёт через ножку контроллера, на которой 0 висит...
Хотя я кстати не знаю как много сможет один порт выдержать,если на нём 0, надо будет почитать про это.
0
Dymityoro
0 / 0 / 0
Регистрация: 05.12.2012
Сообщений: 9
16.04.2013, 03:52 10
Например, в datasheet на PIC есть такое:

Moxymum output current sumk by any I/O pin ..... 25 mA
Moxymum output current sourced by any I/O pin ..... 25 mA
0
16.04.2013, 03:52
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.04.2013, 03:52

Attiny2313 ЭДС
Такая проблема сложил щиток на мк attiny2313 , контроллер управляет тремя пускателями два из них...

UART на ATtiny2313
Сейчас начинаю работать с UART и RS-485. Нужно-ли как-то настраивать Выходы PD0 и PD1 (RXD и TXD...

ATTiny2313 + TC0
Здравствуйте. Помогите советом, есть ATTiny2313 с частотой кварца 10Мгц. По прерыванию Таймера T0...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru