Точно така го ползвам.
Ето малко по-подробно.
a. WAVE файла се конвертира към 8bit MONO.
b. По някакъв начин WAVE файла се записва в NAND FLASH чип (в случая с JFlashSPI.exe).
c. SPI модула на процесора се настройва (пинове, алтернативни функции, с каква честота ще говори с чипа и т.н.).
d. TIM15 се настройва за PWM изход
******* WAVE file header
1. Трябва да се прочете 'WAVE file header'. SPI модула се настройва за TX и RX да праща заявка към DMA.
-> При празен SPI TX буфер ще извиква DMA-то да му даде байт, прочетен от някъде си - това е DMA1_Channel3
-> При получен байт в SPI RX буфера ще извиква DMA-то да запише този байт някъде си - това е DMA1_Channel2
2. DMA1_Channel3 се настройва да сочи към правилни адреси за Memory=RAM_txBuff и Peripheral=&(SPI1->DR), указва се посоката на данни и т.н.
3. DMA1_Channel2 се настройва да сочи към правилни адреси за Memory=RAM_rxBuff и Peripheral=&(SPI1->DR), указва се посоката на данни и т.н.
4. Посочва се брой байтове за преточване
5. Разрешава се DMA-то
6. Разрешава се SPI
-> В този момент SPI модула вдига флага TXE (TXEmpty) и DMA1_Channel3 взима байт от RAM_txBuff и го записва в SPI1->DR
-> Това предизвиква физическо изпращане на този байт към NAND FLASH чипа
-> Той отговоря на свой ред през MISO пина
-> И когато се получи целия байт в SPI1->DR вдига флага RXNE (RXNotEmpty) предизвиква заявка по DMA1_Channel2, взима байта и го записва в RAM_rxBuff
-> Когато брояча на байтове се извърти - въртележката спира
7. С това е прочетен 'WAVE file header' на максимално висока скорост според настройките, без участието на потребителски фърмуер.
******* WAVE file play
От хедър файла се гледат някои неща и числа (по желание е).
1. Трябва да се просвири самия WAVE файл. SPI модула се настройва само при RX байт да праща заявка към DMA.
-> При празен SPI TX буфер нищо няма да прави
-> При получен байт в SPI RX буфера ще извиква DMA-то да запише този байт някъде си - това е DMA1_Channel2
2. Подготвя се един таймер който да замести изключената SPI TX заявка. В случая на всеки ~62us (16000Hz) да завърта въртележката
-> Този таймер периодично ще задейства точно DMA1_Channel3 което ще предизвиква изпращането на dummyByte към NAND FLASH чипа
-> Той пък ще отговори с полезен байт от WAVE поредицата
3. DMA1_Channel3 се настройва да сочи към правилни адреси за Memory=RAM_dummyByte и Peripheral=&(SPI1->DR), указва се посоката на данни и т.н.
4. DMA1_Channel2 се настройва да сочи към правилни адреси за Memory=&(TIM15->CCR2) и Peripheral=&(SPI1->DR), указва се посоката на данни и т.н.
5. Посочва се брой байтове за преточване
6. Разрешава се DMA-то
7. Разрешава се SPI
8. Разрешава се TIM3
-> Според брояча (първия път е след няколко такта) таймера прави DMA заявка, DMA1_Channel3 взима байт от RAM_dummyByte и го записва в SPI1->DR
-> Това предизвиква физическо изпращане на този байт към NAND FLASH чипа
-> Той отговоря на свой ред през MISO пина
-> И когато се получи целия байт в SPI1->DR вдига флага RXNE (RXNotEmpty) предизвиква заявка по DMA1_Channel2, взима байта и го записва в TIM15->CCR2
-> Когато брояча на байтове се извърти - въртележката спира
9. С това е просвирен целия WAVE файл или фрагмент от него
->
без участието на потребителски фърмуер или някакви междинни RAM буфери->
процесора е напълно свободен за други дейности през цялото време******* DMA interrupts
На самото DMA се активират някои прекъсвания за да се извършват необходими действия при приключване на въртележките