Ви не увійшли.
Сторінки 1
Помогите, пожалуйста, разобраться.
Наинаю осваивать программирование контроллеров.
До этого немного покаталсяна меге16, все относительно понятно и получалось
Решил перейти на мега 128 - не могу запустить простое мигание светодиодом через прерывание
Если закоментировать sei(); работает основной цикл.
Но при раскоментировании зажигается PA4 и горит постоянно, а PD5 (основной цикл) не моргает.
Не понимаю почему не работает основной цикл?
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
ISR(TIMER0_OVF_vect)
{
PORTA |= (1<<PA4);
}
int main(void)
{
//TIMER0 -------------------------------------------------
TCCR0 |= (1<<CS02)|(1<<CS00); // устанавливаем прескалер - 1024
TIFR = 1<<TOV0; // очищаем флаг прерывания таймера Т0
TIMSK |= 1<<TOIE0; // разрешаем прерывание по переполнению
TCNT0 = 0; // загружаем начальное зн. в счетный регистр
sei();
DDRA = 0xFF;
DDRD = 0xFF;
PORTA |= (1<<PA4); _delay_ms(500);
PORTD |= (1<<PD5); _delay_ms(500);
PORTA = 0;
PORTD = 0;
while (1)
{
PORTD ^= (1<<PD5); _delay_ms(500);
}
}
Остання редакція VLDnepr (2020-03-20 18:41:50)
Неактивний
Всё правильно работает. Вы только включаете светодиод, в прерывании, и никогда не выключаете. И видимо так часто, что основной программе не достаётся процессорного времени. А почему догадайтесь сами.
это понятно, в прерывании просто тестовый код.
Почему перестает работать основной цикл, вот в чем вопрос? PD5 не моргает, просто не горит.
Что то не так. Смотрите примеры и эрраты. Хоть AVR и сбрасыват флаги запросов прерываний автоматически, попробуйте сбрасывать флаг переполнения счетчика, в конце ISR, программно.
Давай разбираться.
1. Внимательно посмотри даташит и исправь вот эту строчку, ты ту явно не 1024 устанавливаешь:
TCCR0 |= (1<<CS02)|(1<<CS00); // устанавливаем прескалер - 1024
В остальном так: у меня твой код работает - нормально мигает. Поэтому, смотри на фьюзы, всё ли там в порядке. Далее, убедись, что USART1 выключен (заткни его принудительно), иначе он переопределяет пин PD5 под себя.
И общий совет (в данном коде ни на что не влияет, но может аукнуться в другом). Когда ты впервые инициализируешь таймер (или ещё чего), делай это полностью. Не надейся, что там было что-то разумное до тебя. Вот зачем ты используешь |=, а не присваивание? Тебе важно сохранить то, что было в других битах до тебя? Зачем? Ты знаешь, что там было? При включении питания - умолчательные значения (см. даташит), а вот, например, если будешь делать это в среде той же ардуино, с удивлением обнаружишь, что в настройках таймера уже поковырялись до тебя и сохраняя "старые" биты, ты неправильно настраиваешь таймер. Т.е. при первой настройке - настраиваем все регистры и все биты.
Неактивний
... В остальном так: у меня твой код работает - нормально мигает. ...
Значит начинающий, что-то темнит. Если с запрещенными прерываниями работает, а с разрешёнными нет. То вывод очевиден; или бесконечный цикл обработки прерываний (по таинственной причине), или дефективный чип, или что-то темнит, всё-таки.
темнит, всё-таки.
Через раз напарываешься на умника, который выкладывает не свой код, а скачанный откуда-нибудь (и схему тоже) и потом говорит, так я там ничего не менял, ну вот только ... но это же ни на что не влияет! Или выкладывает сокращённый код из которого он выбросил то, по его просвещённому мнению "ни на что не влияет".
Один деятель, как-то вылез типа analogRead на тини'85 не работает. Скетч выложил. Вроде, должен работать. И так его пытали и эдак, через полдня вымогли, что это скетч из статьи, и заставили таки выложить именно его скетч, копи-пастом (таки выложил, когда уже "утюгом пытать начали"). При этом невинно так: "да, такой же точно скетч, только с другого пина читаю, какая нахрен разница, мне с того удобнее!". Вот так, полдня потратили, чтобы таки узнать, что поциент пытался на 85-ой тиньке analogRead'ом пин ADC0 читать! Так, сука, хоть бы извинился, что полдня из-за него с левым скетчем трахались - нет, ещё и мудаками обозвал - недостаточно вежливо ему всё объяснили.
Остання редакція Kaka (2020-03-22 20:55:41)
Неактивний
Ребята, Вы конечно может быть и великие Знайки, но я ничего не темню и не скрываю, мне хочется просто понять что я делаю не так, или где ковырять чтобы разобраться.
Еще раз
1.Полный код приведен ниже, контроллер atmega128a, 8 мг
2.Не суть какой делитель устанавлиывется, суть вопроса в прекращении работы основного цикла
3.Сгенерировал настройки таймера в CodeVisionAVR
4.Фьюзы как по мне тут непричем, ну или подскажите как они влияют.
5.Из подключенный внешних устройств только USBASP на USART0.
6.Только что рассмотрел, что при подаче питания сразу зажигается PA4 и больше ничего не происходит.
7.Если закоментировать TIMSK=... и ETIMSK=.... - все работает как написано, т.е. код в преравыние не заходит, т.к. перавание таймара не разрешено, основной цикл моргает.
Что то-то не так, не понимаю что именно.
Буду благодарен, если подскажете.
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char z1;
ISR(TIMER0_OVF_vect)
{
TCNT0=0xB2;
z1++;
if (z1<=250) {return;}
z1=0;
PORTA ^= (1<<PA4);
}
int main(void)
{
//TIMER0 -------------------------------------------------
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
// Timer Period: 9,984 ms
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0xB2;
OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
DDRA = 0xFF;
DDRD = 0xFF;
PORTA = 0;
PORTD = 0;
z1=0;
sei();
PORTA |= (1<<PA4); _delay_ms(1000);
PORTD |= (1<<PD5); _delay_ms(1000);
PORTA = 0;
PORTD = 0;
while (1)
{
PORTD ^= (1<<PD5); _delay_ms(500);
}
}
Неактивний
Ребята, Вы конечно может быть и великие Знайки, ...
Проверьте все цифры, в определениях TIMER0_OVF_vect, TIMSK, ETIMSK (все те, что используете), а точнее их соответствие реальным. Всякое бывает, опечатки, и.т.п. Выбросите всё лишнее, оставьте ISR пустым, и воспроизведите конфликт. На все вектора неиспользуемых прерываний установите ISR c индикацией их вызовов. Ошибки могут быть где угодно, вплоть до "дохлого" чипа, компилятора и мозгов.
Мы возможно знайки,
Но вы прям скажем зайки!
В этом деле суть и соль
Есть на заднице мозоль.
Код в посте выше приводил копипастом, без правки.
Результат тотже, если раскоментировать строки установки TIMSK - сразу после сброса зажигается первый светодиод (в данном коде это PD5) и все. Такое ощущение что программа вешается на
_delay_ms(1000);
потому как если раскоментировать строку
//PORTA |= (1<<PA4); _delay_ms(1000);
записало все после зажигания PA4, это все при том что сейчас обработчик ISR(TIMER0_OVF_vect) пустой
может ли зависать _delay_ms?
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char z1;
ISR(TIMER0_OVF_vect)
{
}
ISR(INT1_vect){PORTD |= (1<<PA3);}
ISR(INT2_vect){PORTD |= (1<<PA3);}
ISR(INT3_vect){PORTD |= (1<<PA3);}
ISR(INT4_vect){PORTD |= (1<<PA3);}
ISR(INT5_vect){PORTD |= (1<<PA3);}
ISR(INT6_vect){PORTD |= (1<<PA3);}
ISR(INT7_vect){PORTD |= (1<<PA3);}
ISR(TIMER0_COMP_vect){PORTD |= (1<<PA5);}
ISR(TIMER1_CAPT_vect){PORTD |= (1<<PA5);}
ISR(TIMER1_COMPA_vect){PORTD |= (1<<PA5);}
ISR(TIMER1_COMPB_vect){PORTD |= (1<<PA5);}
ISR(TIMER1_OVF_vect){PORTD |= (1<<PA5);}
ISR(TIMER3_CAPT_vect){PORTD |= (1<<PA6);}
ISR(TIMER3_COMPA_vect){PORTD |= (1<<PA6);}
ISR(TIMER3_COMPB_vect){PORTD |= (1<<PA6);}
ISR(TIMER3_COMPC_vect){PORTD |= (1<<PA6);}
ISR(TIMER3_OVF_vect){PORTD |= (1<<PA6);}
ISR(USART1_RX_vect){PORTD |= (1<<PA6);}
ISR(USART1_UDRE_vect){PORTD |= (1<<PA6);}
ISR(USART1_TX_vect){PORTD |= (1<<PA6);}
ISR(TWI_vect){PORTD |= (1<<PA6);}
ISR(SPM_READY_vect){PORTD |= (1<<PA6);}
int main(void)
{
//TIMER0 -------------------------------------------------
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
// Timer Period: 9,984 ms
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0xB2;
OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
DDRA = 0xFF;
DDRD = 0xFF;
PORTA = 0;
PORTD = 0;
z1=0;
sei();
//PORTA |= (1<<PA4); _delay_ms(1000);
PORTD |= (1<<PD5); _delay_ms(1000);
PORTA |= (1<<PA3); _delay_ms(1000);
PORTA |= (1<<PA5); _delay_ms(1000);
PORTA |= (1<<PA6); _delay_ms(1000);
PORTA = 0;
PORTD = 0;
while (1)
{
PORTD ^= (1<<PD5); _delay_ms(500);
}
}
Неактивний
А как вы указываете компилятору на тип микроконтроллера? Все может быть, если где-то хотя бы один бит испорчен. Напишите свою delay, если подозреваете. И что? Есть паразитные вызовы прерываний? Заниматься отладкой и тестированием, по испорченному телефону, дело неблагодарное. За текстом, вашей программы, скрыта целая технология компиляции. А дара ясновидения у меня нет.
Что не ясновидец - понятно.
AtmelStudio menu Project\Device\CurrentDevice: ATmega128
Я бубен использую в таких случах. Что-то вы напутали, или ваш микроконтроллер негоден.
что я делаю не так
Не читаешь, что тебе пишут. Я ж тебе уже написал, что у меня твой код работает, значит, дело не в коде.
Не суть какой делитель устанавлиывется
С точки зрения работоспособности кода, не влияет, а вот с точки зрения "общей аккуратности" ... если ты говоришь, что делитель такой, а он совсем другой, какие у меня основания доверять, что у тебя там в вправду 128-ая на 8МГц, а не 32U на 20?
Фьюзы как по мне тут непричем
Ну, тебе виднее. Раз ты всё и сам знаешь - что причём, а что - нет, зачем было сюда обращаться?
Неактивний
VLDnepr пише:что я делаю не так
Не читаешь, что тебе пишут. Я ж тебе уже написал, что у меня твой код работает, значит, дело не в коде.
VLDnepr пише:Не суть какой делитель устанавлиывется
С точки зрения работоспособности кода, не влияет, а вот с точки зрения "общей аккуратности" ... если ты говоришь, что делитель такой, а он совсем другой, какие у меня основания доверять, что у тебя там в вправду 128-ая на 8МГц, а не 32U на 20?
VLDnepr пише:Фьюзы как по мне тут непричем
Ну, тебе виднее. Раз ты всё и сам знаешь - что причём, а что - нет, зачем было сюда обращаться?
Мне не видно, потому и обратился.
Но и надпись типа "... Поэтому, смотри на фьюзы, всё ли там в порядке. ..." - тоже очень информативна, конкретна и после нее сразу понятно куда смотреть и что делать.
Неактивний
Дабы разобраться не в среде ли дело, не согласится ли кто-то скомпилить код и переслать мне бинарный файл для заливки.
Atmega125a 8мг
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char z1;
ISR(TIMER0_OVF_vect)
{
z1++;
if (z1<=250) {return;}
z1=0;
PORTA ^= (1<<PA4);
}
int main(void)
{
//TIMER0 -------------------------------------------------
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
// Timer Period: 9,984 ms
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0xB2;
OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
DDRA = 0xFF;
DDRD = 0xFF;
PORTA = 0;
PORTD = 0;
z1=0;
sei();
PORTA |= (1<<PA4); _delay_ms(1000);
PORTD |= (1<<PD5); _delay_ms(1000);
PORTA |= (1<<PA3); _delay_ms(1000);
PORTA |= (1<<PA5); _delay_ms(1000);
PORTA |= (1<<PA6); _delay_ms(1000);
PORTA = 0;
PORTD = 0;
while (1)
{
PORTD ^= (1<<PD5); _delay_ms(500);
}
}
Неактивний
Дабы разобраться не в среде ли дело, не согласится ли кто-то скомпилить код и переслать мне бинарный файл для заливки.
Atmega125a 8мг
Для вставки программ есть специальный фрейм, с подсветкой. Нужно на кнопку нажать, всего лишь.
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned char z1;
ISR(TIMER0_OVF_vect)
{
z1++;
if (z1<=250) {return;}
z1=0;
PORTA ^= (1<<PA4);
}
int main(void)
{
//TIMER0 -------------------------------------------------
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
// Timer Period: 9,984 ms
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0xB2;
OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
DDRA = 0xFF;
DDRD = 0xFF;
PORTA = 0;
PORTD = 0;
z1=0;
sei();
PORTA |= (1<<PA4); _delay_ms(1000);
PORTD |= (1<<PD5); _delay_ms(1000);
PORTA |= (1<<PA3); _delay_ms(1000);
PORTA |= (1<<PA5); _delay_ms(1000);
PORTA |= (1<<PA6); _delay_ms(1000);
PORTA = 0;
PORTD = 0;
while (1)
{
PORTD ^= (1<<PD5); _delay_ms(500);
}
}
https://forum.arduino.ua/img/members/1550/test-m128.zip
Пробуйте. Скомпилировано из коммандной строки (avr-gcc (AVR_8_bit_GNU_Toolchain_3.5.4_1709) 4.9.2).
Неактивний
Не помогло. Тогда остается причина - чтото с самим контролером?
Вы просили скомпилировать, я скомпилировал. Всё может быть, попробуйте на другом.
Неактивний
Сторінки 1