Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> lvalue required as left operand of assignment 
V
    Опции темы
supercelt
Дата 4.10.2015, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Блин ошибка смешная вышла и не могу понять в чём дело

Код СИ

Код

struct{
        volatile unsigned char crc_row_total: 4;  
}counter;

struct{
        unsigned short CRC_rows_check: 10; 
}buffer;


Код

buffer.CRC_rows_check & (1 << counter.crc_row_total) ^= 1;


counter.crc_row_total - щёлкает от 0 до 9

Мне надо в цикле сделать исключающее или для каждого из 10 битов. И результат этой операции присвоить этому же биту. А выдаётся ошибка
lvalue required as left operand of assignment

Это сообщение отредактировал(а) supercelt - 4.10.2015, 15:38
PM   Вверх
tzirechnoy
Дата 4.10.2015, 16:11 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: -1
Всего: 16



Цитата
не могу понять в чём дело


В том, что результат выполнения операцыи var & N -- это некоторое значение, т.е. число. И попытка присвоить этому числу что-нибудь столь жэ безсмысленна, как попытка присвоить что-нибудь какому-нибудь другому числу, например 4.

Т.е. компилятор офигевает примерно такжэ, как если бы Вы написали 4 = 2;
PM MAIL   Вверх
feodorv
Дата 4.10.2015, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Код
unsigned short curFlag = 1 << counter.crc_row_total;
if( buffer.CRC_rows_check & curFlag )
  buffer.CRC_rows_check &= ~curFlag;
else
  buffer.CRC_rows_check |= curFlag;

или
Код
unsigned short curFlag = 1 << counter.crc_row_total;
buffer.CRC_rows_check = (buffer.CRC_rows_check & ~curFlag) | ((buffer.CRC_rows_check ^ curFlag) & curFlag);

???


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 4.10.2015, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



а почему не просто
Код

buffer.CRC_rows_check ^= curFlag;

?
PM MAIL   Вверх
supercelt
Дата 4.10.2015, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Код

struct{
        volatile unsigned char RFID[5]; //Буфер для кода ёмкостью 5 байт.
        volatile unsigned char TMP: 8; //Буфер для 1 байта, ёмкостью 8 бит.
        volatile unsigned short CRC_rows: 10; //Буфер для CRC битов чётности по строкам. Объявлено 16 разрядное число, но кол-во бит для хранения - 10, т.к. больше не надо (см. формат EM-Marine)
        volatile unsigned char CRC_columns: 4; //Буфер для CRC битов чётности по столбцам. 
        volatile unsigned char Logic: 1; //Хранит принятый либо лог 0, либо лог 1
        unsigned char CRC_row: 1; //Хранит вычисляемое значение СРС для рядов
        unsigned char CRC_column: 1; //Хранит вычисляемое значение СРС для столбцов
        unsigned short CRC_rows_check: 10; //Хранит весь вычисленный в основном цикле программы (перебор массива после наполнения буфера) СРС для рядов
        unsigned char CRC_columns_check: 4; //Хранит высисленные CRC по столбцам
}buffer;

struct{
        volatile unsigned char data: 1; //Флаг, 0 - приём заголовка, 1 - заголовок принят, можно принимать данные.
        volatile unsigned char Buffer_full: 1;
}flag;

struct{
        volatile unsigned char crc: 3; //Счётчик CRC битов. Доходит до 4 и сбрасывается. Т.к. каждый 4-й принятый бит это CRC. Число 4 занимает 3 бита.
        volatile unsigned char crc_row_total: 4; //Счётчик всех CRC битов по строкам. В Em-Marine их 10. Число 10 занимает 4 бита. 
        volatile unsigned char bit: 4; //Счётчик принятых битов. Счёт битов идёт до 8. А число 8 занимает 4 бита.
        volatile unsigned char byte: 3; //Размер счётчика байтов (6 байт) - 3 бита. Т.е число 6 занимает 3 бита
        volatile unsigned char header: 4; //Размер заголовка (9 единиц) - 4 бита. То есть число 9 занимает 4 бита. Увеличить это число (4), если заголовок будет длинее! 
        volatile unsigned char edge: 8; //Переменная для хранения значения TCNT1. Из расчёта что в стандарте e-marine максимальное число сколько 1 бит занимает - это 64 периода такта. Значит макс число будет 128, округлям до 130. 130 занимает 8 бит 
        //volatile unsigned char main_bit: 6;
}counter;


Код

