使用标准库函数(不要用hal库),写一个stm32f4单片机实现PB5和PB9的SPI主机只发送与DMA传输的代码
时间: 2024-09-25 10:15:10 浏览: 46
在STM32F4中,使用标准库函数编写一个仅包含SPI主机发送和DMA传输的例子,需要注意的是,标准库并没有直接提供对DMA的支持,所以我们需要手动管理DMA和中断。以下是简单的示例代码:
首先,我们需要配置GPIO用于SPI:
```c
void GPIO_Init()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_NOPULL;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF7_SPI5); // PB5连接到SPI5
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
```
接下来,配置并初始化SPI:
```c
void SPI_Init()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI5, ENABLE); // 启动SPI5时钟
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; // 设定合适的波特率
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI5, &SPI_InitStructure);
SPI_Cmd(SPI5, ENABLE);
}
```
然后,创建一个DMA传输结构,并手动分配资源:
```c
void DMA_Init()
{
// 创建一个通用DMA请求
DMA_HandleTypeDef hdma_spi SendDMA;
hdma_spi.Instance = DMA1_Channel3;
hdma_spi.Init.Channel = DMA_CHANNEL_3;
hdma_spi.Init.Direction = DMA_DIR_PeripheralToMemory;
hdma_spi.Init.PeriphInc = DMA_PINC_Enable;
hdma_spi.Init.MemInc = DMA_MINC_Enable;
hdma_spi.Init.PeriphDataAlignment = DMA_PDATAALIGN_Word;
hdma_spi.Init.MemDataAlignment = DMA_MDATAALIGN_Word;
hdma_spi.Init.Mode = DMA_Mode_Circular;
hdma_spi.Init.Priority = DMA_PRIORITY_High;
hdma_spi.Init.FIFOMode = DMA_FIFOMode_Enable;
hdma_spi.Init.FIFOThreshold = DMA_FIFOThreshold_HalfFull;
hdma_spi.Init.MemBurst = DMA_MBurst_Single;
hdma_spi.Init.PeriphBurst = DMA_PBurst_Single;
HAL_DMA_Init(&hdma_spi);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); // Enable DMA interrupt
// ...其他必要的DMA资源分配...
}
// 假设我们有个缓冲区和长度
void SendData(uint8_t* data, uint16_t length)
{
while (length > 0)
{
if (HAL_DMA_IsActiveFlagSet(hdma_spi, DMA_FLAG_TCIF3)) // 当前传输完成
{
HAL_DMA_IRQHandler(&hdma_spi); // 手动处理DMA完成中断
HAL_DMA洁白(&hdma_spi); // 清除标志并准备新的传输
}
uint16_t bytes_to_send = min(length, DMA_BUFFER_SIZE); // 分配合理的DMA传输大小
HAL_DMA_Start_IT(&hdma_spi, (uint32_t)data, (uint32_t)&spiSendBuffer, bytes_to_send); // 开始DMA传输
data += bytes_to_send;
length -= bytes_to_send;
}
}
```
最后,记得处理DMA中断:
```c
void DMA1_Channel3_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi);
if (hdma_spi.State == HAL_DMA_STATE_COMPLETED)
{
// 执行接收操作后的动作,比如更新缓冲区指针
// ... 更新SPI接收缓冲区 ...
}
}
```
阅读全文