
В этом тексте я покажу, как из подручных материалов на основе микроконтроллера, аудиокодека и SD карты запрограммировать самый настоящий диктофон. Покажу принципы работы звукозаписывающей аппаратуры. Но обо всем по порядку...
Постановка задачи
Разработать прототип диктофона на основе микроконтроллера STM32F407VG и аудио кодека WM8731. Написать прошивку для записи звука в wav файлы. Звук передавать по интерфейсу I2S2. Аудиокодек конфигурировать по интерфейсу I2C2. Использовать фирменный HAL SDK от производителя микроконтроллера STM. Записанные файлы хранить на SD карте, подключенной по интерфейсу SDIO. Использовать DMA потоки для интерфейса I2S2_RX, SDIO и UART2_TX. Внутри SD карты должна быть файловая система FAT16. В прошивке использовать функции из API файловой системы FatFS. Обеспечить возможность записывать в wav файлы через интерфейс командной строки поверх UART2. Указывать длительность записываемого файла аргументами командной строки. Обеспечить возможность работать со стерео WAV файлом на частоте дискретизации 96kHz, семплами разрешением 16-бит. Вот, пожалуй, и все требования к прототипу диктофона.
Аппаратная часть
Итак, танцуем от печки... Из чего же я буду собирать диктофон? Основа диктофона - это учебно-тренировочная электронная плата DevEBox STM32F4XX_M_V3. PCB хороша тем, что она миниатюрна и на ней построен гараж для microSD карты. Вот так она выглядит.

Вот блок-схема DevEBox STM32F4XX_M_V3.

Аудиокодек - это ASIC WM8731 и модуль на его основе.

WM8731 - это по сути 2xADC + 2xDAC с торчащим наружу I2S и с управлением по I2C.

Надо учинить вот такой прототип. Следует установить всего 12 перемычек. Вот так, просто и незатейливо:

Микрофон я выбрал первый попавшийся под рукой. Это оказался микрофон aceline AMIC-7.

Блок-схема диктофона получается такая

В качестве накопителя я выбрал микро SD карту на 128 MByte.

Теория цифровой звукозаписи
Главная трудность записи звука на микроконтроллерах заключается в том, что в микроконтроллерах нет столько много RAM памяти, чтобы за раз записать привычный нам звуковой файл. Одна песня в WAV формате может занимать 60MByte. Для решения этой проблемы существует классическое решение на основе двух массивов. Суть проста. Пока по I2S записывается в RAM память фрагмент 1, микроконтроллер сохраняет из RAM памяти в FAT16 файл фрагмент 2. Пока по I2S записывается в RAM память фрагмент 2, микроконтроллер сохраняет из RAM памяти в файл фрагмент 1. Таким образом становится возможным непрерывно записывать файлы, размер которых в тысячи раз превышает количество RAM памяти в микроконтроллере.

Для контролирования процесса записи внутри прошивки должен работать вот такой простой конечный автомат. Состояние автомата можно переключать прямо внутри обработчика прерываний по DMA каналам. А непосредственную запись в SD карту делать в супер цикле функции main по командам конечного автомата записи.

Реализация
Настройка GPIO
Для работы диктофона надо активировать альтернативные функции на I2S2, I2C2, SDIO, UART2. Плюс добавить несколько GPIO пинов для отладки на логическом анализаторе или осциллографе.
--> -->gl +-----+-------+---------+------+------+-----+-----+---------------+ | No | pad | mode | dir | pull |MuxS |MuxG | name | +-----+-------+---------+------+------+-----+-----+---------------+ | 0 | PA8 | Out | Out | Air | 0 | 0 | I2S2_TX_DMA | | 1 | PA4 | Out | Out | Air | 0 | 0 | I2S2_RX_DMA | +-----+-------+---------+------+------+-----+-----+---------------+ | 2 | PB13 | ALT1 | Out | Down | 5 | 5 | I2S2_CK | | 3 | PB12 | ALT1 | Out | Down | 5 | 5 | I2S2_WS | | 4 | PB15 | ALT1 | In | Down | 5 | 5 | I2S2_SD | +-----+-------+---------+------+------+-----+-----+---------------+ | 5 | PB10 | ALT1 | Out | Up | 4 | 4 | I2C2_SCL | | 6 | PB11 | ALT1 | Io | Up | 4 | 4 | I2C2_SDA | +-----+-------+---------+------+------+-----+-----+---------------+ | 7 | PA2 | ALT1 | Out | Air | 7 | 7 | USART2_TX | | 8 | PA3 | ALT1 | In | Up | 7 | 7 | USART2_RX | +-----+-------+---------+------+------+-----+-----+---------------+ | 10 | PC12 | ALT1 | Out | Air | 12 | 12 | SD_CLK | | 11 | PD2 | ALT1 | Out | Up | 12 | 12 | SD_CMD | | 12 | PC8 | ALT1 | Io | Up | 12 | 12 | SD_D0 | | 13 | PC9 | ALT1 | Io | Up | 12 | 12 | SD_D1 | | 14 | PC10 | ALT1 | Io | Up | 12 | 12 | SD_D2 | | 15 | PC11 | ALT1 | Io | Up | 12 | 12 | SD_D3 | +-----+-------+---------+------+------+-----+-----+---------------+ | 9 | PA1 | Out | Out | Air | 0 | 0 | LedGreem | +-----+-------+---------+------+------+-----+-----+---------------+ -->
Настройка I2S трансивера
Для работы я выбрал I2S2. I2S2 трансивер надо сконфигурировать на режим записи. Микроконтроллер должен выступать в роли мастера. Есть два варианта для пина I2S2_SD: PC3 и PB15.
GPIO |
Dir |
MCU pin |
PinMux |
Connector |
Connector |
PC3 |
out |
18 |
AF5 |
J3.35 |
-- |
PB15 |
in |
54 |
AF5 |
J2.8 |
J4.3 |
В STM32 каждый отдельный I2S трансивер может либо записывать, либо отправлять звук через пин I2Sx_SD. Поэтому для записи и последующего воспроизведения вам придется пере инициализировать I2S трансивер. Есть и отдельный режим полного дуплекса, но он требует еще одного экземпляра I2S трансивера. Полный дуплекс достигается за счет тандемной работы двух трансиверов, но это тема для отдельной статьи.
Запись звука должна происходить на таких настройках GPIO.
PinMux |
GPIO |
DIR |
Pull |
PIN |
PinMux |
Connector |
Connector |
I2S2_SD |
PB15 |
in |
down |
54 |
AF5 |
J2.8 |
J4.3 |
GPIO |
PC3 |
in |
down |
18 |
0 |
J3.35 |
-- |
I2S2_CK |
PB13 |
out |
down |
47 |
5 |
J3.13 |
-- |
I2S2_WS |
PB12 |
Out |
down |
51 |
5 |
J3.11 |
J4.5 |
Синтез WAV файла
Как только поступит запрос на запись надо понять сколько вообще надо семплов звука. Для простоты положим, что в запросе на запись задается продолжительность записи в секундах. Известна частота дискретизации, размер одного семпла, количество каналов. Надо определить сколько памяти потребуется для поля данных. Это можно рассчитать по простой формуле:
MemNeed [byte] = SampleFreq [Hz] x SampleSize [byte] x Channels [Num] x RevDuration [s]
Зная параметры предстоящей записи надо синтезировать заголовок WAV файла. Этот заголовок прописывается в WAV файл и после этого дается отмашка DMA на пуск I2S_RX .
Настройка каналов DMA
Записывать звук следует через DMA канал для I2S2_RX. Должен быть включен циклический режим, активированы DMA прерывания, выравнивание 16 бит. Тут надо сразу вспомнить что в STM32 микроконтроллерах I2S - это режим SPI. Поэтому настройки каналов DMA надо тоже копировать от SPI.