for(counter.byte = 0; counter.byte < 5; counter.byte++){ //Перебор в цикле 5 байт
                                for(counter.bit = 0; counter.bit < 8; counter.bit++){ //Перебор в цкле каждого бита целого байта
                                        if(buffer.RFID[counter.byte] & (1 << counter.bit)){ //Если N-ый бит N-ого байта установлен в 1, то
                                                buffer.CRC_row ^= 1; //Вычисляем CRC (CRC вычисляется только для битов установленных в 1)(CRC = бит ^ 1, а далее CRC прошлого вычисления ^ 1)
                                                buffer.CRC_column = ((buffer.CRC_columns_check & (1 << counter.crc)) ^ 1);
                                                if(buffer.CRC_column){
                                                        buffer.CRC_columns_check |= (1 << counter.crc);
                                                }else{
                                                        buffer.CRC_columns_check &= ~(1 << counter.crc);
                                                }
                                        }
                                        if(!(counter.bit ^ 0x3) || !(counter.bit ^ 0x7)){ //Если в цикле мы на 3 бите или на 7
                                                if(buffer.CRC_row){buffer.CRC_rows_check |= (1 << 9);} //Если вычисленный CRC = 1, то записываем в переменную (которую потом будем сравнивать) единицу в 9 бит (строки)
                                                if(counter.crc_row_total ^ 0x9){buffer.CRC_rows_check >>= 1;} //Если принимаем не последний бит (т.е не 9-й), то сдвигаем вправо на 1 (наполняем стек)
                                                counter.crc_row_total++; //Увеличиваем счётчик битов CRC по строкам
                                                buffer.CRC_row = 0; //Обнуляем CRC по строкам, так как приём полубайта завершился и далее будет заново расчёт CRC для следующего полубайта, а для этого исходное состояние CRC должно быть = 0
                                                counter.crc = 0;
                                        }
                                        counter.crc++; //Увеличиваем счётчик полубайтов. Этот счётчик досчитывает до 4 и сбрасывается в 0
                                }
                        }


Сделал как-то так. Появилась другая проблема.  Вот этот кусок
Код

buffer.CRC_column = ((buffer.CRC_columns_check & (1 << counter.crc)) ^ 1);
                                                if(buffer.CRC_column){
                                                        buffer.CRC_columns_check |= (1 << counter.crc);
                                                }else{
                                                        buffer.CRC_columns_check &= ~(1 << counter.crc);
                                                }

В дебаггере дохожу до того что бы buffer.CRC_column юыл равен 1. Он равен 1 в инспекторе переменных видно. Потом дебаггер попадает сюда
buffer.CRC_columns_check |= (1 << counter.crc); Проходит эту строчку и buffer.CRC_columns_check не меняется никак вообще. В этот момент counter.crc = 2.

UPD Причём я заметил если строчку
Код

buffer.CRC_columns_check |= (1 << counter.crc);

вынести перед первым циклом фор, ну так просто для проверки, то бит установится.

Это сообщение отредактировал(а) supercelt - 4.10.2015, 21:16
PM   Вверх
feodorv
Дата 5.10.2015, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(volatile @  4.10.2015,  19:09 Найти цитируемый пост)
а почему не просто

