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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
sphincs
Нашел транзистор. Понюхал.
Сообщения: 174
Зарегистрирован: Вт сен 11, 2012 09:13:52
Откуда: Брест, Беларусь
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение sphincs »

del. разобрался
amd9800
Опытный кот
Сообщения: 822
Зарегистрирован: Вс июн 02, 2013 12:23:03

Re: CodeVision AVR в вопросах и ответах

Сообщение amd9800 »

Как в codevisionavr проверить если прерывания включены или выключены?
Включаю с помощью
#asm("sei")
Выключаю с помощью
#asm("cli")
Последний раз редактировалось amd9800 Чт июл 09, 2015 12:43:05, всего редактировалось 1 раз.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Проверять бит I регистра SREG. Собственно, эти функции именно его устанавливают и снимают.
amd9800
Опытный кот
Сообщения: 822
Зарегистрирован: Вс июн 02, 2013 12:23:03

Re: CodeVision AVR в вопросах и ответах

Сообщение amd9800 »

SREG&=(1<<SREG_I);
такая команда занимает 6 байт

#asm("sei")
а такая всего 2

каким это образом
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Может, это потому, что первая команда обнуляет все биты SREG, не затрагивая SREG_I, а вторая - устанавливает SREG_I, не трогая остальные биты?

Или, если это опечатка - то потому, что нельзя просто установить (SBI) бит в SREG, нужно его сначала вычитать в один из РОН, поменять, и вернуть назад. Видимо, для того SEI/CLI специально для бита прерываний и существуют, чтобы было быстрее.
amd9800
Опытный кот
Сообщения: 822
Зарегистрирован: Вс июн 02, 2013 12:23:03

Re: CodeVision AVR в вопросах и ответах

Сообщение amd9800 »

Пишу функцию которая должна выполнятся с отключенными прерываниями.

И я хочу сохранить состояние регистра
Потом отключить прерывания
Выполнить функцию

А потом восстановить состояние прерываний - если они до выполнения функции были значит включить если нет то оставить в выключенном состоянии

Но хочу сделать это с минимальными затратами процессорного времени

Чтоб потратить всего 3 такта процессора
я читаю SREG в переменную reg
отключаю прерывание командой #asm(cli) - просто если проверять это займет больше циклов

а в самом конце в SREG записываю SREG|=(reg&(1<<SREG_I))
но последняя команда это аж 12 байт значит 6 инструкций процессора
это только потому что я хочу записать только бит SREG_I
если использовать другую конструкцию

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

reg=SREG&(1<<SREG_I);
#asm("cli")
SREG|=reg;

сэкономлю одну инструкцию и будет 7 инструкций вместо 8


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

reg=SREG;
#asm("cli")
if (reg&(1<<SREG_I)) {#asm("sei")}

такая конструкция еще меньше на 4 байта - значит итого 5 инструкций

Если же сделать так то всего 3 инструкции

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

reg=SREG;
#asm("cli")
SREG=reg;


Но у меня вопрос если я в регистр SREG запишу все его содержимое до начала функции не возникнуть ошибки
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Я бы не советовал писать напрямую в SREG вообще. Можно нарваться на трудноуловимые ошибки.
amd9800
Опытный кот
Сообщения: 822
Зарегистрирован: Вс июн 02, 2013 12:23:03

Re: CodeVision AVR в вопросах и ответах

Сообщение amd9800 »

тогда придется использовать этот код

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

reg=SREG;
#asm("cli")
if (reg&(1<<SREG_I)) {#asm("sei")}
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: CodeVision AVR в вопросах и ответах

Сообщение pokk »

WiseLord, заинтересовал ваш вариант использование определений для инициализации решил по пробовать.

В первом варианте компилятор IAR определят дефайн LED_PORT_CLOCK как функцию и начинает ругаться на неё
Warning[Pe223]: function "RCC_APB2Periph_" declared implicitly C:\Users\Ìàêñèì\Desktop\W5500+BORD\Libraries\led.c 14

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

#define CONCAT(x,y) x ## y

#define   LED_PORT GPIOB
#define   LED_PORT_CLOCK(x)         CONCAT(RCC_APB2Periph_,x)


void init_led(void){
   GPIO_InitTypeDef  GPIO_InitStructure;

   RCC_APB2PeriphClockCmd(LED_PORT_CLOCK(LED_PORT),ENABLE);
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
   GPIO_InitStructure.GPIO_Pin = LED_ERT|LED_ERR|LED_BR ;
   GPIO_Init(LED_PORT, &GPIO_InitStructure);
}

А если изменить GPIOB на несуществующий к примеру GPIOB1
то он начинает правильно ругаться на неизвестный дефайн (RCC_APB2Periph_GPIOB1)
Error[Pe020]: identifier "RCC_APB2Periph_GPIOB1" is undefined C:\Users\Ìàêñèì\Desktop\W5500+BORD\Libraries\led.c 14

В чём может быть ошибка?
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

GPIOB определён как ((GPIO_TypeDef *) GPIOB_BASE), в stm32f0xx.h, и эту кучу скобок и вложенных макроопределений препроцесср не может нормально склеить.

Попробуйте лучше как-то так:

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

#define   LED_PORT      B
#define   GPIO(x)       CONCAT(GPIO, x)
#define   CLOCK(x)      CONCAT(APB2Periph_GPIO,x)

void init_led(void){
   GPIO_InitTypeDef  GPIO_InitStructure;

   RCC_APB2PeriphClockCmd(CLOCK(LED_PORT), ENABLE);
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
   GPIO_InitStructure.GPIO_Pin = LED_ERT | LED_ERR | LED_BR ;
   GPIO_Init(GPIO(LED_PORT), &GPIO_InitStructure);
}
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: CodeVision AVR в вопросах и ответах

Сообщение pokk »

Благодарю за помощь, я примерно так и думал в чём ошибка ,но как решить не знал.
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: CodeVision AVR в вопросах и ответах

Сообщение mixon46 »

инициализация внешних прерываний

    void INTinit()
    {
    MCUCR = (1<<ISC10) | (1<<ISC11);//0b00001100
    GICR = (1<<INT1);//0b10000000
    }

Разрешает внешние прерывания на INT1 по нарастанию фронта так ведь?




(1<<ISC10) \\ установка бита?
(1<<ISC11) \\тоже установка бита?

черточка между скобками обозначает логические или. где есть хоть одна 1 на выходе будет 1


почему бы не записать так
{
MCUCR = 0x0C;
GICR = 0x80;
}
просто взять и присвоить те биты только так
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение Аlex »

Такс... это Вы сейчас с кем ? Сами с собой ? Или отвечали кому ?
Rtmip
Держит паяльник хвостом
Сообщения: 963
Зарегистрирован: Чт апр 03, 2014 23:16:55
Откуда: Россия

Re: CodeVision AVR в вопросах и ответах

Сообщение Rtmip »

Аlex, это был вопрос такой. :idea:
mixon46, да, в данном случае так можно, но не наглядно, не будет написано, какие биты меняете.
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: CodeVision AVR в вопросах и ответах

Сообщение mixon46 »

Да это был вопрос. Правильно ли я думаю или нет. Теперь осталось еще немного информации и я возможно закончу свою программу. мне нужно сделать по двум внешним прерываниям два разных действия на tiny2313. по int0 и int1. Возможно ли так сделать?
amd9800
Опытный кот
Сообщения: 822
Зарегистрирован: Вс июн 02, 2013 12:23:03

Re: CodeVision AVR в вопросах и ответах

Сообщение amd9800 »

можно
DarkWolf
Встал на лапы
Сообщения: 117
Зарегистрирован: Ср ноя 05, 2014 19:04:31

Re: CodeVision AVR в вопросах и ответах

Сообщение DarkWolf »

Всем доброго времени суток!
Вопрос вот в чем. В программе имеется два счетчика импульсов (импульсы разные). Числа большие по этому пришлось поместить в long int. В итоге контроллер стал жутко тормозить. ATmega324P, 1 MHz частота контроллера(важно потребление). Возможно ли обойти данную проблему или нужно увеличивать частоту контроллера? Других вариантов не вижу(
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Если с этими 32-битными числами не производить операций умножения и, особенно, деления, то тормозить не должно.

Включив режим телепатии, предположу, что Вы эти числа у себя в программе делите на 10/100/1000 и так далее для разбора на разряды, что и вызывает эти тормоза. Особенно, если эти деления идут внутри прерывания. Если так, то нужно избавляться от делений, и всё будет ОК. Либо хотя бы делать это не в прерываниях.
DarkWolf
Встал на лапы
Сообщения: 117
Зарегистрирован: Ср ноя 05, 2014 19:04:31

Re: CodeVision AVR в вопросах и ответах

Сообщение DarkWolf »

WiseLord писал(а):Если с этими 32-битными числами не производить операций умножения и, особенно, деления, то тормозить не должно.

Включив режим телепатии, предположу, что Вы эти числа у себя в программе делите на 10/100/1000 и так далее для разбора на разряды, что и вызывает эти тормоза. Особенно, если эти деления идут внутри прерывания. Если так, то нужно избавляться от делений, и всё будет ОК. Либо хотя бы делать это не в прерываниях.


увы но вы почти правы, деление происходит именно для разбора на разряды, но не в прерываниях а в основной программе , но с частотой раз в 1 секунду.
Аватара пользователя
mixon46
Говорящий с текстолитом
Сообщения: 1644
Зарегистрирован: Сб фев 18, 2012 15:42:29
Откуда: Курск

Re: CodeVision AVR в вопросах и ответах

Сообщение mixon46 »

Привет всем. Я столкнулся с проблемой ещё одной. Чем больше узнаешь тем больше сложностей :))

В общем принимаю биты с PIND.0 по внешнему прерыванию. Как только получил сигнал начинаю принимать биты. Сначала задержка 1 мсек что бы попасть в золотую середину импульса. Потом через каждые 2 мсек считываю PIND.0. Мне нужно записать бит в каждый следующий бит переменной int b. Можно воспользоваться сдвигом переменной на 1 влево допустим.


flash unsigned int kod [2] = {2499, 8432};

void delay (void)
{функция задержки};

void delay1 (void)
{функция задержки 1};

void main (voud)

unsigned char a;
unsigned int b;
unsigned int c;

while (1)
{

delay (); \\выполнение задержки 1 мсек
for (a=0; a<16; a++) \\выполним цикл 16 раз для записи каждого бита в переменную b
b&0=PIND.0 \\присвоение младшему биту переменной b значение младшего бита порта PIND (тут я вроде что то не верно сделал
\\так как codevision ругался, поправьте меня если не так)
b=b<<1; \\сдвиг содержимого на 1 к старшему биту
delay1 (); \\выполнение задержки 2 мсек

}; \\после завершения цикла мне нужно сравнить переменную b с каждым значением из массива по очереди.

for (a=0; a<2; a++) \\выполним цикл два раза для каждого значения массива kod
{if (b==kod[a]) \\сравниваю переменную b со значением массива kod[элемент массива] если верно то перейду к
\\выполнению действия
{goto m1;
}
else \\если неверно то прибавлю к переменной c +1 (переменную с пришлось ввести по ходу написания кода, в
\\зависимости чему равно с (0 или 1) будет выполнятся два разных кода)
{с=с++;}

\\ну а далее будет выбор действия в зависимости от того чему равна переменная с. но это уже другая история

косяк в том правильно ли я записал присвоение младшему биту переменной b младшего бита порта PIND и если не правильно то как правильно записать? :)
Ответить

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