Вопросы по С/С++ (СИ)

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

Re: Вопросы по С/С++ (СИ)

Сообщение Kavka »

Чёт мне кажется, что у вас с терминологией и пониманием проблемы. :)
baron_P писал(а):0xd0000001u (7 бит)
Это шестнадцатеричное число (префикс 0x). Unsigned long это 4 байта, 8 шестнадцатеричных цифр. Приведённое число влазит в 4 байта. И о каких 7 битах вы говорите? :kill: Лично я так и не понял.

baron_P писал(а):0xd00000001u (8 бит)
А тут уже 9 шестнадцатеричных цифр и цифра d уже не влазит в 4 байта.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
lakec
Открыл глаза
Сообщения: 78
Зарегистрирован: Вт мар 12, 2013 09:13:16

Re: Вопросы по С/С++ (СИ)

Сообщение lakec »

Товарищи коты. Написал такой код
Спойлер

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

#include <tiny2313.h>
#include <delay.h>
   #define   ledon(reg, bit)       reg &= (~(1<<bit))
   #define   ledoff(reg, bit)          reg |= (1<<bit)       


void main (void){ 
 DDRB = 0b11111111;   
 PORTB = 0b11111111;

  while (1) {
   
  ledon(PORTB, 0);
  delay_ms(10);
  ledoff(PORTB, 0);
  delay_ms(10);
 
    ledon(PORTB, 1);
  delay_ms(10);
  ledoff(PORTB, 1);
  delay_ms(10);
 
    ledon(PORTB, 2);
  delay_ms(10);
  ledoff(PORTB, 2);
  delay_ms(10);
   
    ledon(PORTB, 3);
  delay_ms(10);
  ledoff(PORTB, 3);
  delay_ms(10);
   
    ledon(PORTB, 4);
  delay_ms(10);
  ledoff(PORTB, 4);
  delay_ms(10);     
 
    ledon(PORTB, 5);
  delay_ms(10);
  ledoff(PORTB, 5);
  delay_ms(10); 
 
    ledon(PORTB, 6);
  delay_ms(10);
  ledoff(PORTB, 6);
  delay_ms(10);   
     
    ledon(PORTB, 7);
  delay_ms(10);
  ledoff(PORTB, 7);   
     delay_ms(10); 
     }
 }

Как создать дополнительно функцию чтобы не писать каждый раз

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

 ledon(порт, номер); 
  delay_ms(10);
  ledoff(порт, номер);
  delay_ms(10);
? Пробовал писать функции, но лампы либо не горят, либо компилятор выдает ошибки. И еще вопрос: как нить можно уменьшить (сжать) код. Зависит ли размер хекса от длины названия констант, функций и т.д. Сорри за ламерские вопросы, я пока учусь:)
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

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

Запихнуть в цикл:

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

for(i=0;i<8;i++){
..............   // Тут код повторится 8 раз. При этом переменная i будет увеличиваться от 0 до 7
}


Зависит ли размер хекса от длины названия констант, функций и т.д.
Нет, не зависит.
В кексе не хранится Ваш код, там только адреса переменных и функций. Компилятор меняет имена на адреса.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Goldsmith »

baron_P писал(а):Спасибо.
появился еще вопрос.

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

-(lfsr & 1u) & 0xd0000001u

Левая часть в итоге будет типа unsigned long. Справа, исходно, unsigned char, которое, перед проведением операции "И", превращается в unsigned long. Т.е. 0xd0000001u превратится в 31 ноль и единицу в младшем разряде.
Неверно. Двоичное значение hex-константы 0xD0000001U равно 1101 0000 0000 0000 0000 0000 0000 0001.

С точки зрения стандарта последовательность действий следующая.

1.

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

(lfsr & 1u)
Поскольку переменная lfsr имеет тип unsigned long, второй операнд операции "побитовое И" (константа 1U типа unsigned int) сначала будет "продвинут" до более "широкого" типа unsigned long и превратится в 1UL. Затем Будет произведена собственно операция "И". В зависимости от значения переменной lfsr результатом операции будет либо 0UL (для четных значений), либо 1UL (для нечетных значений).

2.

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

-(lfsr & 1u)
Результат операция смены знака для беззнакового числа, как уже упоминалось ранее, может выйти за пределы разрядной сетки. Стандарт предписывает в таком случае прибавлять к результату (либо вычитать из него) константу ULONG_MAX + 1 (= 2^32) до тех пор, пока значение не попадет в допустимые для данного диапазона границы. В нашем случае -(0UL) оставляет значение тем же самым, а -(1UL) превратится в 0xFFFFFFFFUL (напоминаю, что побитовое представление отрицательных чисел зависит от реализации, поэтому данный код довольно-таки "грязноват"!).

3.

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

-(lfsr & 1u) & 0xd0000001u
Наконец, над результатом предыдущих операций выполняется побитовое "И" с константой 0xD0000001U. Поскольку мы уже выяснили, что этот результат может быть либо 0UL, либо 0xFFFFFFFFUL, то все выражение в итоге дает либо 0UL, либо 0xD0000001UL.

Если это действительно не нужно на практике, а взято лишь как пример для изучения, настоятельно рекомендую бросить его (поскольку качество данного кода, мягко говоря, неважное) и взять что-нибудь качественнее.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
unalex
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

Re: Вопросы по С/С++ (СИ)

Сообщение unalex »

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

while(1)
{
   static unsigned char count = 0;
   
   ledon(PORTB, count);
   _delay_ms(10);
   ledoff(PORTB, count);
   _delay_ms(10);
   (count < 7) ? (count++) : (count = 0);
}
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
lakec
Открыл глаза
Сообщения: 78
Зарегистрирован: Вт мар 12, 2013 09:13:16

Re: Вопросы по С/С++ (СИ)

Сообщение lakec »

unalex, Аlex, большое вам спасибо :)

UPD. И все же ради спортивного интереса, как можно сделать функцией? Чтобы можно было передавать 2 параметра: порт и номер порта (пример: funkciya (PORTB, 5);
funkciya (PORTD, 2);
). Пишу по всякому, но компилятор только ругается.
Аватара пользователя
baron_P
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Вт сен 14, 2010 23:07:10
Откуда: Ростов

Re: Вопросы по С/С++ (СИ)

Сообщение baron_P »

Спасибо.
Не будь проблем с пониманием, не было б и вопросов. Запутался маленько в типах, но теперь понятно.
Сначала доизучаю, а потом что-то более качественное найду. Очень тут доступно все разложенно именно в плане рассмотения пары железо-софт, потому и взялся. Сам объект изучения: "Занимательные проекты на базе микроконтроллеров tinyAVR".
We do what we must because we can (c) GLaDOS
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

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

lakec писал(а):UPD. И все же ради спортивного интереса, как можно сделать функцией? Чтобы можно было передавать 2 параметра: порт и номер порта (пример: funkciya (PORTB, 5);
funkciya (PORTD, 2);
). Пишу по всякому, но компилятор только ругается.
С портом можно работать через указатель, принимая его как аргумент функции. Ну а номер бита - обычная переменная.
Почитайте про указатели в Си.
lakec
Открыл глаза
Сообщения: 78
Зарегистрирован: Вт мар 12, 2013 09:13:16

Re: Вопросы по С/С++ (СИ)

Сообщение lakec »

Аlex, после копания интернета пришел к такому коду
Спойлер

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

#include <tiny2313.h>
#include <delay.h>
   #define   ledon(reg, bit)       reg &= (~(1<<bit))
   #define   ledoff(reg, bit)          reg |= (1<<bit)       

  void funkciya ( unsigned char *data, char nomer){
 
  DDRB = 0b11111111;   
  PORTB = 0b11111111;
  DDRD = 0b11111111;   
  PORTD = 0b11111111;
 
  ledon( *data, nomer);
  delay_ms(5);
  ledoff( *data, nomer);
 
  }


void main (void){ 
 
  while (1) {
    funkciya (PORTD, 0);
  }
 }
на что CVAVR ругается Error: full.c(23): function argument #1 of type 'unsigned char' is incompatible with required parameter of type 'unsigned char *' :(
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Re: Вопросы по С/С++ (СИ)

Сообщение Goodefine »

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

 funkciya (&PORTD, 0);
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Goldsmith »

baron_P писал(а):объект изучения: "Занимательные проекты на базе микроконтроллеров tinyAVR".
Рекомендую посмотреть Application Notes с сайта Atmel. Там можно найти небольшие, но рабочие проекты для решения несложных задач. Они обычно более тщательно отбирают код для публикаций, поэтому меньше шанс нарваться на подобные выкрутасы; а у любителей часто в ходу ущербный аргумент "зато работает!", который оправдывает любую глупость.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
unalex
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

Re: Вопросы по С/С++ (СИ)

Сообщение unalex »

