|
Мой первый блин), Перехожу на Си |
|
|
|
Oct 6 2009, 13:08
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
CODE #include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> volatile int i = 0; int main() { PORTE = 0x01; DDRE = 0x7F;
wdt_disable();
TCNT0 = 0x00; TCCR0A = 0; TCCR0B = 3; TIFR0 = 0; TIMSK0 = 0x01; sei(); //cli(); while (1) {
if (PORTK == 255) PORTK = 0; else PORTK++;
} }
ISR(TIMER0_OVF_vect) { //TCNT0 = 0x00;
if(i++ == 0xFF55) { PORTE ^= 0x01; i = 0; } } Суть проблемы - прерывание срабатывает, но на ноге порта Е никаких изменений, а если убрать условие (if) то все норм. Чиво не так сделал? Заранее спасибо.
Причина редактирования: Нарушение правил цитирования исходников.
|
|
|
|
|
 |
Ответов
(15 - 29)
|
Oct 6 2009, 14:43
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 18-02-08
Из: Челябинск
Пользователь №: 35 141

|
А так? Код unsigned char i = 0x00; ISR(TIMER0_OVF_vect) { i++; if(i == 0x55) { PORTE ^= 0x01; i = 0; } }
|
|
|
|
|
Oct 6 2009, 14:48
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
Цитата(_Pasha @ Oct 6 2009, 17:37)  Объявите в теле прерывания как static. Или глобально volatile unsigned char i=0; Я проверил оба эти варианта, на осмыслографе ожидаемы пеньки не появились... Цитата(Ledmaster @ Oct 6 2009, 17:43)  А так? Пробовал, но без комбинации глобальная/статическая переменная. Последняя на сегодня мысль, поставлю 16 вместо 17 студии, проверю еще так. И WinAVR переставлю.
Причина редактирования: Излишнее цитирование.
|
|
|
|
|
Oct 6 2009, 17:48
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
Цитата(OLEG_BOS @ Oct 6 2009, 18:16)  ОFFTOP Если не получится попробуйте еще и Windows переставить. А если и это не поможет то и комп. сменить А если серьезно - откройте книжку по "Си" и почитайте там об типах переменных, их расположением в памяти ( я имею ввиду ключевые слова static и volatile) . Тогда и не надо будет ничего переставлять - путь длинный но зато надежный и с малым количеством "грабель" в будущем  P.S. Кстати у Вас там используется порт E контроллера. А у Вас какой контроллер ( я так думаю Atmega64(128)) - есть там порт Е ?  Спасибо за помощь, но ерничать все же не стоит.. С типами данных я знаком, на сях пишу достаточно долго (С#), таких вот проблем))) с типами не встречал. Просто в первый же день захотел много). А проц обычная атмега640. Задача у меня - бутлоадер написать, поэтому и решил на си. Если кто сталкивался или сразу видит причину - ткните уже носом меня, и если есть дока по подводным камням авр студии - поделитесь, пожалуйста. Всем еще раз спасибо.
Сообщение отредактировал novlev - Oct 6 2009, 18:11
|
|
|
|
|
Oct 6 2009, 18:46
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
Цитата(INT1 @ Oct 6 2009, 21:31)  Я конечно не спец по Си , но чегото бросилось в глаза, PORTK++;, а так можно делать? И не плохо бы указать, какому компилятору(реализации) вы это поручаете, а то я чегото все время уверен, что это наверняка ИАР  . PORTK++ - думаю можно, взяли что было, инкремент и перезаписали. По поводу чему я это поручаю... Есть в студии привязка к WinAVR-20090313, там есть утилиты avr-gcc.exe(компилятор языков C и C++ для AVR) и make.exe(автоматический генератор Make-файлов for AVR GCC), пока это все что я знаю) я пока еще не освоился во всем обилии средств рвзработки... А что посоветуете? просто "будет работать из коробки" не состоялось))
Сообщение отредактировал novlev - Oct 6 2009, 19:10
|
|
|
|
|
Oct 6 2009, 19:43
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
Цитата(INT1 @ Oct 6 2009, 22:08)  насколько помнится операции над портом (если мы говорим проМК) типа инкркемент и т.п. напрямую производить нельзя. Т.е. туда можно или писать или читать. Т.е. объявить переменную, сделать с ней что захотеть, а потом значенеие записать в порт. Ничего утверждать не берусь, но вот пример дизасма: Код 23: if (PORTK == 255) +00000099: 91800108 LDS R24,0x0108 Load direct from data space +0000009B: 3F8F CPI R24,0xFF Compare with immediate +0000009C: F419 BRNE PC+0x04 Branch if not equal 24: PORTK = 0; +0000009D: 92100108 STS 0x0108,R1 Store direct to data space +0000009F: CFF9 RJMP PC-0x0006 Relative jump 26: PORTK++; +000000A0: 91800108 LDS R24,0x0108 Load direct from data space +000000A2: 5F8F SUBI R24,0xFF Subtract immediate +000000A3: 93800108 STS 0x0108,R24 Store direct to data space +000000A5: CFF3 RJMP PC-0x000C Relative jump Никаких замечаний и ошибок нет, эмулятор все корректно отображает. И под volatile unsigned int выделил 2 байта. Т е в теории все красиво. Вот пример моего мейкфайла.
|
|
|
|
|
Oct 6 2009, 21:41
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(novlev @ Oct 6 2009, 17:08)  CODE if (PORTK == 255) PORTK = 0; else PORTK++;
А зачем здесь вобще нужен if ? достаточно просто PORTK++; или Вы думаете что прибавление 1 к unsigned volatile char переменной в которой уже 255 может дать что-нить кроме 0 ? Цитата(INT1 @ Oct 6 2009, 23:08)  Насколько помнится операции над портом (если мы говорим про МК) типа инкркемент и т.п. напрямую производить нельзя. Т.е. туда(в регистр порта) можно или писать или читать. Т.е. нужно объявить переменную, сделать с ней что захотеть, а потом значенеие записать в порт. Это верно только для процов в которых разделены регистры записи/стирания бита (ARM непример), для AVR здесь все валидно, PORTK++; <=> PORTK = PORTK + 1; то есть сначала считать, инкрементировать и затем записать
|
|
|
|
|
Oct 6 2009, 21:46
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
Код if (PORTK == 255) PORTK = 0; else PORTK++; Ну если честно, эта конструкция там просто так, чтобы небыло пустого цикла while(1). Предметом обсуждения была многострадальная переменная i, из-за которой if не давал истину.
|
|
|
|
|
Oct 7 2009, 05:49
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 17-08-07
Пользователь №: 29 855

