(?) Небольшой вопрос по С

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

Здравствуйте, уважаемые коты!

Простите за вопрос не совсем по теме контроллеров, но по близкой...

Скажите, почему не работает следующий код:

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


PORTD = 0b11000011;
tmp=0;

while(1){
  tmp++;
  if (tmp>3)tmp=0;
  PORTD = PORTD & (0b11000011 | (1<<(2+tmp)) );
}
В теории это должно вызвать "бегущий огонь" диодов, подключенных к portd.2-portd.5, не трогая остальные выводы...
На практике творится что попало.

Либо, подскажите другой способ, пожалуйста.
Только просьба, тупой перебор битов порта не предлагать. Нужно именно по формуле, смещая огонек в зависимости от значения tmp...

PS: Компилятор CVAVR
PPS: Не знаю, важно ли это, но PORTD = PORTD & (0b11000011 | (1<<(2+tmp)) ); вызывается из прерывания таймера.
Контактная информация:
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва

Сообщение romazan »

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

int main()
{
  unsigned char tmp=0;
  DDRD = 0b00111100;
  while(1)
  {
    tmp++;
    if (tmp>3)tmp=0;
    PORTD = 0b00111100 ^ (1<<(2+tmp));
    _delay_ms(1000);
  }
}
Вот. Как-то так.
Последний раз редактировалось romazan Ср авг 01, 2012 14:50:39, всего редактировалось 1 раз.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск

Сообщение pyzhman »

2romazan:
Тогда уж

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

PORTD = 0b00111100 ^ (1<<(2+tmp));
Docendo discimus
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва

Сообщение romazan »

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

Сообщение Goldsmith »

Johnson писал(а):Либо, подскажите другой способ, пожалуйста.
Попробуйте что-то вроде:

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

...
unsigned char mask;
...
for (;;)
  for (mask = 0b00000100; mask <= 0b00100000; mask <<= 1)
  {
    PORTD |= mask; // включить
    pause(); // сделать паузу, чтобы зафиксировать текущую позицию
    PORTD &= ~mask; // погасить
  }
Функцию pause() реализуйте по собственному вкусу. Само собой, задержка не должна находиться в обработчике прерывания таймера.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Реклама
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

PORTD = 0b00111100 ^ (1<<(2+tmp));
Не пойдет по одному из требований - необходимо, чтоб ноги 0,1,6,7 не изменили текущего состояния.

PORTD &= ~mask;
А вот над этим уже можно подумать, спасибо!

PS: мне не нужен конкретно бегущий огонь, паузы и всё такое.
Просто в своем примере я упростил код для понимания.
Мне нужно управлять ногами 2-5 в зависимости от значения переменной (сдвигать бит на значение переменной, но относительно второго бита порта, но не больше 5-го бита включительно).
В схеме даже диодов нет...
Контактная информация:
Реклама
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

Всё, разобрался... Вопрос отменяется, спасибо большое всем, кто откликнулся!

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

PORTD = (PORTD & 0b11000011) | (1<<2+tmp2);
Затупил в логике, нудо было сначала обнулить нужные биты, а потом уже ИЛИ по маске производить.
А я производил И по маске, ничтоже сумнящийся, что в порте будут лог1 на нужных битах :)

PS: Можно даже подправить так на всякий случай, чтоб эта единица за пределы не вышла по ошибке...:
PORTD = (PORTD & 0b11000011) | ((1<<2+tmp2) & 0b00111100);
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

Johnson писал(а):Мне нужно управлять ногами 2-5 в зависимости от значения переменной (сдвигать бит на значение переменной, но относительно второго бита порта, но не больше 5-го бита включительно).
Тогда такой небольшой джентльменский набор:

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

static uint8_t mask(uint8_t n)
{
  return ((1 << (n+2)) & 0b00111100);
}

void bit_set(uint8_t n)
{
  PORTD |= mask(n);
}

void bit_clear(uint8_t n)
{
  PORTD &= ~mask(n);
}
Тип uint8_t определить самостоятельно, если не поддерживается вашим компилятором.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

