Страница 1 из 2
Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 08:24:11
moonlight1
День добрый, ломал голову как сделать счетчик от 0 до 99 с обнуление при переполнении. Вроде бы сломал и сделал, через прерывания, таймер и все такое. Проверил в протеусе работает. Стал проверять на железе высвечиваются по 0 на обоих сегментах

думал мк закосячил, залил старую программку для вывода чисел указанных в коде - все нормально вывело, а тут не считает. Делал по урокам в инете, все в кучу собрал но не повезло. В протеусе адекватно работает на частоте в 2МГЦ, в реале перепробовал все частоты внутреннего генератора от 1-2-4-8 на всех высвечивается по 00
Может быть кто подскажет что не так в коде? Подключение на макетке правильно ибо если было бы не правильно прошлые программы не работали бы.
сделано в CVAVR код и схему прилагаю, а так же проект+протеус.
Код программы:
Спойлер
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
static flash unsigned char digit[] = {
~(0b00111111), // 0
~(0b00000110), // 1
~(0b01011011), // 2
~(0b01001111), // 3
~(0b01100110), // 4
~(0b01101101), // 5
~(0b01111101), // 6
~(0b00000111), // 7
~(0b01111111), // 8
~(0b01101111), // 9
};
////
unsigned char sek;
bit m;
////
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{
TCNT2=0b00000000; //счетный регистр 0-255
sek++;
if(sek>=100) {
sek=0;}
}
//вывод на индикатор
void ind(unsigned char chislo)
{
unsigned char des=0;
while(chislo>=10){
chislo-=10; //вычитаем и присваиваем заново
des++;}
if(m==0){
PORTB.0=1;
PORTD=digit[des];
delay_ms(5);
PORTB.0=0;
PORTB.1=1;
PORTD=digit[chislo];
delay_ms(5);
PORTB.1=0;}
}
//////////////
void main (void){
PORTB=0b00000000;
DDRB= 0b00000011;
PORTD=0b00000000;
DDRD= 0b01111111;
//настройки 2 таймера и его прерываний
ASSR= 0b00001000;
TCCR2=0b00000110; //деление 32768 на 256
TCNT2=0b00000000; //счетный регистр 0-255
OCR2=127; //регистр сравнения
TIMSK=0b10000000;
#asm("sei"); //разрешение глобавльных прерываний
/////////////////////////////////////////
while (1){ind(sek);}
}
Схема:
Спойлер

