STM32 SPI+DMA (HAL库)使用方法

发布者:hxcp18最新更新时间:2018-08-19 来源: eefocus关键字:STM32  SPI  DMA 手机看文章 扫描二维码
随时随地手机看文章

/*

* SPI硬件初始化,内存地址初始化

*/

static void Init(void)

{

    uint8_t i;

    /*失能SPI1*/

    HAL_SPI_DeInit(&hspi1);


    /*清空FpgaRevData内存*/

    for(i=0;i

    {

        memset(FpgaRevData[i],0,FPGA_DATA_PAKET_LENGTH);

    }

    /*初始化内存指针*/

    gWritePtr=0;

    gReadPtr=0;

    /*使能SPI1*/

    HAL_SPI_Init(&hspi1);

    /*SPI DMA初始化,并开启一次数据接收*/    

    HAL_SPI_Receive_DMA_INIT(&hspi1,FpgaRevData[gWritePtr],FPGA_DATA_PAKET_LENGTH);

}


/*

* SPI DMA初始化,并开启一次数据接收,

* 关键是返回函数的初始化,DMA 源地址和目的地址的初始化,各标志位的清空与开启

* 该程序修改与HAL库的HAL_SPI_Receive_DMA函数

*/

void HAL_SPI_Receive_DMA_INIT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)

{

  hspi->State       = HAL_SPI_STATE_BUSY_RX;

  hspi->RxXferSize  = Size;


  /*Init field not used in handle to zero */

  hspi->RxISR       = NULL;


  /* Set the SPI Rx DMA transfer complete callback */

  hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;


  /* Enable the Rx DMA Stream */

  HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)(uint8_t *)pData, Size);


  /* Check if the SPI is already enabled */

  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)

  {

    /* Enable SPI peripheral */

    __HAL_SPI_ENABLE(hspi);

  }


  /* Enable the SPI Error Interrupt Bit */

  SET_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);


  /* Enable Rx DMA Request */

  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);

}



/*

* FPGA SPI1数据接收函数,一次接收6个字节数据包

* 该程序修改与HAL库的HAL_DMA_Start_IT函数和HAL_SPI_Receive_DMA函数

*/

__INLINE void FPGA_ReadBuffer(SPI_HandleTypeDef *hspi, uint8_t *DstAddress)

{

//  HAL_StatusTypeDef status = HAL_OK;


  /* calculate DMA base and stream number */

//  DMA_Base_Registers *regs = (DMA_Base_Registers *)(hspi->hdmarx)->StreamBaseAddress;


      /* Process locked */

//  __HAL_LOCK(hspi->hdmarx);

//  

//  if(HAL_DMA_STATE_READY == hspi->hdmarx->State)

//  {

    /* Change DMA peripheral state */

//    hspi->hdmarx->State = HAL_DMA_STATE_BUSY;


    /* Clear DBM bit */

    hspi->hdmarx->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM);


    /* Configure DMA Stream destination address */

    hspi->hdmarx->Instance->M0AR = (uint32_t)(uint8_t *)DstAddress;


    /* Clear all interrupt flags at correct offset within the register */

//    regs->IFCR = 0x3FU << hspi->hdmarx->StreamIndex;


    /* Enable Common interrupts*/

    hspi->hdmarx->Instance->CR  |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME;

    hspi->hdmarx->Instance->FCR |= DMA_IT_FE;


    /* Enable the Peripheral */

    __HAL_DMA_ENABLE(hspi->hdmarx);

//  }

//  else

//  {

//    /* Process unlocked */

//    __HAL_UNLOCK(hspi->hdmarx);     

//    

//    /* Return error status */

//    status = HAL_BUSY;

//  }

      /* Check if the SPI is already enabled */

//  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)

//  {

//    /* Enable SPI peripheral */

//    __HAL_SPI_ENABLE(hspi);

//  }


  /* Enable the SPI Error Interrupt Bit */

  SET_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE|SPI_CR2_RXDMAEN);


//  /* Enable Rx DMA Request */

//  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);


//  return HAL_OK;

}




/*

*SPI 返回函数,打开SPI DMA开关,一次接收6个字节数据包

*/

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)

{

    if(hspi==&hspi1)

    {           

        //HAL_SPI_DMAStop(hspi);//先关掉DMA

         /* Disable the SPI DMA Tx & Rx requests */

        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);//关掉DMA其实就是执行了这个操作

        if((gWritePtr + 1 == gReadPtr) || (gWritePtr == REV_MAX_NUM && gReadPtr == 0))//我的数据存储在一个二维数组中,这里判断满了

            return ;

        gWritePtr++;

        if (gWritePtr==REV_MAX_NUM) gWritePtr=0;        

        FPGA_ReadBuffer(hspi,FpgaRevData[gWritePtr]);       

    }

}

当SPI DMA硬件初始化(SPI DMA mode为DMA_NORMAL)后,就可以开始一次初始 
化HAL_SPI_Receive_DMA_INIT,之后,当有数据到来,SPI接收完成返回函数会被调用,在返回函数中,首先关掉DMA,接收到数据后,提供下一次接收数据的地址,重新打开DMA。

关键字:STM32  SPI  DMA 引用地址:STM32 SPI+DMA (HAL库)使用方法

上一篇:STM32:Flash擦除与读写操作(HAL库)
下一篇:STM32 Flash 擦除 读写 成功

推荐阅读最新更新时间:2024-03-16 16:11

