#include "spi.h" u8 spi1_rec_buf[SPI1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. u8 spi1_tx_buf[SPI1_TX_LEN]; // 发送缓冲区 u8 spi1_rec_cnt; u8 spi1_rec_flag = 0; // spi1接收标志位 void SPI1DMA_Enable(DMA_Stream_TypeDef *DMA_Streamx, u16 count) { DMA_Cmd(DMA_Streamx, DISABLE); //关闭DMA传输 while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE) { } //确保DMA可以被设置 DMA_SetCurrDataCounter(DMA_Streamx, count); //数据传输量 DMA_Cmd(DMA_Streamx, ENABLE); //开启DMA传输 } void spi1_config(void) { /* 硬件SPI */ SPI_InitTypeDef SPI_InitStructure; /* 配置SPI硬件参数*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 2线全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 8位 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 时钟上升沿采样数据 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 时钟的第2个边沿采样数据 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 片选控制方式 软件控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 设置波特率预分频系数 实测SCK周期800ns 12.5MHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 数据位传输次序 高位先传 SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC多项式寄存器 本例不用 SPI_Init(SPI1, &SPI_InitStructure); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE); } void spi1_dma_config(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // DMA2时钟使能 DMA_DeInit(SPI1_DMA_TXCH); while (DMA_GetCmdStatus(SPI1_DMA_TXCH) != DISABLE) ; //等待DMA可配置 /* 配置 DMA Stream */ DMA_InitStructure.DMA_Channel = SPI1_DMA; //通道选择 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR; // DMA外设地址 DMA_InitStructure.DMA_Memory0BaseAddr = (u32)spi1_tx_buf; // DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //存储器到外设模式 DMA_InitStructure.DMA_BufferSize = SPI1_TX_LEN; //数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 使用普通模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级6 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输 DMA_Init(SPI1_DMA_TXCH, &DMA_InitStructure); //初始化DMA Stream DMA_DeInit(SPI1_DMA_RXCH); while (DMA_GetCmdStatus(SPI1_DMA_RXCH) != DISABLE) ; //等待DMA可配置 /* 配置 DMA Stream */ DMA_InitStructure.DMA_Channel = SPI1_DMA; //通道选择 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR; // DMA外设地址 DMA_InitStructure.DMA_Memory0BaseAddr = (u32)spi1_rec_buf; // DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //外设到存储器模式 DMA_InitStructure.DMA_BufferSize = SPI1_REC_LEN; //数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 使用循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输 DMA_Init(SPI1_DMA_RXCH, &DMA_InitStructure); //初始化DMA Stream } void spi1_init(void) { spi1_config(); spi1_dma_config(); SPI_Cmd(SPI1, ENABLE); // 使能SPI SPI_I2S_ClearITPendingBit(SPI1, SPI_I2S_IT_RXNE); } void SPI1DMA_Trans(const u8 *data, u16 count) { DMA_Cmd(SPI1_DMA_RXCH, DISABLE); DMA_Cmd(SPI1_DMA_TXCH, DISABLE); DMA_SetCurrDataCounter(SPI1_DMA_RXCH, count); DMA_SetCurrDataCounter(SPI1_DMA_TXCH, count); SPI1->DR; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) ; DMA_Cmd(SPI1_DMA_RXCH, ENABLE); DMA_Cmd(SPI1_DMA_TXCH, ENABLE); while (DMA_GetFlagStatus(SPI1_DMA_RXCH, DMA_FLAG_TCIF2) != RESET) ; while (DMA_GetFlagStatus(SPI1_DMA_TXCH, DMA_FLAG_TCIF3) != RESET) ; DMA_Cmd(SPI1_DMA_RXCH, DISABLE); DMA_Cmd(SPI1_DMA_TXCH, DISABLE); DMA_ClearFlag(SPI1_DMA_RXCH, DMA_FLAG_TCIF2); DMA_ClearFlag(SPI1_DMA_TXCH, DMA_FLAG_TCIF3); }