Архив с проектом и схемой в протеусе:
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 10:20:34
codenamehawk
Лишний кусок кода.
Попробуйте заменить на.
Ваша программа, если работает в Протеусе, должна работат и в проце.
Возмозно в проце выставлена работа от внешнего кварца.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 11:47:33
moonlight1
codenamehawk писал(а):Возмозно в проце выставлена работа от внешнего кварца.
Сделал как вы сказали, в протеусе работает на железе опять нет. Фьюзы стоял на внутренний кварц 8МГц если я не ошибаюсь. Вот скриншот как выставлены фьюз-биты
Спойлер

Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 12:06:07
Vov123
Поставь студию попроще, к примеру 4.19, файл .cof в отладчик.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 12:56:12
Z_h_e
Порт B то у Вас явно перегружен.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 13:28:33
moonlight1
Vov123 писал(а):Поставь студию попроще, к примеру 4.19, файл .cof в отладчик.
а где взять этот файл и как туда запихать?
Z_h_e писал(а):Порт B то у Вас явно перегружен.
а как его собственно разгрузить? на нем же только 2 анода сегментов висят и все...
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 13:33:02
Z_h_e
moonlight1 писал(а):а как его собственно разгрузить? на нем же только 2 анода сегментов висят и все...
А Вы посчитайте какой ток будет, если зажечь все сегменты. Аноды говорите... поставте биполярный NPN транзистор. База на порт, коллектор на + питания, эмиттер на анод.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 13:47:16
moonlight1
Z_h_e писал(а):moonlight1 писал(а):а как его собственно разгрузить? на нем же только 2 анода сегментов висят и все...
А Вы посчитайте какой ток будет, если зажечь все сегменты. Аноды говорите... поставте биполярный NPN транзистор. База на порт, коллектор на + питания, эмиттер на анод.
без этого вполне на другой программе работает.
вот в этой программе, счет от 0 до 999 по нажатию кнопки, все нормально работает на железе
Спойлер
Код: Выделить всё
#define F_CPU 8000000UL //выбор частоты тактирования (8Мгц)
#include <mega8.h>
#include <delay.h>
unsigned char number[] =
{
~0x3f, //0
~0x06, //1
~0x5b, //2
~0x4f, //3
~0x66, //4
~0x6d, //5
~0x7d, //6
~0x07, //7
~0x7f, //8
~0x6f //9
};
unsigned char count = 0;
//числа для вывода на индикатор
unsigned char data1 = 9;
unsigned char data2 = 9;
unsigned char data3 = 5;
void main( void )
{
//порт, к которому подкл. сегменты
PORTD = 0xff;
DDRD = 0xff;
//порт, к которому подкл. анод
PORTB = 0;
DDRB = (1<<0)|(1<<1)|(1<<2);
while(1)
{
//гасим все разряды
PORTB &= ~((1<<0)|(1<<1)|(1<<2));
//зажигаем следующий разряд
if (count == 0) {
PORTD = number[data1];
PORTB |= (1<<0);
}
if (count == 1) {
PORTD = number[data2];
PORTB |= (1<<1);}
if (count == 2) {
PORTD = number[data3];
PORTB |= (1<<2);
}
//типо кнопка
if (PINB.3==0)
{ delay_ms(200); //типо антидребезг
data3++;
}
//счет 0-999
while(data3>=10){
data3-=10;
data2++;}
while(data2>=10){
data2-=10;
data1++;}
if(data1==10) {data1=0; data2=0; data3=0;}
count++;
if (count == 3) count = 0;
delay_ms(10);
}
}
схема
Спойлер

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

Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 13:55:14
Z_h_e
Да я и не говорил что у Вас нули показывает из-за перегрузки порта.
Попробуйте функцию ind вызывать редко, например раз 3 сек и используйте в параметре не переменную, а некое число. Может увидите, что у Вас происходит и локализуете проблему.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 13:55:56
moonlight1
Z_h_e писал(а):Да я и не говорил что у Вас нули показывает из-за перегрузки порта.
Попробуйте функцию ind вызывать редко, например раз 3 сек и используйте в параметре не переменную, а некое число. Может увидите, что у Вас происходит и локализуете проблему.
а) ну значит я не так понял. попробую спасибо
попробовал, вызывать реже, чет все равно тоже самое =\
ладно черт с ней, потом додумаю может быть почему не работает.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср июл 27, 2016 17:29:25
COKPOWEHEU
Фьюзы стоял на внутренний кварц 8МГц
Где вы нашли контроллер с внутренним кварцем? Явно ведь не ATmega8, у нее встроенного кварца нет, только RC-генератор.
static flash unsigned char digit[] = {
~(0b00111111), // 0
Не самый удобный способ записи. Хотя в вашем примере на 999, эта инициализация реализована еще хуже.
PORTB.0=1;
PORTD=digit[des];
delay_ms(5);
В cvavr не надо делать ручное чтение из flash? В avr-gcc для этого pgm_read_byte() и т.п.
Можно попробовать увеличить задержку здесь.
ASSR= 0b00001000;
Форматирование ужасно. Какая религия мешает писать по-человечески? Запретите ее на форуме. ASSR = (1<<AS2);
Сам асинхронный таймер тактируется? Попробуйте помигать диодами из его прерывания или затактировать от системного таймера. Кстати, на схеме низкочастотного кварца нет.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт июл 28, 2016 06:09:18
moonlight1
COKPOWEHEU писал(а):только RC-генератор.
я это и умел ввиду
Не самый удобный способ записи. Хотя в вашем примере на 999, эта инициализация реализована еще хуже.
как смог так сделал. не все же сразу должно быть хорошо
Сам асинхронный таймер тактируется? Попробуйте помигать диодами из его прерывания или затактировать от системного таймера. Кстати, на схеме низкочастотного кварца нет.
хорошо. спасибо
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт июл 28, 2016 07:42:10
COKPOWEHEU
Код: Выделить всё
#define SEG_PORT PORTD
#define SEG_A 0
#define SEG_B 1
...
#define SEG_F 5
#define SEG_G 6
PROGMEM const char num[]={
~(1<<SEG_A | 1<<SEG_B | 1<<SEG_C | 1<<SEG_D | 1<<SEG_E | 1<<SEG_F), //0
~(1<<SEG_B | 1<<SEG_C), //1
...
~(1<<SEG_A | 1<<SEG_B | 1<<SEG_C | 1<<SEG_D | 1<<SEG_E | 1<<SEG_F | 1<<SEG_G), //8
~(1<<SEG_A | 1<<SEG_B | 1<<SEG_C | 1<<SEG_D | 1<<SEG_F | 1<<SEG_G) //9
};
Такой способ позволяет легко менять выводы местами, плюс этот кусок можно таскать из кода в код. Ну и выглядит нагляднее, чем "магические числа".
как смог так сделал. не все же сразу должно быть хорошо

Когда я делаю динамическую индикацию, обычно завожу "видеобуфер" и отрисовываю его по таймеру.
Код: Выделить всё
#define DIG_PORT PORTB
#define DIG_MASK (1<<0 | 1<<1)
const char digits[2]={
(1<<0),
(1<<1)
};
volatile char video_buf[2];
//динамическая индикация
ISR(TIM0_OVF_vect){
static unsigned char digit=0;
DIG_PORT &=~DIG_MASK; //перед переключением обязательно надо погасить предыдущий разряд
SEG_PORT = video_buf[ digit ];
DIG_PORT |= digits[ digit ];
digit++;
if(digit > 1)digit = 0; //знаю, что можно обойтись инверсией младшего бита, но этот вариант проще масштабировать
}
//вывод целого числа (0-99)
void OutInt(unsigned char data){
char dec;
while(data > 10){
dec++;
data -= 10;
}
video_buf[1] = pgm_read_byte( &num[ dec ] );
video_buf[0] = pgm_read_byte( &num[ data ] );
}
Примерно так. Писал из головы под avr-gcc, но суть должна быть понятна.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт июл 28, 2016 13:30:51
moonlight1
COKPOWEHEU писал(а):легко менять выводы местами
т.е. не важно как будут подключены выводы к мк? круто если так.
все понял в чем соль, не надо считать по битам легко прикинуть как будет.
Когда я делаю динамическую индикацию, обычно завожу "видеобуфер" и отрисовываю его по таймеру.
Примерно так. Писал из головы под avr-gcc, но суть должна быть понятна.
подкинули вы мне пищу для размышлений, освобожусь от дел насущных обязательно буду пробовать
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт июл 28, 2016 14:55:01
COKPOWEHEU
Преимущество в том, что в пределах одного порта можно вешать сегменты на произвольные пины. Часто у контроллеров выводы одного порта сгруппированы рядом (к сожалению, не всегда, классическая ATmega8 примером), а сегменты у индикатора расположены в произвольном порядке (наверное, какая-то логика в их расположении есть, но я ее не увидел). Тогда для упрощения разводки платы можно поменять местами какие-нибудь выводы.
Несложно сделать и полностью произвольный доступ к каждому выводу, но на мой взгляд это проигрыш по скорости.
подкинули вы мне пищу для размышлений, освобожусь от дел насущных обязательно буду пробовать
Это радует
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср авг 08, 2018 20:58:00
Владимир-32
Здравствуйте, коты, кошечки и котята!
Хочу поделиться некоторым опытом. Написал я программу для Атмеги8 на ассемблере. Программа не очень чтобы сложная, но для меня, как в некоторой степени начинающего пользователя АВРов, довольно сложная и запутанная. Отладил её в Протеусе. Работает отлично! Записал код в микруху, запустил на макетной платке. Не работает! Начал ковырять. Перечитал много тем на разных форумах о причинах неработы программы в железе. Сначала думал, что помехи по питанию. Поставил соответствующие кондёры. Безрезультатно. Потом начал ковырять фьюзы. Дело в том, что раньше когда-то я имел дело с АТ89S52, а там фьюзов нет. Перепробовал разные варианты. Безрезультатно. Думаю, пойду другим путём. Урезал программу до минимума и начал проверять её работу в железе, постепенно добавляя блоки. Вначале всё работало отлично, но после добавления одного из блоков стало происходить странное. Программа то работала, то не работала. Иногда при включении питания или сбросе работала несколько раз подряд, а иногда - по несколько раз подряд не работала. И ещё: если программа не отработала до конца, а я подавал сигнал сброса, то после этого сброса она переставала работать. Знатоки, вероятно, уже поняли причину такого поведения. А мне пришлось повозиться, прежде чем я понял причину, хотя тоже мог бы догадаться.
Теперь о том, как я искал причину.
В некоторых блоках программы поставил команды, которые выводили в свободный порт какое-то число, которое соответствовало порядку выполнения программы. Т. е., если в порту появляется это число, это значит, что программа зашла в своей работе в этот блок. По этому признаку можно определить, что происходит в программе. Но как определить, что это число появляется в порту, ведь программа выполняется довольно быстро? Для этого я использовал 2-канальный цифровой осциллограф в ждущем режиме. Один вход подсоединил на линию порта 0, от неё же брал синхронизацию. А второй вход подключал к остальным выводам порта. Зарисовывал графики. Получилось нечто вроде картины логического анализатора. Совместив графики и проанализировав их, я узнал, куда, в какие блоки заходит программа. Получилось, что программа не заходила в один блок, в который она должна была обязательно зайти. Проанализировав код, я предположил причину, по которой программа не заходит в этот блок. Устранив причину, я добился того, что программа заработала так, как надо!
В чём же была причина?
Причина очень проста. Дойдя до определённого момента, программа анализировала флаг (бит в регистре), который в начале программы должен был быть сброшенным, т. е. равняться 0. Зная, что после команды сброса, МК обнуляет все РОНы, я не позаботился его принудительно обнулить. Оказывается, что МК не обнуляет РОНы при сбросе и включении питания! Это для меня было новостью. МК, с которыми я ранее имел дело, обнуляли все РОНы при сбросе и включении питания. Оказывается, к Атмеге8 это правило не относится. А может быть, схема сброса у меня была не лучшего качества, хотя я перепробовал разные варианты, которые не дали желаемого результата.
Конечно, взрослые жирные коты, наверно, посмеются, что, мол, кот таких простых вещей не знает. Но молодым котятам может пригодиться опыт, который я приобрёл ценой нескольких дней ковыряния в коде программы, поиска схожей причины на форумах и тыкания деталек в макетку. И я буду рад, если мой пост кому-то сэкономит часы, а то и дни поиска неисправности.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Ср авг 08, 2018 21:42:22
B@R5uk
Инициализировать нужно всё, чем собираешься пользоваться. Это каждый программист знает. Даже если в даташите пишут, что при ресете регистр ввода-вывода инициализируется каким-либо значением, то это утверждение всегда лучше поставить под сомнение и проинициализировать регистр самостоятельно. У меня была забавная ситуация с ATmega128, когда USART работал не с той скоростью, а всё потому, что я поленился проинициализировать бит, задающий удвоение частоты, из-за того, что он мол по ресету сам устанавливается в нужное значение.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт авг 09, 2018 09:33:00
Z_h_e
B@R5uk писал(а):Даже если в даташите пишут, что при ресете регистр ввода-вывода инициализируется каким-либо значением, то это утверждение всегда лучше поставить под сомнение
Что за чушь?
Добавлено after 12 minutes 14 seconds:
Владимир-32 писал(а):Оказывается, что МК не обнуляет РОНы при сбросе и включении питания! Это для меня было новостью. МК, с которыми я ранее имел дело, обнуляли все РОНы при сбросе и включении питания. Оказывается, к Атмеге8 это правило не относится. А может быть, схема сброса у меня была не лучшего качества, хотя я перепробовал разные варианты, которые не дали желаемого результата.
А где написано что должны были сбрасываться?
На счет поиска ошибки + Вам, тут часто бывает так, код напишут - не работает, ничего не попробовав бегут сразу за помощью.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт авг 09, 2018 09:34:41
B@R5uk
Z_h_e, мне по чём знать? Спросите разработчиков и производителей. Может очетпятка в документе, ноль и единицу перепутали, а может баг при производстве был, не к той линии питания развели. Мне главное чтобы работало без излишнего мозгосношения, поэтому сомневаюсь во всём и не верю никому на слово.
Re: Программа работает в proteus'e но на железе отказывается
Добавлено: Чт авг 09, 2018 09:41:21
Z_h_e
Если бы контроллер не инициализировал РВВ так как написано, он бы не работал в принципе.
Если Вам попался неисправный МК, то никакие "правила сделать на всякий случай которые все программисты знают" не помогут.
Если есть такой явный баг, он по-любому будет описан в erratа или в свежем ДШ.