Наверное, просто захотелось повыпендриваться(((


Цитата(supercelt @  4.10.2015,  19:49 Найти цитируемый пост)
Появилась другая проблема

Есть у меня сильное подозрение, что где-то в коде & заменилось на ^. Но все равно многое остается непонятным. Например, алгоритм совершаемых действий. Если здесь понятно, что требуется:
Цитата(supercelt @  4.10.2015,  14:35 Найти цитируемый пост)
Мне надо в цикле сделать исключающее или для каждого из 10 битов. И результат этой операции присвоить этому же биту.

Как совершенно справедливо заметил volatile, это решается просто:
Код
buffer.CRC_rows_check ^= 1 << counter.crc_row_total;
без заморочек. И я приношу свои извинения за свой несовершенный код, отголоски которого видны в Вашем коде.


Что подразумевается вот здесь:
Цитата(supercelt @  4.10.2015,  19:49 Найти цитируемый пост)
CRC = бит ^ 1, а далее CRC прошлого вычисления ^ 1



А что должно здесь проверяться:
Цитата(supercelt @  4.10.2015,  19:49 Найти цитируемый пост)
if(!(counter.bit ^ 0x3) || !(counter.bit ^ 0x7)){ //Если в цикле мы на 3 бите или на 7



Цитата(supercelt @  4.10.2015,  19:49 Найти цитируемый пост)
Проходит эту строчку и buffer.CRC_columns_check не меняется никак вообще. В этот момент counter.crc = 2.
Может, второй бит у buffer.CRC_columns_check уже выставлен? Не могли бы Вы описать словами, что Вы хотите сделать с buffer.CRC_columns_check.



Очень подозрительно выглядит и такой код:
Цитата(supercelt @  4.10.2015,  19:49 Найти цитируемый пост)
buffer.CRC_column = ((buffer.CRC_columns_check & (1 << counter.crc)) ^ 1);
Если counter.crc не равен нулю, то значение CRC_columns_check никак не учитывается. А старое значение buffer.CRC_column пропадает.



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
supercelt
Дата 5.10.2015, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



user posted image

Алгоритм такой. Нужно высчитать CRC по строкам и столбам. Строки работают. А вот со столбами загвоздка.

Код

CRC = бит ^ 1, а далее CRC прошлого вычисления ^ 1

Это означает следующее. Есть буфер которй хранит вычисленый CRC по столбам. Солбов 4 значит 4 битная переменная. 0 бит - это срс 1 столба, 1-2, 2-3,3-4
По мере прохождения массива я постоянно высчитываю срс и меняю его в этой переменной. так вот пояснение означает что изначально срс = 0. Потом допустим поступила
1 и высчитывем срс, оно будет =1, так как пока мы встретили всего одну 1, значит срс - нечётно. Потом мы принимаем следующую единицу (в этом же столбе) и делаем ^ c предыдущим
высчитанным срс именно для этого столба разумеется.

Код

if(!(counter.bit ^ 0x3) || !(counter.bit ^ 0x7)){ //Если в цикле мы на 3 бите или на 7

Это для срс по стркам. В цикле перебираются все 8 бит байта и нужно после каждого полубайта (4 бит) сделать расчёт срс. По рисунку вначале понятно.
Эта строчка всё равно что 
Код

if(conter.bit == 3 || counter.bit == 7) просто вроде как битовые операции работают быстрее чем логические.

Может, второй бит у buffer.CRC_columns_check уже выставлен? Не могли бы Вы описать словами, что Вы хотите сделать с buffer.CRC_columns_check.
Цитата

Нет он не выставлен. В инспекторе переменных при отладке видно. что я хочу сделать?, вот что: допустим 1 пришла на 2 итерации цикла, поэтому мы будем работать со 2 битом
в переменной buffer.CRC_columns_check. Нужно просто выставить в 1 это 2 бит и всё. А он не выставляется.

Далее вот по этой строчке
Код

buffer.CRC_column = ((buffer.CRC_columns_check & (1 << counter.crc)) ^ 1);

Я думал так: берём текущее значение бита ( counter.crc) переменной buffer.CRC_columns_check, делаем с этим значением искл ИЛИ с 1 и записываем результат в buffer.CRC_column
И пофиг что он будет каждый раз перезаписываться. так и надо

PM   Вверх
math64
Дата 5.10.2015, 14:57 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Операции &, |, ^ работают сразу с несколькими битами - не нужно разделять на отдельные биты, а потом собирать.
Паковать в битовые структуры лучше только тогда, когда нужно экономить память. Они работают медленнее, чем обычные.
Код

unsigned char data[10]; // в младших битах data[0] - биты D00, D01, D02, D03,  в млаших битах data[1] - биты D04, D05, D06, D07 и т. д.
unsigned char pc = 0;
for(int i=0; i < 10; i++) pc ^= data[i];
// теперь в младших битах pc - биты PC0, PC1, PC2, PC3

P0, P1, P2, ... P9 - считаются с помощью таблицы:
Код

const unsigned char paritytable[16] = { 0, 1,  1, 0,  1, 0, 0, 1,  1, 0, 0, 1,  0, 1, 1, 0 };
for(int i=0; i < 10; i++) p[i] = paritytable[data[i]&0x0F];

PM   Вверх
volatile
Дата 5.10.2015, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(supercelt @  5.10.2015,  14:09 Найти цитируемый пост)
Алгоритм такой. 

я бы вообще все это вычисление сделал так
Код

// на входе 5 байт упакованных данных
// на выходе будет записано 11 байт (10 байт = 2х5 тетрад + 1 байт паритет по столбцам)
void code (const unsigned char * in, unsigned char * out)
{
   static const unsigned char paritytable [16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
   unsigned pcolumn = 0; // здесь будет паритет по столбцам
   for (int i = 0; i < 5; ++ i)
   {
      unsigned l = *in & 0xf;
      unsigned h = (*in >> 4) & 0xf;
      
      *out++ = (l << 1) | paritytable [l];
      *out++ = (h << 1) | paritytable [h];
      pcolumn ^= l; 
      pcolumn ^= h;
      ++ in;   
   }
   *out = pcolumn << 1;
}


Это сообщение отредактировал(а) volatile - 5.10.2015, 16:51
PM MAIL   Вверх
volatile
Дата 5.10.2015, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Сорри. не заметил. На рисунке биты перевернуты, там сначала идут младшие биты, потом старшие.
Цитата(supercelt @ 5.10.2015,  14:09)
user posted image


Если это действительно так, то надо будет еще перевернуть тетраду.

Код

unsigned rever_tetrade (unsigned tetr)
{
   unsigned rever = 0;
   for (int j = 0; j < 4; ++ j)
      rever = (rever << 1) | ((tetr >> j) & 1);
   return rever;
}

// на входе 5 байт
// на выходе будет записано 11 байт
int code (const unsigned char * in, unsigned char * out)
{
   static const unsigned char paritytable [16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
   unsigned pcolumn = 0; // здесь будет паритет по столбцам
   for (int i = 0; i < 5; ++ i)
   {
      unsigned l = rever_tetrade (*in & 0xf);
      unsigned h = rever_tetrade ((*in >> 4) & 0xf);
      
      *out++ = (l << 1) | paritytable [l];
      *out++ = (h << 1) | paritytable [h];
      pcolumn ^= l; 
      pcolumn ^= h; 
      ++ in;
   }
   *out = pcolumn << 1;
}


Это сообщение отредактировал(а) volatile - 5.10.2015, 17:39
PM MAIL   Вверх
supercelt
Дата 5.10.2015, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Я вот и делаю битовые структуры потому что хочу сэкономить память. 
Не могли бы вы пояснить как работает 
Код

unsigned h = rever_tetrade ((*in >> 4) & 0xf);

Просто не в первый раз вижу подобное. Например видел что делают так:
Код

unsigned char CheckCRC(unsigned char *buffer)
{
        unsigned char i;
        crc = 0;
        for (i=0; i<5; i++){
                crc = crc ^ ( buffer[i] & 0x0F ) ^ ( ( buffer[i] >> 4 ) & 0x0F );    
        }
        if (crc != ( buffer[5] & 0x0F )) { return 0; } else { return 1; } 
}

Зачем делается сдвиг на 4 и тут же И с 0x0f?

UPD Не могу понять как применяются эти таблицы. Вы извините, если что, я ещё просто учусь и многого не знаю. Почему в таблице 16 элементов и именно такой порядок нулей и единиц? 

Это сообщение отредактировал(а) supercelt - 5.10.2015, 20:40
PM   Вверх
volatile
Дата 5.10.2015, 21:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(supercelt @  5.10.2015,  20:28 Найти цитируемый пост)
Я вот и делаю битовые структуры потому что хочу сэкономить память. 

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

да и что вы там сэкономите? пару байтов?

Цитата(supercelt @  5.10.2015,  20:28 Найти цитируемый пост)
Не могли бы вы пояснить как работает 
unsigned h = rever_tetrade ((*in >> 4) & 0xf);

старшая тетрада, сдвигается на младшую, и очищаются все остальные биты.
т.е. если в байте было например 0x8f, то после сдвига *in >> 4 там будет будет 0x08
(старшая тетрада (8), сдвинулась на место младшей тетрады)
& 0xf - очищает все остальные биты, кроме младших четырех битов. (конкретно, в данном случае это необязательно, так как они и так обнулены, но для успокоения совести, не помешает  smile )

Цитата(supercelt @  5.10.2015,  20:28 Найти цитируемый пост)
Не могу понять как применяются эти таблицы.

это просто предвычесленные значения четности для тетрады
В тетраде может быть только 16 вариантов, вот для всех вариантов там и вычислено уже значение паритета.
(это сделано чисто для ускорения)
все эти значения, можно вывести с помощью например такой программки:
Код

int main ()
{
  for (int i = 0; i < 16; ++ i) // пробегаем всю тетраду. 16 значений.
  {
     int p = 0;
     for (int j = 0; j < 8; ++ j) // вычисляем паритет для каждого значения.
        p ^= (i >> j) & 1;
     printf ("%d, ", p);
  }
}

http://codepad.org/oRBlo3yM
PM MAIL   Вверх
supercelt
Дата 5.10.2015, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Значит вы не советовали бы собирать 5 байт из полубайтов, а делать массив[10] в каждом элементе которого размещались бы полубайты?
PM   Вверх
volatile
Дата 5.10.2015, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(supercelt @  5.10.2015,  21:44 Найти цитируемый пост)
Значит вы не советовали бы собирать 5 байт из полубайтов, а делать массив[10] 


supercelt, зависит от того сколько таких значений в вашей программе.
Если их мульон, то вероятно стоит упаковать.
Если 1, 2.., 10 - то смысла нет.


PM MAIL   Вверх
supercelt
Дата 5.10.2015, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Нет, их всего и есть 5 байт. Ну изначально в программу передаётся 64 бита кода следуя из картинки и вот с ними и происходят все действия. Тогда понятно, что лучше не упаковывать, спасибо!
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1241 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.