AVR studio в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18679
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

и в чем проблема-то? переменную опишите volatile - да и все...
да, еще: константы SIG_xxx давно считаются не рекомендованными к применению - оставлены лишь для совместимости. используйте правильные константы, например, TIMER1_OVF_vect
ну и работайте с TCNT1 как с 16-битной переменной - зачем по кусочкам туда вести запись? TCNT1 = 0x1234; да и все дела
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Родился
Сообщения: 9
Зарегистрирован: Чт июн 16, 2011 10:48:32

Сообщение katu6ka »

IfoR, очень благодарна Вам за подробные рекомендации!

С макросами я просто еще как-то не успела познакомиться, как их делают и с чем едят =) Буду знать.

Проблема с прерыванием заключалась в том,что в таблице векторов у меня неправильно прописаны адреса, 000 -> 002 -> 004, я читала пример ШИМа на другой Атмеге и на автомате написала адреса как в том примере, а не как в даташите на 8 атмегу :)

.ORG $000
rjmp RESET ; Reset Handler

.ORG $001 ;rjmp EXT_INT0 ; IRQ0 Handler
reti
.ORG $002 ;rjmp EXT_INT1 ; IRQ1 Handler
reti
.ORG $003 ;rjmp TIM2_COMP ; Timer2 Compare Handler
reti
.ORG $004
rjmp TIM2_OVF ; Timer2 Overflow Handler
(и прочие вектора)


Теперь обработчик прерывания работает, на него стрелка прыгает, действие выполняется. АВР студия не виновата =)

А вот по команде (напишу ее пока так,как писала я) ничего не происходит:

ldi R16, 0b11111111 ; ПОЛОЖИТЬ В OCR 0*FF ; на выходе будет лог. 1
out OCR2, R16 ;

Но в общем-то программа может работать и без этого) Возможно, OCR нельзя обновить в то время, когда считает таймер-счетчик, и можно обновить только в момент переполнения , к началу нового периода.. ?

Теперь остался какой-то странный глюк, что значение в ОСR из АЦП кладется с отставанием .
Т.е кладу в АЦП 0200 (нужен старший байт,т.е в ОСR будет 02) . таймер переполнился, в обработчике прерывания кладем значение АЦП в OCR, но ничего не происходит, там ноль как и был.
Меняю значение в АЦП (пусть 03) в обработчике прерывания по переполнению таймера в OCR кладется... прежнее значение - 02.
По следующему переполнению в OCR положится 03 и т.д., т.е кладется не текущее значение, а предыдущее!

Буду искать причины, но если кто-то знает, в чем дело, поделитесь мнением =)
Реклама
Родился
Сообщения: 13
Зарегистрирован: Пн апр 19, 2010 09:58:37

Сообщение kyraxinoff »

Все анчало работать когда поменял на TIMER1_OVF_vect. спс.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18679
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

katu6ka писал(а):По следующему переполнению в OCR положится 03 и т.д., т.е кладется не текущее значение, а предыдущее!

Буду искать причины, но если кто-то знает, в чем дело, поделитесь мнением =)
искать причины надо в даташите: в режиме ШИМ содержимое OCR обновляется не в момент записи туда, а в момент наступления события обновления, которое в зависимости от варианта ШИМ может наступать либо в момент переполнения счетчика таймера, либо в момент совпадения счетчика с содержимым OCR.

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

katu6ka писал(а): А вот по команде (напишу ее пока так,как писала я) ничего не происходит:

ldi R16, 0b11111111 ; ПОЛОЖИТЬ В OCR 0*FF ; на выходе будет лог. 1
out OCR2, R16 ;

Но в общем-то программа может работать и без этого) Возможно, OCR нельзя обновить в то время, когда считает таймер-счетчик, и можно обновить только в момент переполнения , к началу нового периода.. ?
Ну, как я уже говорил, вероятно это подглючивает студия. Если прогнать данный код в PROTEUS-е, то там он обновляется мгновенно. Во всяком случае, верить на 99% можно только реальному контроллеру. :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Реклама
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

Здравствуйте уважаемы коты.
Я новичок в программировании, программировал на AVRSTUDIO 4.18 + update. Вопрос такой используя указатели на переменные и записывая в них, получаю в протеусе какие то глюки типа с UDR данные считаны, а данные не готовы или ошибка чтения с регистров АЦП хаотичные ошибки. USART я вообще не использую.

Код: Выделить всё

unsigned int key_paint_or_pressed (unsigned char *x, unsigned char *y,unsigned char mode )
{
*x=1;
*y=2;
}
Подскажите пожалуйста как возвращать с функций переменные правильно, простенький пример, нужно вернуть 2 байта. Я думал может с размером стека поиграться только не знаю где и как.
я с делал так

Код: Выделить всё

unsigned int key_paint_or_pressed (unsigned char x, unsigned char y,unsigned char mode )
{
return((переменная_А<<8)| переменная_Б);
}
так работает, а хотелось бы правильно, с указателями.Спасибо за ранее.
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

katu6ka писал(а): А вот по команде (напишу ее пока так,как писала я) ничего не происходит:

ldi R16, 0b11111111 ; ПОЛОЖИТЬ В OCR 0*FF ; на выходе будет лог. 1
out OCR2, R16 ;

Но в общем-то программа может работать и без этого) Возможно, OCR нельзя обновить в то время, когда считает таймер-счетчик, и можно обновить только в момент переполнения , к началу нового периода.. ?
Я так думаю что не обязательно
The double buffered Output Compare Register (OCR2) is compared with the Timer/Counter
value at all times. The result of the compare can be used by the waveform generator to generate
a PWM or variable frequency output on the Output Compare Pin (OC2)The OCR2 Register is double buffered when using any of the Pulse Width Modulation (PWM)
modes.

For the normal and Clear Timer on Compare (CTC) modes of operation, the double buffering
is disabled. The double buffering synchronizes the update of the OCR2 Compare Register
to either top or bottom of the counting sequence.
The synchronization prevents the occurrence
of odd-length, non-symmetrical PWM pulses, thereby making the output glitch-free.
Наверно это говорится о том, что положили в один буфер,а второй работает,пока нельзя обновлять. как только можно обновить - обновляется.
В поисках истины человек развивается.
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

phanis писал(а):Здравствуйте уважаемы коты.
Вопрос такой используя указатели на переменные и записывая в них, получаю в протеусе какие то глюки типа с UDR данные считаны, а данные не готовы или ошибка чтения с регистров АЦП хаотичные ошибки. USART я вообще не использую.
А АЦП вы не используете?
Кстати, в вашем примере лучше использовать ссылки:

Код: Выделить всё

unsigned int key_paint_or_pressed (unsigned char &x, unsigned char &y,unsigned char mode )
{
x=1;
y=2;
return 0;
}
И корректно писать, раз у вас функция возвращает значение, надо return. Например, return 0.
phanis писал(а): Подскажите пожалуйста как возвращать с функций переменные правильно, простенький пример, нужно вернуть 2 байта.
Тут есть несколько способов. Например, вы можете создать новый тип-структуру из двух переменных и работать через неё:

Код: Выделить всё

struct byte2
{ char a,b; };

...

byte2 func ( char mode )
{
 byte2 newStruct;

 newStruct.a = mode;
 newStruct.b = -mode;

 return byte2;
}

...

int main()
{
 byte2 structura = func(5);

 return 0;
}

Либо через указатели, что рекомендуется при больших структурах:

Код: Выделить всё

struct byte2
{ char a,b; };

...

byte2* func ( char mode )
{
 byte2* newStruct = new byte2;

 newStruct->a = mode;
 newStruct->b = -mode;

 return byte2;
}

...

int main()
{
 byte2 *structura = func(5);

 return 0;
}

Так же можно передавать структуру в формальных параметрах:

Код: Выделить всё

struct byte2
{ char a,b; };

...

void func ( char mode, byte2 &newStruct )
{
 newStruct.a = mode;
 newStruct.b = -mode;
}

...

int main()
{
 byte2 structura;
 func(5, structura);

 return 0;
}

И с указателями:

Код: Выделить всё

struct byte2
{ char a,b; };

...

