你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【原创】STM32F103的SPI2的配置函数,DMA发送和接收!

[复制链接]
wjandsq 发布时间:2015-6-22 22:22
本帖最后由 wjandsq 于 2015-6-25 14:12 编辑

/*
* spi2.c
*
*  Created on: 2015年6月22日
*      Author: WJ
*/


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_conf.h"

#define SPI_Flash_CS_Low()  {GPIO_ResetBits(GPIOC, GPIO_Pin_13);}
#define SPI_Flash_CS_High() {GPIO_SetBits(GPIOC, GPIO_Pin_13);}

uint8_t SPI2_Rx_Buf[4096];
uint8_t SPI2_Tx_Buf[4096];

extern uint16_t Flag_DMA_Rxd_Finished;

extern uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte);

/**
  * @brief  Configures the SPI2 Peripheral.
  * @param  None
  * @retval None
  */
void SPI2_Config(void){
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
        DMA_InitTypeDef  DMA_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        /* Forces or releases High Speed APB (APB2) peripheral reset --------------*/
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE);
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE);

        RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);

        RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);

        RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE);
        RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE);

        RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
        RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
        /* Peripheral Clock Enable -------------------------------------------------*/
        /* DMA1 clock enable */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, DISABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
        /* Enable GPIO clocks */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
        /* SPI GPIO Configuration --------------------------------------------------*/
        /*
         * PB13 --> SPI1 SCK         Mode: GPIO_Mode_AF_PP
         * PB15 --> SPI1 MOSI Write  Mode: GPIO_Mode_AF_PP
         * PB14 --> SPI1 MISO Read   Mode: GPIO_Mode_IPU
         * PC13 --> SPI1 CS
         */

        GPIO_DeInit(GPIOB);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB, GPIO_Pin_15);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_SetBits(GPIOB, GPIO_Pin_14);

        GPIO_DeInit(GPIOC);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
        GPIO_SetBits(GPIOC, GPIO_Pin_13);

        SPI_Cmd(SPI2, DISABLE);
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;
        SPI_Init(SPI2, &SPI_InitStructure);
        if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != RESET){
                SPI_I2S_ReceiveData(SPI2);
                SPI_I2S_ClearFlag(SPI2, SPI_FLAG_CRCERR);
        }

        /* DMA1 Channel4 Configures for SPIS Receive */
        DMA_DeInit(DMA1_Channel4);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR);
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Rx_Buf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = 0;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel4, &DMA_InitStructure);

        if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET){
                DMA_ClearITPendingBit(DMA1_IT_TC4);
        }
        DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
        SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);

        /* Enable DMA1 Channel4 SPI2_RX */
        DMA_Cmd(DMA1_Channel4, DISABLE);

        /* DMA1 Channel5 Configures for SPI2 Send */
        DMA_DeInit(DMA1_Channel5);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI2->DR);
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Tx_Buf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = 0;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel5, &DMA_InitStructure);

        if(DMA_GetITStatus(DMA1_IT_TC5)!= RESET){
                DMA_ClearITPendingBit(DMA1_IT_TC5);
        }
        DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
        SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

        /* Enable DMA1 Channel5 SPI1_TX */
        DMA_Cmd(DMA1_Channel5, DISABLE);

        /* Enable the DMA1_Channel4、DMA1_Channel5 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
        NVIC_Init(&NVIC_InitStructure);

        /* Enable SPI2  */
        SPI_Cmd(SPI2, ENABLE);
}
/**
  * @brief  SPI1_DMA_Start
  * @param  len <= 4096
  * @retval None
  */

void SPI2_DMA_Read_Write(uint16_t len) {
        SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
        SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
        DMA1_Channel4->CMAR  = (uint32_t)SPI2_Rx_Buf;
        DMA1_Channel5->CMAR  = (uint32_t)SPI2_Tx_Buf;
        DMA1_Channel4->CNDTR = len;
        DMA1_Channel5->CNDTR = len;
        DMA_Cmd(DMA1_Channel4, ENABLE);
        DMA_Cmd(DMA1_Channel5, ENABLE);
        SPI_Cmd(SPI2, ENABLE);
}

