Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
Pnjom-Penb
Мучитель микросхем
Сообщения: 469
Зарегистрирован: Вс авг 30, 2015 03:52:59

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Pnjom-Penb »

В двух предыдущих постах, рассуждения об атомарности - оторваны от рассматриваемой ситуации. То есть - мимо кассы. :dont_know:
Аватара пользователя
DronVolk
Встал на лапы
Сообщения: 109
Зарегистрирован: Чт сен 03, 2015 15:52:10
Откуда: Сибирский федеральный округ

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение DronVolk »

Почему? я говорил о том что если писать в регистры как обычно и так придется использовать несколько инструкций (записать значение бита в один регистр и во второй это минимум 2 инструкции) для одной настройки. А битовые поля сами по себе не атомарны запись: [перейти по указателю-> считать исходное значение-> применить логическое или с новым значением -> записать обратно] (само значение бита(ов) двигать еще придется) чтение [перейти по указателю-> считать значение -> применить маску] (возможно ее тоже считать во время исполнения придется).
я повелитель электронов! Но иногда появляются электроны бунтари и делают, что им вздумается, например, прокладывают новые пути движения...

"Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного." Альберт Эйнштейн.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение COKPOWEHEU »

DronVolk писал(а):не бред! Любые манипуляции с регистрами желательно защищать если нет уверенности в атоморности и тут нужно смотреть высер компилятора

Обычно эти настройки выполняются в начале программы, когда прерывания запрещены. То есть просто обернуть их парой cli/sei нельзя (а то прерывания будут разрешены слишком рано). Можно, конечно, сохранить весь SREG, но это все равно минимум 2 лишние команды.
Pnjom-Penb писал(а):В двух предыдущих постах, рассуждения об атомарности - оторваны от рассматриваемой ситуации. То есть - мимо кассы. :dont_know:
А какую ситуацию вы рассматриваете? Лично я - общую, для нее пример и дал.
Кстати, я не в курсе, гарантируется ли постоянство адресов. То есть если в ATmega8 регистры TCCR1A и TCCR1B расположены по адресам 0x2F и 0x2E, будут ли они во всех контроллерах идти последовательно и в том же порядке? Это представляется логичным, но гарантируется ли где-нибудь?
Ну и запись значений напрямую в регистры выглядит компактнее и проще, чем нагромождение настроек отдельных битов. Даже не повторяя про умение avr-gcc работать с битовыми полями.
Может, проще через макросы? Что-то вроде

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

TIMER_SET_MODE(1,TIMER_PWM);
TIMER_SET_PRESCALER(0, TIMER_128);
Причем, поскольку менять режим работы таймера "на лету" вряд ли понадобится, можно обойтись без атомарности, при необходимости реализовав ее снаружи.
А битовые поля сами по себе не атомарны
Если использовать именно указатель - да, по скорости, объему и, частично, надежности все будет печально. А вот изменение 1-2 битов в регистре это 1-2 команды sbr/cbr. Положить битовую структуру на константный адрес может быть непросто (скорее по внешнему виду).
Pnjom-Penb
Мучитель микросхем
Сообщения: 469
Зарегистрирован: Вс авг 30, 2015 03:52:59

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Pnjom-Penb »

DronVolk писал(а):Почему?
Честно говоря, мне сейчас не по-джентльменски отвлекаться на всякие мелочи и оставлять даму без внимания. 8)
Выше уже достаточно сказано, чтобы все отловить. Кстати - в статье, по второй ссылке, предоставленной Вами же, все уже сказано. Вы только ищете статьи, но не читаете их? :))) :))) 8)
Аватара пользователя
DronVolk
Встал на лапы
Сообщения: 109
Зарегистрирован: Чт сен 03, 2015 15:52:10
Откуда: Сибирский федеральный округ

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение DronVolk »

COKPOWEHEU писал(а):Может, проще через макросы? Что-то вроде

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

TIMER_SET_MODE(1,TIMER_PWM);
TIMER_SET_PRESCALER(0, TIMER_128);

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


вопрос изначально полез не в ту сторону :) он был в само-документировании кода. До этого я решал эту проблему макросами примерный вид:

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

Timer_setup(0)
  Com_A_Disable()
  Com_B_Set()
  Prescale_x8()
  ...
End_Timer_Setup()


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

Каждый сам решит через призму своего опыта и заблуждений что лучше для него самого.
я повелитель электронов! Но иногда появляются электроны бунтари и делают, что им вздумается, например, прокладывают новые пути движения...

"Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного." Альберт Эйнштейн.
Аватара пользователя
c2n
Сверлит текстолит когтями
Сообщения: 1193
Зарегистрирован: Ср июл 25, 2012 21:40:09
Откуда: Самара
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение c2n »

Комрады! наткнулся на грабли. АВР студия 5 и выше. Микроконтроллер 8535 и атмега16.

При попытке выполнить следующий код:

unsigned long uValue = 0;

uValue |= (1<<15);

uValue принимает значение 0xFF FF 80 00

хотя я ожидаю 0x00 00 80 00

код: uValue |= (0b1000000000000000); такое безобразие не делает.

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

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

Всё верно.
1) Числа 1 и 15 - это signed int,
2) (1<<15) даёт 0x8000 - отрицательное 16-битное число (signed int), оно же равно -32768.
3) Приведение его к 32-битному даёт 0xFFFF8000, оно же -32768
Аватара пользователя
c2n
Сверлит текстолит когтями
Сообщения: 1193
Зарегистрирован: Ср июл 25, 2012 21:40:09
Откуда: Самара
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение c2n »

Да. Разобрался. Спасибо!

По умолчанию компилятор студии воспринимает все не явно объявленные значения как signed int.

Для борьбы с подобного рода неясностями необходимо числа объявлять явно.

Конструкция
uValue |= (1UL<<15);
дает ожидаемый результат :)
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

c2n писал(а):По умолчанию компилятор студии воспринимает все не явно объявленные значения как signed int.
вообще-то любой вменяемый компилятор Си так поступает. причем не как signed int, а как просто int (signed int это масло масляное)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Balzercvua
Потрогал лапой паяльник
Сообщения: 311
Зарегистрирован: Вт дек 31, 2013 17:36:43

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Balzercvua »

Добрый Вечер Коты!!!
У меня есть один вопрос точнее прошение обьясните что конкретно делает конткретный фрагмент кода!!!Я программирую в баском с Си практически не знаком :(
Спойлер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);
}
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

Реализация SPI. Достаточно кривая, но вроде как рабочая.
Аватара пользователя
Balzercvua
Потрогал лапой паяльник
Сообщения: 311
Зарегистрирован: Вт дек 31, 2013 17:36:43

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Balzercvua »

WiseLord писал(а):Реализация SPI. Достаточно кривая, но вроде как рабочая.

Я попросил обьяснить что он делает а не что это такое я не могу понять сами циклы и условия обьясните пожайлуста если не трудно :(
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Kavka »

Телепатирую... :)) IMHO, т.е.
CB и SB скорее всего макросы принимающие два параметра - порт и номер бита.
CB - clear bit, очистить, сбросить бит в "0"
SB - set bit, установить в "1"
PORT_LCD, RS, MOSI, MISO и т.д. определённые с помощью #define метки указывающие на реальные порт и биты.
Если ты представляешь что такое SPI, то дальше вопросов быть не должно.

Выбор устройства, устанавливается бит команда или данные и строб.

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

CB(PORT_LCD,CS);
  if(com==0)
    CB(PORT_LCD,RS);
  else
    SB(PORT_LCD,RS);
  SB(PORT_LCD,SCK);


Далее цикл отправки 8 бит.
В if-е проверка i-того бита...
Строб.
После цикла "отпустить" устройство.

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

  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);


Если надо более детально, то сужай область непонятного.
Если не видел ещё, полезно бывает.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
Balzercvua
Потрогал лапой паяльник
Сообщения: 311
Зарегистрирован: Вт дек 31, 2013 17:36:43

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Balzercvua »

Kavka писал(а):Телепатирую...

Спойлерvoid WriteTwoByte(unsigned char LCD_DataH,unsigned char LCD_DataL)
{
write_byte(LCD_DataH,1);
write_byte(LCD_DataL,1);
}

void OutColor(unsigned int color)
{
WriteTwoByte((color>>8),((color<<8)>>8));
}

Обьясни пожалуйста операции со сдвигом битов первое я понял что они здвигаютса в право на 8 а вот второй кусок для меня непонятен :idea:
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение COKPOWEHEU »

Kavka писал(а):

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

    if(((c>>(7-i))&1) == 1)


Вот так делать не стоит - слишком медленно. Лучше скопировать в локальную переменную, а ее сдвигать не боясь
char temp - c;

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

for(i=0;i<8;i++){
  if( temp & (1<<7))
    SB(PORT_LCD,MOSI);
  else
    CB(PORT_LCD,MOSI);

  temp <<=1;
  CB(PORT_LCD,SCK);
  SB(PORT_LCD,SCK);
}
SB(PORT_LCD,CS);
Или, если уж хотите проверки по маске,

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

char temp=(1<<7);
for(i=0;i<8;i++){
  if( c & temp)
    SB(PORT_LCD,MOSI);
  else
    CB(PORT_LCD,MOSI);

  temp >>=1;
...
Или даже так

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

const char mask[8]={(1<<7), (1<<6), (1<<5), (1<<4), (1<<4), (1<<3), (1<<2), (1<<1), (1<<0)};
for(i=0;i<8;i++){
  if( c & mask[i])
...
Два первых варианта одинаковы по скорости и объему, третий чуть-чуть быстрее, но занимает на 7 байт ОЗУ больше. Как по мне, первый вариант наиболее прост.
Обьясни пожалуйста операции со сдвигом битов первое я понял что они здвигаютса в право на 8 а вот второй кусок для меня непонятен :idea:

Первое - да, сдвиг вправо на 8 бит, то есть старший байт числа, второе - шаманство, не очень понятно что и зачем делается, если можно обойтись простым приведением типа.
WriteTwoByte((unsigned char)(color>>8),(unsigned char)color);
причем не как signed int, а как просто int (signed int это масло масляное)
Если я правильно помню, стандартом не оговариваются ни размер, ни наличие знака у стандартных типов, это сделано для упрощения разработки компиляторов. То есть int может быть эквивалентен int32_t, uint16_t и другим, и это нормально.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

COKPOWEHEU писал(а):Если я правильно помню, стандартом не оговариваются ни размер, ни наличие знака у стандартных типов, это сделано для упрощения разработки компиляторов. То есть int может быть эквивалентен int32_t, uint16_t и другим, и это нормально.
нет, int всегда знаковый.

COKPOWEHEU писал(а):Или даже так

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

char temp=(1<<7);
for(; temp; temp >>= 1){
  if( c & temp)
    SB(PORT_LCD,MOSI);
  else
    CB(PORT_LCD,MOSI);
...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Kavka »

Balzercvua писал(а):

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

void OutColor(unsigned int color)
{
WriteTwoByte((color>>8),((color<<8)>>8));
}


unsigned int тут это 16-битное целое (например тынц).
Соответственно задвинув его влево на 8 бит теряются старшие 8 бит. И сдвинув обратно получаем нули в старших битах.
Проще или сделать приведение типов (как уже упоминалось) или побитовое "И" с маской из 8-ми бит.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Юрасик
Родился
Сообщения: 4
Зарегистрирован: Пн июн 17, 2013 14:22:37

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Юрасик »

Здравствуйте всем.
Только начал изучать программирование AVR. Решил начать с Си. Поставил AVRStudio 5.0. И AtTiny13. Написал программку включения диода:
#include <avr/io.h>
#include <avr/interrupt.h> // Подключение системного файла для работы с прерываниями

//SIGNAL(INT0_vect)
SIGNAL(SIG_INTERRUPT0) // Обработчик прерываний
{
PORTB ^= 0x01;
}

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>

//SIGNAL(INT0_vect)
SIGNAL(SIG_INTERRUPT0)
{
_delay_ms(200); // Задержка 200 миллисекунд
if (bit_is_clear(PINB,PB1)) // Опрос PB1
PORTB ^= 0x01;
}
int main(void)
{
PORTB = 0b11111111;
DDRB = 0b00000001;

GIMSK = 0b01000000; // Разрешение прерываний INT0 на входе PB1
MCUCR = 0b00000010; // при перепаде из 1 в 0

sei();
while (1) {}
}
И плучаю .hex объемом 6 кбайт.
Может я чего не понимаю?
У AtTiny13 flash 1 кБайт.
Помогите понять, пожалуйста, я с дуба рухнул вниз башкой, или 5-я AVRStudio ?
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение oleg110592 »

.hex это текстовый файл, его размер не отражает объем занимаемого flash
https://ru.wikipedia.org/wiki/Intel_HEX
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

а) Первое компилируется в 94 байта (hex 279 байт), второе - в 120 байт (hex 357 байт). Это при уровне оптимизации -Os.

б) SIGNAL(SIG_INTERRUPT0) - устарело и новые компиляторы на это ругаются (poisoned interrupt). Лучше использовать ISR(INT0_vect).

в) Код странноват. Да, он рабочий - в рамках техзадания - и установка бита 0 в лог. 1 перед выходом из прерывания приведёт к новому прерыванию сразу после выхода. Но боюсь, на основной цикл, будь там что-то посерьёзнее while() {}, процессора уже не хватит.

г) Ну и классика - задержка (тем более такая большая) в прерывании - зло. Хотя в рамках изучения прерываний сойдёт.
Ответить

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