Страница 1 из 2
(?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 14:21:10
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)) ); вызывается из прерывания таймера.
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 14:40:04
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);
}
}
Вот. Как-то так.
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 14:46:37
pyzhman
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 14:49:51
romazan
согласен, забыл

Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 14:56:38
Goldsmith
Johnson писал(а):Либо, подскажите другой способ, пожалуйста.
Попробуйте что-то вроде:
Код: Выделить всё
...
unsigned char mask;
...
for (;;)
for (mask = 0b00000100; mask <= 0b00100000; mask <<= 1)
{
PORTD |= mask; // включить
pause(); // сделать паузу, чтобы зафиксировать текущую позицию
PORTD &= ~mask; // погасить
}
Функцию
pause() реализуйте по собственному вкусу. Само собой, задержка не должна находиться в обработчике прерывания таймера.
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 15:07:32
Johnson
PORTD = 0b00111100 ^ (1<<(2+tmp));
Не пойдет по одному из требований - необходимо, чтоб ноги 0,1,6,7 не изменили текущего состояния.
PORTD &= ~mask;
А вот над этим уже можно подумать, спасибо!
PS: мне не нужен конкретно бегущий огонь, паузы и всё такое.
Просто в своем примере я упростил код для понимания.
Мне нужно управлять ногами 2-5 в зависимости от значения переменной (сдвигать бит на значение переменной, но относительно второго бита порта, но не больше 5-го бита включительно).
В схеме даже диодов нет...
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 15:17:15
Johnson
Всё, разобрался... Вопрос отменяется, спасибо большое всем, кто откликнулся!
Код: Выделить всё
PORTD = (PORTD & 0b11000011) | (1<<2+tmp2);
Затупил в логике, нудо было сначала обнулить нужные биты, а потом уже ИЛИ по маске производить.
А я производил И по маске, ничтоже сумнящийся, что в порте будут лог1 на нужных битах
PS: Можно даже подправить так на всякий случай, чтоб эта единица за пределы не вышла по ошибке...:
PORTD = (PORTD & 0b11000011) | ((1<<2+tmp2) & 0b00111100);
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 15:26:37
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 определить самостоятельно, если не поддерживается вашим компилятором.
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 15:33:03
Johnson
Спасибо большое, пригодится!
Да, это переменная в CVAVR значится как unsigned char X;
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 15:40:47
BCluster
В кодвижне есть фича можно непосредственно к битам порта обращаться: PORTD.1 PORTD.2 и т.д.
Устанавливать и снимать бит просто PORTD.1 = 1; PORTD.1 = 0;
Учтите что это костыли, в стандарте такого нет, а в кодвижне есть )
Успехов
Re: (?) Небольшой вопрос по С
Добавлено: Ср авг 01, 2012 16:35:13
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.
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 04:11:50
Johnson
BCluster, не понимаю, к чему Вы...
Вы мои посты и примеры кода не читали вообще?
Во-первых, проблема уже решена логикой, а не костылями.
Во-вторых, я писал, что меня не устроит решение на побитном обращении...
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 07:15:14
BCluster
clawham писал(а):А почему это костыль обращение к битам??????
а что же такое тогда асмовая комманда
Ничего не имею против асмовой команды ) Я говорю к тому, что данное обращение не является стандартным и непереносимо, вот и все
Johnson писал(а):Во-первых, проблема уже решена логикой, а не костылями.
Решена и решена, а кому-то может пригодится то о чем я написал. Вы свой ответ уже получили - чего злитесь?

Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 15:21:14
Johnson
Решил не создавать новую тему...
Скажите, пожалуйста, как можно число (int) преобразовать в строку?
И ещё...
Может быть, у кого-нибудь есть готовый код, который позволит число из переменной вывести большими цифрами на LCD дисплее в нужном месте?
Дисплей WG12232, 122*32, по горизонтали разделен на 4 страницы (строки).
Нужен вывод цифры (а точнее двухзначного числа) на высоту всего дисплея.
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 15:38:51
Goldsmith
Johnson писал(а):Скажите, пожалуйста, как можно число (int) преобразовать в строку?
Нестандартная, но широко распространенная функция:
Код: Выделить всё
void* itoa(int input, char *buffer, int radix)
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 15:51:21
Johnson
А пример использования можно?
Не очень представляю, как нужно организовать буфер, и что есть 3й аргумент...
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 15:55:51
Goldsmith
Вот здесь достаточно подробно, и вроде на первый взгляд ошибок не заметил.
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 16:36:39
BCluster
А есче можно printf() иcпользовать... или sprintf(). Жрет память программ.
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 16:38:12
BCluster
3 аргумент это вроде как база системы счисления... И если я правильно помню он не во всех реализациях есть вообще.
буфер можете сразу по разрядности числа сделать.
Скажем если 2 разряда то
Код: Выделить всё
#define BASE 10
unsigned char buf[3];
unsigned char digit;
itoa ( digit, buf, BASE );
Re: (?) Небольшой вопрос по С
Добавлено: Чт авг 02, 2012 20:32:37
Goldsmith
BCluster писал(а):Скажем если 2 разряда то
Код: Выделить всё
...
unsigned char buf[2];
...
itoa ( digit, buf, BASE );
Классическая реализация от Кернигана/Ритчи дописывает в конец строки еще и '\0'. Вполне вероятно, что остальные делают то же самое (хотя для нестандартной функции наверняка ничего утверждать нельзя). Поэтому для 2-разрядного числа лучше все же заложить буфер длиной не меньше 3 байт, чтобы не наступить на одни из наиболее популярных "сишных" граблей.