/**
  * @brief  SPI2_Set_Speed
  * @param  SPI2 CR1 bit 9 8 7
  *          SPI_BaudRatePrescaler_2   ---> 000
  *          SPI_BaudRatePrescaler_4   ---> 001
  *          SPI_BaudRatePrescaler_8   ---> 010
  *          SPI_BaudRatePrescaler_16  ---> 011
  *          SPI_BaudRatePrescaler_32  ---> 100
  *          SPI_BaudRatePrescaler_64  ---> 101
  *          SPI_BaudRatePrescaler_128 ---> 110
  *          SPI_BaudRatePrescaler_256 ---> 111
  * @retval None
  */

void SPI2_Set_Speed(uint8_t BaudRatePrescaler) {
        SPI2->CR1 &= 0xFFC7; /* Clear BaudRatePrescaler Value (bit 9 8 7) */
        SPI2->CR1 |= BaudRatePrescaler;
        SPI_Cmd(SPI2,ENABLE);
}

/**
  * @brief  SPI1_Byte_Read_Write
  * @param  None
  * @retval None
  */
uint8_t SPI2_Byte_Read_Write(uint8_t SPI_Byte) {
        // 发送一字节
        while((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET);
        SPI2->DR = SPI_Byte;
        // 接收一字节
        while((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET);
        return(SPI2->DR);
}

/*
* Function Name  : DMA1_Channel4_IRQHandler
* Description    : None
* Input          : None
* Output         : None
* Return         : None
*/
void DMA1_Channel4_IRQHandler(void) {
        if (DMA_GetITStatus(DMA1_IT_TC4))  {
                SPI_Flash_CS_High();
                DMA_Cmd(DMA1_Channel4, DISABLE);
                DMA_ClearITPendingBit(DMA1_IT_TC4);
                SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);
                SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE);
                Flag_DMA_Rxd_Finished = 1;
        }
}

/*
* Function Name  : DMA1_Channel5_IRQHandler
* Description    : None
* Input          : None
* Output         : None
* Return         : None
*/
void DMA1_Channel5_IRQHandler(void) {
        if (DMA_GetITStatus(DMA1_IT_TC5)) {
                DMA_Cmd(DMA1_Channel5, DISABLE);
                DMA_ClearITPendingBit(DMA1_IT_TC5);
        }
}



1 收藏 4 评论6 发布时间:2015-6-22 22:22

举报

6个回答
Paderboy 回答时间:2015-6-23 06:53:11
多谢分享,支持个
wjandsq 回答时间:2015-6-23 08:51:16
本帖最后由 wjandsq 于 2015-6-23 08:57 编辑

命令字节发送和接收, 可以使用SPI2_Byte_Read_Write, 也可以使用SPI2_DMA_Read_Write,
这里使用SPI2读写SPI_Flash, SPI2_DMA_Read_Write 可以按照下面的方法使用:

SP2_Tx_Buf_load();            // 数据装入发送缓冲
SPI2_Flash_CS_Low();         // 片选使能
SPI2_DMA_Read_Write(6);   // 启动发送和接收, 在DMA传输完毕中断里片选关闭
while(Flag_DMA_Rxd_Finished==0) {
// 使用DMA连续收发时, 可以利用这个空闲做一些事情
// 如果是用SPI2_Byte_Read_Write, 单字节收发就没有多少空闲时间了
;
}
Flag_DMA_Rxd_Finished = 0; // DMA收发完毕,标志清0





stary666 回答时间:2015-6-23 10:02:01
看看,,,,,,,,,,,
☞❤安❤☜ 回答时间:2015-10-23 16:21:32
楼主这个问题解决了吗,我也遇到这个问题求指教
jcx0324 回答时间:2015-12-24 16:49:37
mark下,下次需要研究下
SPDF 回答时间:2024-7-22 12:07:50

研究,研究

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版