Для I2S2 настройки каналов DMA получаются такие
Flow |
DMA |
Stream |
Channel |
Mode |
Direction |
I2S2_RX |
DMA1 |
Stream_3 |
Channel_0 |
CIRCULAR |
PERIP->MEM |
I2S2_TX |
DMA1 |
Stream_4 |
Channel_0 |
CIRCULAR |
MEM->PERIP |
В коде это выглядит так
#define DMA_CHANNEL_I2S_COMMON \ .memory_burst = DMA_BURST_SINGLE, \ .periph_burst = DMA_BURST_SINGLE, \ .aligment_per = DMA_ALIGNMENT_WORD, \ .aligment_mem = DMA_ALIGNMENT_WORD, \ .interrupt_on = true, \ .block_count = 1, \ .valid = true, \ .mode = DMA_MODE_CIRCULAR, \ .fifo = DMA_FIFO_OFF, \ .priority = DMA_PRIOR_VERY_HIGH, #define DMA_CHANNEL_I2S2_RX \ { \ .DmaChPad = { .dma_num = 1, .stream=3, .channel = 0, .name = "I2S2_RX", }, \ DMA_CHANNEL_I2S_COMMON \ .per_inc = DMA_INC_OFF, \ .mem_inc = DMA_INC_ON, \ .dir = DMA_MCAL_DIR_PERIPH_TO_MEMORY, \ .name = "I2S2_RX", \ .num = DMA_CHANNEL_NUM_I2S2_RX, \ .base_addr_source = (uint32_t) fromArray, \ .base_addr_destination = (uint32_t) &(I2S2ext->DR), \ .block_size = (uint32_t) DMA_MEMCPY_SIZE, \ .CallBackHalf = CallBackHalfI2s2Rx, \ .CallBackDone = CallBackDoneI2s2Rx, \ },
Настройка и интерфейса SDIO
В экспериментах я работал на частоте тактирования SDIO равной 12 MHz (фактическое значение по осциллографу). Повышение частоты до 24MHz не оказало существенного прироста производительности. SDIO интерфейс надо настроить на работу с DMA каналами.
Flow |
DMA |
Stream |
Channel |
Mode |
Direction |
SDIO_RX |
DMA2 |
Stream_3 |
Channel_4 |
PFCTRL |
PERIP->MEM |
SDIO_TX |
DMA2 |
Stream_6 |
Channel_4 |
PFCTRL |
MEM->PERIP |
В коде это выглядит так
#ifndef DMA_CHANNEL_SDIO_CONFIG_H #define DMA_CHANNEL_SDIO_CONFIG_H #ifdef __cplusplus extern "C" { #endif #include "std_includes.h" #include "dma_channel_types.h" #include "dma_channel_config.h" #ifndef MIN #define MIN(n, m) (((n) < (m)) ? (n) : (m)) #endif bool CallBackDoneSdio1Rx(void); bool CallBackDoneSdio1Tx(void); bool CallBackHalfSdio1Rx(void); bool CallBackHalfSdio1Tx(void); bool CallBackErrorSdio1Rx(void); bool CallBackErrorSdio1Tx(void); /*DMA_PFCTRL DMA_PFCTRL DMA_PFCTRL DMA_PFCTRL*/ #define DMA_CHANNEL_SDIO_COMMON \ .block_size = (uint32_t) MIN( sizeof(toArray) ,sizeof(fromArray)) , \ .per_inc = DMA_INC_OFF, \ .mem_inc = DMA_INC_ON, \ .aligment_mem = DMA_ALIGNMENT_DWORD, \ .aligment_per = DMA_ALIGNMENT_DWORD, \ .memory_burst = DMA_BURST_INC4, \ .periph_burst = DMA_BURST_INC4, \ .fifo = DMA_FIFO_ON, \ .priority = DMA_PRIOR_VERY_HIGH, \ .mode = DMA_MODE_PFCTRL, \ .valid = true, \ .interrupt_on = true, #define DMA_CHANNEL_SDIO_RX \ { \ .DmaChPad = { .dma_num = 2, .stream = 3, .channel = 4, .name = "SDIO1_RX", }, \ .dir = DMA_MCAL_DIR_PERIPH_TO_MEMORY, \ DMA_CHANNEL_SDIO_COMMON \ .name = "SDIO1_RX", \ .num = DMA_CHANNEL_NUM_SDIO_RX, \ .CallBackHalf = CallBackHalfSdio1Rx, \ .CallBackDone = CallBackDoneSdio1Rx, \ .base_addr_source = (uint32_t) fromArray, \ .base_addr_destination = (uint32_t) toArray, \ .block_count = 1, \ .mux = 0, \ }, #define DMA_CHANNEL_SDIO_TX \ { \ .DmaChPad = { .dma_num = 2, .stream = 6, .channel = 4, .name = "SDIO_TX",}, \ .dir = DMA_MCAL_DIR_MEMORY_TO_PERIPH, \ DMA_CHANNEL_SDIO_COMMON \ .num = DMA_CHANNEL_NUM_SDIO_TX, \ .name = "SDIO_TX", \ .CallBackHalf = CallBackHalfSdio1Tx, \ .CallBackDone = CallBackDoneSdio1Tx, \ .base_addr_source = (uint32_t)fromArray, \ .base_addr_destination =(uint32_t) toArray, \ .block_count = 1, \ .mux = 0, \ }, #define DMA_CHANNEL_SDIO \ DMA_CHANNEL_SDIO_TX \ DMA_CHANNEL_SDIO_RX #ifdef __cplusplus } #endif #endif /* DMA_CHANNEL_SDIO_CONFIG_H */
Настройка SD карты
Может так получиться, что вы нашли SD карту на 2GB, установили в PC и вам показывает 7 MByte. Дело в том что на ней уже прописана какая-н linux-овая файловая система и win это не видит. Надо удалить старые разделы и заново отформатировать карту памяти. Это можно сделать утилитой DISKPART. Для пуска утилиты DISKPART потребуются админские права.
Microsoft DiskPart version 10.0.19041.3636 Copyright (C) Microsoft Corporation. On computer: LAPTOP-xxxxxx DISKPART> DISKPART> list disk list VDISK Disk ### Status Size Free Dyn Gpt -------- ------------- ------- ------- --- --- Disk 0 Online 476 GB 1024 KB * Disk 1 Online 7600 MB 7592 MB DISKPART> select disk 1 Disk 1 is now the selected disk. DISKPART> DISKPART> list part Partition ### Type Size Offset ------------- ---------------- ------- ------- Partition 1 Primary 7568 KB 31 KB DISKPART> DISKPART> select part 1 Partition 1 is now the selected partition. DISKPART> DISKPART> delete part DiskPart successfully deleted the selected partition. DISKPART> DISKPART> create part pri DiskPart succeeded in creating the specified partition. DISKPART> DISKPART> format fs=fat32 quick 100 percent completed DiskPart successfully formatted the volume. DISKPART> DISKPART> exit
Затем перед установкой SD карты в устройство надо проверить, что карта в самом деле поддерживает нужную битовую скорость на запись. Для этого есть другая утилита, называется H2testw.exe. Скачать H2testw можно по ссылке. Утилита H2testw не стирает данные с карты. Эта утилита по частям пишет , читает и проверяет прочитанное с записанным. И так по всей памяти.

