Проблема с Blink на таймере

GOST
Offline
Зарегистрирован: 29.09.2013

Написал простенький скретч, в котором мигаю светодиодом с помощью второго таймера.

У меня Мега 2560.



volatile unsigned char i = 0;

void setup()
{
    TCCR2A = 0x00;						// нормальный режим таймера
    TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);			//предделитель на 1024
    TIMSK2 |= 1<<TOIE2;				// прерывание по переполнению
        
    DDRB |= 0x80;							// конфигурируем      13  ногу (по дуиновской маркировке) как выход
    PORTB &= ~(0x80);					// ставим низкий уровень на 13 ноге
}

ISR(TIMER2_OVF_vect)
{
    i++;
    if (i>100) { 
        PORTB ^= 0x80;					// инвертируем состояние на 13 ноге
        i=0;
    }
}

void loop()
{
 
}

Наблюдаю такую ситуацию: при запуске мигает два раза подряд, а потом с нормальным периодом.

Почему так? 

maksim
Offline
Зарегистрирован: 12.02.2012

Потому что при запуске светодиод на 13 выводе мигает всегда и без вашего блинка. Делает это бутлоудер.

GOST
Offline
Зарегистрирован: 29.09.2013

Не люблю, когда что-то делается без моего ведома ))

А за ответ спасибо.

maksim
Offline
Зарегистрирован: 12.02.2012

Прошивайте по ISP, тогда бут можно будет затереть, или подредактируйте бут.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Подключите светик на другой пин и не парьтесь. 13 пин занят системой. Не используйте пин13 и шерсть..нервы будут в порядке :)

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Если уж по  ISP прошивать то лучше бит BOOTRST  "распрограммировать" .

И грузится будет сразу, и бутлодер живым останется,

а если  надо - можно быстро обратно включить.

 

GOST
Offline
Зарегистрирован: 29.09.2013

Ну, раз такая пьянка, то подскажите, можно ли использовать AVRStudio для разработки и прошивки камня. Если можно, то как?

P.S. Можете поделиться ссылками/инфой на тему прошивок, бутлоадеров и т.д. и т.п.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Если есть ICSP, то и Загрузчик не нужен

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

По поводу студии информации вроде достаточно. Использовать можно. У нас на форуме несколько тем про это.

GOST
Offline
Зарегистрирован: 29.09.2013

2 kisoft

Вбив в поиске по сайту AVRStudio ничего вразумительного не нашел... 

А вообще где-то видел, что работы с дуино в студии нужно чуток модифицировать плату + играться с бутлоадером (инфа под сомнением), ну и т.д. Вот и написал о просьбе...

Клапауций
Offline
Зарегистрирован: 10.02.2013

GOST пишет:

2 kisoft

Вбив в поиске по сайту AVRStudio ничего вразумительного не нашел... 

А вообще где-то видел, что работы с дуино в студии нужно чуток модифицировать плату + играться с бутлоадером (инфа под сомнением), ну и т.д. Вот и написал о просьбе...

нужно вбивать AVR Studio

GOST
Offline
Зарегистрирован: 29.09.2013

Клапауций пишет:

нужно вбивать AVR Studio

Гугл не такой уж и дурак в этом плане.

tsostik
Offline
Зарегистрирован: 28.02.2013

GOST пишет:

Ну, раз такая пьянка, то подскажите, можно ли использовать AVRStudio для разработки и прошивки камня. Если можно, то как?

Можно:

1)Создаем в студии новый проект, указав камень, имеющийся на дуине.

2)Пишем, компилим.

3)Заливаем через имеющийся программатор (я так вообще заливаю через бутлоадер, параметры avrdude один раз подсмотрел в ArduinoIDE и скопировал в батник).

Ничего на дуине не менял, ни в плате, ни в фьюзах. Лично на моей леонарде перед прошивкой с помощью бутлоадера нужно руками нажать ресет, если шить через USBAsp то и этого не надо.

И да, я ArduinoIDE не использую вообще, как-то так сложилось. Единственный минус - невозможность использования родных библиотек, но меня это не напрягает.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

tsostik пишет:

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

Это не правда, можно использовать Wiring в Atmel Studio. Есть два варианта, оба в темах проскакивали.

 

tsostik
Offline
Зарегистрирован: 28.02.2013

Не буду спорить, мне оно просто не требовалось -)

GOST
Offline
Зарегистрирован: 29.09.2013

tsostik пишет:

3)Заливаем через имеющийся программатор (я так вообще заливаю через бутлоадер, параметры avrdude один раз подсмотрел в ArduinoIDE и скопировал в батник).

Можно поподробней этот момент?

tsostik
Offline
Зарегистрирован: 28.02.2013

GOST пишет:

tsostik пишет:

3)Заливаем через имеющийся программатор (я так вообще заливаю через бутлоадер, параметры avrdude один раз подсмотрел в ArduinoIDE и скопировал в батник).

Можно поподробней этот момент?

Что конкретно подробнее?

Вариант 1, через бутлоадер) Подсматриваем в ArduinoIDE параметры, с которыми вызывается avrdude. Этой строкой и заливаем нашу прошивку поменяв имя ардуиновского .hex файла на свой свое собственное. Перед прошивкой не забываем нажать ресет. Я для удобства вынес ее в отдельный батник. В зависимости от УСБ в который воткнута дуина может меняться номер ком-порта. Этот номер тоже надо не забыть корректно передать avrdude.

Вариант 2, через сторонний програматор - вообще забываем, что имеющаяся у нас плата называется "ардуино", считаем, что это просто МК с обвязкой. Заливаем способом, штатным для программатора и используемого МК.

 

GOST
Offline
Зарегистрирован: 29.09.2013

tsostik пишет:

Вариант 1, через бутлоадер) Подсматриваем в ArduinoIDE параметры, с которыми вызывается avrdude. Этой строкой и заливаем нашу прошивку поменяв имя ардуиновского .hex файла на свой свое собственное. Перед прошивкой не забываем нажать ресет. Я для удобства вынес ее в отдельный батник. В зависимости от УСБ в который воткнута дуина может меняться номер ком-порта. Этот номер тоже надо не забыть корректно передать avrdude.

И снова здравствуйте! Не могли бы вы выложить строку, которой запускаете avrdude?

tsostik
Offline
Зарегистрирован: 28.02.2013

avrdude -CD:\arduino\arduino-1.0.5\hardware/tools/avr/etc/avrdude.conf -v  -patmega32u4 -cavr109 -P\\.\COM23 -b57600 -D -Uflash:w:myhex.hex:i

Компорт и МК поменять не забудьте.

GOST
Offline
Зарегистрирован: 29.09.2013

Пробовал запускать с командной строки - не получается...

tsostik
Offline
Зарегистрирован: 28.02.2013

Ну не знаю, я уроки телепатии в школе прогуливал...

GOST
Offline
Зарегистрирован: 29.09.2013

Согласен, плохая формулировка. ))

Разобрался сам. Вынес папку с avrdude.exe в корень диска и закинул туда avrdude.conf. Только тогда заработало, проблема была в путях, которые использует Arduino IDE. 

Может кому-то поможет )

GOST
Offline
Зарегистрирован: 29.09.2013

И снова вопросы ))

Когда именно нужно нажимать ресет: просто перед прошивкой или нужно попасть в какой-то временной интервал?

Что будет, если не нажимать ресет: вообще не пойдет процес прошивки или зальется, но не будет работать?

Как заливать *.еер файлы (и нужно ли)?

Ну и наконец, залил хекс проэкта (мигалка на таймере), сгенерированого студией, аврдюд говорит все ок, но ничего не происходит; залил тем же способом хекс, который сгенерировала дуина - все работает...

tsostik
Offline
Зарегистрирован: 28.02.2013

Я нажимаю ресет меньше чем за секунду до заливки - то есть нажел ресет, увидел, что замигал светодиод на 13 пине, запустил прошивку.

.eep я не заливаю, так как мне не надо. Если это нужно (заранее делаете какие-то данные для еепрома), то там же в параметрах avrdude его можно указать.

В каких конкретно - не знаю, мне не требовалось, так что я обхожусь без него.

GOST
Offline
Зарегистрирован: 29.09.2013

А что скажете по последнему пункту?

З.Ы. В студии нужно где-то указывать частоту камня?

tsostik
Offline
Зарегистрирован: 28.02.2013

В студии частота камня указывается в настройке проекта.

Покажите исходники вашей мигалки.

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

GOST
Offline
Зарегистрирован: 29.09.2013

Лазил в настройках - не нашел...

 

#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned char i = 0;

int main(void)
{
		
	TCCR2A = 0x00;						// нормальный режим таймера
	TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);			//предделитель на 1024
	TIMSK2 |= 1<<TOIE2;				// прерывание по переполнению
	
	DDRB |= 0x80;							// конфигурируем 13 ногу (по дуиновской маркировке) как выход
	PORTB &= ~(0x80);					// ставим низкий уровень на 13 ноге
	
	
    while(1)
    {
        //TODO:: Please write your application code 
    }
}

ISR(TIMER2_OVF_vect)
{
	i++;
	if (i>50) {
		PORTB ^= 0x80;					// инвертируем состояние на 13 ноге
		i=0;
	}
}

 

tsostik
Offline
Зарегистрирован: 28.02.2013

А плата какая?

Вы мигаете пином PB6

На уне 13 пин это PB5 http://www.pighixxx.com/pgdev/Temp/ARDUINO_V2.png

На леонарде - PC7 http://www.pighixxx.com/pgdev/Temp/leonardov2.png

На меге 2560 - PB7 http://www.pighixxx.com/pgdev/Temp/mega2.png

GOST
Offline
Зарегистрирован: 29.09.2013

Мега 2560. Почему РВ6? 0х80 разве не 7-й пин?

tsostik
Offline
Зарегистрирован: 28.02.2013

Нет, 7 пин это 0xF0, пины считаются от нуля.

Вообще, лучше, использовать конструкцию _BV(7) или даже _BV(PB7), меньше шансов промазать с магическими константами. Ну или хотя бы (1 << 7)

#include <avr/io.h>
#include <avr/interrupt.h>
volatile unsigned char i = 0;

#define LED_PORT PORTB
#define LED_DDR DDRB
#define LED_PIN (_BV(7))

int main(void)
{
		
	TCCR2A = 0x00;						// нормальный режим таймера
	TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);			//предделитель на 1024
	TIMSK2 |= 1<<TOIE2;				// прерывание по переполнению
	
	LED_DDR |= LED_PIN;							// конфигурируем 13 ногу (по дуиновской маркировке) как выход
	LED_PORT &= ~LED_PIN;					// ставим низкий уровень на 13 ноге
	
	
    while(1)
    {
        //TODO:: Please write your application code 
    }
}

ISR(TIMER2_OVF_vect)
{
	i++;
	if (i>50) {
		LED_PORT ^= LED_PIN;					// инвертируем состояние на 13 ноге
		i=0;
	}
}
GOST
Offline
Зарегистрирован: 29.09.2013

Эффекта никакого.

Если поменять 

LED_PORT &= ~LED_PIN;

на 

LED_PORT |= LED_PIN;

то диод горит, постоянно горит, если код из прерывания закинуть в цыкл, то еффекта никакого.

tsostik
Offline
Зарегистрирован: 28.02.2013

Вот текст блинка, который точно работает (мигает TXLED на леонарде с частотой 2Гц):

/*
 * TestBlink.c
 *
 * Created: 10.03.2013 8:24:07
 *  Author: tsostik
 */ 


#include <avr/io.h>
#include <util/delay.h>

#define LED_PIN 5
int main(void)
{
    DDRD |= 1 << LED_PIN;
    PORTD &= ~(1 << LED_PIN);
    while(1)
    {
        PORTD |= 1 << LED_PIN;
        _delay_ms(250);
        PORTD &= ~(1 << LED_PIN);
        _delay_ms(250); 
        //TODO:: Please write your application code 
    }
}

Отдельно посмотрел насчет частоты - не нашел в настройках проекта, я ее задавал добавиви в Project->Properties->AVR/GNU C Compiler->Symbols строчку F_CPU=16000000UL

 

Если диод горит, это как минимум значит, что его пин верно определен, хекс успешно залит и плата подает признаки жизни -)

А значит, все остальное - вопрос правильно написаной програмы.

Попробуйте, для начала, скопировать мой блинк, поменяв DDRB на DDRD, PORTB на PORTD и LED_PIN на 7.

Только заранее просьба - если "ничего не работает", сразу копируйте сюда код целиком.

GOST
Offline
Зарегистрирован: 29.09.2013

Все работает, но если сделать так:

#include <avr/io.h>
#include <avr/interrupt.h>


#define LED_PIN 7
int main(void)
{
	
	TCCR2A = 0x00;                      // нормальный режим таймера
	TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);          //предделитель на 1024
	TIMSK2 |= 1<<TOIE2;
	
	DDRB |= 1 << LED_PIN;
	PORTB &= ~(1 << LED_PIN);
	while(1)
	{
	
	}
}

ISR(TIMER2_OVF_vect)
{
	PORTB |= 1 << LED_PIN;
	PORTB &= ~(1 << LED_PIN);
		
}

то опять ничего не работает ))

tsostik
Offline
Зарегистрирован: 28.02.2013

Ну так у Вас в прерывании диод включается и тут же выключается. Конечно не работает. Точнее, работает, но этого не видно.

К тому же, при частоте 16 МГЦ предделитель 1024 на 8-битном таймере дает 60 прерываний в секунду. С такой частотой таймер просто не будет видно.

Ну и прерывания все-таки надо разрешить.

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

#include <avr/io.h>
#include <avr/interrupt.h>


#define LED_PIN 7
volatile unsigned char cnt;
int main(void)
{
	
	TCCR2A = 0x00;                      // нормальный режим таймера
	TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);          //предделитель на 1024
	TIMSK2 |= 1<<TOIE2;
	
	DDRB |= 1 << LED_PIN;
	PORTB &= ~(1 << LED_PIN);
	cnt = 0;
	sei();
	while(1)
	{
		
	}
}

ISR(TIMER2_OVF_vect)
{
	cnt++;
	if(cnt == 30)
	{
		cnt = 0;
		PORTB ^= (1 << LED_PIN);
	}
}

 

GOST
Offline
Зарегистрирован: 29.09.2013

Работает!!!!! Большое спасибо!