341 lines
15 KiB
C
Raw Normal View History

2021-07-28 13:15:22 +08:00
#include "sai.h"
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>ѧϰʹ<CFB0>ã<EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD>;
//ALIENTEK STM32H7<48><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//SAI<41><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>@ALIENTEK
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳:www.openedv.com
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:2017/8/17
//<2F><EFBFBD><E6B1BE>V1.0
//<2F><>Ȩ<EFBFBD><C8A8><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE><EFBFBD>
//Copyright(C) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿƼ<D3BF><C6BC><EFBFBD><EFBFBD>޹<EFBFBD>˾ 2014-2024
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
SAI_HandleTypeDef SAI1A_Handler; //SAI1 Block A<><41><EFBFBD><EFBFBD>
SAI_HandleTypeDef SAI1B_Handler; //SAI1 Block B<><42><EFBFBD><EFBFBD>
DMA_HandleTypeDef SAI1_TXDMA_Handler; //DMA<4D><41><EFBFBD>;<EFBFBD><CDBE><EFBFBD>
DMA_HandleTypeDef SAI1_RXDMA_Handler; //DMA<4D><41><EFBFBD>վ<EFBFBD><D5BE><EFBFBD>
//SAI Block A<><41>ʼ<EFBFBD><CABC>,I2S,<2C><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>׼
//mode:<3A><><EFBFBD><EFBFBD>ģʽ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:SAI_MODEMASTER_TX/SAI_MODEMASTER_RX/SAI_MODESLAVE_TX/SAI_MODESLAVE_RX
//cpol:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>/<2F>½<EFBFBD><C2BD><EFBFBD>ѡͨ<D1A1><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>SAI_CLOCKSTROBING_FALLINGEDGE/SAI_CLOCKSTROBING_RISINGEDGE
//datalen:<3A><><EFBFBD>ݴ<EFBFBD>С,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>SAI_DATASIZE_8/10/16/20/24/32
void SAIA_Init(u32 mode,u32 cpol,u32 datalen)
{
HAL_SAI_DeInit(&SAI1A_Handler); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SAI1A_Handler.Instance=SAI1_Block_A; //SAI1 Bock A
SAI1A_Handler.Init.AudioMode=mode; //<2F><><EFBFBD><EFBFBD>SAI1<49><31><EFBFBD><EFBFBD>ģʽ
SAI1A_Handler.Init.Synchro=SAI_ASYNCHRONOUS; //<2F><>Ƶģ<C6B5><C4A3><EFBFBD>
SAI1A_Handler.Init.OutputDrive=SAI_OUTPUTDRIVE_ENABLE; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶģ<C6B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SAI1A_Handler.Init.NoDivider=SAI_MASTERDIVIDER_ENABLE; //ʹ<><CAB9><EFBFBD><EFBFBD>ʱ<EFBFBD>ӷ<EFBFBD>Ƶ<EFBFBD><C6B5>(MCKDIV)
SAI1A_Handler.Init.FIFOThreshold=SAI_FIFOTHRESHOLD_1QF; //<2F><><EFBFBD><EFBFBD>FIFO<46><4F>ֵ,1/4 FIFO
SAI1A_Handler.Init.MonoStereoMode=SAI_STEREOMODE; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1A_Handler.Init.Protocol=SAI_FREE_PROTOCOL; //<2F><><EFBFBD><EFBFBD>SAI1Э<31><D0AD>Ϊ:<3A><><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><><D6A7>I2S/LSB/MSB/TDM/PCM/DSP<53><50>Э<EFBFBD><D0AD>)
SAI1A_Handler.Init.DataSize=datalen; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD>С
SAI1A_Handler.Init.FirstBit=SAI_FIRSTBIT_MSB; //<2F><><EFBFBD><EFBFBD>MSBλ<42><CEBB><EFBFBD><EFBFBD>
SAI1A_Handler.Init.ClockStrobing=cpol; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>/<2F>½<EFBFBD><C2BD><EFBFBD>ѡͨ
//֡<><D6A1><EFBFBD><EFBFBD>
SAI1A_Handler.FrameInit.FrameLength=64; //<2F><><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>Ϊ64,<2C><>ͨ<EFBFBD><CDA8>32<33><32>SCK,<2C><>ͨ<EFBFBD><CDA8>32<33><32>SCK.
SAI1A_Handler.FrameInit.ActiveFrameLength=32; //<2F><><EFBFBD><EFBFBD>֡ͬ<D6A1><CDAC><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>,<2C><>I2Sģʽ<C4A3><CABD>=1/2֡<32><D6A1>.
SAI1A_Handler.FrameInit.FSDefinition=SAI_FS_CHANNEL_IDENTIFICATION;//FS<46>ź<EFBFBD>ΪSOF<4F>ź<EFBFBD><><CDA8>ʶ<EFBFBD><CAB6><EFBFBD>ź<EFBFBD>
SAI1A_Handler.FrameInit.FSPolarity=SAI_FS_ACTIVE_LOW; //FS<46>͵<EFBFBD>ƽ<EFBFBD><C6BD>Ч(<28>½<EFBFBD><C2BD><EFBFBD>)
SAI1A_Handler.FrameInit.FSOffset=SAI_FS_BEFOREFIRSTBIT; //<2F><>slot0<74>ĵ<EFBFBD>һλ<D2BB><CEBB>ǰһλʹ<CEBB><CAB9>FS,<2C><>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>׼
//SLOT<4F><54><EFBFBD><EFBFBD>
SAI1A_Handler.SlotInit.FirstBitOffset=0; //slotƫ<74><C6AB>(FBOFF)Ϊ0
SAI1A_Handler.SlotInit.SlotSize=SAI_SLOTSIZE_32B; //slot<6F><74>СΪ32λ
SAI1A_Handler.SlotInit.SlotNumber=2; //slot<6F><74>Ϊ2<CEAA><32>
SAI1A_Handler.SlotInit.SlotActive=SAI_SLOTACTIVE_0|SAI_SLOTACTIVE_1;//ʹ<><CAB9>slot0<74><30>slot1
HAL_SAI_Init(&SAI1A_Handler); //<2F><>ʼ<EFBFBD><CABC>SAI
__HAL_SAI_ENABLE(&SAI1A_Handler); //ʹ<><CAB9>SAI
}
//SAI Block B<><42>ʼ<EFBFBD><CABC>,I2S,<2C><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>׼
//mode:<3A><><EFBFBD><EFBFBD>ģʽ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:SAI_MODEMASTER_TX/SAI_MODEMASTER_RX/SAI_MODESLAVE_TX/SAI_MODESLAVE_RX
//cpol:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>/<2F>½<EFBFBD><C2BD><EFBFBD>ѡͨ<D1A1><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>SAI_CLOCKSTROBING_FALLINGEDGE/SAI_CLOCKSTROBING_RISINGEDGE
//datalen:<3A><><EFBFBD>ݴ<EFBFBD>С,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>SAI_DATASIZE_8/10/16/20/24/32
void SAIB_Init(u32 mode,u32 cpol,u32 datalen)
{
HAL_SAI_DeInit(&SAI1B_Handler); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SAI1B_Handler.Instance=SAI1_Block_B; //SAI1 Bock B
SAI1B_Handler.Init.AudioMode=mode; //<2F><><EFBFBD><EFBFBD>SAI1<49><31><EFBFBD><EFBFBD>ģʽ
SAI1B_Handler.Init.Synchro=SAI_SYNCHRONOUS; //<2F><>Ƶģ<C6B5><C4A3>ͬ<EFBFBD><CDAC>
SAI1B_Handler.Init.OutputDrive=SAI_OUTPUTDRIVE_ENABLE; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶģ<C6B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SAI1B_Handler.Init.NoDivider=SAI_MASTERDIVIDER_ENABLE; //ʹ<><CAB9><EFBFBD><EFBFBD>ʱ<EFBFBD>ӷ<EFBFBD>Ƶ<EFBFBD><C6B5>(MCKDIV)
SAI1B_Handler.Init.FIFOThreshold=SAI_FIFOTHRESHOLD_1QF; //<2F><><EFBFBD><EFBFBD>FIFO<46><4F>ֵ,1/4 FIFO
SAI1B_Handler.Init.MonoStereoMode=SAI_STEREOMODE; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1B_Handler.Init.Protocol=SAI_FREE_PROTOCOL; //<2F><><EFBFBD><EFBFBD>SAI1Э<31><D0AD>Ϊ:<3A><><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><><D6A7>I2S/LSB/MSB/TDM/PCM/DSP<53><50>Э<EFBFBD><D0AD>)
SAI1B_Handler.Init.DataSize=datalen; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD>С
SAI1B_Handler.Init.FirstBit=SAI_FIRSTBIT_MSB; //<2F><><EFBFBD><EFBFBD>MSBλ<42><CEBB><EFBFBD><EFBFBD>
SAI1B_Handler.Init.ClockStrobing=cpol; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>/<2F>½<EFBFBD><C2BD><EFBFBD>ѡͨ
//֡<><D6A1><EFBFBD><EFBFBD>
SAI1B_Handler.FrameInit.FrameLength=64; //<2F><><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>Ϊ64,<2C><>ͨ<EFBFBD><CDA8>32<33><32>SCK,<2C><>ͨ<EFBFBD><CDA8>32<33><32>SCK.
SAI1B_Handler.FrameInit.ActiveFrameLength=32; //<2F><><EFBFBD><EFBFBD>֡ͬ<D6A1><CDAC><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>,<2C><>I2Sģʽ<C4A3><CABD>=1/2֡<32><D6A1>.
SAI1B_Handler.FrameInit.FSDefinition=SAI_FS_CHANNEL_IDENTIFICATION;//FS<46>ź<EFBFBD>ΪSOF<4F>ź<EFBFBD><><CDA8>ʶ<EFBFBD><CAB6><EFBFBD>ź<EFBFBD>
SAI1B_Handler.FrameInit.FSPolarity=SAI_FS_ACTIVE_LOW; //FS<46>͵<EFBFBD>ƽ<EFBFBD><C6BD>Ч(<28>½<EFBFBD><C2BD><EFBFBD>)
SAI1B_Handler.FrameInit.FSOffset=SAI_FS_BEFOREFIRSTBIT; //<2F><>slot0<74>ĵ<EFBFBD>һλ<D2BB><CEBB>ǰһλʹ<CEBB><CAB9>FS,<2C><>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>׼
//SLOT<4F><54><EFBFBD><EFBFBD>
SAI1B_Handler.SlotInit.FirstBitOffset=0; //slotƫ<74><C6AB>(FBOFF)Ϊ0
SAI1B_Handler.SlotInit.SlotSize=SAI_SLOTSIZE_32B; //slot<6F><74>СΪ32λ
SAI1B_Handler.SlotInit.SlotNumber=2; //slot<6F><74>Ϊ2<CEAA><32>
SAI1B_Handler.SlotInit.SlotActive=SAI_SLOTACTIVE_0|SAI_SLOTACTIVE_1;//ʹ<><CAB9>slot0<74><30>slot1
HAL_SAI_Init(&SAI1B_Handler);
SAIB_DMA_Enable(); //ʹ<><CAB9>SAI<41><49>DMA<4D><41><EFBFBD><EFBFBD>
__HAL_SAI_ENABLE(&SAI1B_Handler); //ʹ<><CAB9>SAI
}
//SAI<41>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>ʱ<EFBFBD><CAB1>ʹ<EFBFBD><CAB9>
//<2F>˺<EFBFBD><CBBA><EFBFBD><EFBFBD>ᱻHAL_SAI_Init()<29><><EFBFBD><EFBFBD>
//hsdram:SAI<41><49><EFBFBD><EFBFBD>
void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_SAI1_CLK_ENABLE(); //ʹ<><CAB9>SAI1ʱ<31><CAB1>
__HAL_RCC_GPIOE_CLK_ENABLE(); //ʹ<><CAB9>GPIOEʱ<45><CAB1>
//<2F><>ʼ<EFBFBD><CABC>PE2,3,4,5,6
GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //<2F><><EFBFBD><EFBFBD><ECB8B4>
GPIO_Initure.Pull=GPIO_PULLUP; //<2F><><EFBFBD><EFBFBD>
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //<2F><><EFBFBD><EFBFBD>
GPIO_Initure.Alternate=GPIO_AF6_SAI1; //<2F><><EFBFBD><EFBFBD>ΪSAI
HAL_GPIO_Init(GPIOE,&GPIO_Initure); //<2F><>ʼ<EFBFBD><CABC>
}
//SAI Block A<><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ʽ:
//MCKDIV!=0: Fs=SAI_CK_x/[512*MCKDIV]
//MCKDIV==0: Fs=SAI_CK_x/256
//SAI_CK_x=(HSE/pllm)*PLLSAIN/PLLSAIQ/(PLLSAIDivQ+1)
//һ<><D2BB>HSE=25Mhz
//pllm:<3A><>Stm32_Clock_Init<69><74><EFBFBD>õ<EFBFBD>ʱ<EFBFBD><CAB1>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>25
//PLLSAIN:һ<><D2BB><EFBFBD><EFBFBD>50~432
//PLLSAIQ:2~15
//PLLSAIDivQ:1~32
//MCKDIV:0~15
//SAI A<><41>Ƶϵ<C6B5><CFB5><EFBFBD><EFBFBD>@pllm=25,HSE=25Mhz,<2C><>vco<63><6F><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5>Ϊ1Mhz
const u16 SAI_PSC_TBL[][5]=
{
{800 ,344,7,1,12}, //8Khz<68><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{1102,429,2,19,2}, //11.025Khz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{1600,344,7, 1,6}, //16Khz<68><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{2205,429,2,19,1}, //22.05Khz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{3200,344,7, 1,3}, //32Khz<68><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{4410,429,2,19,0}, //44.1Khz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{4800,344,7, 1,2}, //48Khz<68><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{8820,271,2, 3,1}, //88.2Khz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{9600,344,7, 1,1}, //96Khz<68><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{17640,271,6,3,0}, //176.4Khz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{19200,295,6,1,0}, //192Khz<68><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
//<2F><><EFBFBD><EFBFBD>SAI<41><49>DMA<4D><41><EFBFBD><EFBFBD>,HAL<41><4C>û<EFBFBD><C3BB><EFBFBD><EFBFBD>˺<EFBFBD><CBBA><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>дһ<D0B4><D2BB>
void SAIA_DMA_Enable(void)
{
u32 tempreg=0;
tempreg=SAI1_Block_A->CR1; //<2F>ȶ<EFBFBD><C8B6><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
tempreg|=1<<17; //ʹ<><CAB9>DMA
SAI1_Block_A->CR1=tempreg; //д<><D0B4>CR1<52>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>
}
//<2F><><EFBFBD><EFBFBD>SAIB<49><42>DMA<4D><41><EFBFBD><EFBFBD>,HAL<41><4C>û<EFBFBD><C3BB><EFBFBD><EFBFBD>˺<EFBFBD><CBBA><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>дһ<D0B4><D2BB>
void SAIB_DMA_Enable(void)
{
u32 tempreg=0;
tempreg=SAI1_Block_B->CR1; //<2F>ȶ<EFBFBD><C8B6><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
tempreg|=1<<17; //ʹ<><CAB9>DMA
SAI1_Block_B->CR1=tempreg; //д<><D0B4>CR1<52>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>
}
//<2F><><EFBFBD><EFBFBD>SAIA<49>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>(@MCKEN)
//samplerate:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>λ:Hz
//<2F><><EFBFBD><EFBFBD>ֵ:0,<2C><><EFBFBD>óɹ<C3B3>;1,<2C>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>.
u8 SAIA_SampleRate_Set(u32 samplerate)
{
u8 i=0;
RCC_PeriphCLKInitTypeDef RCCSAI1_Sture;
for(i=0;i<(sizeof(SAI_PSC_TBL)/10);i++)//<2F><><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><D6A7>
{
if((samplerate/10)==SAI_PSC_TBL[i][0])break;
}
if(i==(sizeof(SAI_PSC_TBL)/10))return 1;//<2F>ѱ<EFBFBD><D1B1><EFBFBD>Ҳ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>
RCCSAI1_Sture.PeriphClockSelection=RCC_PERIPHCLK_SAI1;
RCCSAI1_Sture.Sai1ClockSelection=RCC_SAI1CLKSOURCE_PLL2;
RCCSAI1_Sture.PLL2.PLL2M=25;
RCCSAI1_Sture.PLL2.PLL2N=(u32)SAI_PSC_TBL[i][1];
RCCSAI1_Sture.PLL2.PLL2P=(u32)SAI_PSC_TBL[i][2];
HAL_RCCEx_PeriphCLKConfig(&RCCSAI1_Sture);
__HAL_SAI_DISABLE(&SAI1A_Handler); //<2F>ر<EFBFBD>SAI
SAI1A_Handler.Init.AudioFrequency=samplerate; //<2F><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>Ƶ<EFBFBD><C6B5>
HAL_SAI_Init(&SAI1A_Handler); //<2F><>ʼ<EFBFBD><CABC>SAI
SAIA_DMA_Enable(); //<2F><><EFBFBD><EFBFBD>SAI<41><49>DMA<4D><41><EFBFBD><EFBFBD>
__HAL_SAI_ENABLE(&SAI1A_Handler); //<2F><><EFBFBD><EFBFBD>SAI
return 0;
}
//SAIA TX DMA<4D><41><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>Ϊ˫<CEAA><CBAB><EFBFBD><EFBFBD>ģʽ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
//buf0:M0AR<41><52>ַ.
//buf1:M1AR<41><52>ַ.
//num:ÿ<>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//width:λ<><CEBB>(<28><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD>),0,8λ;1,16λ;2,32λ;
void SAIA_TX_DMA_Init(u8* buf0,u8 *buf1,u16 num,u8 width)
{
u32 memwidth=0,perwidth=0; //<2F><><EFBFBD><EFBFBD><EFBFBD>ʹ<CDB4><E6B4A2>λ<EFBFBD><CEBB>
switch(width)
{
case 0: //8λ
memwidth=DMA_MDATAALIGN_BYTE;
perwidth=DMA_PDATAALIGN_BYTE;
break;
case 1: //16λ
memwidth=DMA_MDATAALIGN_HALFWORD;
perwidth=DMA_PDATAALIGN_HALFWORD;
break;
case 2: //32λ
memwidth=DMA_MDATAALIGN_WORD;
perwidth=DMA_PDATAALIGN_WORD;
break;
}
__HAL_RCC_DMA1_CLK_ENABLE(); //ʹ<><CAB9>DMA1ʱ<31><CAB1>
__HAL_LINKDMA(&SAI1A_Handler,hdmatx,SAI1_TXDMA_Handler); //<2F><>DMA<4D><41>SAI<41><49>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>
SAI1_TXDMA_Handler.Instance=DMA1_Stream5; //DMA1<41><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD>5
SAI1_TXDMA_Handler.Init.Request=DMA_REQUEST_SAI1_A; //SAI1 Bock A
SAI1_TXDMA_Handler.Init.Direction=DMA_MEMORY_TO_PERIPH; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1_TXDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1_TXDMA_Handler.Init.MemInc=DMA_MINC_ENABLE; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1_TXDMA_Handler.Init.PeriphDataAlignment=perwidth; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>:16/32λ
SAI1_TXDMA_Handler.Init.MemDataAlignment=memwidth; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>:16/32λ
SAI1_TXDMA_Handler.Init.Mode=DMA_CIRCULAR; //ʹ<><CAB9>ѭ<EFBFBD><D1AD>ģʽ
SAI1_TXDMA_Handler.Init.Priority=DMA_PRIORITY_HIGH; //<2F><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
SAI1_TXDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE; //<2F><>ʹ<EFBFBD><CAB9>FIFO
SAI1_TXDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SAI1_TXDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //<2F><><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>
HAL_DMA_DeInit(&SAI1_TXDMA_Handler); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HAL_DMA_Init(&SAI1_TXDMA_Handler); //<2F><>ʼ<EFBFBD><CABC>DMA
HAL_DMAEx_MultiBufferStart(&SAI1_TXDMA_Handler,(u32)buf0,(u32)&SAI1_Block_A->DR,(u32)buf1,num);//<2F><><EFBFBD><EFBFBD>˫<EFBFBD><CBAB><EFBFBD><EFBFBD>
__HAL_DMA_DISABLE(&SAI1_TXDMA_Handler); //<2F>ȹر<C8B9>DMA
delay_us(10); //10us<75><73>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ֹ-O2<4F>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
__HAL_DMA_ENABLE_IT(&SAI1_TXDMA_Handler,DMA_IT_TC); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
__HAL_DMA_CLEAR_FLAG(&SAI1_TXDMA_Handler,DMA_FLAG_TCIF1_5); //<2F><><EFBFBD><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϱ<D0B6>־λ
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn,0,0); //DMA<4D>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ȼ<EFBFBD>
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}
//SAIA TX DMA<4D><41><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD>Ϊ˫<CEAA><CBAB><EFBFBD><EFBFBD>ģʽ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
//buf0:M0AR<41><52>ַ.
//buf1:M1AR<41><52>ַ.
//num:ÿ<>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//width:λ<><CEBB>(<28><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD>),0,8λ;1,16λ;2,32λ;
void SAIA_RX_DMA_Init(u8* buf0,u8 *buf1,u16 num,u8 width)
{
u32 memwidth=0,perwidth=0; //<2F><><EFBFBD><EFBFBD><EFBFBD>ʹ<CDB4><E6B4A2>λ<EFBFBD><CEBB>
switch(width)
{
case 0: //8λ
memwidth=DMA_MDATAALIGN_BYTE;
perwidth=DMA_PDATAALIGN_BYTE;
break;
case 1: //16λ
memwidth=DMA_MDATAALIGN_HALFWORD;
perwidth=DMA_PDATAALIGN_HALFWORD;
break;
case 2: //32λ
memwidth=DMA_MDATAALIGN_WORD;
perwidth=DMA_PDATAALIGN_WORD;
break;
}
__HAL_RCC_DMA1_CLK_ENABLE(); //ʹ<><CAB9>DMA1ʱ<31><CAB1>
__HAL_LINKDMA(&SAI1B_Handler,hdmarx,SAI1_RXDMA_Handler); //<2F><>DMA<4D><41>SAI<41><49>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>
SAI1_RXDMA_Handler.Instance=DMA1_Stream6; //DMA1<41><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD>6
SAI1_RXDMA_Handler.Init.Request=DMA_REQUEST_SAI1_B; //SAI1 Bock B
SAI1_RXDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY; //<2F><><EFBFBD><EFBFBD><EFBFBD><E6B4A2>ģʽ
SAI1_RXDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1_RXDMA_Handler.Init.MemInc=DMA_MINC_ENABLE; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
SAI1_RXDMA_Handler.Init.PeriphDataAlignment=perwidth; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>:16/32λ
SAI1_RXDMA_Handler.Init.MemDataAlignment=memwidth; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>:16/32λ
SAI1_RXDMA_Handler.Init.Mode=DMA_CIRCULAR; //ʹ<><CAB9>ѭ<EFBFBD><D1AD>ģʽ
SAI1_RXDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM; //<2F>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ȼ<EFBFBD>
SAI1_RXDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE; //<2F><>ʹ<EFBFBD><CAB9>FIFO
SAI1_RXDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //<2F><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SAI1_RXDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //<2F><><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>
HAL_DMA_DeInit(&SAI1_RXDMA_Handler); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HAL_DMA_Init(&SAI1_RXDMA_Handler); //<2F><>ʼ<EFBFBD><CABC>DMA
HAL_DMAEx_MultiBufferStart(&SAI1_RXDMA_Handler,(u32)&SAI1_Block_B->DR,(u32)buf0,(u32)buf1,num);//<2F><><EFBFBD><EFBFBD>˫<EFBFBD><CBAB><EFBFBD><EFBFBD>
__HAL_DMA_DISABLE(&SAI1_RXDMA_Handler); //<2F>ȹرս<D8B1><D5BD><EFBFBD>DMA
delay_us(10); //10us<75><73>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ֹ-O2<4F>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
__HAL_DMA_CLEAR_FLAG(&SAI1_RXDMA_Handler,DMA_FLAG_TCIF2_6); //<2F><><EFBFBD><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϱ<D0B6>־λ
__HAL_DMA_ENABLE_IT(&SAI1_RXDMA_Handler,DMA_IT_TC); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
HAL_NVIC_SetPriority(DMA1_Stream6_IRQn,0,1); //DMA<4D>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ȼ<EFBFBD>
HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
}
//SAI DMA<4D>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
void (*sai_tx_callback)(void); //TX<54>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
void (*sai_rx_callback)(void); //RX<52>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
//DMA1_Stream5<6D>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void DMA1_Stream5_IRQHandler(void)
{
if(__HAL_DMA_GET_FLAG(&SAI1_TXDMA_Handler,DMA_FLAG_TCIF1_5)!=RESET) //DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
__HAL_DMA_CLEAR_FLAG(&SAI1_TXDMA_Handler,DMA_FLAG_TCIF1_5); //<2F><><EFBFBD><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϱ<D0B6>־λ
if(sai_tx_callback!=NULL)sai_tx_callback(); //ִ<>лص<D0BB><D8B5><EFBFBD><EFBFBD><EFBFBD>,<2C><>ȡ<EFBFBD><C8A1><EFBFBD>ݵȲ<DDB5><C8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A6>
SCB_CleanInvalidateDCache();//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7>D-Cache
}
}
//DMA1_Stream6<6D>жϷ<D0B6><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void DMA1_Stream6_IRQHandler(void)
{
if(__HAL_DMA_GET_FLAG(&SAI1_RXDMA_Handler,DMA_FLAG_TCIF2_6)!=RESET) //DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
__HAL_DMA_CLEAR_FLAG(&SAI1_RXDMA_Handler,DMA_FLAG_TCIF2_6); //<2F><><EFBFBD><EFBFBD>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϱ<D0B6>־λ
if(sai_rx_callback!=NULL)sai_rx_callback(); //ִ<>лص<D0BB><D8B5><EFBFBD><EFBFBD><EFBFBD>,<2C><>ȡ<EFBFBD><C8A1><EFBFBD>ݵȲ<DDB5><C8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A6>
}
}
//SAI<41><49>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
void SAI_Play_Start(void)
{
__HAL_DMA_ENABLE(&SAI1_TXDMA_Handler); //<2F><><EFBFBD><EFBFBD>DMA TX<54><58><EFBFBD><EFBFBD>
}
//<2F>ر<EFBFBD>SAI<41><49><EFBFBD><EFBFBD>
void SAI_Play_Stop(void)
{
__HAL_DMA_DISABLE(&SAI1_TXDMA_Handler); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
//SAI<41><49>ʼ¼<CABC><C2BC>
void SAI_Rec_Start(void)
{
__HAL_DMA_ENABLE(&SAI1_RXDMA_Handler); //<2F><><EFBFBD><EFBFBD>DMA RX<52><58><EFBFBD><EFBFBD>
}
//<2F>ر<EFBFBD>SAI¼<49><C2BC>
void SAI_Rec_Stop(void)
{
__HAL_DMA_DISABLE(&SAI1_RXDMA_Handler); //<2F><><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>
}