Заголовок сообщения: Re: Нескольно простых вопросов о программировании AVR на Си.
Добавлено: Вт дек 01, 2015 19:52:19
Встал на лапы
Зарегистрирован: Чт сен 03, 2015 15:52:10 Сообщений: 109 Откуда: Сибирский федеральный округ
Рейтинг сообщения:0
Почему? я говорил о том что если писать в регистры как обычно и так придется использовать несколько инструкций (записать значение бита в один регистр и во второй это минимум 2 инструкции) для одной настройки. А битовые поля сами по себе не атомарны запись: [перейти по указателю-> считать исходное значение-> применить логическое или с новым значением -> записать обратно] (само значение бита(ов) двигать еще придется) чтение [перейти по указателю-> считать значение -> применить маску] (возможно ее тоже считать во время исполнения придется).
_________________ я повелитель электронов! Но иногда появляются электроны бунтари и делают, что им вздумается, например, прокладывают новые пути движения...
"Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного." Альберт Эйнштейн.
не бред! Любые манипуляции с регистрами желательно защищать если нет уверенности в атоморности и тут нужно смотреть высер компилятора
Обычно эти настройки выполняются в начале программы, когда прерывания запрещены. То есть просто обернуть их парой cli/sei нельзя (а то прерывания будут разрешены слишком рано). Можно, конечно, сохранить весь SREG, но это все равно минимум 2 лишние команды.
Pnjom-Penb писал(а):
В двух предыдущих постах, рассуждения об атомарности - оторваны от рассматриваемой ситуации. То есть - мимо кассы.
А какую ситуацию вы рассматриваете? Лично я - общую, для нее пример и дал. Кстати, я не в курсе, гарантируется ли постоянство адресов. То есть если в ATmega8 регистры TCCR1A и TCCR1B расположены по адресам 0x2F и 0x2E, будут ли они во всех контроллерах идти последовательно и в том же порядке? Это представляется логичным, но гарантируется ли где-нибудь? Ну и запись значений напрямую в регистры выглядит компактнее и проще, чем нагромождение настроек отдельных битов. Даже не повторяя про умение avr-gcc работать с битовыми полями. Может, проще через макросы? Что-то вроде
Причем, поскольку менять режим работы таймера "на лету" вряд ли понадобится, можно обойтись без атомарности, при необходимости реализовав ее снаружи.
Цитата:
А битовые поля сами по себе не атомарны
Если использовать именно указатель - да, по скорости, объему и, частично, надежности все будет печально. А вот изменение 1-2 битов в регистре это 1-2 команды sbr/cbr. Положить битовую структуру на константный адрес может быть непросто (скорее по внешнему виду).
Честно говоря, мне сейчас не по-джентльменски отвлекаться на всякие мелочи и оставлять даму без внимания. Выше уже достаточно сказано, чтобы все отловить. Кстати - в статье, по второй ссылке, предоставленной Вами же, все уже сказано. Вы только ищете статьи, но не читаете их?
это разворачивалось уже в запись в регистры, но проблемы были в том, что макросы иногда уезжали и на выходе получалось не то. (сами макросы получались больше чем если бы битовые поля использовать вот и задумался)
Каждый сам решит через призму своего опыта и заблуждений что лучше для него самого.
_________________ я повелитель электронов! Но иногда появляются электроны бунтари и делают, что им вздумается, например, прокладывают новые пути движения...
"Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного." Альберт Эйнштейн.
Всё верно. 1) Числа 1 и 15 - это signed int, 2) (1<<15) даёт 0x8000 - отрицательное 16-битное число (signed int), оно же равно -32768. 3) Приведение его к 32-битному даёт 0xFFFF8000, оно же -32768
Добрый Вечер Коты!!! У меня есть один вопрос точнее прошение обьясните что конкретно делает конткретный фрагмент кода!!!Я программирую в баском с Си практически не знаком Спойлерvoid write_byte(unsigned char c,unsigned char com)//0-command 1-data { CB(PORT_LCD,CS); if(com==0) CB(PORT_LCD,RS); else SB(PORT_LCD,RS); SB(PORT_LCD,SCK); for(unsigned char i=0;i<8;i++) { if(((c>>(7-i))&1) == 1) SB(PORT_LCD,MOSI); else CB(PORT_LCD,MOSI); CB(PORT_LCD,SCK); SB(PORT_LCD,SCK); } SB(PORT_LCD,CS); }
Телепатирую... IMHO, т.е. CB и SB скорее всего макросы принимающие два параметра - порт и номер бита. CB - clear bit, очистить, сбросить бит в "0" SB - set bit, установить в "1" PORT_LCD, RS, MOSI, MISO и т.д. определённые с помощью #define метки указывающие на реальные порт и биты. Если ты представляешь что такое SPI, то дальше вопросов быть не должно.
Выбор устройства, устанавливается бит команда или данные и строб.
Если надо более детально, то сужай область непонятного. Если не видел ещё, полезно бывает.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
void OutColor(unsigned int color) { WriteTwoByte((color>>8),((color<<8)>>8)); } Обьясни пожалуйста операции со сдвигом битов первое я понял что они здвигаютса в право на 8 а вот второй кусок для меня непонятен
Два первых варианта одинаковы по скорости и объему, третий чуть-чуть быстрее, но занимает на 7 байт ОЗУ больше. Как по мне, первый вариант наиболее прост.
Цитата:
Обьясни пожалуйста операции со сдвигом битов первое я понял что они здвигаютса в право на 8 а вот второй кусок для меня непонятен
Первое - да, сдвиг вправо на 8 бит, то есть старший байт числа, второе - шаманство, не очень понятно что и зачем делается, если можно обойтись простым приведением типа. WriteTwoByte((unsigned char)(color>>8),(unsigned char)color);
Цитата:
причем не как signed int, а как просто int (signed int это масло масляное)
Если я правильно помню, стандартом не оговариваются ни размер, ни наличие знака у стандартных типов, это сделано для упрощения разработки компиляторов. То есть int может быть эквивалентен int32_t, uint16_t и другим, и это нормально.
Если я правильно помню, стандартом не оговариваются ни размер, ни наличие знака у стандартных типов, это сделано для упрощения разработки компиляторов. То есть int может быть эквивалентен int32_t, uint16_t и другим, и это нормально.
void OutColor(unsigned int color) { WriteTwoByte((color>>8),((color<<8)>>8)); }
unsigned int тут это 16-битное целое (например тынц). Соответственно задвинув его влево на 8 бит теряются старшие 8 бит. И сдвинув обратно получаем нули в старших битах. Проще или сделать приведение типов (как уже упоминалось) или побитовое "И" с маской из 8-ми бит.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Здравствуйте всем. Только начал изучать программирование AVR. Решил начать с Си. Поставил AVRStudio 5.0. И AtTiny13. Написал программку включения диода: #include <avr/io.h> #include <avr/interrupt.h> // Подключение системного файла для работы с прерываниями
int main(void) { PORTB = 0b11111111; DDRB = 0b00000001;
GIMSK = 0b01000000; // Разрешение прерываний INT0 на входе PB1 MCUCR = 0b00000010; // при перепаде из 1 в 0
sei(); // Общее разрешение прерываний while (1) {} } Получил .hex фаил 1кБайт. Предел, но можно Добавляю задержку #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h>
GIMSK = 0b01000000; // Разрешение прерываний INT0 на входе PB1 MCUCR = 0b00000010; // при перепаде из 1 в 0
sei(); while (1) {} } И плучаю .hex объемом 6 кбайт. Может я чего не понимаю? У AtTiny13 flash 1 кБайт. Помогите понять, пожалуйста, я с дуба рухнул вниз башкой, или 5-я AVRStudio ?
а) Первое компилируется в 94 байта (hex 279 байт), второе - в 120 байт (hex 357 байт). Это при уровне оптимизации -Os.
б) SIGNAL(SIG_INTERRUPT0) - устарело и новые компиляторы на это ругаются (poisoned interrupt). Лучше использовать ISR(INT0_vect).
в) Код странноват. Да, он рабочий - в рамках техзадания - и установка бита 0 в лог. 1 перед выходом из прерывания приведёт к новому прерыванию сразу после выхода. Но боюсь, на основной цикл, будь там что-то посерьёзнее while() {}, процессора уже не хватит.
г) Ну и классика - задержка (тем более такая большая) в прерывании - зло. Хотя в рамках изучения прерываний сойдёт.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 24
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения