CodeVision AVR в вопросах и ответах
- sphincs
- Нашел транзистор. Понюхал.
- Сообщения: 174
- Зарегистрирован: Вт сен 11, 2012 09:13:52
- Откуда: Брест, Беларусь
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
del. разобрался
Re: CodeVision AVR в вопросах и ответах
Как в codevisionavr проверить если прерывания включены или выключены?
Включаю с помощью
#asm("sei")
Выключаю с помощью
#asm("cli")
Включаю с помощью
#asm("sei")
Выключаю с помощью
#asm("cli")
Последний раз редактировалось amd9800 Чт июл 09, 2015 12:43:05, всего редактировалось 1 раз.
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
Проверять бит I регистра SREG. Собственно, эти функции именно его устанавливают и снимают.
Re: CodeVision AVR в вопросах и ответах
SREG&=(1<<SREG_I);
такая команда занимает 6 байт
#asm("sei")
а такая всего 2
каким это образом
такая команда занимает 6 байт
#asm("sei")
а такая всего 2
каким это образом
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
Может, это потому, что первая команда обнуляет все биты SREG, не затрагивая SREG_I, а вторая - устанавливает SREG_I, не трогая остальные биты?
Или, если это опечатка - то потому, что нельзя просто установить (SBI) бит в SREG, нужно его сначала вычитать в один из РОН, поменять, и вернуть назад. Видимо, для того SEI/CLI специально для бита прерываний и существуют, чтобы было быстрее.
Или, если это опечатка - то потому, что нельзя просто установить (SBI) бит в SREG, нужно его сначала вычитать в один из РОН, поменять, и вернуть назад. Видимо, для того SEI/CLI специально для бита прерываний и существуют, чтобы было быстрее.
Re: CodeVision AVR в вопросах и ответах
Пишу функцию которая должна выполнятся с отключенными прерываниями.
И я хочу сохранить состояние регистра
Потом отключить прерывания
Выполнить функцию
А потом восстановить состояние прерываний - если они до выполнения функции были значит включить если нет то оставить в выключенном состоянии
Но хочу сделать это с минимальными затратами процессорного времени
Чтоб потратить всего 3 такта процессора
я читаю SREG в переменную reg
отключаю прерывание командой #asm(cli) - просто если проверять это займет больше циклов
а в самом конце в SREG записываю SREG|=(reg&(1<<SREG_I))
но последняя команда это аж 12 байт значит 6 инструкций процессора
это только потому что я хочу записать только бит SREG_I
если использовать другую конструкцию
сэкономлю одну инструкцию и будет 7 инструкций вместо 8
такая конструкция еще меньше на 4 байта - значит итого 5 инструкций
Если же сделать так то всего 3 инструкции
Но у меня вопрос если я в регистр SREG запишу все его содержимое до начала функции не возникнуть ошибки
И я хочу сохранить состояние регистра
Потом отключить прерывания
Выполнить функцию
А потом восстановить состояние прерываний - если они до выполнения функции были значит включить если нет то оставить в выключенном состоянии
Но хочу сделать это с минимальными затратами процессорного времени
Чтоб потратить всего 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 в вопросах и ответах
Я бы не советовал писать напрямую в SREG вообще. Можно нарваться на трудноуловимые ошибки.
Re: CodeVision AVR в вопросах и ответах
тогда придется использовать этот код
Код: Выделить всё
reg=SREG;
#asm("cli")
if (reg&(1<<SREG_I)) {#asm("sei")}
Re: CodeVision AVR в вопросах и ответах
WiseLord, заинтересовал ваш вариант использование определений для инициализации решил по пробовать.
В первом варианте компилятор IAR определят дефайн LED_PORT_CLOCK как функцию и начинает ругаться на неё
Warning[Pe223]: function "RCC_APB2Periph_" declared implicitly C:\Users\Ìàêñèì\Desktop\W5500+BORD\Libraries\led.c 14
А если изменить GPIOB на несуществующий к примеру GPIOB1
то он начинает правильно ругаться на неизвестный дефайн (RCC_APB2Periph_GPIOB1)
Error[Pe020]: identifier "RCC_APB2Periph_GPIOB1" is undefined C:\Users\Ìàêñèì\Desktop\W5500+BORD\Libraries\led.c 14
В чём может быть ошибка?
В первом варианте компилятор 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 в вопросах и ответах
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);
}Re: CodeVision AVR в вопросах и ответах
Благодарю за помощь, я примерно так и думал в чём ошибка ,но как решить не знал.
- mixon46
- Говорящий с текстолитом
- Сообщения: 1644
- Зарегистрирован: Сб фев 18, 2012 15:42:29
- Откуда: Курск
Re: CodeVision AVR в вопросах и ответах
инициализация внешних прерываний
Разрешает внешние прерывания на INT1 по нарастанию фронта так ведь?
(1<<ISC10) \\ установка бита?
(1<<ISC11) \\тоже установка бита?
черточка между скобками обозначает логические или. где есть хоть одна 1 на выходе будет 1
почему бы не записать так
{
MCUCR = 0x0C;
GICR = 0x80;
}
просто взять и присвоить те биты только так
- 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 в вопросах и ответах
Такс... это Вы сейчас с кем ? Сами с собой ? Или отвечали кому ?
-
Rtmip
- Держит паяльник хвостом
- Сообщения: 963
- Зарегистрирован: Чт апр 03, 2014 23:16:55
- Откуда: Россия
Re: CodeVision AVR в вопросах и ответах
Аlex, это был вопрос такой.
mixon46, да, в данном случае так можно, но не наглядно, не будет написано, какие биты меняете.
mixon46, да, в данном случае так можно, но не наглядно, не будет написано, какие биты меняете.
- mixon46
- Говорящий с текстолитом
- Сообщения: 1644
- Зарегистрирован: Сб фев 18, 2012 15:42:29
- Откуда: Курск
Re: CodeVision AVR в вопросах и ответах
Да это был вопрос. Правильно ли я думаю или нет. Теперь осталось еще немного информации и я возможно закончу свою программу. мне нужно сделать по двум внешним прерываниям два разных действия на tiny2313. по int0 и int1. Возможно ли так сделать?
Re: CodeVision AVR в вопросах и ответах
Всем доброго времени суток!
Вопрос вот в чем. В программе имеется два счетчика импульсов (импульсы разные). Числа большие по этому пришлось поместить в long int. В итоге контроллер стал жутко тормозить. ATmega324P, 1 MHz частота контроллера(важно потребление). Возможно ли обойти данную проблему или нужно увеличивать частоту контроллера? Других вариантов не вижу(
Вопрос вот в чем. В программе имеется два счетчика импульсов (импульсы разные). Числа большие по этому пришлось поместить в long int. В итоге контроллер стал жутко тормозить. ATmega324P, 1 MHz частота контроллера(важно потребление). Возможно ли обойти данную проблему или нужно увеличивать частоту контроллера? Других вариантов не вижу(
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
Если с этими 32-битными числами не производить операций умножения и, особенно, деления, то тормозить не должно.
Включив режим телепатии, предположу, что Вы эти числа у себя в программе делите на 10/100/1000 и так далее для разбора на разряды, что и вызывает эти тормоза. Особенно, если эти деления идут внутри прерывания. Если так, то нужно избавляться от делений, и всё будет ОК. Либо хотя бы делать это не в прерываниях.
Включив режим телепатии, предположу, что Вы эти числа у себя в программе делите на 10/100/1000 и так далее для разбора на разряды, что и вызывает эти тормоза. Особенно, если эти деления идут внутри прерывания. Если так, то нужно избавляться от делений, и всё будет ОК. Либо хотя бы делать это не в прерываниях.
Re: CodeVision AVR в вопросах и ответах
WiseLord писал(а):Если с этими 32-битными числами не производить операций умножения и, особенно, деления, то тормозить не должно.
Включив режим телепатии, предположу, что Вы эти числа у себя в программе делите на 10/100/1000 и так далее для разбора на разряды, что и вызывает эти тормоза. Особенно, если эти деления идут внутри прерывания. Если так, то нужно избавляться от делений, и всё будет ОК. Либо хотя бы делать это не в прерываниях.
увы но вы почти правы, деление происходит именно для разбора на разряды, но не в прерываниях а в основной программе , но с частотой раз в 1 секунду.
- mixon46
- Говорящий с текстолитом
- Сообщения: 1644
- Зарегистрирован: Сб фев 18, 2012 15:42:29
- Откуда: Курск
Re: CodeVision AVR в вопросах и ответах
Привет всем. Я столкнулся с проблемой ещё одной. Чем больше узнаешь тем больше сложностей
В общем принимаю биты с 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 и если не правильно то как правильно записать?
В общем принимаю биты с 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 и если не правильно то как правильно записать?