реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Таймер на Atmega8, Работает при симуляции, но не работает в железе
shatov
сообщение Oct 16 2013, 03:19
Сообщение #1





Группа: Новичок
Сообщений: 5
Регистрация: 17-09-13
Пользователь №: 78 360



Таймер на Atmega8.

Таймер должен считать дни, питание от 3В. При нажатии на кнопку INT0 высвечивается счет секунд (нужно для проверки работоспособности таймера), при повторном нажатии высвечиваются отсчитанные дни. В спящий режим таймер переходит при нажатии на кнопку в третий раз, либо по истечении 5 сек с момента нажатия на кнопку в первый раз:

if (secL==5) {flagbutton=0;}
if (secL>9) {secH++; secL=0; flagbutton=0;}


Также необходим reset, но не замыканием соответствующего вывода на землю, а так, чтобы человек перепутав кнопки не сбросил свое насчитанное. Поэтому Reset осуществляется при последовательном нажатии int0 и зажимании PB5, т.е. нажав только PB5 таймер не сбросить.

Два индикатора: на одном отображаются единицы (PORTC), на другом - десятки (PORTD).
Т.к. питание от двух пальчиковых батареек, то необходим power save mode, поэтому ставлю внешний часовой кварц и по нему считает timer2.
Из спящего режима МК выходит по низкому уровню на INT0.

При симуляции всё работает, но при реализации на макетной плате ничего не выходит. Не пойму ошибку в коде. На этой же плате проверялась более простая версия прошивки (файл: as_work.c). Reset подтянул через 10k к питанию, кварц выдает что то похожее на нужную частоту с размахом около 0,5В. МК никак не реагирует на нажатие кнопки (INT0). Даже если бы совпадали моменты обнуления flagbutton и нажатия, то при повторном нажатии индикатор должен был бы показать число. МК обрабатывает нажатие INT0, т.к. ток потребления увеличивается (подключал к лабораторному БП), также варьировал с питанием (от 3 до 5В). Если кнопку не трогать, БП показывает ноль по потреблению тока, значит МК находится в режиме Powre Save и при нажатие обрабатывается прерывание... но почему ничего не выводится на сегменты, не могу понять.


#include <mega8.h>
#include <delay.h>

char sec=0;
int min=0;
int hour=0;
char secH=0, secL=0;
int flagbutton=0;
char dayH=0, dayL=0;


interrupt [EXT_INT0] void ext_int0_isr(void)
{
flagbutton++;
}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
secL++;
if (secL==5) {flagbutton=0;}
if (secL>9) {secH++; secL=0; flagbutton=0;}
if (secH>5) {secH=0;}
if (sec>59) {min++; sec=0;}
if (min>59) {hour++; min=0;}
if (hour>23) {dayL++; hour=0;}
if (dayL>9) {dayH++; dayL=0;}
if (dayH>9) {dayH=0;}
}

void main(void)
{
PORTB=0x20;
DDRB=0x1F;
PORTD=0x04;
DDRD=0x3B;
PORTC=0x00;
DDRC=0xFF;

ASSR=0x08;
TCCR2=0x05;
TCNT2=0x00;
OCR2=0x00;

GICR|=0x40;
GIFR=0x40;

MCUCR=0xB0;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;

#asm("sei");

while (1)
{while (flagbutton==1)
{
switch(secL)
{
case 0:{PORTC=~0xC0; PORTB.0=0; break;}
case 1:{PORTC=~0xF9; break;}
case 2:{PORTC=~0xA4; PORTB.0=1; break;}
case 3:{PORTC=~0xB0; break;}
case 4:{PORTC=~0x99; break;}
case 5:{PORTC=~0x92; PORTB.0=1; break;}
case 6:{PORTC=~0x82; break;}
case 7:{PORTC=~0xF8; PORTB.0=0; break;}
case 8:{PORTC=~0x80; PORTB.0=1; break;}
case 9:{PORTC=~0x90; break;}
};

switch(secH)
{
case 0:{PORTD=~0x40; break;}
case 1:{PORTD=~0x79; break;}
case 2:{PORTD=~0xA0; break;}
case 3:{PORTD=~0x30; break;}
case 4:{PORTD=~0x19; break;}
case 5:{PORTD=~0x12; break;}
case 6:{PORTD=~0x02; break;}
case 7:{PORTD=~0x78; break;}
case 8:{PORTD=~0x00; break;}
case 9:{PORTD=~0x10; break;}
};
}
while (flagbutton==2)
{
switch(dayL)
{
case 0:{PORTC=~0xC0; PORTB.0=0; break;}
case 1:{PORTC=~0xF9; break;}
case 2:{PORTC=~0xA4; PORTB.0=1; break;}
case 3:{PORTC=~0xB0; break;}
case 4:{PORTC=~0x99; break;}
case 5:{PORTC=~0x92; PORTB.0=1; break;}
case 6:{PORTC=~0x82; break;}
case 7:{PORTC=~0xF8; PORTB.0=0; break;}
case 8:{PORTC=~0x80; PORTB.0=1; break;}
case 9:{PORTC=~0x90; break;}
};

switch(dayH)
{
case 0:{PORTD=~0x40; break;}
case 1:{PORTD=~0x79; break;}
case 2:{PORTD=~0xA0; break;}
case 3:{PORTD=~0x30; break;}
case 4:{PORTD=~0x19; break;}
case 5:{PORTD=~0x12; break;}
case 6:{PORTD=~0x02; break;}
case 7:{PORTD=~0x78; break;}
case 8:{PORTD=~0x00; break;}
case 9:{PORTD=~0x10; break;}
};
};

PORTD=0x04; PORTC=0x00; PORTB.0=0;
#asm("sleep");
}

}

Прикрепленные файлы
Прикрепленный файл  Timer_7sg.rar ( 33.86 килобайт ) Кол-во скачиваний: 10
 
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 16 2013, 04:30
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(shatov @ Oct 16 2013, 07:19) *
... но почему ничего не выводится на сегменты, не могу понять.
Вероятно, из-за дребезга контактов по однократному нажатию кнопки переменная flagbutton принимает значение гораздо больше единицы.
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 16 2013, 04:41
Сообщение #3


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(shatov @ Oct 16 2013, 07:19) *
... питание от 3В.
... Два индикатора: на одном отображаются единицы (PORTC), на другом - десятки (PORTD).
Т.к. питание от двух пальчиковых батареек, то необходим power save mode, поэтому ставлю внешний часовой кварц и по нему считает timer2.
Из спящего режима МК выходит по низкому уровню на INT0.

При симуляции всё работает, но при реализации на макетной плате ничего не выходит. Не пойму ошибку в коде.... МК находится в режиме Powre Save и при нажатие обрабатывается прерывание... но почему ничего не выводится на сегменты, не могу понять.

Если при симуляции все работает, зачем искать ошибку в коде? Попробуйте поискать ошибку в монтаже, о грамотной разводке земли недавно тема была. Опять же, два индикатора - это порядочный ток, как питание себя ведет? Ну и наконец - у меги 8-8 нижний предел питания 2.7в, у Вас какой?
В крайнем случае, код можно проверить по кускам, отключите прерывание и проверьте циклический вывод индикации, а потом уже двигайтесь дальше. Кстати, fuse как определяете sm.gif


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
shatov
сообщение Oct 16 2013, 05:17
Сообщение #4





Группа: Новичок
Сообщений: 5
Регистрация: 17-09-13
Пользователь №: 78 360



Цитата(Палыч @ Oct 15 2013, 18:30) *
Вероятно, из-за дребезга контактов по однократному нажатию кнопки переменная flagbutton принимает значение гораздо больше единицы.


Чтобы исключить дребезг, замкнул вывод int0 на землю перемычкой еще до включения, тогда на индикаторе должен был бы отображаться ход секунд (идентично зажатому состоянию кнопки), но никаких изменений это не принесло.

Цитата(Abell @ Oct 15 2013, 18:41) *
Если при симуляции все работает, зачем искать ошибку в коде? Попробуйте поискать ошибку в монтаже, о грамотной разводке земли недавно тема была. Опять же, два индикатора - это порядочный ток, как питание себя ведет? Ну и наконец - у меги 8-8 нижний предел питания 2.7в, у Вас какой?
В крайнем случае, код можно проверить по кускам, отключите прерывание и проверьте циклический вывод индикации, а потом уже двигайтесь дальше. Кстати, fuse как определяете sm.gif


На одной и той же отладочной плате проверяю две прошивки. Ту, что привел, и ту, что попроще:

#include <mega8.h>
#include <delay.h>

char sec=0;
int min=0;
int hour=0;
int day=0;
char secH=0, secL=0;
int flagbutton=0;

interrupt [EXT_INT0] void ext_int0_isr(void)
{
flagbutton=1;
}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
TCNT2=0x00;
secL++;
if (secL>9) {secH++; secL=0;}
if (secH>5) {secH=0;}
if (sec>59) {min++; sec=0;}
if (min>59) {hour++; min=0;}
if (hour>23) {day++; hour=0;}
if (day>99) {day=0;}

}


void main(void)
{

PORTB=0x00;
DDRB=0x3F;
PORTD=0x04;
DDRD=0xFB;
PORTC=0x00;
DDRC=0x01;

ASSR=0x08;
TCCR2=0x05;
TCNT2=0x00;
OCR2=0x00;

GICR|=0x40;
GIFR=0x40;

MCUCR=0xB0;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;

#asm("sei")

while (1)
{
if (flagbutton==1)
{switch(secL)
{
case 0:{PORTB=~0xC0; break;}
case 1:{PORTB=~0xF9; break;}
case 2:{PORTB=~0xE4; PORTC.0=1; break;}
case 3:{PORTB=~0xF0; PORTC.0=1; break;}
case 4:{PORTB=~0xD9; PORTC.0=1; break;}
case 5:{PORTB=~0xD2; PORTC.0=1; break;}
case 6:{PORTB=~0xC2; PORTC.0=1; break;}
case 7:{PORTB=~0xF8; PORTC=0x00; break;}
case 8:{PORTB=~0xC0; PORTC.0=1; break;}
case 9:{PORTB=~0xD0; PORTC.0=1; break;}
};

switch(secH)
{
case 0:{PORTD=~0x40; break;}
case 1:{PORTD=~0x79; break;}
case 2:{PORTD=~0xA0; break;}
case 3:{PORTD=~0x30; break;}
case 4:{PORTD=~0x19; break;}
case 5:{PORTD=~0x12; break;}
case 6:{PORTD=~0x02; break;}
case 7:{PORTD=~0x78; break;}
case 8:{PORTD=~0x00; break;}
case 9:{PORTD=~0x10; break;}
};
}

flagbutton=0;
delay_ms(10);
if (flagbutton==0)
{PORTB=0x00; PORTD=0x04; PORTC.0=0x00;}

#asm("sleep");
}}

Эта работает как надо. Фьюзы в обоих случаях ставлю одинаково:


Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 16 2013, 10:27
Сообщение #5


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(shatov @ Oct 16 2013, 09:17) *
На одной и той же отладочной плате проверяю две прошивки. Ту, что привел, и ту, что попроще:

while (1)
{
if (flagbutton==1)
{switch(secL)
{
};

switch(secH)
{
};
}

flagbutton=0;
delay_ms(10);
if (flagbutton==0)
{PORTB=0x00; PORTD=0x04; PORTC.0=0x00;}

#asm("sleep");
}}

Извиняюсь спросить, а если в первом варианте, который не работает, после свичей тоже обнулять flagbutton, и тоже выдержку поставить, изменения будут? Или я просто не заметил, где обнуление впендюрено и сколько времени индикатор отрабатывает, прежде чем контроллер заснет - тогда извиняюсь laughing.gif ...


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
shatov
сообщение Oct 16 2013, 11:18
Сообщение #6





Группа: Новичок
Сообщений: 5
Регистрация: 17-09-13
Пользователь №: 78 360



Цитата(Abell @ Oct 16 2013, 01:27) *
Извиняюсь спросить, а если в первом варианте, который не работает, после свичей тоже обнулять flagbutton, и тоже выдержку поставить, изменения будут? Или я просто не заметил, где обнуление впендюрено и сколько времени индикатор отрабатывает, прежде чем контроллер заснет - тогда извиняюсь laughing.gif ...


обнуление каждые пять секунд

Проблема в строке: flagbutton++;
Но т.к. дребезг был исключен замыканием INT0 на землю, то совсем не ясно, почему нет увеличения переменной по нажатию...
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 16 2013, 11:23
Сообщение #7


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(shatov @ Oct 16 2013, 15:18) *
обнуление каждые пять секунд

Проблема в строке: flagbutton++;
Но т.к. дребезг был исключен замыканием INT0 на землю, то совсем не ясно, почему нет увеличения переменной по нажатию...

Да, уже разглядел. Ну как-то надо исключать дребезг, аппаратно или программно laughing.gif А пока, если вообще отключить прерывание и присвоить flagbutton значение 1, то контроллер запускается и на индикаторе идет отсчет 5 секунд, правильно понял?


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 16 2013, 11:31
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(shatov @ Oct 16 2013, 15:18) *
Проблема в строке: flagbutton++;

Не в самой строке, но - близко. Вы настроили прерывание по int0 на низкий уровень, и этот уровень в настоящее время постоянно присутствует - прерывания генерятся, переменная наращивается... Нажатие кнопки, как правило, фиксируют по перепаду уровня.
Go to the top of the page
 
+Quote Post
shatov
сообщение Oct 16 2013, 11:58
Сообщение #9





Группа: Новичок
Сообщений: 5
Регистрация: 17-09-13
Пользователь №: 78 360



Цитата(Abell @ Oct 16 2013, 02:23) *
Да, уже разглядел. Ну как-то надо исключать дребезг, аппаратно или программно laughing.gif А пока, если вообще отключить прерывание и присвоить flagbutton значение 1, то контроллер запускается и на индикаторе идет отсчет 5 секунд, правильно понял?


Даже если в прерывании записать flagbutton=1, то при нажатии кнопки будут отображаться 5 сек счета. Поняли правильно.