Утилита H2testw проверяет SD карту в случае успеха утилита выдает строку Test finished without errors. Тут же есть отчет по битовой скорости записи и чтения.

Результат тестирования SD карты положительный. Фактическая скорость получилась 13.8 MByte/s. Это в 37.68 раз превышает необходимую скорость записи звука.
Warning: Only 3758 of 3820 MByte tested. Test finished without errors. You can now delete the test files *.h2w or verify them again. Writing speed: 13.8 MByte/s Reading speed: 67.4 MByte/s H2testw v1.4
Однако может попасться и бракованная SD карта. В этом случае утилита H2testw выдаст примерно такое красное сообщение

Отрицательный тест SD карты
The media is likely to be defective. 951.9 MByte OK (1949692 sectors) 2 KByte DATA LOST (4 sectors) Details:0 KByte overwritten (0 sectors) 0 KByte slightly changed (< 8 bit/sector, 0 sectors) 2 KByte corrupted (4 sectors) 0 KByte aliased memory (0 sectors) First error at offset: 0x000000000df64e00 Expected: 0x000000000df64e00 Found: 0x000000000df24e00 H2testw version 1.3 Writing speed: 6.47 MByte/s Reading speed: 20.9 MByte/s H2testw v1.4
У каждой SD карты есть регистры: CSD, CID и прочие. Вот значения регистров той SD карты с которой я делал эксперименты.
3.191-->sdio_diag_ll 4.299,308,W,[SDIO], CardCSD... 4.300,309,I,[SDIO],CSD_CRC:119 ,ECC:0,FileFormat:0,TempWrProtect:0 ,PermWrProtect:0,CopyFlag:0,FileFormatGroup:0,ContentProtectAppli:0 ,WriteBlockPaPartial:0,MaxWrBlockLen:9,WrSpeedFact:5,ManDeflECC:0 ,WrProtectGrEnable:1,WrProtectGrSize:3,EraseGrMul:127,EraseGrSize:0 ,DeviceSizeMul:4,MaxWrCurrentVDDMax:5,MaxWrCurrentVDDMin:5,MaxRdCurrentVDDMax:5 ,MaxRdCurrentVDDMin:5,DeviceSize:3879,DSRImpl:0,RdBlockMisalign:0 ,WrBlockMisalign:0,PartBlockRead:1,RdBlockLen:9,CardComdClasses:501 ,MaxBusClkFrec:50,NSAC:0,TAAC:94,SysSpecVersion:0,CSDStruct:0 CID... 4.327,343,I,[SDIO],ManID:29 0x1d AData 4.328,344,I,[SDIO],OemAppId:16708 0x4144 DA 4.328,345,I,[SDIO],ProdName1:1297293344 0x4d532020 MS 4.331,346,I,[SDIO],ProdRev:0x10=0.1 4.331,347,I,[SDIO],ProdSN:939530821 0x38001a45 4.333,348,I,[SDIO],ManufactDate: Month:11 Year:2000 4.334,349,I,[SDIO],CID_CRC:55=0x37 4.337,350,W,[SDIO], DsCardInfo... 4.337,351,I,[SDIO],CardVersion:0 4.337,352,I,[SDIO],Class:501 4.340,353,I,[SDIO],RelCardAdd:45928 4.340,354,I,[SDIO],BlockNbr:248320 4.340,355,I,[SDIO],BlockSize:512 4.343,356,I,[SDIO],TotalSize:127139840 Byte=124160 kByte=121.25 MBytes 4.344,357,I,[SDIO],LogBlockNbr:248320 4.346,358,I,[SDIO],LogBlockSize:512 4.346,359,I,[SDIO],CardType:0 4.347,360,I,[SDIO],1 CardState ?
Отформатировать SD карту в файловую систему FAT16. Назначить Allication Unit size равным 16 kбайт.
Диктофоны - это устройства hi-load обработки. Сейчас объясню почему... Для записи набегающего потока двухканальных 16-битных аудио семплов на частоте дискретизации 96kHz надо чтобы в SDIO, скорость записи превышала 384000 байт в секунду. Это не мало. Каждый семпл дает Вам в WAV файле 4 байта: левый и правый каналы по 16 бит каждый. Внутри прошивки я измерил фактическую битовую скорость записи в файловую систему FAT16 и получил такую справку. Понял, что надо заняться оптимизацией и ускорить запись в файл.
SDIO clock, MHz |
kByte/s |
Byte/s |
ratio |
режим, bit |
5 |
159 |
162847 |
0,42 |
1 |
16.6 |
262 |
269003 |
0.70 |
1 |
12 |
737 |
754883 |
1.9* |
4 |
25 |
292 |
299304 |
0,77 |
1 |
Для увеличения скорости записи пришлось принять ряд совсем неочевидных мер:
-
Увеличить частоту ARM Cortex-M4 ядра до максимума: 168MHz (было 100 MHz). Так системная шина тактирует SDIO MAC с максимальной частотой 84MHz.

-
Установил подтяжки к питанию для всех SDIO проводов кроме тактирования.
-->gl sd +-----+-------+--------+-------+------+------+-----+-----+---------+ | No | pad | mode | level | dir | pull |MuxS |MuxG | name | +-----+-------+--------+-------+------+------+-----+-----+---------+ | 3 | PC12 | ALT1 | L | out | Air| 12 | 12 | SD_CLK | | 4 | PD2 | ALT1 | H | out | Up | 12 | 12 | SD_CMD | | 5 | PC8 | ALT1 | H | io | Up | 12 | 12 | SD_D0 | | 6 | PC9 | ALT1 | H | io | Up | 12 | 12 | SD_D1 | | 7 | PC10 | ALT1 | H | io | Up | 12 | 12 | SD_D2 | | 8 | PC11 | ALT1 | H | io | Up | 12 | 12 | SD_D3 | +-----+-------+--------+-------+------+------+-----+-----+---------+ Записывать блоки размером 4k Byte за раз.
Перевести SDIO на 4-битный режим. То есть задействовать параллельную шину.
Работать в SDIO в режиме DMA2.
Закомментировать отладочное логирование в коде SDIO операций чтения и записи.
Повысить приоритет DMA каналов для SDIO до максимума.
Повысить приоритет прерываний для DMA каналов SDIO до максимума.
Отформатировать SD карту в файловую систему FAT16. Назначить Allocation Unit size равным 16 kбайт.
Увеличил тактирование на SDIO тактировании до 24 MHz (максимальное).
Увеличил стековую RAM память до 16k Byte.
После этих мер скорость записи файлов заметно увеличилась и стала доходить до 853 kByte/s. Можно провернуть модульный тест fat_fs_write для измерения фактической скорости записи в файл.

