Не получается мигание светодиодом с AVR Studio

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Открыл глаза
Аватара пользователя
Сообщения: 57
Зарегистрирован: Вс мар 01, 2009 16:41:36

Сообщение РобоКОТ »

Здравствуйте. Попытался написать простую программку для мигания светодиодом в AVR Studio с использованием таймера/счетчика Т/С0 (ATmega64). Идея такая: при переполнении таймера программа уходит в отработчик прерывания, там декрементируется некоторое число, которое затем сравнивается с нулем и если оно равно нулю- меняется состояние светодиода.
Написал, но симулятор не хочет показывать то, что я ожидал. Исходник присоединен к посту.
При компиляции и запуске в симуляторе программа не хочет уходить в отработчик.
И что еще интересно- в функции main() есть цикл while(1), который по идее должен быть бесконечным. Но бегать внутри него симулятор не хочет.
При создании хекса и прошитии контроллера ничего не происходит.
При переносе программы в IAR и изименении кое-чего кое-где для совпадения синтаксиса программа шьется и работает нормально (диод мигает).
Ткните носом, люди добрые
Вложения
diod.c
(764 байт) 312 скачиваний
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

#include (avr/io.h)
#include (avr/iom64.h)       //[1]
#include (avr/signal.h)       //[2]
#include (avr/interrupt.h)
long SYS_FREQ=14745600;//тактовая частота [3]
int STROBE_FREQ=1;		//частота мигания
int i;					//просто переменная
long Schetchik;			/*Число переполнений
счетчика до смены состояния*/
// обработчик прерывания по переполнению Т/С0
SIGNAL (SIG_OWERFLOW0) // [4]
{Schetchik--;
 if (Schetchik==0)
 {
  PORTD^=(1<<6);/*Смена значения бита
  6 порта Д*/
  Schetchik=SYS_FREQ/(STROBE_FREQ*256);
 }
}

void main (void) // [5]
{	TCCR0=1;/*установка предделителя=1*/
	TIMSK=0b00000001;/*разрешение прерывания
по переполнению Т/С1*/
	sei();/*установка бита I в регистре SREG*/
	Schetchik=SYS_FREQ/(STROBE_FREQ*256);
	DDRD=0xFF;
	PORTD=0xFF;
	while (1)
	{i++;
	}
}
я пометил строки с ошибками и недочетами цифрами в квадратных скобках. из-за особенностей движка форума треугольные скобки заменил на круглые - иначе код был бы почикан парсером.

[1] вы должны подключать только avr/io.h и все, подключение конкретного хидера выбранного МК происходит автоматически
[2] signal.h не нужно подключать - это устаревший модуль, функции которого полностью реализованы (с улучшениями) в interrupt.h
[3] здесь есть недочет и ошибка:
- недочет: есть макрос F_MCU, который необходимо задавать для сборки проекта - он определяет тактовую частоту в герцах, поэтому вводить дополнительную переменную - излишество
- ошибка: 14745600 нельзя указывать в таком виде, т.к. по умолчанию все числа имеют тип int и значение вашей переменной будет совсем не то, что вы ждете. надо указать суффикс UL - тогда все будет верно: 14745600UL
[4] макрос SIGNAL - устаревший, рекомендуется использовать макрос ISR
[5] функция main должна определяться как int main(void)

почти на каждое из мойх примечаний компилятор должен давать WARNING - вы не читаете, что он вам пишет?

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

что касается "не хождения" по циклу, то этому есть простое объяснение: компилятор выкидывает абсолютно бессмысленные куски кода, которые вы напишите. в частности, инкремент переменной i никому нафиг не нужен - зачем же его делать?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 57
Зарегистрирован: Вс мар 01, 2009 16:41:36

Сообщение РобоКОТ »

Спасибо за ответ. Внес исправления, но :
- Встал вопрос: "как "поймать" процесс в бесконечный цикл?". Ведь иначе декрементируемая переменная в новом прогоне функции main() вернет себе старое значение.
- в окне Build осталось единственное предупреждение "../diod.c:10: warning: 'SIG_OWERFLOW0' appears to be a misspelled signal handler" - я так воспринял это как ошибку синтаксиса (misspelled - неправильное написание). Поменял 'SIG_OWERFLOW0' на "TIMER0_OVF_Vect"- предупреждение пропало. Но почему оно появлялось? ведь это два описания одного вектора прерывания, судя по хидеру, они равнозначны.
- еще на первом курсе учили что т.к. функция main не возвращает значения- она описывается как void. Почему здесь важно чтобы функция имела тип целого числа?

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