跑马灯+蜂鸣器的位操作实现&什么是STM32中的位操作?
跑马灯+蜂鸣器的位操作实现 代码部分 Led.c部分 #include buzzer.h #include stm32f10x.h #include sys.h void BUZZER_Init(void) { // 使能时钟 RCC- APB2ENR |= RCC_APB2ENR_IOPBEN; // 配置相应引脚的状态 GPIOB- CRH &= ~(GPIO_CRH_MODE8|GPIO_CRH_CNF8); GPIOB- CRH |= GPIO_CRH_MODE8; // 配置相应引脚的初始电平(寄存器操作) //GPIOB- BSRR |=
[单片机]
跑马灯+蜂鸣器的位操作实现&什么是<font color='red'>STM32</font>中的位操作?
STM32 输出比较错误及解决
程序1:TIM2输出比较,产生频率为366.2Hz的方波 #include stm32f10x.h void RCC_configuration(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); //开启GPIO的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); } void Led_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO初始化的结构体 GPIO_Init
[单片机]
玩转STM32(3)使用模板工程
前面学习了安装什么样的软件,这时就已经具备开发嵌入式软件的基本条件。只要把前面的开发板电源使用USB的电源线插入5V的电源,然后把JLink的USB插头插入到开发的电脑,硬件就已经连接好了。如下图这样连接起来: 在这里一定要注意使用电源供电,而不能使用JLink的供电,因为CPU和外围元件的电压会不稳定,导致调试时,CPU可以下载和运行代码,但外围元件工作不正常的现象。这里都是使用USB接头,电源的USB接头可以插入到手机充电器,现在的手机充电器都能提供比较大的功率。同时手机充电器也随处可见,随时可以买得到,使用这样的电源是最方便的。 当你把硬件按这样接好之后,就可以进入软件开发了。但是这时候,你就感觉到迷茫了,到底怎么样
[单片机]
玩转<font color='red'>STM32</font>(3)使用模板工程
STM32学习之路-感觉自己走到了一个天大的坑里了!
先前兴致勃勃的来弄16位并口驱动LCD,本以为就需要改下LCD IC的初始化就行了,没想到弄了这么多天终于发现自己走进了一个深坑了 T T 原因是我的开发板是奋斗V5的, 它确实有MCU外扩IO口, 还支持16位并口驱动,但是!! 感觉它完全是为了迎合FSMC-LCD来设定TFT接口的.. 这是它的原理图.. 再来看看正点原子的 再来看看它的芯片中关于这些IO口的部分 正点原子这个应该是不支持FSMC的.这个就很容易写数据: #define LCD_CS_SET span style= white-space:pre /span GPIOC- BSRR=1 9 //片选端口 PC9
[单片机]
<font color='red'>STM32</font>学习之路-感觉自己走到了一个天大的坑里了!
STM32单片机-PWM波形输出
一、引脚映像与寄存器 1、定时器引脚复用功能映像 ----------------------------------------------------------- 2、定时器 1)定时器介绍 STM32中一共有11个定时器,其中TIM6、TIM7是基本定时器;TIM2、TIM3、TIM4、TIM5是通用定时器;TIM1和TIM8是高级定时器,以及2个看门狗定时器和1个系统嘀嗒定时器SysTick。 其中TIM1和TIM8能够产生3对WM互补输出,常用于三相电机的驱动,时钟由APB2的输出产生; TIM2~TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。
[单片机]
<font color='red'>STM32</font>单片机-PWM波形输出
STM32和ENC28J60嵌入uip实现web服务器的设计
本设计功能有 1可以在计算机浏览器上,输入设备的的ip地址后,打开需要显示的网页控制界面,比如可以控制LED灯的开关,继电器的闭合。 2可采集数据。比如可以将温度,湿度,等参数获取显示在浏览器的页面上。 而设计实现需要需要一下知识 一、了解网络协议三大协议中的TCP/ip协议。 二、了解TCP/ip协议中应用层中的HTTP协议。 三、TCP/ip协议在单片机上实现的源码有uip和lwip.在这里主要学习uip。 四、了解http协议中的请求相应的方式GET和post。 五、了解ENC28J60硬件网卡。 六、了解HTML网页语言知识。 架构 如下 实物图
[单片机]
<font color='red'>STM32</font>和ENC28J60嵌入uip实现web服务器的设计
利用stm32的lwip TCP/IP协议栈的通信的思路
利用stm32f103vet6作为平台,enc28j60网卡,lwip tcp/ip作为协议栈进行相应的程序编写。 Stm32作为服务器与stm32作为客户端程序编写的基本步骤,思路清理: 1、stm32作为服务器端 当stm32作为服务器端的时候,首先有一点要明确的是端口与ip的确定性,当然,后期需要改变的是,如果服务器地址的变动,就需要相应的做些程序的改变。 程序的步骤如下所示: 1、利用lwip对网卡做相应的初始化工作,例如ip地址,网络掩码,以及网关的操作。 2、对服务器端的相应操作。(包括pcb控制块的获取,结构体的初始化工作。) 3、绑定相应的远程计算机,设置相应的ip地址和端口。 4、监听相应的信
[单片机]
利用<font color='red'>stm32</font>的lwip TCP/IP协议栈的通信的思路
STM32-printf重定向到USART
在使用STM32的过程中,尤其是刚开始学习使用的时候,由于不知道自己的程序写的对不对,就经常需要一点验证的方法,点亮一个LED灯就是最简单的验证方法,但是有的时候还经常需要串口的输出来验证自己的程序是否正确,但是官方提供的函数库中用于串口发送的好像就一个USART_SendData(),通过外设USARTx发送单个数据,对于熟悉C语言的同学来说,这个函数还没有格式输出,当想要输出一个数字,或者字符串的时候,使用起来可能有点麻烦,现在有一个很好的方法就可以使用C语言中的printf()函数,而且使用方法是一样的。如何使用,很简单,我们只需要重新定向printf就可以,将它的数据用STM32的串口进行发送出去就可以了。 首先添加pr
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved