|
|
  |
Как из Байта получить восемь значений 0 и 1, CodeVision AVR |
|
|
|
Dec 25 2008, 17:23
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 11-12-08
Из: Республика Беларусь, г.Минск
Пользователь №: 42 380

|
Цитата(xemul @ Dec 25 2008, 17:13)  Странно, что еще до интегралов не добрались... Код #define BIT 1 /* задаем нужный номер пина (0...7) */ for (unsigned char bitmask = 1; bitmask; bitmask <<= 1) { (byte & bitmask)? PORTW |= (1<<BIT): PORTW &= ~(1<<BIT); delay_ms(x); } Не знаю, помню когда сдвиг вправо у меня компилёр ошибался и иногда задвигал в старший бит '1', а влево - всегда '0' (Или это был кольцевой сдвиг?) (Или это был глючный компилёр?) (Или тип переменной был signed?) Не сталкивались?
|
|
|
|
|
Dec 25 2008, 17:36
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(DenisIV @ Dec 25 2008, 22:23)  иногда задвигал в старший бит '1', а влево - всегда '0' (Или это был кольцевой сдвиг?) Нету такого сдвига в стандарте Си. Цитата(DenisIV @ Dec 25 2008, 22:23)  (Или тип переменной был signed?) Угу, скорее всего именно так. Операция сдвига над переменной типа signed проводилась. Когда у переменной типа signed устанавливают старший бит, то число становится отрицательным. А при операции сдвига знак у такой переменной меняется не должен. Т.е. единичка-то вправо сдвигается, но в старшем бите она все равно остается.
|
|
|
|
|
Dec 25 2008, 18:19
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Цитата(xemul @ Dec 25 2008, 17:13)  Компилятор CAVR (и avr-gcc тоже) не поймет запись Код (byte & bitmask)? PORTW |= (1<<BIT): PORTW &= ~(1<<BIT); Кроме того, CAVR не допускает объявления вида: Код for (unsigned char mask ...) Цитата(xemul @ Dec 25 2008, 17:13)  Странно, что еще до интегралов не добрались... До интегралов ща доберемся... Код ... #define BIT 0 #define PORTW PORTD #define x 10 ... void transmit_byte(unsigned char const *byte, unsigned char direct){ unsigned char mask; switch(direct){ case 0: //младший бит вперед for (mask=1;mask;mask<<=1) {PORTW=(*byte&mask)? PORTW|(1<<BIT):PORTW&~(1<<BIT); delay_us(x); /*или delay_ms(x); */} break; case 1: //старший бит вперед for (mask=0x80;mask;mask>>=1) {PORTW=(*byte&mask)? PORTW|(1<<BIT):PORTW&~(1<<BIT); delay_us(x);} break; } } ... transmit_byte(&byte,0); //младший бит вперед ... transmit_byte(&byte,1); //старший бит вперед ...
Сообщение отредактировал Goodefine - Dec 25 2008, 18:28
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Dec 25 2008, 20:13
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Goodefine @ Dec 25 2008, 20:19)  Компилятор CAVR (и avr-gcc тоже) не поймет запись Код (byte & bitmask)? PORTW |= (1<<BIT): PORTW &= ~(1<<BIT); Что именно в этой записи ему будет непонятно? Единственным возможным побочным эффектом может быть лишнее чтение PORTW после записи.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 25 2008, 20:27
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Цитата(Сергей Борщ @ Dec 25 2008, 23:13)  Что именно в этой записи ему будет непонятно?.. Х/з, самому интересно. Сначала и я так же написал... CAVR говорит "Error... mising":" ", у avr-gcc более длинное ругательство... Насколько я понял, компилятору не нравятся знаки равенства в выражениях после оператора сравнения...
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Dec 25 2008, 20:42
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Goodefine @ Dec 25 2008, 22:27)  у avr-gcc более длинное ругательство... Насколько я понял, компилятору не нравятся знаки равенства в выражениях после оператора сравнения... Я заменил PORTW на PORTD, поскольку у меги8 нет порта W: CODE main.cpp: #include <avr/io.h> #include <stdint.h> #define BIT 1 void Test1(uint8_t byte, uint8_t bitmask) { (byte & bitmask)? PORTD |= (1<<BIT): PORTD &= ~(1<<BIT); }
main.lst: 484 .section .text._Z5Test1hh,"ax",@progbits 485 .global _Z5Test1hh 487 _Z5Test1hh: 488 .LFB37: 489 .LSM75: 490 /* prologue: frame size=0 */ 491 /* prologue end (size=0) */ 492 .LVL9: 493 .LSM76: 494 0000 70E0 ldi r23,lo8(0) ; bitmask, 495 .LVL10: 496 0002 90E0 ldi r25,lo8(0) ; byte, 497 .LVL11: 498 0004 6823 and r22,r24 ; bitmask, byte 499 0006 7923 and r23,r25 ; bitmask, byte 500 .LVL12: 501 0008 672B or r22,r23 ; bitmask 502 000a 01F0 breq .L57 ; , 503 .LSM77: 504 000c 919A sbi 50-0x20,1 ; , 505 000e 0895 ret 506 .L57: 507 0010 9198 cbi 50-0x20,1 ; , 508 0012 0895 ret 509 /* epilogue: frame size=0 */ 510 /* epilogue: noreturn */ 511 /* epilogue end (size=0) */ 512 /* function void Test1(uint8_t, uint8_t) size 10 (10) */ Никакой ругани.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 25 2008, 21:03
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Цитата(Сергей Борщ @ Dec 25 2008, 23:42)  Я заменил PORTW на PORTD, поскольку у меги8 нет порта... Дык и я заменил Код #define PORTW PORTD Цитата(Сергей Борщ @ Dec 25 2008, 23:42)  Никакой ругани... У Вас объектный код (*.cpp)? Привожу скриншот компиляции Вашего кода (просто вставил его в рабочий проект) в WinAVR 20080610 под AVR Studio 4 А вот так компилится: Код void Test1(uchar byte, uchar bitmask) { PORTD=(byte & bitmask)? PORTD | (1<<BIT): PORTD & ~(1<<BIT); }
Эскизы прикрепленных изображений
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Dec 25 2008, 21:27
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 11-12-08
Из: Республика Беларусь, г.Минск
Пользователь №: 42 380