Спасибо большое, пригодится!

Да, это переменная в CVAVR значится как unsigned char X;
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

В кодвижне есть фича можно непосредственно к битам порта обращаться: PORTD.1 PORTD.2 и т.д.
Устанавливать и снимать бит просто PORTD.1 = 1; PORTD.1 = 0;
Учтите что это костыли, в стандарте такого нет, а в кодвижне есть )
Успехов
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса

Сообщение clawham »

А почему это костыль обращение к битам??????

а что же такое тогда асмовая комманда

из даташита

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

SBI P,b Set Bit in I/O Register I/O(P,b) ← 1 None 2
CBI P,b Clear Bit in I/O Register I/O(P,b) ← 0
а интерпретатор или эту команду ставит или просто логик если нет аткого в ядре..но помоему даж в тине 13 есть

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

All ATmega8 I/Os and peripherals are placed in the I/O space. The I/O locations are accessed
by the IN and OUT instructions, transferring data between the 32 general purpose working registers
and the I/O space. I/O Registers within the address range 0x00 - 0x1F are directly bitaccessible
using the SBI and CBI instructions. In these registers, the value of single bits can be
checked by using the SBIS and SBIC instructions.
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
Контактная информация:
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

BCluster, не понимаю, к чему Вы...
Вы мои посты и примеры кода не читали вообще?

Во-первых, проблема уже решена логикой, а не костылями.
Во-вторых, я писал, что меня не устроит решение на побитном обращении...
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

clawham писал(а):А почему это костыль обращение к битам??????

а что же такое тогда асмовая комманда
Ничего не имею против асмовой команды ) Я говорю к тому, что данное обращение не является стандартным и непереносимо, вот и все :)
Johnson писал(а):Во-первых, проблема уже решена логикой, а не костылями.
Решена и решена, а кому-то может пригодится то о чем я написал. Вы свой ответ уже получили - чего злитесь? :)))
Контактная информация:
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

Решил не создавать новую тему...

Скажите, пожалуйста, как можно число (int) преобразовать в строку?

И ещё...
Может быть, у кого-нибудь есть готовый код, который позволит число из переменной вывести большими цифрами на LCD дисплее в нужном месте?
Дисплей WG12232, 122*32, по горизонтали разделен на 4 страницы (строки).
Нужен вывод цифры (а точнее двухзначного числа) на высоту всего дисплея.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

Johnson писал(а):Скажите, пожалуйста, как можно число (int) преобразовать в строку?
Нестандартная, но широко распространенная функция:

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

void* itoa(int input, char *buffer, int radix)
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Встал на лапы
Сообщения: 93
Зарегистрирован: Чт мар 05, 2009 08:15:25

Сообщение Johnson »

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

Сообщение Goldsmith »

Вот здесь достаточно подробно, и вроде на первый взгляд ошибок не заметил.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

А есче можно printf() иcпользовать... или sprintf(). Жрет память программ.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

3 аргумент это вроде как база системы счисления... И если я правильно помню он не во всех реализациях есть вообще.
буфер можете сразу по разрядности числа сделать.
Скажем если 2 разряда то

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

#define BASE  10
unsigned char buf[3];
unsigned char digit;
itoa ( digit, buf, BASE );
Последний раз редактировалось BCluster Пт авг 03, 2012 08:50:59, всего редактировалось 1 раз.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону

Сообщение Goldsmith »

BCluster писал(а):Скажем если 2 разряда то

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

...
unsigned char buf[2];
...
itoa ( digit, buf, BASE );
Классическая реализация от Кернигана/Ритчи дописывает в конец строки еще и '\0'. Вполне вероятно, что остальные делают то же самое (хотя для нестандартной функции наверняка ничего утверждать нельзя). Поэтому для 2-разрядного числа лучше все же заложить буфер длиной не меньше 3 байт, чтобы не наступить на одни из наиболее популярных "сишных" граблей.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Контактная информация:
Ответить

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