вот наклепал в виде функции, но проверить не на чем

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

typedef enum {TOGGLE, SET, CLEAR}CHANGE;

void changePortPin(unsigned char port_name, unsigned char bit_nr,
      CHANGE how)
{
   unsigned char* port = (unsigned char*) &port_name; //профукал точку с запятой
   
   if (how == TOGGLE)
      *port ^= 1 << bit_nr;
   else if (how == SET)
      *port |= 1 << bit_nr;
   else if (how == CLEAR)
      *port &= ~(1 << bit_nr);
}

void main()
{
   //.........
   changePortPin(PortA, 5, TOGGLE);
   //...........
}


пусть гуру оценят и исправят что не так
Последний раз редактировалось unalex Вс мар 17, 2013 09:46:36, всего редактировалось 1 раз.
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Goldsmith »

unalex писал(а):пусть гуру оценят и исправят что не так
IMHO вместо лестницы if ... else if ... else if ... прямо напрашивается switch. И нагляднее, и простора для потенциальных ошибок поменьше.

И по поводу первого параметра функции есть некоторые сомнения.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Tolmi »

плюсанул.
... но точку с запятой после &port_name лучше всё же поставить. :tea:
In theory, theory and practice are the same. In practice, they're not.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

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

на что CVAVR ругается
У CV какие-то проблемы с этим, не помню уже как там это делается, вроде явно указывали константой адрес порта. В соседней ветке разбирались с указателями на порт, я не вникал особо.
Вообще, CVAVR - какой-то недокомпилятор, нормальные компили без проблем работают с портами через указатель.
lakec
Открыл глаза
Сообщения: 78
Зарегистрирован: Вт мар 12, 2013 09:13:16

Re: Вопросы по С/С++ (СИ)

Сообщение lakec »

Аlex амперсанд перед портом помог, как подсказал Goodefine. Да и я тоже заметил что он не всегда компилит код, который без проблем компилится в ИАР и Атмел Студио.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

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

phenomen
Потрогал лапой паяльник
Сообщения: 310
Зарегистрирован: Пт дек 17, 2010 14:41:25

Re: Вопросы по С/С++ (СИ)

Сообщение phenomen »

unalex писал(а):вот наклепал в виде функции, но проверить не на чем

Сразу же: нормальный С-компилятор создаст копию переменной PortA для обработки в теле функции.
Добавьте банальный принтф:

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

typedef enum {TOGGLE, SET, CLEAR}CHANGE;

void changePortPin(unsigned char port_name, unsigned char bit_nr,
      CHANGE how)
{
   unsigned char* port = (unsigned char*) &port_name; //профукал точку с запятой
   printf("Received: %p\n", port);
}

void main()
{
   //.........
   int PortA = 10;
   printf("Passed: %p\n", &PortA);
   changePortPin(PortA, 5, TOGGLE);
   //...........
}


Результат:

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

Passed: 0xbf6be98c
Received: 0xbf6be954


Изменяем код:

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

typedef enum {TOGGLE, SET, CLEAR}CHANGE;

void changePortPin(unsigned char   /*Принимаем указатель*/   *port_name, unsigned char bit_nr,
      CHANGE how)
{
   unsigned char* port = (unsigned char*) /*Не забываем что у нас уже указатель (нету &)*/ port_name;
   printf("Received: %p\n", port);
}

void main()
{
   //.........
   int PortA = 10;
   printf("Passed: %p\n", &PortA);
   changePortPin(   /*Ну передаем адрес переменной или порта*/   &PortA, 5, TOGGLE);
   //...........
}
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Goldsmith »

phenomen писал(а):Изменяем код
И заодно не забываем добавить volatile во избежание сюрпризов от оптимизатора.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

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

 typedef enum {TOGGLE, SET, CLEAR}CHANGE; 

по мне так вот это вообще лишнее, вместо простой смены порта мы наблюдаем лишнее сравнение ненужной переменной, так почему бы это сравнение не сделать на этапе компиляции(умственно ) и исключить лишний параметр функции, просто будут три функции. может и будет больше места занимать в памяти, зато не будет больше времени занимать при обработке.
Как представишь себе, что эта функция вызывается каждый раз и делает этот switch просто вспоминается мысль о говнокоде. Но ведь работает, как говорили недавно.
На крайняк можно сделать функцию присвоения значения порту через указатель,
а потом три функции для первичной обработки перед присвоением в порт.
Ответить

Вернуться в «Разные вопросы по МК»