Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Прошу помочь найти косяк в программе. В железе не работает , AVRStudio подвисает при попытке выйти из прерывания. Причём, аналогичное происходит и при использовании прерывания от таймера. // ADC interrupt service routine interrupt [ADC_INT] void adc_isr(void) { unsigned char adc_data; // Read the 8 most significant bits // of the AD conversion result // Place your code here adc_data=ADCH; adc_data=(adc_data>>1); // j не больше 127 if(adc_data==1) adc_data=0;// j==1 исключается - особенность функции poworot if(i_adc_buf==2) i_adc_buf=0; else ++i_adc_buf; j=(adc_buf[0]+adc_buf[1]+adc_buf[2]+adc_data)/4; //рекурсия adc_buf[i_adc_buf]=j; } Куска хватит или нужно всё? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Замените if(i_adc_buf==2) i_adc_buf=0; else ++i_adc_buf; на if(i_adc_buf>=2) i_adc_buf=0; else ++i_adc_buf; ИМХО у вас типичная ошибка возникает - выход указателя за границы массива. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Спасибо. Заменил - симулятору не полегчало. Всё по прежнему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Делать фильтрацию внутри прерывания это моветон. Кольцевой буфер сделайте и считайте ваше плавающее среднее в main-е. А насчет зависания не совсем понял. Зависает сам симулятор? Или программа в симуляторе? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба ...А насчет зависания не совсем понял. Зависает сам симулятор? Или программа в симуляторе?Загрузка процессора при симулировании - 97% (1,3 ГГц) при попытке выйти из прерывания. И выхода собственно и не происходит. Через пару минут я просто останавливаю. И в железе не работает. Сама программа коротенькая, не возьмётесь просимулировать своим симулятором? Мне нужно только увидеть в симуляторе выход из прерывания. Дальше я попробую сам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Это не ко мне. У меня и AVRStudio-то нету :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Покажите остальной код, и МК укажите какой у вас. Сообразим.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Как на этом движке дать вложение? Или дать программу текстом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Или дать программу текстом? [codebox]тут код[/codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 (изменено) · Жалоба /***************************************************** This program was produced by the CodeWizardAVR V2.03.4 Standard Automatic Program Generator © Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Подсос С АЦП и без таймеров Version : 3-5 Date : 30.09.2009 Author : Company : Comments: Пропущенный участок работает в железе без проблем. Chip type : ATmega164 Program type : Application Clock frequency : 16.000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/ #pragma savereg- // Выключить автоматическое сохранение регистров #include <mega164.h> #include <delay.h> #define start_ADC ADCSRA|=(1<<6);// Запуск АЦП #define ADC_VREF_TYPE 0x60 char i=0,j_tec=0,j_max=130,t_i=0,adc_data=0,i_adc_buf,k; //i - номер фазы коммутации обмоток ШД //j-tec - текущее положение ротора ШД 0<=j_tec<=j_max //j-max - максимальное число полушагов ротора //t_i - период коммутации фаз (0-16ms,130-8,193-4,224-2,239-1) //i_adc_buf - номер в буфере АЦП signed char j=0; //j=1 пр. часовой,j=-1 по часовой,иначе - координата. char step[]={16,80,64,96,32,160,128,144};// комбинации фаз char adc_buf[3]={0,0,0};// Кольцевой буфер для усреднения АЦП void SW_step(void) { if (i==7)i=0; else ++i; PORTA=step[i]; } void SSW_step(void) {if (i==0)i=7; else --i; PORTA=step[i]; } void poworot (void) { if (j==-1)goto L0; if (j!=1)goto L3; if (j_tec==j_max)return; L1: SSW_step(); j_tec++; return; L0: if (j_tec==0) { return; } L2: SW_step(); j_tec--; return; L3: if(j<0) { return; } if(j>j_tec) goto L1; if(j<j_tec) goto L2; } // ADC interrupt service routine interrupt [ADC_INT] void adc_isr(void) { unsigned char adc_data; // Read the 8 most significant bits // of the AD conversion result // Place your code here adc_data=ADCH; adc_data=(adc_data>>1); // j не больше 127 if(adc_data==1) adc_data=0;// j==1 исключается - особенность функции poworot if(i_adc_buf>=2) i_adc_buf=0; else ++i_adc_buf; j=(adc_buf[0]+adc_buf[1]+adc_buf[2]+adc_data)/4; //рекурсия adc_buf[i_adc_buf]=j; } // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port A initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=T State2=T State1=T State0=0 PORTA=0x00; DDRA=0xF1; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00; // Port C initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func7=Out Func6=Out Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=0 State5=0 State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0xE0; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped // Mode: Normal top=FFh // OC0A output: Disconnected // OC0B output: Disconnected TCCR0A=0x00; TCCR0B=0x00; TCNT0=0x00; OCR0A=0x00; OCR0B=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2A output: Disconnected // OC2B output: Disconnected ASSR=0x00; TCCR2A=0x00; TCCR2B=0x00; TCNT2=0x00; OCR2A=0x00; OCR2B=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off // Interrupt on any change on pins PCINT0-7: Off // Interrupt on any change on pins PCINT8-15: Off // Interrupt on any change on pins PCINT16-23: Off // Interrupt on any change on pins PCINT24-31: Off EICRA=0x00; EIMSK=0x00; PCICR=0x00; // Timer/Counter 0 Interrupt(s) initialization TIMSK0=0x00; // Timer/Counter 1 Interrupt(s) initialization TIMSK1=0x00; // Timer/Counter 2 Interrupt(s) initialization TIMSK2=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; ADCSRB=0x00; // ADC initialization // ADC Clock frequency: 125.000 kHz // ADC Voltage Reference: AVCC pin // ADC Auto Trigger Source: None // Only the 8 most significant bits of // the AD conversion result are used // Digital input buffers on ADC0: Off, ADC1: Off, ADC2: Off, ADC3: Off // ADC4: Off, ADC5: Off, ADC6: Off, ADC7: Off DIDR0=0xFF; ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x8F; goto L11; k=0; j=1; while(j_tec!=125) { poworot(); delay_ms(2); } delay_ms(2000); j=-1; while(j_tec!=20) { poworot(); delay_ms(50); } delay_ms(2000); j=70; while(k<200) { poworot(); delay_ms(1); k++; } delay_ms(2000); L11: #asm("sei") // Разрешить прерывания ADMUX=1;// Первый канал АЦП start_ADC; while (1) { poworot(); delay_ms(2); start_ADC; } } Изменено 1 октября, 2009 пользователем Александр К. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Ну вот: #pragma savereg- // Выключить автоматическое сохранение регистров Потому и не работает ( http://telesys.ru/wwwboards/mcontrol/287/m...es/136890.shtml ). PS: уберите тег [коде][/коде] вокруг [кодебокс][/кодебокс], я вас запутал немножко. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 (изменено) · Жалоба Потому и не работает ... Спасибо. Посмотрел по ссылке, но не понял - почему нельзя использовать штатную команду? Я в прерывании регистры не использую, все переменные - глобальные. И почему ж нельзя? Глюк CV? ----------------------------------------------------------------------------------------------------------- Исправил и проверил. Всё нормально. Ещё раз спасибо. Вопрос остался ... Изменено 1 октября, 2009 пользователем Александр К. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба Регистры общего назначения и SREG. Они используются практически при каждой операции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба не понял - почему нельзя использовать штатную команду? Я в прерывании регистры не использую, все переменные - глобальные.Как это не используете? А unsigned char adc_data и результаты промежуточных вычислений где по-вашему хранятся? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр К. 0 1 октября, 2009 Опубликовано 1 октября, 2009 · Жалоба В регистрах. Но их (регистров) больше, чем переменных. И все переменные - глобальные. Пересечений нет. Вот фрагмент на асемблере. После остановки симулятора указатель показывает на адрес 180. +00000172: E7AA LDI R26,0x7A Load immediate +00000173: E0B0 LDI R27,0x00 Load immediate +00000174: 91EC LD R30,X Load indirect +00000175: E0F0 LDI R31,0x00 Load immediate +00000176: 64E0 ORI R30,0x40 Logical OR with immediate +00000177: 93EC ST X,R30 Store indirect +00000178: 9508 RET Subroutine return +00000179: 91E9 LD R30,Y+ Load indirect and postincrement +0000017A: 91F9 LD R31,Y+ Load indirect and postincrement +0000017B: 9630 ADIW R30,0x00 Add immediate to word +0000017C: F039 BREQ PC+0x08 Branch if equal +0000017D: EA80 LDI R24,0xA0 Load immediate +0000017E: E09F LDI R25,0x0F Load immediate +0000017F: 9701 SBIW R24,0x01 Subtract immediate from word +00000180: F7F1 BRNE PC-0x01 Branch if not equal +00000181: 95A8 WDR Watchdog reset +00000182: 9731 SBIW R30,0x01 Subtract immediate from word +00000183: F7C9 BRNE PC-0x06 Branch if not equal +00000184: 9508 RET Subroutine return +00000185: 95F1 NEG R31 Two's complement +00000186: 95E1 NEG R30 Two's complement +00000187: 40F0 SBCI R31,0x00 Subtract immediate with carry +00000188: 9508 RET Subroutine return +00000189: 2400 CLR R0 Clear Register Я в этом не понимаю ... Конкретный косяк не видно? Очень хочется не сохранять все РОН при прерывании. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться