typedef struct { unsigned char JmpBoot[3]; // JMP на загрузчик (0xEB5890) unsigned char OEMName[8]; // Строка форматера ОС ("MSDOS5.0") unsigned short BytePerSec; // Количество байт в секторе ............ 0x00B: 512 unsigned char SecPerClus; // Количество секторов к кластере ....... 0x00D: 8 unsigned short RsvdSecCnt; // Всего резервных секторов (ВРВ + копия) ................. 0x00E: 2 186 unsigned char NumFATs; // Сколько копий FAT-таблицы 0x010: 2 unsigned short RootEntCnt; // Объектов в корневом каталоге (нуль для FAT-32) unsigned short TotSec16; // Всего секторов на диске (нуль для FAT-32) unsigned char Media; // Тип диска (F8) unsigned short FATSz16; // Размер таблицы FAT-16 в секторах (нуль для FAT-32) unsigned short SecPerTrk; // Секторов в дорожке (63) unsigned short NumHeads; // Всего головок Head (255) unsigned int HiddSec; // Cекторов перед началом раздела ....... 0x01C: 2 048 unsigned int TotSec32; // Всего секторов на диске .............. 0x020: 15 689 728 unsigned int FATSz32; // Размер таблицы FAT-32 в секторах ..... 0x024: 15 291 unsigned short ExtFlags; // Флаги unsigned short FSVer; // Версия файловой системы unsigned int RootClus; // Кластер корневого каталога (смещение в блоке данных) ... 0x02C: 2 unsigned short FSInfo; // Сектор структуры FSINFO .............. 0x030: 1 unsigned short BkBootSec; // Сектор копии этой записи (6) unsigned char Reserved[12]; // unsigned char DrvNum; // Номер диска для INT-13h (00 или 80h) unsigned char Reserved1; // unsigned char BootSig; // Сигнатура 29h, если имеются сл.три поля unsigned int VolID; // Серийник тома unsigned char VolLabel[11]; // Строка с меткой тома по умолчанию ("NO NAME "). unsigned char FilSysType[8]; // Строка "FAT32 ". unsigned char Reserved2[420]; // unsigned short Signature; // Сигнатура 55AAh } FAT32_BPB;
Есть функция которая читает сектор 512 байт из SD карты и записывает в массив. Как можно эти данные массива записать в структуру, чтобы потом можно было пользоваться полями структуры ? Какие есть способы ?
Последний раз редактировалось Юрий1239 Сб окт 26, 2024 20:42:02, всего редактировалось 1 раз.
Приглашаем 3 декабря 2024 на вебинар, посвященный силовым модулям ведущего китайского производителя SUNCO - одного из мировых лидеров по производству дискретных полупроводниковых компонентов. На вебинаре вы узнаете о новинках, включая модули 17 класса в корпусе E3, и контроле качества на всех этапах производства. Вы также узнаете о новейших продуктах – IGBT-, SiC-, диодных и тиристорных модулях, погрузитесь в современные топологии, сравните характеристики IGBT-чипов разных поколений.
Указатель. Указатель на структуру. Любая структура, объявленная в виде указателя, "натягивается" на любой участок памяти, как разметочный шаблон. То есть:
и начиная с указанного адреса память разбивается на ячейки в соответствии с полями структуры. Доступ к этим ячейкам - через поля структуры вот так как написано.
Последний раз редактировалось Базилюк Сб окт 26, 2024 21:09:18, всего редактировалось 1 раз.
Всплески перенапряжения являются серьезной угрозой надежности работы радиоэлектронных устройств. Причины их появления различны, это могут быть коммутационные переходные процессы в системе электропитания устройств, разряды молний, электростатические разряды. Для создания эффективной и современной системы защиты от ЭСР компания SUNCO разработала надежные и качественные супрессоры, представляющие собой TVS- и ESD-диоды, а также сборки на их основе. Компоненты SUNCO не только не уступают, но часто превосходят по характеристикам аналогичную продукцию других брендов.
то есть, если есть uint8_t buf[512];, тогда Str *x = (Str*)buf; указателю *x присваивается адрес начала buf[] и участок памяти от начала buf[] будет разбит на ячейки в соответствии с "натянутой" на него структурой.
Последний раз редактировалось Базилюк Сб окт 26, 2024 21:14:40, всего редактировалось 1 раз.
typedef union { struct { unsigned char JmpBoot[3]; // JMP на загрузчик (0xEB5890) unsigned char OEMName[8]; // Строка форматера ОС ("MSDOS5.0") unsigned short BytePerSec; // Количество байт в секторе ............ 0x00B: 512 unsigned char SecPerClus; // Количество секторов к кластере ....... 0x00D: 8 unsigned short RsvdSecCnt; // Всего резервных секторов (ВРВ + копия) ................. 0x00E: 2 186 unsigned char NumFATs; // Сколько копий FAT-таблицы 0x010: 2 unsigned short RootEntCnt; // Объектов в корневом каталоге (нуль для FAT-32) unsigned short TotSec16; // Всего секторов на диске (нуль для FAT-32) unsigned char Media; // Тип диска (F8) unsigned short FATSz16; // Размер таблицы FAT-16 в секторах (нуль для FAT-32) unsigned short SecPerTrk; // Секторов в дорожке (63) unsigned short NumHeads; // Всего головок Head (255) unsigned int HiddSec; // Cекторов перед началом раздела ....... 0x01C: 2 048 unsigned int TotSec32; // Всего секторов на диске .............. 0x020: 15 689 728 unsigned int FATSz32; // Размер таблицы FAT-32 в секторах ..... 0x024: 15 291 unsigned short ExtFlags; // Флаги unsigned short FSVer; // Версия файловой системы unsigned int RootClus; // Кластер корневого каталога (смещение в блоке данных) ... 0x02C: 2 unsigned short FSInfo; // Сектор структуры FSINFO .............. 0x030: 1 unsigned short BkBootSec; // Сектор копии этой записи (6) unsigned char Reserved[12]; // unsigned char DrvNum; // Номер диска для INT-13h (00 или 80h) unsigned char Reserved1; // unsigned char BootSig; // Сигнатура 29h, если имеются сл.три поля unsigned int VolID; // Серийник тома unsigned char VolLabel[11]; // Строка с меткой тома по умолчанию ("NO NAME "). unsigned char FilSysType[8]; // Строка "FAT32 ". unsigned char Reserved2[420]; // unsigned short Signature; // Сигнатура 55AAh }; unsigned char raw[512]; }FAT32_type;
extern FAT32_type Data_Fat32;
....
Data_Fat32.raw[0] = ... Data_Fat32.JmpBoot[0] = ... эти две операции обращаются к одной и той же области памяти
Добавлено after 11 minutes 31 second: но вообще, это неэкономно. Для чтения FAT достаточно байт 32, наверное, чтобы удобно следовать алгоритму его разбора, описанного в спецификации.
Потому что размер Вашей структуры больше 512 байт. Вы где-то ошиблись с типом данных или размером массива в ней. Вот поле и берёт данные откуда-то за пределами 512 байт
Вы где-то ошиблись с типом данных или размером массива в ней.
Не считал точно, но возможно ошибки с типом/размером нет. Но в структуре есть "дырки" (не компилировал для проверки, но есть уверенность, что это именно так).
Юрий1239,
1) не есть хорошо предполагать размеры char/short/int/long... и их беззнаковые варианты. Как минимум - это непереносимо. Если надо поля/переменные определенного размера, для этих целей существуют специальные типы int8_t/int16_t/int32_t... (uint8_t/uint16_t/uint32_t...) из stdint.h
2) Не стоит предполагать, что компилятор разместит поля в структуре одно за другим без "дырок". Если это (размещение полей без "дырок") требуется, то надо явно об этом указать компилятору. Для gcc - __attribute__((packed)), в других компиляторах - по-другому.
Берем этот конкретный пример, очень вероятно (близко к 100%), что будет скомпилировано так:
Код:
struct { /*смещение 0 */ unsigned char JmpBoot[3]; /*смещение 3 */ unsigned char OEMName[8]; /* ВНИМАНИЕ! Здесь будет "дырка", */ /*смещение 12 */ unsigned short BytePerSec; ....
Вы (наверное) надеялись, что у поля BytePerSec будет смещение 11 (ведь перед полем два массива байт 3 + 8 ), а на самом деле это не так - компилятор после двух полей сделает "дырку" (вставит байт) и, соответственно, смещение поля BytePerSec будет 12.
Если добавить к структуре __attribute__((packed)), то "дырка" уберется (и поле BytePerSec будет иметь смещение 11). НО ПОЯВИТСЯ ДРУГАЯ ПРОБЛЕМА - как только в вашей программе будет обращение к полю BytePerSec, будет сгенерировано исключение. Дело в том, что в ARMах (не знаю во всех ли вариантах, но на тех, с которыми я знаком) не допускается обращения к слову/полуслову по адресу не выровненному на границу слова/полуслова. Другими словами к при обращении к 32 битному слову, адрес должен быть кратным 4, к 16 битному полуслову - кратным 2 (а в этом примере смещение 11, что не кратно 2).
3) Опять же, не надо забывать, что бывает разный порядок байт - big-endian (BE) или little-endian (LE). Желательно, чтобы код работал и там, и там.
Т.е. исходя из сказанного выше, ничего плохого не вижу, если в подобных случаях не будет "наложения" считанного буфера на какую-либо структуру, свои структуры делаем как нам надо, доступ к полям в буфере будет через функцию/макрос. Типа так: Спойлер
Код:
/* определяем смещения */ ... #define BYTE_PER_SEC_OFFSET 11 ... /* "вытаскивает" 8/16/32-ти битное значение по смещению * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * можно заинлайнить (или определить макросами), если надо * для переносимости сделать две версии: одна - для little-endian (LE), вторая - * для big-endian (BE) и условной компиляцией подключать нужные */
uint8_t fetch_u8 (void* ptr, int offset) { return ((uint8_t *) ptr) [offset]; } uint16_t fetch_u16 (void* ptr, int offset) { uint16_t val = fetch_u8 (ptr, offset); return val | (fetch_u8 (ptr, offset + 1) << 8); } uint32_t fetch_u32 (void* ptr, int offset) .... uint8_t *buf; - это указатель на считанный блок .... uint16_t block_size = fetch_u16 (buf, BYTE_PER_SEC_OFFSET).
Разве они неизвестны? В структуре Вы заранее определили их размер. Работа со смещениями избавляет программу хранить 512 байт в ОЗУ, Вы всегда можете взять только нужное, если организуете обработку этих смещений в чтении данных с SD карты. К тому же, часть полученных данных этого блока необходимо хранить всю жизнь работы с FAT, и не хранить же его весь, как минимум, пустышка в 420 байт вообще не нужна. Уж лучше тогда отдельно прочитать сигнатуру, чем ради неё стольким жертвовать.
Вот именно. Она тогда не нужна. Говоря, что Вы в структуре определили размеры данных, я лишь имел ввиду, что они Вам известны. Вы можете добавить их в комментарии к #define, чтобы лишний раз не лазить в документацию. Например, как здесь: https://asf.microchip.com/docs/latest/s ... group.html
Да. я так об этом тоже думал но остановился и решил поискать более красивое решение. Но с #define конечно будет экономичней с памятью. Буду так делать, тем более не все поля нужно использовать.
не есть хорошо предполагать размеры char/short/int/long... и их беззнаковые варианты. Как минимум - это непереносимо.
Я использую старый чип ATSAM7S256, Там все драйвера и файл заголовков написаны unsigned int, unsigned char... и т. д. Правилом хорошего тона считается использовать один стиль написания. К тому же я знаю что все эти типы просто переопределены.
Код:
typedef unsigned int uint32_t ...
Добавлено after 2 minutes 32 seconds:
Цитата:
Зачем весь этот геморрой, когда есть FATFS от Чана? Много лишнего времени?
Долго разбираться, не знаю как она работает, много лишнего кода. А там есть поддержка длинных имён ?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения