初中生
最后登录1970-1-1
在线时间 小时
注册时间2017-12-7
|
本帖最后由 你说冬瓜是冬瓜 于 2018-10-15 17:46 编辑
功能是存储器通过DMA双缓冲到SAI SAI主发送模式 逻辑分析仪 波形不对
[mw_shl_code=c,true]#include "stm32f4xx.h"
#include "bsp_sai.h"
#include "bsp_SysTick.h"
#include "bsp_led.h"
extern uint16_t SendBuff0[SENDBUFF_SIZE];
extern uint16_t SendBuff1[SENDBUFF_SIZE];
extern uint8_t Isread; /* DMA传输完成标志 */
extern uint8_t bufflag; /* 数据缓存区选择标志 */
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
uint32_t j;
uint32_t i;
SAI_stop();
SAI_GPIO_Config();
SAI_Config();
SAI_DMA_Config();
SAI_stop();
bufflag=0;
Isread=0;
while(1)
{
for(i=0;i<SENDBUFF_SIZE;i++)
{
SendBuff0=0xABCD;
}
for(j=0;j<SENDBUFF_SIZE;j++)
{
SendBuff1[j]=0x5A5A;
}
SAI_send_start();
DMA_ITConfig(DEBUG_SAI1_A_DMA_STREAM,DMA_IT_TC,DISABLE);//开启传输完成中断
}
}
#include "stm32f4xx.h"
#include "bsp_sai.h"
#include "bsp_led.h"
uint16_t SendBuff0[SENDBUFF_SIZE];
uint16_t SendBuff1[SENDBUFF_SIZE];
uint8_t Isread=0; /* DMA传输完成标志 */
uint8_t bufflag=0; /* 数据缓存区选择标志 */
void SAI_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_SAI1,ENABLE);
//GPIO口配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉
GPIO_InitStructure.GPIO_Speed= GPIO_High_Speed; //高速 GPIO_Low_Speed GPIO_High_Speed
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource2,GPIO_AF_SAI1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource3,GPIO_AF_SAI1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource4,GPIO_AF_SAI1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_SAI1);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_SAI1);
}
void SAI_Config(void)
{
SAI_InitTypeDef SAI_InitStructure;
SAI_FrameInitTypeDef SAI_FrameInitStructure;
SAI_SlotInitTypeDef SAI_SlotInitStructure;
uint32_t n = 0;
FlagStatus status = RESET;
// DMA_Cmd(DEBUG_SAI1_A_DMA_STREAM, DISABLE); //配置 SAI 模块前,必须禁止 SAI DMA 通道。
/***********************配置SAI和FIFO阈值***********************************/
RCC_PLLSAIConfig(128,15,3);
SAI_DeInit(SAI1);
RCC_SAIBlockACLKConfig(RCC_SAIACLKSource_PLLSAI);
RCC_PLLSAICmd(ENABLE);
for (n = 0; n < 500; n++)
{
status = RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY);
if (status == 1)break;
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SAI1,ENABLE);
SAI_InitStructure.SAI_AudioMode=SAI_Mode_MasterTx; //主模式发送
SAI_InitStructure.SAI_Protocol=SAI_Free_Protocol; //自由协议
SAI_InitStructure.SAI_DataSize=SAI_DataSize_16b; //16bit数据
SAI_InitStructure.SAI_FirstBit=SAI_FirstBit_MSB; //从高位开始读
SAI_InitStructure.SAI_ClockStrobing=SAI_ClockStrobing_FallingEdge;//时钟下降沿有效
SAI_InitStructure.SAI_Synchro=SAI_Asynchronous; //音频模块异步
SAI_InitStructure.SAI_OUTDRIV=SAI_OutputDrive_Enabled;//输出驱动使能
SAI_InitStructure.SAI_NoDivider=SAI_MasterDivider_Enabled; //主时钟分频器开启
SAI_InitStructure.SAI_MasterDivider=12;
SAI_InitStructure.SAI_FIFOThreshold=SAI_FIFOThreshold_1QuarterFull; //当FIFO没有数据时产生中断 设置FIFO阈值,1/4 FIFO SAI_Threshold_FIFOEmpty SAI_FIFOThreshold_1QuarterFull
SAI_Init(SAI1_Block_A,&SAI_InitStructure);
//帧配置
SAI_FrameInitStructure.SAI_FrameLength=128; //帧长度
SAI_FrameInitStructure.SAI_ActiveFrameLength=1; //帧有效长度为1
SAI_FrameInitStructure.SAI_FSDefinition=SAI_FS_StartFrame; // 帧同步定义,SOF信号 FS=0
SAI_FrameInitStructure.SAI_FSPolarity=SAI_FS_ActiveHigh; //FS上升沿有效 SAI_FS_ActiveHigh SAI_FS_ActiveLow
SAI_FrameInitStructure.SAI_FSOffset=SAI_FS_BeforeFirstBit;//最后一位使能FS SAI_FS_BeforeFirstBit SAI_FS_FirstBit
SAI_FrameInit(SAI1_Block_A,&SAI_FrameInitStructure);
//SAI Block Slot Init
SAI_SlotInitStructure.SAI_FirstBitOffset=0; //Specifies the position of first data transfer bit in the slot.This parameter must be a number between 0 and 24.
SAI_SlotInitStructure.SAI_SlotSize=SAI_SlotSize_16b;//slot大小为16位
SAI_SlotInitStructure.SAI_SlotNumber=8; //slot个数为8
SAI_SlotInitStructure.SAI_SlotActive=SAI_SlotActive_0|SAI_SlotActive_1|SAI_SlotActive_2|SAI_SlotActive_3|SAI_SlotActive_4|SAI_SlotActive_5|SAI_SlotActive_6|SAI_SlotActive_7;
SAI_SlotInit(SAI1_Block_A,&SAI_SlotInitStructure);
}
/*********************配置SAI DMA通道*************************************/
void SAI_DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*开启DMA时钟*/
RCC_AHB1PeriphClockCmd(DEBUG_SAI1_A_DMA_CLK, ENABLE);
DMA_DeInit(DEBUG_SAI1_A_DMA_STREAM);
/* 确保DMA数据流复位完成 */
while (DMA_GetCmdStatus(DEBUG_SAI1_A_DMA_STREAM) != DISABLE) {
}
DMA_ClearITPendingBit(DEBUG_SAI1_A_DMA_STREAM,DMA_IT_FEIF3|DMA_IT_DMEIF3|DMA_IT_TEIF3|DMA_IT_HTIF3|DMA_IT_TCIF3);//清空DMA2_Stream3上所有中断标志
/*sai1_a 对应dma2,通道0,数据流3*/
DMA_InitStructure.DMA_Channel = DEBUG_SAI1_A_DMA_CHANNEL;
/*设置DMA源:SAI1_A数据寄存器地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = DEBUG_SAI1_A_DR_BASE;
/*内存地址(要传输的变量的指针)*/
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SendBuff0;
/*方向:从内存到外设*/
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
/*传输大小DMA_BufferSize=SENDBUFF_SIZE*/
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;
/*外设地址不增*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*内存地址自增*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*外设数据长度 16位*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/*内存数据长度 16位 */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/*DMA模式:循环 DMA_Mode_Circular DMA_Mode_Normal*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*优先级:高*/
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/*禁用FIFO,直接模式 DMA_FIFOMode_Enable DMA_FIFOMode_Disable*/
DMA_InitStructure.DMA_FIFOMode =DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
/*存储器突发传输 单次传输*/
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
/*外设突发传输 单次传输*/
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
/*配置DMA2的数据流3*/
DMA_Init(DEBUG_SAI1_A_DMA_STREAM, &DMA_InitStructure);
DMA_DoubleBufferModeConfig(DEBUG_SAI1_A_DMA_STREAM,(uint32_t)SendBuff0,DMA_Memory_0);//双缓冲模式配置
DMA_DoubleBufferModeConfig(DEBUG_SAI1_A_DMA_STREAM,(uint32_t)SendBuff1,DMA_Memory_1);//双缓冲模式配置
DMA_DoubleBufferModeCmd(DEBUG_SAI1_A_DMA_STREAM,ENABLE);//双缓冲模式开启
DMA_ITConfig(DEBUG_SAI1_A_DMA_STREAM,DMA_IT_TC,ENABLE);//开启传输完成中断
SAI_DMACmd(SAI1_Block_A, ENABLE);//SAIA DMA 请求使能
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置
}
/* DMA发送完成中断回调函数 */
void SAIA_DMA_Callback(void)
{
if(DEBUG_SAI1_A_DMA_STREAM->CR&(1<<19)) //当前使用DMA_Memory_1数据 CT位
{
bufflag=0; //可以将数据读取到缓冲区0
}
else //当前使用DMA_Memory_0数据
{
bufflag=1; //可以将数据读取到缓冲区1
}
Isread=1; // DMA传输完成标志
}
/**
* @brief SPIx_TX_DMA_STREAM中断服务函数
* @param 无
* @retval 无
*/
void SAIA_DMA_STREAM_IRQFUN(void)
{
if(DMA_GetITStatus(DEBUG_SAI1_A_DMA_STREAM, DMA_IT_TCIF3)==SET)//DMA传输完成标志
{
DMA_ClearITPendingBit(DEBUG_SAI1_A_DMA_STREAM,DMA_IT_TCIF3);//清DMA传输完成标准
SAIA_DMA_Callback(); //执行回调函数,读取数据等操作在这里面处理
}
}
/*********************禁止SAI DMA通道*************************************/
void SAI_stop(void)
{
DMA_Cmd(DEBUG_SAI1_A_DMA_STREAM, DISABLE); //配置 SAI 模块前,必须禁止 SAI DMA 通道。
}
void SAI_send_start(void)
{
__IO uint32_t Timeout = TIMEOUT_MAX;
DMA_Cmd(DEBUG_SAI1_A_DMA_STREAM, ENABLE); //开启 SAI DMA 通道。
/* 检测DMA数据流是否传输完成并带有超时检测功能 */
Timeout = TIMEOUT_MAX;
while ((DMA_GetFlagStatus(DEBUG_SAI1_A_DMA_STREAM,DMA_FLAG_TCIF3)==DISABLE) && (Timeout-- > 0))
{
}
/* 判断是否超时 */
if (Timeout == 0)
{
/* 超时就让程序运行下面循环:RGB彩色灯闪烁 */
while (1)
{
LED_RED;
Delay(0xFFFFFF);
LED_RGBOFF;
Delay(0xFFFFF);
}
}
}[/mw_shl_code]
|
|