void func ( char mode, byte2 *newStruct )
{
 newStruct->a = mode;
 newStruct->b = -mode;
}

...

int main()
{
 byte2 *structura = new byte2;
 func(5, structura);

 return 0;
}

Либо вообще без структур, прям так как вы и писали:

Код: Выделить всё


void func ( char mode, char &a, char &b )
{
 a = mode;
 b = -mode;
}

...

int main()
{
 char a,b;
 func(5, a, b);

 return 0;
}

Ну в таком духе, в общем. Это уже зависит от вашего стиля программирования. :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город

Сообщение Мастер Ломастер »

IfoR, ну все в ваших советах было бы замечательно, если бы добрая половина из них не относилась к С++ и стилю "больших" компов... например, ссылки и new...
битва с дураками проиграна, победители торжествуют. слава победителям!
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Это печально. :?
Ну на счёт new и прочих динамических типов, это да, я действительно погорячился.
На счёт ссылок. Я не пробовал их заюзать, т.к. нет компилятора под рукой, но, вроде бы, ссылки - это не сложнее указателей. Может и работать, если компилятор поддерживает некоторые конструкции C++.

Кстати, phanis, уточните, вы передавали функции сами переменные или их адреса?
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

А АЦП вы не используете?
Кстати, в вашем примере лучше использовать ссылки:
АЦП использую.
С ссылками пробовал ошибки выходят.
С структурами не пробовал.
Кстати, phanis, уточните, вы передавали функции сами переменные или их адреса?
Переменные.

А вообще можно что бы в функции были 2 и более указателя. Или можно только один указатель использовать??.
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Ну так нужно передавать адреса переменных, типа того:

Код: Выделить всё

void func(char *a)
{
 *a = *a + 5;
}

int main()
{
 char b;

 func(&b);

 return 0;
}
А вообще можно что бы в функции были 2 и более указателя.
Конечно.
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

Понятно спасибо IfoR попробую отпишу.
Я так понял адрес нужно отправлять если в функции будем записывать что то в указатель. А если ни чего не делаем кроме чтения с указателя то можно просто переменную или я не прав??
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Указатель содержит адрес на элемент, соответственно, если ты передашь функции просто b, то в результате в указатель запишется содержимое этой переменной, т.е. такой указатель будет указывать неизвестно куда. Читать то конечно можно из этого, но только ты прочитаешь какой нибудь мусор, ну а если ты ещё и попробуешь писать туда...
Вот только странно, что компилятор не предупредил тебя об этом. При таком раскладе должна была бы вылезти ошибка, типа: невозможно преобразовать тип char в char *.
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

Да так

Код: Выделить всё

 

func(&b);

работает спасибо еще раз..
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 444
Зарегистрирован: Вс ноя 28, 2010 15:18:52
Откуда: Минск

Сообщение ANALOG »

Почему я ничего не могу записать в регистр TIMSK0?
Пишу в студии, тестирую на симуляторе. Контроллер - ATmega48

Код: Выделить всё

ldi R16,0b00000001
out TIMSK0,R16
Компилятор на это ругается:
error: Operand 1 out of range: 0x6E
Что делать? :o
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

ANALOG писал(а):Компилятор на это ругается:
error: Operand 1 out of range: 0x6E
Правильно ругается.
Последний раз редактировалось Gudd-Head Сб июл 02, 2011 15:10:09, всего редактировалось 1 раз.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Мучитель микросхем
Аватара пользователя
Сообщения: 444
Зарегистрирован: Вс ноя 28, 2010 15:18:52
Откуда: Минск

Сообщение ANALOG »

И шо мне делать? :shock:
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

ANALOG писал(а):И шо мне делать? :shock:
1. Почитать про команду OUT, понять свою ошибку, запомнить.
2. Пользоваться одной из команд ST.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Мучитель микросхем
Аватара пользователя
Сообщения: 444
Зарегистрирован: Вс ноя 28, 2010 15:18:52
Откуда: Минск

Сообщение ANALOG »

То есть, нужно вот так:

Код: Выделить всё

ldi ZL,0x6e
ldi R16,0b00000010
st Z,R16
?
Ответить

Вернуться в «AVR»