|
Как-то это все больше смахивает на какие-то внешние причины. Например: использование альтернативной функции порта, наличие сбросов и перезапусков программы, так что переменная i просто не успевает накопиться и т.д. (кстати, может, когда увеличили частоту переключения, то начало успевать переключаться до сброса). Это можно проверить, вставив в начало программы до начала основного кода сигнал 1 на какой-нибудь безобидный пин. При перезапуске выходы переводятся в состяние входов (можно сказать Z-состояние)где-то на 100мкс-10мс, смотря как задали стартовые задержки, и осциллографом это можно увидеть (подтяжку на -5В 1-5к не забудьте). И наверное есть смысл отключить WDR timer в фусовых битах (галочку на WDTON снимите, если стоит, или впишите в обработчик прерывания wdt_reset () ).
Вот Вам еще довесок из даташита на м640
The Watchdog always on (WDTON) fuse, if programmed, will force the Watchdog Timer to Sys- tem Reset mode. With the fuse programmed the System Reset mode bit (WDE) and Interrupt
Если не ошибаюсь, то WDTON для м640 из программы не доступен, только с программатора.
|
|
|
|
|
Oct 7 2009, 06:04
|
Частый гость
 
Группа: Участник
Сообщений: 116
Регистрация: 24-09-06
Пользователь №: 20 645

|
Цитата(314 @ Oct 7 2009, 08:49)  И наверное есть смысл отключить WDR timer в фусовых битах (галочку на WDTON снимите, если стоит, или впишите в обработчик прерывания wdt_reset () ). Да, действительно - сбрасывается. Буду искать причину. Огромное спасибо.
Причина редактирования: Нарушение п.3.4 Правил форума.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|