|
Цитата(Goodefine @ Dec 26 2008, 00:03)  Дык и я заменил Код #define PORTW PORTD У Вас объектный код (*.cpp)? Привожу скриншот компиляции Вашего кода (просто вставил его в рабочий проект) в WinAVR 20080610 под AVR Studio 4 А вот так компилится: Код void Test1(uchar byte, uchar bitmask) { PORTD=(byte & bitmask)? PORTD | (1<<BIT): PORTD & ~(1<<BIT); } Попробуйте разделить все три прцедуры на строчки и поймёте где трабл. Да, не нравятся ему аргументы, но в какой позиции строки он не написал. Кстати, посмотрите, byte может у вас определено ранее #defin'ом как unsigned char? Может просто имя переменной поменять? Ксати, глотнул пива, идея пришла: А не прокатит ли такая конструкция: Код for ((Direction)? mask=1<<0:mask=1<<7;mask;(Direction)? mask<<=1:mask>>1) {PORTx=(*byte&mask)? PORTx|(1<<BIT):PORTx&~(1<<BIT);delay_us(x);} Сюда даже вместо 7 (в 'for') можно как-то подставить sizeof(); (хоть в байтах*8-1,хоть в битах-1) ? Тогда прога будет просто супер универсальной! (Я даже себе в библию программиста запишу  ) И если Direction задано через union...struct... как бит, то налицо ещё и прямая экономия места... ?
Сообщение отредактировал DenisIV - Dec 25 2008, 22:08
|
|
|
|
|
Dec 25 2008, 22:40
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Goodefine @ Dec 25 2008, 23:03)  У Вас объектный код (*.cpp)? Вопроса не понял. Студию не пользую, вот откомпилил в режиме С (не С++): Код #include <avr/io.h> typedef unsigned char uchar; #define BIT 0 void Test1(uchar byte, uchar bitmask) { (byte & bitmask)? PORTD | (1<<BIT): PORTD & ~(1<<BIT); }
avr-gcc -mmcu=atmega8 -Wall -gdwarf-2 -DF_CPU=3686400UL -Os -fsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT ./release/obj/test.o -MF ./release/dep/test.o.d -ffunction-sections -fdata-sections -fverbose-asm -Wa,-ahlmsdc=./release/lst/test.lst -c test.c -o release/obj/test.o Версия WinAVR - 20071221. Завтра могу поставить более свежую.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 25 2008, 22:40
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 11-12-08
Из: Республика Беларусь, г.Минск
Пользователь №: 42 380

|
Ещё глотнул пива... Ведь оператор for работает так: Код for([первая инструкция];[условие выполнения];[инструкция после тела]) [тело] и его можно заменить на: Код [первая инструкция] while ([условие выполнения]) { [тело] [инструкция после тела] } итого мы можем: Код (Direction)? mask=1<<0:mask=1<<7; while(mask) { PORTx=(*byte&mask)? PORTx|(1<<BIT):PORTx&~(1<<BIT); delay_us(x); (Direction)? mask<<=1:mask>>1) } Или не можем? По-моему это абсолютно идентичные логически и т.д. конструкции... Гуру, если не прав, поправьте...
|
|
|
|
|
Dec 25 2008, 22:46
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(DenisIV @ Dec 25 2008, 23:27)  Сюда даже вместо 7 (в 'for') можно как-то подставить sizeof(); (хоть в байтах*8-1,хоть в битах-1) ? sizeof(mask) * __CHAR_BITS__ Цитата(DenisIV @ Dec 25 2008, 23:27)  И если Direction задано через union...struct... как бит, то налицо ещё и прямая экономия места... ? Скажем так: если это константа, известная на этапе компиляции. В С++ она может быть параметром шаблона. Цитата(DenisIV @ Dec 26 2008, 00:40)  итого мы можем: Код (Direction)? mask=1<<0:mask=1<<7; while(mask) { PORTx=(*byte&mask)? PORTx|(1<<BIT):PORTx&~(1<<BIT); delay_us(x); (Direction)? mask<<=1:mask>>1) } Да. Если мы пойдем еще дальше, и заметим, что при входе в цикл mask никак не может быть равно нулю, т.е. цикл всегда должен выполниться хотя бы один раз - мы можем заменить цикл while() {} на более оптимальный do {} while(): Код mask=1<<(Direction) ? 0 : 7; do { *byte & mask ? PORTx |= (1<<BIT) : PORTx &= ~(1<<BIT); delay_us(x); } while ( Direction ? mask<<=1 : mask>>1 );
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 25 2008, 22:56
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Цитата(DenisIV @ Dec 26 2008, 00:27)  Попробуйте разделить все три процедуры на строчки и поймёте где трабл. Разделил. Ругается на оба знака присваивания: Цитата ../main.c:139: error: expected expression before '=' token ../main.c:144: error: expected expression before '=' token Цитата(DenisIV @ Dec 26 2008, 00:27)  Кстати, посмотрите, byte может у вас определено ранее #defin'ом как unsigned char? Может просто имя переменной поменять? Не-а, не в этом дело... Цитата(DenisIV @ Dec 26 2008, 00:27)  Ксати, глотнул пива, идея пришла: А не прокатит ли такая конструкция: Код ... (Я даже себе в библию программиста запишу lol.gif ) Такая нет. Зато прокатит эта, записывайте... Код void transmit_byte(unsigned char const *byte, unsigned char direct){ unsigned char mask; for (mask=(direct)? 1:0x80;mask;delay_us(x),mask=(direct)? mask<<1:mask>>1) PORTW=(*byte&mask)? PORTW|(1<<BIT):PORTW&~(1<<BIT); } Тока нас застрелить могут за такую конструкцию...  Цитата(Сергей Борщ @ Dec 26 2008, 01:40)  Вопроса не понял... Про С++ в смысле Цитата(Сергей Борщ @ Dec 26 2008, 01:40)  Код ... (byte & bitmask)? PORTD | (1<<BIT): PORTD & ~(1<<BIT); ... Правильно, так без знаков присваивания компилится (первый раз у Вас они были), только не работает, надо: Код PORTD=(byte & bitmask)? PORTD | (1<<BIT): PORTD & ~(1<<BIT);
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Dec 25 2008, 23:42
|

Участник

Группа: Свой
Сообщений: 68
Регистрация: 11-12-08
Из: Республика Беларусь, г.Минск
Пользователь №: 42 380

|
Цитата(Goodefine @ Dec 26 2008, 01:56)  Такая нет. Зато прокатит эта, записывайте... Код void transmit_byte(unsigned char const *byte, unsigned char direct){ unsigned char mask; for (mask=(direct)? 1:0x80;mask;delay_us(x),mask=(direct)? mask<<1:mask>>1) PORTW=(*byte&mask)? PORTW|(1<<BIT):PORTW&~(1<<BIT); } Тока нас застрелить могут за такую конструкцию...  Могут... И будут правы: функция delay вызывается 7 раз из 8... (эт плохо...) А for заменяется while... Походу некоторые компилёры требуют конкретной операции внутри скобок for, а то (условие)?[тело true]:[тело false] - эт ж if(условие)[тело true]else[тело false] и их и тошнит... 2moderator:А может эти вышеперечисленные весчи собирать и в какую-ндь тему отдельно выделенную закидывать? ('Перед тем, как задать вопрос по С/C++, ознакомтесь...') А там и возможность замены ?/if, for/while, volatile, #pragma, и базовые вопросы/вырезки сообщений и т.д. Так сказать, перед тем, как наступить на грабли, прочитайте... Или в поиск... А если нет-то к нам... ?
|
|
|
|
|
Dec 26 2008, 06:52
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Цитата(DenisIV @ Dec 26 2008, 03:42)  Могут... И будут правы: функция delay вызывается 7 раз из 8... (эт плохо...) Согласен, но лечится это легко: Код void transmit_byte(unsigned char const *byte, unsigned char direct){ unsigned char mask; for (mask=(direct)? 1:0x80;mask;mask=(direct)? mask<<1:mask>>1) {PORTW=(*byte&mask)? PORTW|(1<<BIT):PORTW&~(1<<BIT);delay_us(x);} }
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|