Цитата(Палыч @ Oct 16 2013, 02:31) *
Не в самой строке, но - близко. Вы настроили прерывание по int0 на низкий уровень, и этот уровень в настоящее время постоянно присутствует - прерывания генерятся, переменная наращивается... Нажатие кнопки, как правило, фиксируют по перепаду уровня.


Сделал MCUCR=0xB1, т.е. настроил на перепад, перемычку заменил кнопкой, но ничего не изменилось, индикаторы молчат.

Цитата(Палыч @ Oct 16 2013, 02:31) *
Не в самой строке, но - близко. Вы настроили прерывание по int0 на низкий уровень, и этот уровень в настоящее время постоянно присутствует - прерывания генерятся, переменная наращивается... Нажатие кнопки, как правило, фиксируют по перепаду уровня.


Но я понял, что исключив дребезг - зациклил программу. Тогда нужно как то избавляться от дребезга. Пробовал сделать задержку в прерывании (10ms), но не помогло. Что можно еще сделать? Поставить параллельно 10нФ и последовательно резистор около 300Ом?
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 16 2013, 12:02
Сообщение #10


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(shatov @ Oct 16 2013, 15:58) *
Тогда нужно как то избавляться от дребезга. Пробовал сделать задержку в прерывании (10ms), но не помогло. Что можно еще сделать? Поставить параллельно 10нФ и последовательно резистор около 300Ом?

Как вариант. Или в обработчике прерывания сразу же запрещать INT0, генерить задержку по свободному таймеру и разрешать. Прерывание, естественно, по фронту.


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 16 2013, 12:20
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(shatov @ Oct 16 2013, 15:58) *
Сделал MCUCR=0xB1, т.е. настроил на перепад

Логичнее было бы применить "The falling edge of INT0 generates an interrupt request", т.е. прерывание по спаду.

PS. Чтобы не мучать ни себя ни других людей, которые вызовутся Вам помочь, возмите себе за правило записывать значения в регистры таким образом:
Код
MCUCR= (1<<SE) | (1<<SM1) | (1<<SM0) | (1<<ISC10);
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Oct 18 2013, 02:25
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



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

Следует сделать автомат на 4 состояния и вызывать его каждые 10 миллисекунд



void state_machine()
{
static int timeout;
static int state = 0;

switch(state)
{
default:
case 0:
if(button_pressed())
{
state = 1;
timeout = 5;
}
break;


case 1:
if(--timeout == 0)
{
if(button_pressed())
{
state = 2;
/* buton was pressed call button press handler */
buton_press_action();
}
else
{
state = 0;
}
}
break;

case 2:
if(button_pressed())
{
state = 3;
timeout = 5;
}
break;

if(--timeout == 0)
{
if(button_pressed())
{
state = 2;
}
else
{
state = 0;
/* buton was released -- call button press handler */
buton_release_action();
}
}
break;
}
}
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Oct 18 2013, 03:11
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



2 Tarbal:
Где case 3: ??
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 18 2013, 04:28
Сообщение #14


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(shatov @ Oct 16 2013, 15:58) *
Даже если в прерывании записать flagbutton=1, то при нажатии кнопки будут отображаться 5 сек счета. Поняли правильно.

Сделал MCUCR=0xB1, т.е. настроил на перепад, перемычку заменил кнопкой, но ничего не изменилось, индикаторы молчат.

Но я понял, что исключив дребезг - зациклил программу. Тогда нужно как то избавляться от дребезга. Пробовал сделать задержку в прерывании (10ms), но не помогло. Что можно еще сделать? Поставить параллельно 10нФ и последовательно резистор около 300Ом?

От дребезга избавитесь потом, когда станет понятно, что только он - источник всех бед. Хорошо, если при этом станет понятно, что алгоритм работы устройства следует радикально пересмотреть. В частности, совершенно нет обработки критических ситуаций, ошибок.
Микроконтроллер за Вас додумывать не будет, ему надо четко расписать, как себя вести в разных ситуациях sm.gif Переменная flagbutton должна принимать только те значения, которые можно корректно обработать. Ну хотя бы в обработчик прерывания вставьте if, который при переполнении flugbutton будет сбрасывать в 0. В этом случае даже при сильном дребезге у Вас будет веселое перемигивание индикаторов, но оно - будет!
А уж как дребезг устранить - дело десятое, повторяю - хоть программно, хоть аппаратно.


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 18 2013, 04:55
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Tarbal @ Oct 18 2013, 06:25) *
Во первых не следует использовать прерывание для чтения кнопки.

IMHO, вредный совет для разработки устройств с батарейным питанием.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 13:31
Рейтинг@Mail.ru


Страница сгенерированна за 0.01509 секунд с 7
ELECTRONIX ©2004-2016