Отладка диктофона
Чтобы начать запись надо открыть программу PuTTY, подключиться к главной консоли управления на UART2 и выполнить команду sound_recorder_restc DurationS. Первый аргумент задает продолжительность записи. В CLI это выглядит так

То же в виде текста
7:44-->sound_recorder_restc 10 465.426,431,I,[SoundRecorder],Duration,Ok 465.427,432,I,[WAV],File:R_4096_UT462732_10000Ms.wav,state:0,state:3,i2s_error_cnt:0, rec_cnt:4,sample_cnt:960000,ErrCnt:0,total_file_size:3840044, start_rec_ms:462753,stop_rec_ms:459991,data_size:3840000, Spin:6871236,cur_save_size:0,Init:On, 465.429,433,I,[WAV],ChunkId:RIFF,ChunkSize:1920036 Byte,Format:WAVE,Subchunk1Id:fmt , Subchunk1Size:16,AudioFormat:0x0001,NumChannels:2, SampleRate:96000 Hz, ByteRate:384000 Byte,BlockAlign:4 Byte,BitsPerSample:16 bit, Subchunk2Id:data,DataSize:1920000 Byte 465.440,434,I,[I2S],I2S_2,Set,Operation:Rx 465.441,435,I,[I2S],2 init 465.442,436,W,[DmaChannel],N:3=I2S2_RX 465.442,437,W,[Dma],3,DMA1,Stream_3,Init 465.443,438,I,[Dma],Init Id:3 Dma:1 Stream:3 Ok! 465.443,439,I,[I2S],I2S2 initOk 465.444,440,I,[GPIO],Init,PA0,IN 465.444,441,I,[GPIO],Init,PC3,IN 465.445,442,W,[GPIO],PB12,DrvSel:?,I2S2_WS,Dir:Out,Mode:ALT1,Mux:5,LL:H,Pull:Down, Speed:High,Pin:0, 465.446,443,W,[GPIO],PB13,DrvSel:?, I2S2_CK,Dir:Out,Mode:ALT1,Mux:5,LL:H,Pull:Down, Speed:High,Pin:0, 465.447,444,W,[GPIO],PB15,DrvSel:?,I2S2_SDEXT,Dir:In,Mode:ALT1,Mux:5,LL:H,Pull:Down, Speed:High,Pin:0, 465.447,445,I,[SoundRecorder],RecStart... 7:45--> 7:48--> 7:49--> 7:49-->475.277,446,I,[I2S],DmaStopOk! 475.277,447,I,[SoundRecorder],I2sDmaStop,Ok 475.281,448,I,[SoundRecorder],CloseFile:[R_4096_UT465427_10000Ms.wav]Ok 475.281,449,I,[SoundRecorder],RecDuration:9833 ms 475.282,450,I,[SoundRecorder],WrOkCnt:938 475.283,451,I,[SoundRecorder],errorCnt:0 475.283,452,I,[SoundRecorder],WrSzErrorCnt:0 475.283,453,I,[SoundRecorder],longWriteErrorCnt:0
После появления в консоли строки RecDuration на SD карте кристаллизуется уникальный WAV файл, содержащий запись звуковой дорожки.

Этот файл можно проиграть любой мультимедийной утилитой. Например стандартной программой Media Player.

Архитектура прошивки получилась вот такой

В чем трудность создания диктофона?
Сделать прошивку прототипа диктофона оказалось не такой уж и тривиальной задачей. От записи к записи возникали всяческие неожиданные загвоздки:
-
Как это ни странно, но в FatFS API не всегда отрабатывает функция f_write(). Да... Особенно в режиме FAT32. Иной раз f_write выдает OK и правильную записанную длину, а по факту уже на PC в HexViewer выяснятеся, что местами прошивка просто пишет в wav файл вкрапления непрерывных нулей. Согласно наблюдениям нули в WAV файле образуются как раз тогда, когда функция f_write не успевает записать половинчатый массив семплов между прерываниями I2S DMA (RxHalf и RxDone). При этом, в случае работы на файловой системе FAT16 эта ошибка не воспроизводится.

FatFS функция f_write() при записи сваливается в ошибку FR_INT_ERR. В этом случае файловая система на SD карте рушится и laptop PC потом не узнает файловую систему на этой SD карте. Увеличение стека прошивки в два раза частично решило проблему, но не полностью. Есть набор SD карт где FR_INT_ERR вообще не появляется, при этом прошивка на STM32F407VG та же самая.
Функция f_write иной раз может просто заклинить. Возвращает, что записано ноль байт и последующие записи тоже выводят 0 байт. При этом код ошибки возвращается FR_OK. Обычно такое происходит, когда в SD карте просто больше нет свободного места. Это особенно актуально на картах объёмом 128MByte. Поэтому перед созданием файла надо убедиться, что на SD карте есть свободное место.
Функция f_write работает относительно быстро только, если записывать блоки по 4kByte. Другие размеры обычно не проходят тест на производительность (384000 Byte/s) и запись в SD карту происходит слишком медленно. В результате происходит срыв потока, запись просто теряет свою непрерывность и смысл.
FatFS на файловой системе FAT16 работает стабильнее, чем на FAT32. В случае с FAT32 так и не прошел модульный тест на запись 1MByte с последующей проверкой записанных байт.
-
При включенном цифровом фильтре нижних частот аудиокодек на левый канал выдает помехи. При этом правый канал формируется с нормальным сигналом.

левый канал с помехами -
По непонятным мне причинам, самая стабильная работа диктофона наблюдается на SD карте размером 128MByte (форматирование FAT16). Даже не знаю откуда у меня такая реликтовая SD карта.

-
В финальной WAV записи на левый канал эпизодически просачиваются вкрапления подозрительных одиночных пиков.

