Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
03.09.2011, 11:55
|
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Godzilla82,
Большое спасибо, все работает, только индикация обратного счета работает как-то не так. С операторами присваивания в СИ я до конца еще не разобрался, желательно, что бы загоралась при включении тумблера REVERSE и при отключении гасла. Только индикация, все остальное работает нормально!
|
|
|
|
03.09.2011, 18:56
|
|
Почётный гражданин KAZUS.RU
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Я сделал так, чтобы настройки считывались в момент нажатия кнопки "Пуск". То есть, если во время счёта нажать на кнопку "Направление счёта" ничего не произойдёт.
Ну и немного улучшил поведение на нажатие "+" и "-".
PHP код:
|
#include ‹mega8.h›
#include ‹delay.h›
#define ZUMMER 0b00000100
#define WORK 0b00001000
#define REVERSE 0b00010000
unsigned char font[] = {0b11000000,0b11111001,0b10100100,0b10110000,0b100 11001,0b10010010,0b10000010,0b11111000,0b10000000, 0b10010000}; //знакогенератор OA.
unsigned char clock[4] = {0,0,0,0};
signed char start = 0;
unsigned char beep = 0;
unsigned char trigger = 0;
unsigned char x = 0;
unsigned char tik;
unsigned int time;
// динамическая индикация
//
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
x++;
x &= 0x03;
PORTB = 0xFF; // обнуляем порт
PORTD = (PORTD & 0xFC) | x; // выводим двоичный код для дешифраторов
PORTB = font[clock[x]]; // выводим цифры
if(x == 2) PORTB.7 = trigger & start; // выводим точку
}
// отсчет времени
// 200 мс
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
unsigned char sec,min;
tik++;
if (tik › 4) {
tik = 0;
trigger ^= 1;
time += start;
if (time › 5999) { // окончание счёта
if(start == -1) beep = 1; // включаем динамик, если был обратный отсчёт
start = 0;
time = 0;
PORTC &= ~WORK; // выключение индикатора "счёт"
}
sec = time % 60;
min = time / 60;
clock[0] = sec % 10;
clock[1] = sec / 10;
clock[2] = min % 10;
clock[3] = min / 10;
}
}
// Timer2: 1 мс
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
if((beep) && (trigger)) PORTC ^= ZUMMER; //по окончанию обратного счета сигнал 1 кГц
else PORTC &= ~ZUMMER;
}
void main(void)
{
unsigned char k1,k2,sec,min;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x13;
DDRC = 0x3C;
PORTD = 0xF0;
DDRD = 0x0F;
// Timer0: 125 kHz
TCCR0 = 0x03;
TCNT0 = 0x00;
// Timer1: 125 kHz
TCCR1A = 0x00;
TCCR1B = 0x0B;
TCNT1H = 0x00;
TCNT1L = 0x00;
ICR1H = 0x00;
ICR1L = 0x00;
OCR1AH = 0x61;
OCR1AL = 0xA8;
OCR1BH = 0x00;
OCR1BL = 0x00;
// Timer2: 125 kHz
TCCR2 = 0x8C;
TCNT2 = 0x00;
OCR2 = 0x3D;
TIMSK = 0x91;
ACSR = 0x80;
ASSR = 0x00;
#asm("sei")
begin:
if(!PINC.1) { // стоп
start = 0;
beep = 0; // отключаем динамик
PORTC &= ~WORK; // выключение индикатора "счёт"
}
if(!PIND.5) { // сброс
start = 0;
time = 0;
beep = 0; // отключаем динамик
PORTC &= ~WORK; // выключение индикатора "счёт"
}
if(start) goto begin; // повторный запуск только после сброса или останова
if(!PINC.0) { // старт
if(PIND.4 == 1) start = 1;
else start = -1;
beep = 0; // отключаем динамик
PORTC |= WORK; // включение индикатора "счёт"
}
if(PIND.4) PORTC |= REVERSE; // индикация обратного счета
else PORTC &= ~REVERSE;
sec = time % 60;
min = time / 60;
if (!PIND.7) {
if((k1 == 0) || (k1 == 20) ) {
sec++;
sec %= 60;
}
if (k1 ‹ 20) k1++;
}
else k1 = 0;
if (!PIND.6) {
if((k2 == 0) || (k2 == 20) ) {
min++;
min %= 100;
}
if (k2 ‹ 20) k2++;
}
else k2 = 0;
#asm("cli")
time = min * 60 + sec;
clock[0] = sec % 10;
clock[1] = sec / 10;
clock[2] = min % 10;
clock[3] = min / 10;
#asm("sei")
delay_ms(100);
goto begin;
}
|
|
|
|
|
04.09.2011, 12:55
|
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Godzilla82,
CVAVR выдает предупреждение:
Цитата:
|
Локальная переменная 'k1' (к2) используется прежде, чем это значение будет устанавливаться.
|
и
Цитата:
|
Локальная переменная 'k1' (k2) была установлена, но не использовалась.
|
Пробовал задать начальное значение к1 и к2 =0, остается только второе предупреждение.
Пытаюсь разобраться с выражением
Код:
|
if (!PIND.7) {
if((k1 == 0) || (k1 == 20) ) {
sec++;
sec %= 60;
}
if (k1 ‹ 20) k1++;
}
else k1 = 0; |
Если нажата кнопка и к1 меньше 20, идет счет к1. Если к1 равно 0 или 20, прибавляются секунды. Кнопка не нажата - к1 равно 0. Так ли я понял? Но смысла не уловил. И что считает к1?
Из учебника:
Цитата:
|
| | // "ИЛИ" - только "ложь" и "ложь" дают "ложь"
|
к1 =0 это 0, к1=20 это 0, секунды считает или нет?
Для меня было все просто с дискретными микросхемами, здесь приходится перестраивать логику мышления. Тяжеловато.
|
|
|
|
04.09.2011, 16:53
|
|
Почётный гражданин KAZUS.RU
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Сообщение от Dimitrij
|
Пробовал задать начальное значение к1 и к2 =0
|
Это не лишне, но и не принципиально. Если кнопка отжата - само сбросится.
Сообщение от Dimitrij
|
Если нажата кнопка и к1 меньше 20, идет счет к1. Если к1 равно 0 или 20, прибавляются секунды. Кнопка не нажата - к1 равно 0. Так ли я понял? Но смысла не уловил. И что считает к1?
|
При коротком нажатии (менее 2 сек) секунды увеличатся на 1. Если удерживать кнопку - будет ускоренное увеличение секунд.
Сообщение от Dimitrij
|
Из учебника:
к1 =0 это 0, к1=20 это 0, секунды считает или нет?
Для меня было все просто с дискретными микросхемами, здесь приходится перестраивать логику мышления. Тяжеловато.
|
k1=0 и k1 == 0 совершенно разные вещи.
У вас в железе устройство есть?
Можно ещё упростить:
PHP код:
|
// отсчет времени
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
unsigned char sec,min;
trigger ^= 1;
time += start;
if (time › 5999) { // окончание счёта
if(start == -1) beep = 1; // включаем динамик, если был обратный отсчёт
start = 0;
time = 0;
PORTC &= ~WORK; // выключение индикатора "счёт"
sec = time % 60;
min = time / 60;
clock[0] = sec % 10;
clock[1] = sec / 10;
clock[2] = min % 10;
clock[3] = min / 10;
}
}
// Timer1: 31250 Hz
// 1000 ms
TCCR1A = 0x00;
TCCR1B = 0x0C;
TCNT1H = 0x00;
TCNT1L = 0x00;
ICR1H = 0x00;
ICR1L = 0x00;
OCR1AH = 0x7A;
OCR1AL = 0x11;
OCR1BH = 0x00;
OCR1BL = 0x00;
|
P.S. Зуммер надо было делать не прерываниями, а аппаратным счётчиком (выходы OCR1A, OCR1B, OCR2).
Последний раз редактировалось Godzilla82; 04.09.2011 в 20:23.
|
|
|
|
05.09.2011, 13:45
|
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Сообщение от Godzilla82
|
При коротком нажатии (менее 2 сек) секунды увеличатся на 1. Если удерживать кнопку - будет ускоренное увеличение секунд.
|
Теперь код понятен. А это
Сообщение от Godzilla82
|
k1=0 и k1 == 0 совершенно разные вещи.
|
не так написал, здесь я уже разобрался.
Сообщение от Godzilla82
|
У вас в железе устройство есть?
|
Еще нет, проверяю в протеус.
Сообщение от Godzilla82
|
Зуммер надо было делать не прерываниями, а аппаратным счётчиком (выходы OCR1A, OCR1B, OCR2).
|
Когда экспериментировал со счетчиками, выводил OCR2 на зуммер. Но, чтобы получить 1000 ГЦ, все равно используется прерывание по совпадению?
Порты то я переназначу на любые, а код управления сильно надо менять?
В этой части кода
Код:
|
time += start;
if (time › 5999) { // окончание счёта
if(start == -1) beep = 1; // включаем динамик, если был обратный отсчёт
start = 0;
time = 0;
PORTC &= ~WORK; // выключение индикатора "счёт"
sec = time % 60;
min = time / 60;
clock[0] = sec % 10;
clock[1] = sec / 10;
clock[2] = min % 10;
clock[3] = min / 10;
} |
поменял местами вывод показаний на индикаторы,
Код:
|
time += start;
sec = time % 60;
min = time / 60;
clock[0] = sec % 10;
clock[1] = sec / 10;
clock[2] = min % 10;
clock[3] = min / 10;
if (time › 5999) { // окончание счёта
if(start == -1) beep = 1; // включаем динамик, если был обратный отсчёт
start = 0;
time = 0;
PORTC &= ~WORK; // выключение индикатора "счёт"
} |
а то реальные показания появлялись только по окончании счета. Так нормально?
|
|
|
|
05.09.2011, 16:42
|
|
Почётный гражданин KAZUS.RU
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Сообщение от Dimitrij
|
Когда экспериментировал со счетчиками, выводил OCR2 на зуммер. Но, чтобы получить 1000 ГЦ, все равно используется прерывание по совпадению?
|
Прерывание вообще не используется.
Сообщение от Dimitrij
|
Порты то я переназначу на любые, а код управления сильно надо менять?
|
Естесственно.
Сообщение от Dimitrij
|
поменял местами вывод показаний на индикаторы,
а то реальные показания появлялись только по окончании счета. Так нормально?
|
Не совсем. При окончании счёта будет показываться предыдущее значение. Надо после условия if() {...}.
|
|
|
|
05.09.2011, 17:18
|
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Сообщение от Godzilla82
|
Прерывание вообще не используется.
|
Может я задаю глупые вопросы, но ведь таймер2 настраивается на прерывание по совпадению?
Сообщение от Godzilla82
|
Надо после условия if() {...}.
|
Поменял:
PHP код:
|
time += start;
if (time › 5999) { // окончание счёта
if(start == -1) beep = 1; // включаем динамик, если был обратный отсчёт
start = 0;
time = 0;
PORTC &= ~WORK; // выключение индикатора "счёт"
}
sec = time % 60;
min = time / 60;
clock[0] = sec % 10;
clock[1] = sec / 10;
clock[2] = min % 10;
clock[3] = min / 10;
}
|
Так?
В общем, буду пробовать, что не получится, напишу.
|
|
|
|
05.09.2011, 20:43
|
|
Почётный гражданин KAZUS.RU
Регистрация: 29.10.2006
Сообщений: 1,446
Сказал спасибо: 99
Сказали Спасибо 317 раз(а) в 233 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Сообщение от Dimitrij
|
Может я задаю глупые вопросы, но ведь таймер2 настраивается на прерывание по совпадению?
|
Таймер настраивается так, чтобы при достижении OCR2 происходил сброс (режим CTC). При этом также происходит изменение состояния выхода OC2 на противоположное. Прерывание не используется. То есть, флаг разрешения прерывания сброшен и обработчика прерывания нет.
Сообщение от Dimitrij
|
Так?
|
Да.
|
|
|
|
06.09.2011, 10:42
|
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Godzilla82,
Спасибо, попытаюсь переписать программу!
|
|
|
|
06.09.2011, 18:36
|
|
Временная регистрация
Регистрация: 26.02.2005
Сообщений: 78
Сказал спасибо: 15
Сказали Спасибо 16 раз(а) в 16 сообщении(ях)
|
Re: Счетчик-таймер на ATtiny
Godzilla82,
Программу переписал, все работает, на ОС2 выводится частота 1кГц. Можно ли сделать так, чтобы она выводилась как и прежде, только при условии if((beep) && (trigger)) ? Я что-то не соображу как. Или навешивать дополнительно схему совпадения?
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 02:15.
|
|