#include <avr> 
#include <avr> 
#define F_CPU 14745600UL;			//тактовая частота [3] 
volatile int STROBE_FREQ=1;     //частота мигания 
volatile int i;               	//просто переменная 
volatile long Schetchik;      	/*Число переполнений 
 счетчика до смены состояния*/ 

// обработчик прерывания по переполнению Т/С0 
ISR (SIG_OWERFLOW0) // [4] 
{
 Schetchik--; 
 if (Schetchik==0) 
 { 
  PORTD^=(1<<6);				/*Смена значения бита 
  6 порта Д*/ 
  Schetchik=F_CPU/(STROBE_FREQ*256); 
 } 
} 


int main (void) // [5] 
{   TCCR0=1;					/*установка предделителя=1*/ 
   TIMSK=0b00000001;			/*разрешение прерывания 
по переполнению Т/С1*/ 
   sei();						/*установка бита I в регистре SREG*/ 
   Schetchik=F_CPU/(STROBE_FREQ*256); 
   DDRD=0xFF; 
   PORTD=0xFF; 
 while (1) {i++;}
}

Макрос, запоминающий частоту процессора похоже зовется F_CPU.
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 57
Зарегистрирован: Вс мар 01, 2009 16:41:36

Сообщение РобоКОТ »

вроде заработало, прошилось-мигает как надо. Но симулятор первые пару кругов всеравно себя ведет не понятно для меня
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

РобоКОТ писал(а):Спасибо за ответ. Внес исправления, но :
- Встал вопрос: "как "поймать" процесс в бесконечный цикл?". Ведь иначе декрементируемая переменная в новом прогоне функции main() вернет себе старое значение.
- в окне Build осталось единственное предупреждение "../diod.c:10: warning: 'SIG_OWERFLOW0' appears to be a misspelled signal handler" - я так воспринял это как ошибку синтаксиса (misspelled - неправильное написание). Поменял 'SIG_OWERFLOW0' на "TIMER0_OVF_Vect"- предупреждение пропало. Но почему оно появлялось? ведь это два описания одного вектора прерывания, судя по хидеру, они равнозначны.
- еще на первом курсе учили что т.к. функция main не возвращает значения- она описывается как void. Почему здесь важно чтобы функция имела тип целого числа?
1. на счет F_CPU - да, конечно, прошу прощения, зарапортовался.
2. бесконечный цикл это while(1); зачем вы в нем инкрементируете i, если эта самая i никогда нигде никем не используется? просто, щоб було? :))) это лишнее.
2. вообще-то макроса SIG_OWERFLOW не существует и правильно ругался компилятор. существует SIG_OVERFLOW. но для макроса ISR не надо использовать макросы SIG_xxx, я уже об этом говорил: это устаревший синтаксис, сохраняемый пока для совместимости со старыми версиями компиляторов.
3. функция main() по стандарту Си определена как возвращающая int - не знаю, кто и как вас учил... по стандарту эта функция возвращает результат в ОС. т.к. в МК нет "окружающей" ОС (обычно нет), то результат main() может не возвращать, но определяться все равно должна по правилам, иначе будет WARNING компилятора. Принципиального значения это не имеет (для МК), но лучше не привыкать делать неправильно.

в вашем коде есть несколько неоптимальностей, которые, в принципе, ликвидируются компилятром (и его оптимизатором), но в итоге вы можете с удивлением пытаться поставить в отладчике точку останова на вашем i++, а ничего не выйдет... поэтому я бы советовал "причесать" код, выкинув из него все реально лишнее. например, глобальную переменную Schetchik. кстати, действительно нужна аж 32-битовая переменная со знаком для этого? может, лучше сделать предделитель таймера побольше, а счетчик взять типа uint16_t или еще лучше uint8_t ? чем меньше размер переменной, тем оптимальнее результирующий код. переменные со знаком обрабатываются менее оптимально, чем беззнаковые. не используйте типы с "перебором" - старайтесь использовать минимально достаточные.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 57
Зарегистрирован: Вс мар 01, 2009 16:41:36

Сообщение РобоКОТ »

Вроде разобрался с вопросом:) Вещи просты, но почему- то сразу до них не доехал.
Вопрос не совсем по сабжу: На работе программисты сказали что у AVR STudio есть какая-то жутко неприятная особенность при работе с прерываниями, которая делает использование данной среды не возможным при решении многих задач. Так это, или люди не разобрались просто?
Контактная информация:
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

так разве ваши программисты не сказали, что это за особенность? или слышали звон, да не знают, где он?

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

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 57
Зарегистрирован: Вс мар 01, 2009 16:41:36

Сообщение РобоКОТ »

Сказали. По какой-то причине на определенных участках программы при заходе в отработчик не сбрасывался бит I SREG. В итоге выхода из отработчика небыло.
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

РобоКОТ писал(а):Сказали. По какой-то причине на определенных участках программы при заходе в отработчик не сбрасывался бит I SREG. В итоге выхода из отработчика небыло.
одно из двух - либо ваши программисты лохи последние, либо просто вам пудрят мозги. выход из обработчика обеспечивается командой reti которую студия на 100% точно эмулирует :))) то есть если в обработчике такая команда есть - выход из него будет так же неизбежен, как рассвет :)))

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

Мой уютный бложик... заходите!
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 491
Зарегистрирован: Вс янв 07, 2007 01:45:48
Откуда: Российская Федерация, будь она неладна...

Сообщение Pooher »

Ну, если такой "баг" действительно существует, то я готов поспорить с ARV.
Если при входе в обработчик флаг I не сбрасывается, то при наличии задержки достаточной длительности (при использовании прерываний таймеров), и в целом, при наступлении условия прерывания в процессе выполнения обработчика, контроллер в нём и "зависнет".
Научить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Pooher писал(а):Ну, если такой "баг" действительно существует, то я готов поспорить с ARV.
Если при входе в обработчик флаг I не сбрасывается, то при наличии задержки достаточной длительности (при использовании прерываний таймеров), и в целом, при наступлении условия прерывания в процессе выполнения обработчика, контроллер в нём и "зависнет".
во-первых, такого бага нет в студии. во-вторых, все ваши "если" говорят о первом моем предположении - уровень программизма в крови у программистов слишком низкий :)))
даже если бы такой баг был, то никакого зависания быть не должно - будет вхождение в обработчик снова и снова со сдвигом стека до тех пор, пока стек не переполнится... то есть поведение программы хотя и нельзя назвать корректным, но с зависанием это не имеет ничего похожего :)

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

Мой уютный бложик... заходите!
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 491
Зарегистрирован: Вс янв 07, 2007 01:45:48
Откуда: Российская Федерация, будь она неладна...

Сообщение Pooher »

Просвятите. А что произойдёт в "реальном железе", если стек перепролнится? Очень стало интересно, завтра обязательно попробую зашить такой программой.
Научить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
Мучитель микросхем
Аватара пользователя
Сообщения: 491
Зарегистрирован: Вс янв 07, 2007 01:45:48
Откуда: Российская Федерация, будь она неладна...

Сообщение Pooher »

Блин, не удержался, проверил. Поставил sei в начале обработчика, и...ничего не изменилось. Программа как работала, так и работает. Я в прострации...
Научить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Pooher писал(а):Блин, не удержался, проверил. Поставил sei в начале обработчика, и...ничего не изменилось. Программа как работала, так и работает. Я в прострации...
стек есть ОЗУ - когда он переполнится, то затрет сначала рабочие ячеки программы, потом регистры ввода-вывода и регистры общего назначения. скорее всего это приведет либо к рестарту, либо к зависанию, но уж точно вся периферия станет работать черти-как.

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

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3641
Зарегистрирован: Пт апр 03, 2009 22:12:58
Откуда: Из Украины, Кировоградская облась,

Сообщение Redrik Shuhart »

а че низя так
x= имя порта (А,В,С...)
CHA4AJlA include "delay.h";

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


......
PORTX.0=0;
delay_ms(500);
PORTX.0=1;
delay_ms(500);
PORTX.0=0;



все в цикле основном, и оно просто миганет
Мотание тороидов- вышивание по мужски.
Мучитель микросхем
Аватара пользователя
Сообщения: 491
Зарегистрирован: Вс янв 07, 2007 01:45:48
Откуда: Российская Федерация, будь она неладна...

Сообщение Pooher »

sei в начале обработчика прерываний - так это даже нормальная практика в некоторых случаях
Ну, это я в курсе. Просто я совершенно не понял почему ничего не произошло при том, что я разрешил прерывания в обработчике, в котором абсолютно обязательно произойдёт тоже самое прерывание, что как Вы и говорили, непременно должно переполнить стек. Железо как работало, так и продолжает уже больше часа. Мигает, зараза, светодиодом и хоть ты тресни :)
Научить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18786
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Pooher писал(а):Просто я совершенно не понял почему ничего не произошло при том, что я разрешил прерывания в обработчике, в котором абсолютно обязательно произойдёт тоже самое прерывание, что как Вы и говорили, непременно должно переполнить стек. Железо как работало, так и продолжает уже больше часа. Мигает, зараза, светодиодом и хоть ты тресни :)
ну не знаю :) часто бывает так, что программа работает немного не так, как мы думаем. но не потому, что программа неправильная, а потому, что мы думаем не о том :))) приведите код своей программы, что ли... может, вы только думаете, что второе прерывание обязательно придет во время работы обработчика...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»