Водянистый звуковой сигнал
Итог
В результате мне удалось написать STM32F407VG-прошивку для I2S - совместимого диктофона c возможностью записывать WAV файлы на SD карту по SDIO с файловой системой FAT16 на основе широко распространенной учебной платы dev_ebox_stm32f4x и такого же распространенного отладочного аудиокодека WM8731. Бинари микропрограммы представлены на github. Исходный код прошивки диктофона тут же.
Думаю не требуется перечислять все те возможные приложения, где может потребоваться запись звука. Надеюсь этот текст поможет кому-нибудь добавить возможность звукозаписи в свои проекты.
Ссылки
Название |
URL |
Диктофоны для книги рекордов |
|
Диктофон и медицина |
|
Проигрыватель WAV файлов на STM32 |
|
Обзор диктофона Edic Weeny A110 с функцией «чёрного ящика» |
|
Подключение SD карты по SPI (Капсула памяти) |
|
Конечный Aвтомат Аппаратного I2C-Трансивера |
|
Медленная работа SD карточек — кто виноват и что делать? |
|
Пуск I2S трансивера на Artery |
|
Audacity |
|
Запуск I2S Трансивера на Artery [часть 2] (DMA, FSM, PipeLine) |
|
FatFs - Generic FAT Filesystem Module |
|
Сравнение микросхем аудио кодеков |
https://docs.google.com/spreadsheets/d/1r7tuNrQ8PPfIVcM2FeGpwa1eeWjyq41CD0MGq_Q_VV8/edit?gid=0#gid=0 |
STM32 - uSD - SDIO 4bit - DMA |
|
Исходный код прошивки диктофона |
https://github.com/aabzel/trunk/tree/main/source/projects/dev_ebox_stm32f4x_sound_recorder_gcc_m |
Чип AudioСodec(а) WM8731 (или (ADC/DAC)*2 из iPod(а)) |
|
Wave File Format - формат звукового файла WAV |
|
Разбор I2S трафика в программе Logic 2 |
|
|
Цифровой звук на STM32: подключаем аналоговый микрофон через SAI и NAU88C22 |
|
Обзор Aппаратного Aудио кодека MAX9860 (2x ADC+DAC) |
|
Как Работать с UART на Микроконтроллерах (UART + FIFO = LOG) @danil_12345 |
|
Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB |
|
Формат WAV-файлов |
http://solidstate.karelia.ru/p/tutorial/asni/Glava 2/Index3.htm |
Отладка STM32 программатором J-LINK по SWD |
|
Обзор AудиоКодека NAU8814YG |
|
dev_ebox_stm32f4x_sound_recorder_gcc_m |
https://github.com/aabzel/Artifacts/tree/main/dev_ebox_stm32f4x_sound_recorder_gcc_m |
утилита H2testw.exe для испытания SD карт |
Вопросы
Что если реальная звуковая дорожка не совпадает с тем, что указано в заголовке WAV файла?
Существует ли формат аудиозаписи, который в бинарном виде хранит такие метаданные как точное время начала записи и геолокацию места, где была инициирована данная запись звука?
Как на Си изменить конкретный массив в середине бинарного файла, зная отступ от начала файла, размер заменяемого фрагмента и новое значение размера массива? В качестве API файловой системы используется Fat-FS.
Как измерить реальную поддерживаемую скорость записи данной конкретной microSD карты?
Существуют ли в продаже готовые отладочные платы с ARM Cortex M4 микроконтроллером (STM32F4X), каким-н простым аудиокодеком как WM8731, audio-jack портов для наушников, микрофона (и желательно LineIn), гаражом для microSD карты подключаемой по интерфейсу SDIO (или SPI), LEDом и желательно графическим дисплеем? Чтобы можно было полноценно прототипировать и отлаживать прошивки диктофонов и плейеров.
Как проверить, что диктофонная запись звука в самом деле получилась непрерывная? Как убедиться, что звукозаписывающая аппаратура не пропустила 10-30 миллисекунд (или не добавила лишние семплы) ?
Существует ли win утилита для чтения регистров SD карты: Card-specific data, Card IDentification register, SD Status register, Card Status Register, operation conditions register, SD Card Configuration register, Drive stage register , relative card address register, при её подключению к персональному компьютеру с операционной системой Windows 10?
Поддерживают ли microSD карты “горячее подключение”?
Комментарии (40)

rukhi7
06.07.2026 11:35Для этого есть утилита H2testw.exe.
это вы под Windows на десктопе проверяете -
что карта в самом деле поддерживает нужную битовую скорость на запись
интересно? Если да, то как вы проверяете скорость записи на СТМ-ке, мне кажется у вас не очень понятно написано, а было бы интересно понять.
Не знаю это только я не понял есть ли у вас проверка при переключении буферов, что очередной буфер для записи свободен, то есть что данные из него полностью ушли на карту?

aabzel Автор
06.07.2026 11:35то как вы проверяете скорость записи на СТМ-ке, мне кажется у вас не очень понятно написано, а было бы интересно понять.
Вот такой модульный тест я написал для проверки скорости записи
Код измерения скорости записи в FAT-FS
/* tr fat_fs_write */ static uint8_t wrData[WRITE_PART_SIZE+1]={0}; bool test_fat_fs_write(void) { LOG_INFO(TEST, "%s():", __FUNCTION__); bool res = true; static uint32_t sn=0; FRESULT ret; sn++; memset(wrData, 0xAA, sizeof(wrData)); FIL File = {0}; uint32_t i = 0; uint32_t total_size = 0; uint32_t start_ms = time_get_ms32(); char file_name[80]=""; snprintf(file_name,sizeof(file_name),"TWP%u.bin", sn); LOG_INFO(TEST,"sizeof:%s ",file_name ); BYTE mode = FA_WRITE | FA_CREATE_NEW |FA_OPEN_ALWAYS; FRESULT reto = f_open((FIL*)&File, (const TCHAR*) file_name, mode); LOG_INFO(TEST,"file_name:[%s],ret:%s ",file_name , FatFsResToStr(reto )); if(FR_EXIST==reto ) { ret = f_unlink(file_name); LOG_INFO(TEST,"DeleteFile:[%s],ret:%s ",file_name , FatFsResToStr(ret )); reto = f_open((FIL*)&File, (const TCHAR*) file_name, mode); } while(total_size < WAV_WRITE_SIZE) { UINT written = 0; ret = f_write(&File, wrData, WRITE_PART_SIZE, &written); EXPECT_EQ(FR_OK, ret); EXPECT_EQ(WRITE_PART_SIZE, written); if( FR_OK != ret ) { LOG_ERROR(TEST,"%u,WrError:%s",i, FatFsResToStr(ret )); break; } if(WRITE_PART_SIZE!=written) { break; } total_size += written; i++; } ret = f_close(&File); LOG_INFO(TEST,"CloseCode:%s " , FatFsResToStr(ret )); ASSERT_EQ(FR_OK, ret); uint32_t stop_ms = time_get_ms32(); uint32_t diff_ms = stop_ms - start_ms; uint32_t data_rate= (1000*total_size) / (diff_ms); LOG_INFO(TEST,"totalSize:%u Byte,Duration:%u ms,WriteSpeed:%u Byte/s=%f kByte/s", total_size, diff_ms, data_rate, BYTES_2_KBYTES(data_rate)); float ratio =((float) data_rate / (float) WAV_WRITE_SPEED); LOG_INFO(TEST,"ratio:%f ",ratio ); ASSERT_GR(WAV_WRITE_SPEED, data_rate); EXPECT_EQ(WAV_WRITE_SIZE, total_size); return res; }
rukhi7
06.07.2026 11:35так это не тест должен быть, это должна быть встроенная диагностика при переключении буферов в рантайме! Надо обязательно проверять что буфер свободен при переключении, иначе вы и будете ловить артефакты от наложений и не поймете откуда они у вас берутся.
Кстати в этом коде очень странно что вы время на открытие и закрытие файла и всякую другую дребедень тоже охватили:
uint32_t start_ms = time_get_ms32(); char file_name[80]=""; snprintf(file_name,sizeof(file_name),"TWP%u.bin", sn); LOG_INFO(TEST,"sizeof:%s ",file_name ); BYTE mode = FA_WRITE | FA_CREATE_NEW |FA_OPEN_ALWAYS; FRESULT reto = f_open((FIL*)&File, (const TCHAR*) file_name, mode); LOG_INFO(TEST,"file_name:[%s],ret:%s ",file_name , FatFsResToStr(reto )); // ... // ... // ... ret = f_close(&File); // ... // ... // ... uint32_t stop_ms = time_get_ms32();Зачем вы все это учитываете как время записи?

