Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: WinAVR траблы
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
tazik
Есть такой код:
CODE
/*
* main.c
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
//#include <util/delay.h>
#include "sine_table.h"

#define BTN_UP PD0
#define BTN_DOWN PD1

static int16_t step_counter;
uint8_t step;
uint8_t kvadrant;
uint8_t time_delay;

void IOInit(void){
DDRB=(1<<PB3);
PORTD=(1<<BTN_DOWN)|(1<<BTN_UP);
DDRD=(1<<PD4)|(1<<PD3);
}

void Timer1Init(void){
ICR1=0x01FF;
TCCR1A=(1<<COM1A1);
TCCR1B=(1<<WGM13)|(1<<CS11);
TIMSK=(1<<TOV1);
}

ISR(TIMER1_OVF_vect){
switch(kvadrant){
case 1:{
OCR1A=pgm_read_word(pSine+step_counter);
step_counter+=step;
if (step_counter>511) {step_counter-=step; kvadrant=2;}
break;
};
case 2:{
OCR1A=pgm_read_word(pSine+step_counter);
step_counter-=step;
if (step_counter<0) {step_counter+=step; kvadrant=3;}
break;
};
case 3:{
OCR1A=0x1FF-pgm_read_word(pSine+step_counter);
step_counter+=step;
if (step_counter>511) {step_counter-=step; kvadrant=4;}
break;
};
case 4:{
OCR1A=0x1FF-pgm_read_word(pSine+step_counter);
step_counter-=step;
if (step_counter<0) {step_counter+=step; kvadrant=1;}
break;
};
};
};

int main(void){

OCR1A=0x10;
IOInit();
Timer1Init();
sei();
step=20;
step_counter=511;
kvadrant=4;
PORTD=0xFF;

while(1){
cli();
step=10; // в итоговом коде этого нет! (((
sei();
};
return 0;
}


И почему-то, в итоговом коде отсутствует операция step=10 основного цикла. получается так:
CODE

652: 82 bb out 0x12, r24 ; 18
654: f8 94 cli
656: 78 94 sei
658: fd cf rjmp .-6 ; 0x654 <main+0x44>


Отчего такое может быть? В каком месте у меня кривые руки?
Methane
Цитата(tazik @ Dec 3 2009, 06:23) *
Отчего такое может быть? В каком месте у меня кривые руки?

Скорее всего компилер просто за пределы цикла вынес.
tazik
вот так более подробно. К сожалению, не вынес (
CODE
while(1){
cli();
654: f8 94 cli
step=10;
sei();
656: 78 94 sei
658: fd cf rjmp .-6 ; 0x654 <main+0x44>
tazik
надо было добавить volatile в объявлении переменной step. Оказывается, старые чужие грабли
Methane
Цитата(tazik @ Dec 3 2009, 08:07) *
отключил оптимизацию. Теперь выражение step=10 появилось в выходном коде. Почему WinAVR так оптимизирует? И как избавиться от такой оптимизации?
CODE
while(1){
cli();
7d4: f8 94 cli
step=10;
7d6: 8a e0 ldi r24, 0x0A ; 10
7d8: 80 93 66 00 sts 0x0066, r24
sei();
7dc: 78 94 sei
7de: fa cf rjmp .-12 ; 0x7d4 <main+0x3a>

Посмотрите, все же, чему равно step, в отладчике.
tazik
Цитата(Methane @ Dec 3 2009, 13:13) *
Посмотрите, все же, чему равно step, в отладчике.


Спасибо за содействие) В основном цикле пытался обратиться к переменной, обрабатываемой в прерывании. Оказывается, в таких случаях надо писать модификатор volatile перед переменной.
mdmitry
Цитата(tazik @ Dec 3 2009, 09:22) *
Спасибо за содействие) В основном цикле пытался обратиться к переменной, обрабатываемой в прерывании. Оказывается, в таких случаях надо писать модификатор volatile перед переменной.

Почитайте FAQ к Winavr, avr-libc и многие вопросы исчезнут. Этот момент там тоже описан. Чтение документации много времени не отнимет, сэкономит больше.
tazik
Цитата(mdmitry @ Dec 3 2009, 18:17) *
Почитайте FAQ к Winavr, avr-libc и многие вопросы исчезнут. Этот момент там тоже описан. Чтение документации много времени не отнимет, сэкономит больше.


Да, Вы правы! Очень полезный документ. Наткнулся почти случайно, попался бы он раньше...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.