ソフト S/PDIF トランスミッタ (14)
STM32CubeMX で (STM32F4xx 用の) C 初期化コードを生成すると、次のファイル、
- stm32f4xx_hal_conf.h
- stm32f4xx_it.h
- main.c
- stm32f4xx_hal_msp.c
- stm32f4xx_it.c
が作られます。
このうち、「.c」ファイルにはユーザが記述を追加できる領域があり、「お約束」に従って記述しておけば、初期化コードを新たに生成し直してもユーザ記述部分は新しいファイルに受け継がれるようになっています。
今回はユーザ・コードを追加する必要があったのは「main.c」だけなので、「main.c」のソースだけを示します。
STM32CubeMX で生成した「カラ」の状態の「main.c」を下のリストで置き換えてください。
今回はソース・リストのみ掲載し、補足の説明は次回行います。
/** ****************************************************************************** * File Name : main.c * Date : 03/09/2014 18:38:07 * Description : Main program body ****************************************************************************** * * COPYRIGHT(c) 2014 STMicroelectronics * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h" /* Private variables ---------------------------------------------------------*/ I2S_HandleTypeDef hi2s3; DMA_HandleTypeDef hdma_spi3_tx; UART_HandleTypeDef huart2; /* USER CODE BEGIN 0 */ // Software S/PDIF transmitter using SPI/I2S and DMA // 2014/08/26 by pcm1723 // uncomment following line to use BMC table in FLASH to save RAM //#define BMC_TAB_IN_ROM 1 //#define DAC_TEST 1 // LD2 User LED (green) on 'D13' (PA5) pin #define IDLE_LED_ON HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET) #define IDLE_LED_OFF HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET) #define IDLE_LED_TOGGLE HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5) // S/PDIF frame/block definition #define FRAMES_PER_BLOCK 192 // frames per block #define W16_PER_SUBFRAME 4 // 16-bit halfword count per subframe #define W16_PER_FRAME 8 // 16-bit halfword count per frame #define W16_PER_BLOCK (W16_PER_FRAME * FRAMES_PER_BLOCK) // 16-bit halfword count per block #define SPDIF_TXBUF_INDMAX (sizeof(spdif_txbuf)/sizeof(int16_t)) // number of 16-bit halfword in TX buffer // SPI/I2S module definition for S/PDIF TX #define SPDIF SPI3 // module instance name #define hSPDIF hi2s3 // handle object #define hSPDIF_dma hdma_spi3_tx // handle object for DMA // S/PDIF TX buffer index structure typedef struct tag_spdif_txind_t { // room for output data (count in terms of halfword) volatile uint16_t room; // S/PDIF TX buffer pointer volatile uint16_t *ptr; } spdif_txind_t; static spdif_txind_t spdif_txind; // biphase mark code bitmaps // // bitmap for 0 0 0 0 // --__--__ #define BMC_0000 (0xCC) // bitmap for 1 0 0 0 // -_--__-- #define BMC_1000 (0xB3) // bitmap for 0 0 1 1 // --__-_-_ #define BMC_0011 (0xCA) // bitmap for UVCP bits = 0 0 0 0 #define BMC_VUCP_0000 (BMC_0000 << 8) // bitmap for UVCP bits = 0 0 1 1 #define BMC_VUCP_0011 (BMC_0011 << 8) // bitmap for preamble 'B' (frame 0 L-ch indication) // ---_-___ #define BMC_PREAMBLE_B (0xE8) // bitmap for preamble 'W' (R-ch) // ---__-__ #define BMC_PREAMBLE_W (0xE4) // bitmap for preamble 'M' (L-ch) // ---___-_ #define BMC_PREAMBLE_M (0xE2) // bitmap for 0 0 0 0 0 0 0 0 // --__--__--__--__ #define BMC_0000_0000 (0xCCCC) // bitmap for 1 0 0 0 0 0 0 0 // -_--__--__--__-- #define BMC_1000_0000 (0xB333) // S/PDIF channel status bits // // b0 = 0 : PRO=0 (consumer) // b1 = 0 : AUDIO#=0 (digital audio) // b2 = 1 : Copy=1 (permitted) // b3:4:5 = 0 : Pre-emphasis=0 (none) // b7:6 = 0 : Mode=0 (defines byte1-3) // // b8:9:10:11:12:13:14 = 0 : General // b15 = 0 : Generation=0 (no indication) // // b16:17:18:19 = 0 : Source Number=0 (unspecified) // b20:21:22:23 = 0 : Channel Number=0 (unspecified) // // b24:25:26:27 = 4 : fs = 48 kHz // b28:29 = 0 : Clock Acuracy=0 (Level II, +-1000 ppm, default) // b30:31 = 0 : Reserved // first 32 bits of channel status (copy permitted, fs = 48 kHz) #define CH_STATUS_BITS (0x20000040UL) // channel status data mask #define CH_STAT_MASK (0x80000000UL) #define HAS_SPDIF_TXBUF_ROOM (0 < spdif_txind.room) // S/PDIF TX buffer in RAM (1 block) uint16_t spdif_txbuf[W16_PER_BLOCK]; const uint8_t sync_tab[2][2] = { { BMC_PREAMBLE_M, BMC_PREAMBLE_W }, // preamble M/W for L/R (not frame 0) { BMC_PREAMBLE_B, BMC_PREAMBLE_W } // preamble B/W for L/R (frame 0 only) }; // const uint8_t sync_tab[][] const uint16_t vucp_tab[2] = { BMC_VUCP_0000, // bitmap for C=0, P=0 BMC_VUCP_0011 // bitmap for C=1, P=1 }; // const uint16_t vucp_tab[] // Biphase Mark Code (BMC) table for byte (8-bit) data // ('0' ending pattern) #if defined(BMC_TAB_IN_ROM) const uint16_t bmc8b[256] = { 0xCCCC, 0x4CCC, 0x2CCC, 0xACCC, // 0x00..0x03 0x34CC, 0xB4CC, 0xD4CC, 0x54CC, // 0x04..0x07 0x32CC, 0xB2CC, 0xD2CC, 0x52CC, // 0x08..0x0B 0xCACC, 0x4ACC, 0x2ACC, 0xAACC, // 0x0C..0x0F 0x334C, 0xB34C, 0xD34C, 0x534C, // 0x10..0x13 0xCB4C, 0x4B4C, 0x2B4C, 0xAB4C, // 0x14..0x17 0xCD4C, 0x4D4C, 0x2D4C, 0xAD4C, // 0x18..0x1B 0x354C, 0xB54C, 0xD54C, 0x554C, // 0x1C..0x1F 0x332C, 0xB32C, 0xD32C, 0x532C, // 0x20..0x23 0xCB2C, 0x4B2C, 0x2B2C, 0xAB2C, // 0x24..0x27 0xCD2C, 0x4D2C, 0x2D2C, 0xAD2C, // 0x28..0x2B 0x352C, 0xB52C, 0xD52C, 0x552C, // 0x2C..0x2F 0xCCAC, 0x4CAC, 0x2CAC, 0xACAC, // 0x30..0x33 0x34AC, 0xB4AC, 0xD4AC, 0x54AC, // 0x34..0x37 0x32AC, 0xB2AC, 0xD2AC, 0x52AC, // 0x38..0x3B 0xCAAC, 0x4AAC, 0x2AAC, 0xAAAC, // 0x3C..0x3F 0x3334, 0xB334, 0xD334, 0x5334, // 0x40..0x43 0xCB34, 0x4B34, 0x2B34, 0xAB34, // 0x44..0x47 0xCD34, 0x4D34, 0x2D34, 0xAD34, // 0x48..0x4B 0x3534, 0xB534, 0xD534, 0x5534, // 0x4C..0x4F 0xCCB4, 0x4CB4, 0x2CB4, 0xACB4, // 0x50..0x53 0x34B4, 0xB4B4, 0xD4B4, 0x54B4, // 0x54..0x57 0x32B4, 0xB2B4, 0xD2B4, 0x52B4, // 0x58..0x5B 0xCAB4, 0x4AB4, 0x2AB4, 0xAAB4, // 0x5C..0x5F 0xCCD4, 0x4CD4, 0x2CD4, 0xACD4, // 0x60..0x63 0x34D4, 0xB4D4, 0xD4D4, 0x54D4, // 0x64..0x67 0x32D4, 0xB2D4, 0xD2D4, 0x52D4, // 0x68..0x6B 0xCAD4, 0x4AD4, 0x2AD4, 0xAAD4, // 0x6C..0x6F 0x3354, 0xB354, 0xD354, 0x5354, // 0x70..0x73 0xCB54, 0x4B54, 0x2B54, 0xAB54, // 0x74..0x77 0xCD54, 0x4D54, 0x2D54, 0xAD54, // 0x78..0x7B 0x3554, 0xB554, 0xD554, 0x5554, // 0x7C..0x7F 0x3332, 0xB332, 0xD332, 0x5332, // 0x80..0x83 0xCB32, 0x4B32, 0x2B32, 0xAB32, // 0x84..0x87 0xCD32, 0x4D32, 0x2D32, 0xAD32, // 0x88..0x8B 0x3532, 0xB532, 0xD532, 0x5532, // 0x8C..0x8F 0xCCB2, 0x4CB2, 0x2CB2, 0xACB2, // 0x90..0x93 0x34B2, 0xB4B2, 0xD4B2, 0x54B2, // 0x94..0x97 0x32B2, 0xB2B2, 0xD2B2, 0x52B2, // 0x98..0x9B 0xCAB2, 0x4AB2, 0x2AB2, 0xAAB2, // 0x9C..0x9F 0xCCD2, 0x4CD2, 0x2CD2, 0xACD2, // 0xA0..0xA3 0x34D2, 0xB4D2, 0xD4D2, 0x54D2, // 0xA4..0xA7 0x32D2, 0xB2D2, 0xD2D2, 0x52D2, // 0xA8..0xAB 0xCAD2, 0x4AD2, 0x2AD2, 0xAAD2, // 0xAC..0xAF 0x3352, 0xB352, 0xD352, 0x5352, // 0xB0..0xB3 0xCB52, 0x4B52, 0x2B52, 0xAB52, // 0xB4..0xB7 0xCD52, 0x4D52, 0x2D52, 0xAD52, // 0xB8..0xBB 0x3552, 0xB552, 0xD552, 0x5552, // 0xBC..0xBF 0xCCCA, 0x4CCA, 0x2CCA, 0xACCA, // 0xC0..0xC3 0x34CA, 0xB4CA, 0xD4CA, 0x54CA, // 0xC4..0xC7 0x32CA, 0xB2CA, 0xD2CA, 0x52CA, // 0xC8..0xCB 0xCACA, 0x4ACA, 0x2ACA, 0xAACA, // 0xCC..0xCF 0x334A, 0xB34A, 0xD34A, 0x534A, // 0xD0..0xD3 0xCB4A, 0x4B4A, 0x2B4A, 0xAB4A, // 0xD4..0xD7 0xCD4A, 0x4D4A, 0x2D4A, 0xAD4A, // 0xD8..0xDB 0x354A, 0xB54A, 0xD54A, 0x554A, // 0xDC..0xDF 0x332A, 0xB32A, 0xD32A, 0x532A, // 0xE0..0xE3 0xCB2A, 0x4B2A, 0x2B2A, 0xAB2A, // 0xE4..0xE7 0xCD2A, 0x4D2A, 0x2D2A, 0xAD2A, // 0xE8..0xEB 0x352A, 0xB52A, 0xD52A, 0x552A, // 0xEC..0xEF 0xCCAA, 0x4CAA, 0x2CAA, 0xACAA, // 0xF0..0xF3 0x34AA, 0xB4AA, 0xD4AA, 0x54AA, // 0xF4..0xF7 0x32AA, 0xB2AA, 0xD2AA, 0x52AA, // 0xF8..0xFB 0xCAAA, 0x4AAA, 0x2AAA, 0xAAAA, // 0xFC..0xFF }; // const uint16_t bmc8b[] #else uint16_t bmc8b[256]; // BMC table in RAM #endif // #if defined(BMC_TAB_IN_ROM) // user callback for DMA half complete void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) { if (SPDIF == hi2s->Instance) { // is SPI/I2S device for SPDIF? spdif_txind.room = (SPDIF_TXBUF_INDMAX / 2); // TX buffer pointer (the first half) spdif_txind.ptr = &(spdif_txbuf[0]); } // } // void HAL_I2S_TxHalfCpltCallback() // user callback for DMA (full) complete void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) { if (SPDIF == hi2s->Instance) { // is SPI/I2S device for SPDIF? spdif_txind.room = (SPDIF_TXBUF_INDMAX / 2); // TX buffer pointer (the second half) spdif_txind.ptr = &(spdif_txbuf[SPDIF_TXBUF_INDMAX / 2]); } // } // HAL_I2S_TxCpltCallback() // build biphase mark code table for byte data #if !defined(BMC_TAB_IN_ROM) void setup_bmc8b( void ) { int i, j, b, d; uint16_t m; // bit pattern of biphase mark coded data for (i = 0; i < 256; i++) { // loop for 8-bit number m = 0; // init biphase mark code bit pattern b = 0; // output bit data (assume 1 start) d = i; // input data for (j = 0; j < 8; j++) { // scan for 8-bit // bit boundary edge (always flip) m <<= 1; // shift left bit patten b ^= 1; // flip always for bit boundary m |= b; // bit boudary edge // data bit edge (flip for (data_bit == 1)) m <<= 1; // shift left bit pattern b ^= (1 & d); // flip / not flip output bit m |= b; // data bit edge // d >>= 1; // shift right input data } // for (j = 0; ... if (0x01 & m) { // test for "1 end" m ^= 0xFFFF; // invert bits to force "0 end" } // if (0x01 & m) bmc8b[i] = m; // store result in table } // for (i = 0; ... } // void setup_bmc8b() #endif // setup S/PDIF TX buffer in RAM for specified block(s) void setup_spdif_txbuf(int blocks, uint32_t chs, int builtin_wave) { int i, j, k, m, cbit; j = 0; // index of SPDIF TX buffer array for (m = 0; m < blocks; m++) { // loop for block(s) cbit = 0; // assume C=0 for the very last subframe of prev. block for (i = 0; i < (FRAMES_PER_BLOCK); i++) { // frame index (0..191) for (k = 0; k < 2; k++) { // subframe index (0..1) spdif_txbuf[j++] = ( vucp_tab[cbit] // VUCP of prev subframe | sync_tab[0 == i][k] // preamble ); spdif_txbuf[j++] = BMC_0000_0000; // AUX (4 bit) + sub_LSB (4 bit) spdif_txbuf[j++] = BMC_0000_0000; // LSByte(8 bit) of audio data (0x00) if (builtin_wave) { // pre-encoded square wave if (1 & ((i + (k << 4)) >> 5)) { // 750 Hz square wave spdif_txbuf[j++] = 0xB334; // MSByte(8 bit) of audio data (0x41:00 = 16640) } else { spdif_txbuf[j++] = 0xCCCA; // MSByte(8 bit) of audio data (0xC0:00 = -16384) } // if (1 & (i >> 5)) { ... } else {// silence spdif_txbuf[j++] = BMC_0000_0000; // MSByte(8 bit) of audio data (0x00) } // if (builtin_wave) { ... if (0 == k) { // frame boundary for VUCP nibble cbit = (0 != (CH_STAT_MASK & chs)); // extract ch status bit chs <<= 1 ; // shift ch status reg for next frame } // if (0 == k) { ... } // for (k = 0; ... } // for (i = 0; ... } // for (m = 0; ... #if !defined(BMC_TAB_IN_ROM) setup_bmc8b(); // build biphase mark code table #endif } // void setup_spdif_txbuf() // encode audio data for specified number of subframe(s) uint16_t spdif_encode_subframe_data(int16_t dat[], uint16_t nsf) { int i; uint16_t bmc_L, bmc_H, aux; // bitmap of biphase mark code const uint32_t BMC_LSB_MASK = (1U << 15); register volatile uint16_t *p; // TX buffer pointer p = spdif_txind.ptr; // get S/PDIF TX buffer pointer for (i = 0; i < nsf; i++) { // for subframe(s) // encode LSByte (d[0:7]) of audio data bmc_L = bmc8b[(uint8_t) dat[i]]; // encode MSByte (d[8:15]) of audio data bmc_H = bmc8b[(uint8_t)(dat[i] >> 8)]; *(p + 3) = bmc_H; // audio data d[8:15] (8 bit) #if (__CORTEX_M >= 0x03) // Cortex-M3/M4 processor ? // invert bmc of d[0:7] if (0 == bmc_H[15]) bmc_L ^= (~((int16_t)bmc_H) >> 16); // gimmick for Cortex-M3/M4 processor (ARMv7-M arch) to avoid conditional aux = (BMC_1000_0000 ^ (((uint32_t)((int16_t)bmc_L)) >> 17)); #else // Cortex-M0 processor (ARMv6-M arch) // invert bmc of d[0:7] if (0 == bmc_H[15]) bmc_L ^= ((bmc_H >> 15) + 0xFFFFU); // straightforward implementation for Cortex-M0 if (BMC_LSB_MASK & bmc_L) { // detect "1 start" aux = BMC_0000_0000; // no need to adjust parity } else { aux = BMC_1000_0000; // adjust parity } // if (BMC_LSB_MASK & bmc_L) { ... #endif // SPDIF TX buffer update for this subframe data // VUCP (4 bit) and preamble (4 bit) not changed (pointed by *(p)) // AUX (4 bit) + audio ext (4 bit) for parity correction *(p + 1) = aux; *(p + 2) = bmc_L; // audio data d[0:7] (8 bit) p += 4; // advance TX buffer pointer by 4 } // for (i = 0; // advance S/PDIF TX buffer pointer spdif_txind.ptr = p; // 4 halfword (64 bit) used per subframe spdif_txind.room -= (4 * nsf); return(spdif_txind.room); } // uint16_t spdif_encode_subframe_data() void modify_i2s_pll( void ) { uint32_t i2s_pllm; // get PLLM value from main PLL i2s_pllm = (0x3F & RCC->PLLCFGR); __HAL_RCC_PLLI2S_DISABLE(); // stop I2S PLL // wait for I2S PLL halted while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET) {} // set PLLM value for I2S PLL RCC->PLLI2SCFGR = ((~0x3F & RCC->PLLI2SCFGR) | i2s_pllm); __HAL_RCC_PLLI2S_ENABLE(); // re-start I2S PLL } // void modify_i2spll() /* USER CODE END 0 */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_I2S3_Init(void); static void MX_USART2_UART_Init(void); int main(void) { /* USER CODE BEGIN 1 */ int16_t sfbuf[2]; // subframe data buffer int32_t sin_acc = 0; int32_t cos_acc = 0x7e00; // initial radius /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* System interrupt init*/ /* Sets the priority grouping field */ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0); HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_I2S3_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ modify_i2s_pll(); // for F411 // init. SPDIF TX buffer for 1 block, fs=48 kHz, copy permitted, no built-in wave setup_spdif_txbuf(1, CH_STATUS_BITS, 0); spdif_txind.room = 0; // assume buffer full at first // start I2S transmission by DMA (automatic repeat by 'circular mode') HAL_I2S_Transmit_DMA(&hSPDIF, // handle of SPI/I2S for S/PDIF spdif_txbuf, // TX buffer (array of uint16_t) SPDIF_TXBUF_INDMAX); // buffer size in 16-bit halfword // Note: I2S configured for 16-bit data word / 16-bit frame per channel /* USER CODE END 2 */ /* USER CODE BEGIN 3 */ /* Infinite loop */ while (1) { // sin_cos_freq = 48 [kHz] * 3775 / (2 * pi * 2^16) = 440.05 [Hz] // sin_cos_freq = 44.1 [kHz] * 4108 / (2 * pi * 2^16) = 439.96 [Hz] const uint16_t acc_mul[2] = {3775, 4108}; const uint32_t acc_shift = 16; if (HAS_SPDIF_TXBUF_ROOM) { IDLE_LED_OFF; // show busy spdif_encode_subframe_data(sfbuf, 2); // put 2 subframes (L-ch/R-ch) // update sin/cos value using DDA calculation cos_acc -= ((sin_acc * acc_mul[0]) >> acc_shift); sin_acc += ((cos_acc * acc_mul[0]) >> acc_shift); sfbuf[0] = cos_acc; // L-ch sfbuf[1] = sin_acc; // R-ch } else { // no room in SPDIF TX buffer IDLE_LED_ON; // show idle } // if (... } /* USER CODE END 3 */ } /** System Clock Configuration */ void SystemClock_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; __PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 5; RCC_OscInitStruct.PLL.PLLN = 210; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; RCC_OscInitStruct.PLL.PLLQ = 7; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S; PeriphClkInitStruct.PLLI2S.PLLI2SN = 192; PeriphClkInitStruct.PLLI2S.PLLI2SR = 5; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); } /* I2S3 init function */ void MX_I2S3_Init(void) { hi2s3.Instance = SPI3; hi2s3.Init.Mode = I2S_MODE_MASTER_TX; hi2s3.Init.Standard = I2S_STANDARD_LSB; hi2s3.Init.DataFormat = I2S_DATAFORMAT_16B; hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; #if defined(DAC_TEST) hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_48K; #else hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_192K; #endif hi2s3.Init.CPOL = I2S_CPOL_LOW; hi2s3.Init.ClockSource = I2S_CLOCK_PLL; hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; HAL_I2S_Init(&hi2s3); } /* USART2 init function */ void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart2); } /** * Enable DMA controller clock */ void MX_DMA_Init(void) { /* DMA controller clock enable */ __DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* Sets the priority grouping field */ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0); HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); } /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __GPIOC_CLK_ENABLE(); __GPIOH_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); /*Configure GPIO pin : PC13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PA5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/