aabzel Автор
06.07.2026 11:35Кстати в этом коде очень странно что вы время на открытие и закрытие файла и всякую другую дребедень тоже охватили:
Потому, что FATFS фактическую запись как раз и делает внутри
f_close.
Внутри f_close вызывается f_sync для фактической загрузки в накопитель.

aabzel Автор
06.07.2026 11:35Не знаю это только я не понял есть ли у вас проверка при переключении буферов, что очередной буфер для записи свободен, то есть что данные из него полностью ушли на карту?
У меня есть проверка на срыв потока.
Если длительность записи фрагмента превысила таймаут REC_PART_TIMEOUT_US , то происходит аварийная остановка записи.static inline bool sound_rec_save_part_offset(SoundRecorderHandle_t* Node, uint32_t offset, uint32_t need_size) { bool res = false; if(Node->cur_save_size < Node->total_file_size) { UINT written = 0; uint32_t start_save_us = time_get_us32(); void* buff = (void* ) ( ( (uint32_t ) Node->RxSampleArray) + offset ); FRESULT ret = f_write(&Node->FileToRec, buff, need_size, &written); uint32_t end_save_us = time_get_us32(); if(FR_OK == ret) { if(need_size == written) { Node->cur_save_size += written; Node->wr_ok_cnt++; res = true; } else { Node->error_size_cnt++; //LOG_ERROR(SOUND_RECORDER,"WriteSmall:%u Byte", written); res = sound_recorder_stop_ll(Node); } Node->action = SOUND_RECORDER_ACTION_NOPE; } else { Node->error_cnt++; Node->action = SOUND_RECORDER_ACTION_NOPE; res = sound_recorder_stop_ll(Node); } uint32_t diff_us = end_save_us-start_save_us; if (REC_PART_TIMEOUT_US < diff_us) { Node->long_write_error_cnt++; res = sound_recorder_stop_ll(Node); } } else { res = sound_recorder_stop_ll(Node); } return res; }
rukhi7
06.07.2026 11:35ну вот здесь у вас один f_write
uint32_t start_save_us = time_get_us32(); void* buff = (void* ) ( ( (uint32_t ) Node->RxSampleArray) + offset ); FRESULT ret = f_write(&Node->FileToRec, buff, need_size, &written); uint32_t end_save_us = time_get_us32();измеряется, и получается он измеряет непонятно что если
FATFS фактическую запись как раз и делает внутри
f_closeНо с точки зрения проверки что буфер свободен это корректно, тем не менее.
Но получается вы используете двойную буферизацию - одна своя, вторая от файловой системы. Это как минимум не очень эффективно, а как максимум будет иметь всякие странные эффекты, которые и приводят к артефактам в записанных данных и которые вы не отладите пока в конце концов не влезете с ногами в код реализации этой файловой системы и ее буферизации. Чужая реализация файловой системы в эмбеддед это почти всегда беда, такая черная дыра в которой размножаются баги безконтрольно. В эмбеддед Операционная Система (ОС) практически не бывает полноценная, там куча ограничений которые еще фиг все найдешь-отловишь. Фактически вы вместо того чтобы заниматься отладкой своего кода вынуждены заниматься исследованием кода этой ОС большую часть времени.

DrGluck07
06.07.2026 11:35Не, ну на кодеке любой сделает. А вот ежели через ADC и DAC микроконтроллера...

aabzel Автор
06.07.2026 11:35У аудиокодека шире динамический диапазон: 24 бит вместо 12 на MCU. Плюс есть аналоговые предусилитель для микрофона, цифровой фильтр нижних частот.
Звук получается чище и разборчивее.
Sdima1357
06.07.2026 11:35Все нормально там со звуком у STM32. Используте i2s microphone и sigma delta.
https://habr.com/ru/articles/662141/
Здесь сигма дельта на тaймерах stm32f401

Sun-ami
06.07.2026 11:35Зачем диктофону частота дискретизации 96 кГц? И тем более 384 кбайт/с, то есть стерео? Ему и 44,1 кГц - много. 32 кГц моно - вполне достаточно. А вот FAT16 - это анахронизм, особенно для диктофона, особенно без сжатия данных. А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее, по крайней мере поштучно.

aabzel Автор
06.07.2026 11:35Зачем диктофону частота дискретизации 96 кГц? Ему и 44,1 кГц - много. 32 кГц - вполне достаточно.
Я хочу сделать автономный сонар из диктофона.
https://habr.com/ru/articles/868672/
Если повысить частоту дискретизации до 96kHz, то это улучшит разрешение измерения расстояния.На частоте дискретизации 44100 Hz за один семпл (22.6 us) звук пролетает 331*(1/44100)=7.5mm. Свертка ЛЧМ дает максимум в одном семпле. Получается погрешность измерения расстояния должна быть -/+ 7.5 mm.
На частоте 96k Hz погрешность измерения расстояния должна быть -/+ 3.4 mm.

aabzel Автор
06.07.2026 11:35А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее.
Зато он прост в программировании (11 регистров всего-лишь) и его можно купить на AliExpress прямо в составе готового модуля


Coder007
06.07.2026 11:35А вот ещё варианты:
LMD2718 + NS4168
PCM5102 + PCM1808
WM8960
WM8978
И идея сделать общение через сеть множества абонентов (один вещает всем или группе, один на один, главный общается с выбранным) с поддержкой записи на сервере всех переговоров.
Изменять дискретизацию перед началом передачи данных, в зависимости от качества канала связи.

aabzel Автор
06.07.2026 11:35А вот FAT16 - это анахронизм, особенно для диктофона.
Ну а что тут поделаешь, если модульные тесты проходят на FAT16 и проваливаются на FAT32?

aabzel Автор
06.07.2026 11:35А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее, по крайней мере поштучно.
Какой тогда аудиокодек Вы предлагаете применить?

Sun-ami
06.07.2026 11:35Не подскажу - задача специфическая.

aabzel Автор
06.07.2026 11:35Да чего тут специфичного?. Заурядная звукозапись.

Sun-ami
06.07.2026 11:35Ну, например есть I2S-кодеки, в которых в усилителе наушников очень плохо подавлен ШИМ, и это не описано в документации. Для слушания ушами не кричитно, но вот если работать с ультразвуком - очень может вылезти.

aabzel Автор
06.07.2026 11:35А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее, по крайней мере поштучно.
WM8731 установлен на плате FPGA Altera-DE1. Плату FPGA Altera-DE1 тоже не продают на Маузере ?

Sun-ami
06.07.2026 11:35Вот такая ситуация и доступностью на Digikey - по всем вариантам корпуса - статус "Obsolet". На Mouser - вообще доступны только "IC Development Tools Eval Bd"
Скрытый текст


Coder007
06.07.2026 11:35Все таки стоит на нормальную SD карту делать запись и как было сказано ранее, сделать готовое устройство. Просто на этих макетках как то кустарно получается. А так, сделать печатную плату, красивый корпус, все укомпоновать, добавить кнопки быстрого доступа к командам, небольшой дисплей и будет изделие, а не полуфабрикат.
Автор, я говорил тебе уже, у тебя такой потенциал, а ты каждый раз переизобретаешь велосипед, самокат, колесо и кирпичи. И все бы ничего, дальше макетной платы ты не идёшь, почему?
Статей много, ты делишься информацией, очень круто, а что дальше? Если ты просто хочешь научить всех, показать, как можно делать и что для этого нужно, то хорошо, пусть будет так.
Это проект - интересный, но много НО! Контроллер на макетке, аудиоплата на макетке, какой микрофон - непонятно, как прослушать на диктофоне - непонятно. Управление - непонятно, индикации нет. Схемы устройства нет. Карта памяти только на FAT16 (объем я так понимаю был только такой в наличии) и FAT32 не работает.
Повторить такое устройство смогут единицы, если захотят (если найдут такие компоненты и будут согласны на программно-аппаратные ограничения).
В итоге, автор сделал классную работу, показал, выяснил, узнал, но для себя. Да я понимаю этот кайф, когда разобрался с какими-то деталями, мелочам, все заработало и на какие-то мелочи даже не обращаешь внимания, потому что сама идея была именно в этом! А про остальные важные моменты забываешь, упускаешь, предполага что это же всё просто, значит люди поймут и разберутся сами... Но это сделают единицы, поймут тоже единицы, а все кто захочет повторить - не смогут...
Это не в упрёк, это взгляд со стороны.

aabzel Автор
06.07.2026 11:35А так, сделать печатную плату, красивый корпус, все укомпоновать, добавить кнопки быстрого доступа к командам, небольшой дисплей и будет изделие
Среди российских программистов-микроконтроллеров в организациях в принципе нет пром-дизайнеров как класса. Хотя факультеты "Промышленного Дизайн" сейчас есть почти в каждом ВУЗзе. Если у нас делают какой-то электронный прибор (пусть даже с хорошей прошивкой), то он похож на кирпич, гробик или шайбу. В качестве корпуса обычно бездумно покупают готовые прямоугольные серые корпуса в ЧипИдип-е. Разъём всегда ставят DB-9 (привет из 195х). Нет уплотнений. щели получаются такие, что между разъёмом и корпусом можно аж палец засунуть. Получившееся изделие даже в руках держать противно. Торчат куски платы об которые можно поцарапаться. Даже если электроника и прошивка вдруг и внезапно получились великолепно, то механическое исполнение продукта все перечеркивает и обнуляет результат на корню.


Coder007
06.07.2026 11:35Даже если электроника и прошивка вдруг и внезапно получились великолепно, то механическое исполнение продукта все перечеркивает и обнуляет результат на корню.
Разве ты такой? Или ты в себя не веришь? Или ты ментально с теми, кто делает только так?
Почему люди часто говорят о других, но смотрят на себя, хоть таковыми и не являются? Ну вот в забре много людей, но не все так делают. Новички электроники - делают, а старички - страдают, думая что они делают только плохо, потому что все вокруг делают плохо.
Это проблема детей СНГ, у нас слишком много самокритики, но беда в том, что мы с этим ничего не делаем, просто страдаем и сидим на попе ровно, потому что вме вокруг нас плохо, криво, некрасиво. Ну так что же мешает это изменить? Все в наших руках!
Поверь, я тоже так считал раньше,а живу я уже долго и застал и сложные и очень сложные времена. И живу я не в России, а в Казахстане, а тут было ещё сложнее чем в России.
Сейчас я вижу, как чувак из аула (небольшой поселок) , со своей простой идеей и небольшой реализацией банальной идеи влетает на поле битвы технологий и идёт вперед, с гробиками корпусов, макетными платами собранными в эти корпуса, но рабочим продуктом и продаёт его! Потом, со временем это превращается в изделие и серийный экземпляр. А по факту, человек просто начал изучать электронику и поверил в себя.
А ты в себя не веришь, потому что вокруг все делают плохо и не красиво. А не нужно в них верить, нужно верить в себя. Искать тех, кто пойдёт вместе с нами и им будет плевать, что корпус выглядит на начальном этапе как квадратная коробка. Завтра, найдётся человек, который скажет - "ребята, у вас классный продукт, давайте я вам забабахаю классный корпус", и останется с нами, и станет тем, кто будет наводить красоту.
Подумай, стоит ли разменивать свою жизнь на такое отношение к жизни. Мир не идеален, мир не совершенен, но это не значит что он останется таким навсегда, если не мы, то его сделают другие идеальным, под себя. А для нас он продолжит оставаться серым и не идеальным.
Возможно много написал, но от чистого сердца, ты подумай, просто подумай.
Я правда мало встречаю вот таких самородков как ты.
P.S. Ты никому ничего не должен, и логика простая. То, что твоё образование оплатило государство, не даёт ему права владения тобой. У тебя нет бумаги или договора, согласно которому ты ДОЛЖЕН:
возвращать результаты полученного технического образования обратно в народ.
Нет такого! У меня старшая дочка училась на бюджете и никто с неё ничего не требует. И не сможет потребовать.
Самое лучшее и правильное, что ты должен и по возможности, со своими знаниями, реализовывать их по максимуму. В первую очередь для себя, а потом уже отдавать государству в виде налогов.

aabzel Автор
06.07.2026 11:35Автор, я говорил тебе уже, у тебя такой потенциал, а ты каждый раз переизобретаешь велосипед, самокат, колесо и кирпичи.
Спасибо. А что еще остается делать ?
В России не разрабатывают по-настоящему крутую электронную технику.
Негде приложить свои силы.
Не разрабатывают вертикально приземляющиеся ракеты (реактивная посадка), не делают смартфоны, не делают электромобили, не делают радары с синтезом апертуры (SAR локаторы), не делают ЯМРТ томографы. Уровень современной embedded разработки РФ - это, условно, сделать прошивку платы для открытия и закрытия трубы - это максимум. И то с натягом.И все бы ничего, дальше макетной платы ты не идёшь, почему?
Я специалист по прошивкам. Чертить 3D корпуса не умею. Топологию PCB трассировать тоже. Для того чтобы спроектировать полноценный продукт надо минимум 3 инженера: электронщик, пром-дизайнер и программист.

Coder007
06.07.2026 11:35В России не разрабатывают по-настоящему крутую электронную технику. Негде приложить свои силы. Не разрабатывают вертикально приземляющиеся ракеты (реактивная посадка), не делают смартфоны, не делают электромобили, не делают радары с синтезом апертуры (SAR локаторы), не делают ЯМРТ томографы. Уровень современной embedded разработки РФ - это, условно, сделать прошивку платы для открытия и закрытия трубы - это максимум. И то с натягом.
Стань тем, кто это начнёт делать. И причём здесь Россия? Разве она тебя тормозит? Разве в ней дело?
Ты сейчас говоришь о стране, о людях очень субъективно, но зачем? Разве они тебе мешают сделать что-то? Разве они тебя как-то ограничивают? Начни делать не ради страны, а для себя, для своего благосостояния. Начни с заботы о себе и све вокруг увидят что если ты можешь сделать для себя, то и для других сможешь.
Не смотри и не пеняй на других, они тебе ничего не делают, максимум - комментируют твои поделки. Порой - недоделки.
Я специалист по прошивкам. Чертить 3D корпуса не умею. Топологию PCB трассировать тоже. Для того чтобы спроектировать полноценный продукт надо минимум 3 инженера: электронщик, пром-дизайнер и программист.
Скажу честно, это мышление того, кто в себе сомневается. Того, кто читает, что он не сможет что-либо сделать и при этом ни разу даже не попробовал это сделать. Просто сомневается и все! "Я специалист по заколачиванию гвоздей, а как их носить и куда забивать - я не знаю и никогда не узнаю, для этого есть другие люди!" - вот так я слышу это очень часто.
Поверь, не боги разводят платы и не боги корпуса разрабатывают.
Сейчас с нашими технологиями мы не то что корпус, мы черта в ступе можем разработать и напечатать, благо есть все для этого. И нет необходимости знать дорогостоящие и сложные продукты для моделирования.
Касательно схем и плат: Easy EDA - как стартовый вариант - идеально! Заказ платы из программы. Хотя как у вас в России, не знаю. Из Казахстана работает прекрасно.
Касательно моделирования корпусов (на первое время хоть кирпичом, хоть гробиком) - SketchUp. Просто и незамысловато.
Принтер для печати - любой, хоть самый дешевый, размерами области печати 200×200×200. Для поделок хватит.
И самое главное - желание идти вперед, стать тем самым, кто будет несмотря на сложности брать и делать.
Я же писал тебе в личку, давай обсудим варианты, интересные, продуктивные, нужные и возможно продаваемые.

aabzel Автор
06.07.2026 11:35Статей много, ты делишься информацией, очень круто, а что дальше? Если ты просто хочешь научить всех, показать, как можно делать и что для этого нужно, то хорошо, пусть будет так.
Логика проста.
Российские налогоплательщики финансировали мое бюджетное образование в казёном Политехе. Теперь надо, по возможности, возвращать результаты полученного технического образования обратно в народ.

aabzel Автор
06.07.2026 11:35какой микрофон - непонятно
Микрофон я выбрал первый попавшийся под рукой. Это оказался микрофон aceline AMIC-7.

микрофон aceline AMIC-7 https://www.dns-shop.ru/product/5217c21ccc0a3330/mikrofon-aceline-amic-7-cernyj/

Mike-M
06.07.2026 11:35Внутри прошивки я измерил реальную фактическую битовую скорость записи в файловую систему FAT и получил такую справку
Такое мог написать либо голимый ИИ, либо...
На КДПВ: вместо ActiveHight должно быть ActiveHigh, вместо Battary — Battery, вместо BlockDiagramVer:2 — Block Diagram v2. Если американская валюта обозначена через $, то и российская должна быть обозначена через ₽, а не RUR (хотя указание стоимости, температурного диапазона и корпусного исполнения на блок-схеме само по себе странно).
Число ошибок в тексте исчисляется десятками.
И так в каждой статье...За период с 2022 года я 47 раз воспользовался Ctrl-Enter, чтобы указать на необходимость корректуры перед публикацией. Просил уделять внимание правописанию, хотя бы с помощью бесплатных сервисов. Но автор с патологическим упорством продолжает писать безграмотные статьи.
Что ж, это его выбор. Мой выбор — нажать кнопку "Скрыть публикации автора".

Coder007
06.07.2026 11:35Так вам не в эту студию, здесь же рассматривают самоделки, разработки, решения, обсуждают моменты улучшения, модернизации, а уроки русского языка здесь не берут и не проводят, так же как и не заказывают услуги по лингвистика и проверке синтаксис и орфографии. Спасибо за вашу инициативу и да, может вам действительно не стоит смотреть на публикации автора, если они настолько вас трогают и тревожат.
Уверяю вас, он не пользуется ИИ, потому как таких решений, которые делает автор, там ещё нет и ИИ пока ещё не существует, а то, что вы называете ИИ - по факту является нейросетью. Это если разговаривать на Вашем языке.
За период с 2022 года я 47 раз воспользовался Ctrl-Enter, чтобы указать на необходимость корректуры перед публикацией. Просил уделять внимание правописанию, хотя бы с помощью бесплатных сервисов. Но автор с патологическим упорством продолжает писать безграмотные статьи.
Вы очень настойчивый человек, но кто вас об этом просит? Хоть один читатель данного автора обратился к вам за этим? Автор просил вас оценивать его статьи? С какой целью вы пытаетесь доказать несостоятельность и безграмотность данного автора в знаниях русского языка? Автор продолжает писать статьи на тему не лингвистики, а на тему разработок своих уникальных устройств, решений и делится этим с народом!
А чем делитесь вы? Обвинениями? Оскорблениями? Претензиями? Чем?
ОТК нужен заводам, предприятиям, выпускающим Товарную продукцию, а не НИИ, которые выпускают идеи, решения, порой безумные. Гении могут не знать правил русского языка, не видеть ошибок, но останутся гениями.
Человеку свойственно ошибаться. Не ошибается тот, кто ничего не делает.
Вы, по всей видимости не ошибаетесь в этой жизни...

Coder007
06.07.2026 11:35Что ж, это его выбор. Мой выбор — нажать кнопку "Скрыть публикации автора".
Надеюсь меня поддержат все читатели автора aabzel. Мы уважаем Ваш выбор! Вам не стоит расстраивать себя такими статьями. Вы старались, стремились, но....

aabzel Автор
06.07.2026 11:35Такое мог написать либо голимый ИИ, либо...
Вот и вправду говорят:
"Не делай добра, не получишь и зла"

aabzel Автор
06.07.2026 11:35Если американская валюта обозначена через $, то и российская должна быть обозначена через ₽, а не RUR
Это просто смешно.
На клавиатуре же просто нет символа P c черточкой под P, как в случае с cимволом $.
Человек явно перфекционист.
Mikhail_Abiht
Очень основательный подход! Следующим этапом было бы: своя печатная плата с расширением памяти и другими фишками под задачи(аппаратное отключение -например...)
aabzel Автор
Проше взять готовую отладочную плату STM32F746G-DISCO . Где всё это добро уже есть
Coder007
STM32F746G-DISCO микроконтроллерная плата jiaboroo за 11 596,23 ₽
Как мне кажется - дороговатая плата для диктофона.
Цифровой диктофон ockic WAV/MP3 128ГБ за 1 436,21 ₽
А вот сколько стоит диктофон, цифровой.
И то и другое с алиэкспресса.
aabzel Автор
Что Вы подразумеваете под расширением памяти?
SDRAM? SPI-NAND? Другое?
Mikhail_Abiht
|Главная трудность записи звука на микроконтроллерах заключается в том, что в микроконтроллерах нет столько много RAM памяти| -у вас так написано...