硬汉嵌入式论坛

 找回密码
 立即注册
查看: 105|回复: 3
收起左侧

[SPI/QSPI] H743 SPI+DMA问题

[复制链接]

1

主题

1

回帖

4

积分

新手上路

积分
4
发表于 3 天前 | 显示全部楼层 |阅读模式
使用DMA+SPI驱动DAC芯片DAC8830,一次只发送一个数据
不使用DMA的时候SPI可以正常输出,加上DMA上就不行,直接SPI没有任何输出clk也没有,下面是我的代码,请问下是什么原因导致的呀



#include "./BSP/SPI/spi_DAC8830.h"
#include "./BSP/LED/led.h"


static SPI_HandleTypeDef g_SPI2_handle = {0};
static SPI_HandleTypeDef g_SPI3_handle = {0};
static DMA_HandleTypeDef g_DMA2_SPI2_handle = {0};

static HAL_DMA_MuxSyncConfigTypeDef dmamux_syncParams;


extern uint16_t triangle_data_out[N_TRIANGLE];



/*
*********************************************************************************************************
*        函 数 名: HAL_SPI_MspInit和HAL_SPI_MspDeInit
*        功能说明: 用于SPI底层的初始化和复位初始化
*        形    参: SPI_HandleTypeDef 类型指针变量
*        返 回 值: 无
*********************************************************************************************************
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *_hspi)
{
        GPIO_InitTypeDef  GPIO_InitStruct;
               
        /* SPI和GPIO时钟 */
        SPI2_CLK_ENABLE();
        SPI2_GPIO_CLK_ENABLE();

   
        /* SPI SCK */
        GPIO_InitStruct.Pin               = SPI2_CLK_GPIO_PIN;   
        GPIO_InitStruct.Mode              = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull              = GPIO_PULLUP;
        GPIO_InitStruct.Speed             = GPIO_SPEED_FREQ_MEDIUM;
        GPIO_InitStruct.Alternate         = SPI2_CLK_GPIO_AF;
        HAL_GPIO_Init(SPI2_CS_MOSI_CLK_GPIO_PORT, &GPIO_InitStruct);

        /* SPI MOSI */
        GPIO_InitStruct.Pin                 = SPI2_MOSI_GPIO_PIN;
        GPIO_InitStruct.Alternate         = SPI2_MOSI_GPIO_AF;
        HAL_GPIO_Init(SPI2_CS_MOSI_CLK_GPIO_PORT, &GPIO_InitStruct);
       
        /* SPI NSS */
        GPIO_InitStruct.Pin                 = SPI2_CS_GPIO_PIN;
        //GPIO_InitStruct.Mode                = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Alternate         = SPI2_CS_GPIO_AF;
        HAL_GPIO_Init(SPI2_CS_MOSI_CLK_GPIO_PORT, &GPIO_InitStruct);
       
        //使能SPI3对应的IO口
        SPI3_CLK_ENABLE();
        SPI3_CS_GPIO_CLK_ENABLE();
        SPI3_CLK_MOSI_GPIO_CLK_ENABLE();
       
        GPIO_InitStruct.Pin               = SPI3_CLK_GPIO_PIN;   
        GPIO_InitStruct.Mode              = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull              = GPIO_PULLUP;
        GPIO_InitStruct.Speed             = GPIO_SPEED_FREQ_MEDIUM;
        GPIO_InitStruct.Alternate         = SPI3_CLK_GPIO_AF;
        HAL_GPIO_Init(SPI3_CLK_MOSI_GPIO_PORT, &GPIO_InitStruct);

        /* SPI MOSI */
        GPIO_InitStruct.Pin                 = SPI3_MOSI_GPIO_PIN;
        GPIO_InitStruct.Alternate         = SPI3_MOSI_GPIO_AF;
        HAL_GPIO_Init(SPI3_CLK_MOSI_GPIO_PORT, &GPIO_InitStruct);
       
        /* SPI NSS */
        GPIO_InitStruct.Pin                 = SPI3_CS_GPIO_PIN;
        GPIO_InitStruct.Alternate         = SPI3_CS_GPIO_AF;
        HAL_GPIO_Init(SPI3_CS_GPIO_PORT, &GPIO_InitStruct);
       
        //初始化DMA配置
        #if USE_DMA
       
        /* 使能DMA时钟 */
        DMA2_CLK_ENABLE();
       
        /* SPI DMA发送配置 */               
        g_DMA2_SPI2_handle.Instance                 = SPI2_TX_DMA_STREAM;      /* 例化使用的DMA数据流 */
        g_DMA2_SPI2_handle.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;     /* 使能FIFO*/
        g_DMA2_SPI2_handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL; /* 用于设置阀值, 如果禁止FIFO此位不起作用*/
        g_DMA2_SPI2_handle.Init.MemBurst            = DMA_MBURST_SINGLE;            /* 用于存储器突发,如果禁止FIFO此位不起作用*/
        g_DMA2_SPI2_handle.Init.PeriphBurst         = DMA_PBURST_SINGLE;            /* 用于外设突发,禁止FIFO此位不起作用 */
        g_DMA2_SPI2_handle.Init.Request             = SPI2_TX_DMA_REQUEST;     /* 请求类型 */  
        g_DMA2_SPI2_handle.Init.Direction           = DMA_MEMORY_TO_PERIPH;    /* 传输方向是从存储器到外设 */  
        g_DMA2_SPI2_handle.Init.PeriphInc           = DMA_PINC_DISABLE;        /* 外设地址自增禁止 */
        g_DMA2_SPI2_handle.Init.MemInc              = DMA_MINC_DISABLE;         /* 存储器地址自增使能 */  
        g_DMA2_SPI2_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;     /* 外设数据传输位宽选择字节,即8bit */
        g_DMA2_SPI2_handle.Init.MemDataAlignment    = DMA_PDATAALIGN_HALFWORD;     /* 存储器数据传输位宽选择字节,即8bit */   
        g_DMA2_SPI2_handle.Init.Mode                = DMA_NORMAL;              /* 正常模式 */
        g_DMA2_SPI2_handle.Init.Priority            = DMA_PRIORITY_LOW;        /* 优先级低 */
       
        HAL_DMA_DeInit(&g_DMA2_SPI2_handle);
        HAL_DMA_Init(&g_DMA2_SPI2_handle);
       
        __HAL_LINKDMA(&g_SPI2_handle, hdmatx, g_DMA2_SPI2_handle);
       
        // 配置DMA中断
        HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
       
        // 配置SPI中断
        HAL_NVIC_SetPriority(SPI2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(SPI2_IRQn);

        #endif
       

       
       
}

/********************* 复位SPI函数 **********************/
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
{

}

void bsp_InitSPI3_Param(void)
{
       
        /* 设置SPI参数 */
        g_SPI3_handle.Instance                               = SPI3;                                   /* 例化SPI */
        g_SPI3_handle.Init.BaudRatePrescaler                 = SPI_BAUDRATEPRESCALER_4;             /* AHB时钟频率200MHz,4分频以后50MHz */
        g_SPI3_handle.Init.Direction                        = SPI_DIRECTION_2LINES_TXONLY;  /* 仅发送 */
        g_SPI3_handle.Init.CLKPhase                          = SPI_POLARITY_LOW;             /* 配置时钟相位 */
        g_SPI3_handle.Init.CLKPolarity                       = SPI_PHASE_1EDGE;                   /* 配置时钟极性 */
        g_SPI3_handle.Init.DataSize                          = SPI_DATASIZE_16BIT;                       /* 设置数据宽度 */
        g_SPI3_handle.Init.FirstBit                          = SPI_FIRSTBIT_MSB;                 /* 数据传输先传高位 */
        g_SPI3_handle.Init.TIMode                            = SPI_TIMODE_DISABLE;                     /* 禁止TI模式  */
        g_SPI3_handle.Init.CRCCalculation                    = SPI_CRCCALCULATION_DISABLE;         /* 禁止CRC */
        g_SPI3_handle.Init.CRCPolynomial                     = 7;                                       /* 禁止CRC后,此位无效 */
        g_SPI3_handle.Init.CRCLength                         = SPI_CRC_LENGTH_8BIT;                     /* 禁止CRC后,此位无效 */
        g_SPI3_handle.Init.FifoThreshold                     = SPI_FIFO_THRESHOLD_04DATA;        /* 设置FIFO大小是一个数据项 */
       
        g_SPI3_handle.Init.NSS                                         = SPI_NSS_HARD_OUTPUT;                         /* 使用硬件方式管理片选引脚 */
        g_SPI3_handle.Init.NSSPMode                                    = SPI_NSS_PULSE_ENABLE;                            /* 使能脉冲输出 */
        g_SPI3_handle.Init.NSSPolarity                                 = SPI_NSS_POLARITY_LOW;               /* 低电平有效 */
        g_SPI3_handle.Init.MasterSSIdleness                = SPI_MASTER_SS_IDLENESS_00CYCLE;        /* MSS, 插入到NSS有效边沿和第一个数据开始之间的额外延迟,单位SPI时钟周期个数 */
        g_SPI3_handle.Init.MasterInterDataIdleness         = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE; /* MIDI, 两个连续数据帧之间插入的最小时间延迟,单位SPI时钟周期个数 */
       
        g_SPI3_handle.Init.MasterKeepIOState                 = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* 禁止SPI后,SPI相关引脚保持当前状态 */  
        g_SPI3_handle.Init.Mode                                          = SPI_MODE_MASTER;                     /* SPI工作在主控模式 */

        /* 复位配置 */
        if (HAL_SPI_DeInit(&g_SPI3_handle) != HAL_OK)
        {}       

        /* 初始化配置 */
        if (HAL_SPI_Init(&g_SPI3_handle) != HAL_OK)
        {}       
}

/*
*********************************************************************************************************
*        函 数 名: bsp_InitSPIParam
*        功能说明: 配置SPI总线参数,时钟分频,时钟相位和时钟极性。
*        形    参: _BaudRatePrescaler  SPI总线时钟分频设置,支持的参数如下:
*                                 SPI_BAUDRATEPRESCALER_2    2分频
*                                 SPI_BAUDRATEPRESCALER_4    4分频
*                                 SPI_BAUDRATEPRESCALER_8    8分频
*                                 SPI_BAUDRATEPRESCALER_16   16分频
*                                 SPI_BAUDRATEPRESCALER_32   32分频
*                                 SPI_BAUDRATEPRESCALER_64   64分频
*                                 SPI_BAUDRATEPRESCALER_128  128分频
*                                 SPI_BAUDRATEPRESCALER_256  256分频
*                                                        
*             _CLKPhase           时钟相位,支持的参数如下:
*                                 SPI_PHASE_1EDGE     SCK引脚的第1个边沿捕获传输的第1个数据
*                                 SPI_PHASE_2EDGE     SCK引脚的第2个边沿捕获传输的第1个数据
*                                 
*             _CLKPolarity        时钟极性,支持的参数如下:
*                                 SPI_POLARITY_LOW    SCK引脚在空闲状态处于低电平
*                                 SPI_POLARITY_HIGH   SCK引脚在空闲状态处于高电平
*
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitSPI2_Param(void)
{
       
        /* 设置SPI参数 */
        g_SPI2_handle.Instance                               = SPI2;                                   /* 例化SPI */
        g_SPI2_handle.Init.BaudRatePrescaler                 = SPI_BAUDRATEPRESCALER_4;             /* AHB时钟频率200MHz,4分频以后50MHz */
        g_SPI2_handle.Init.Direction                        = SPI_DIRECTION_2LINES_TXONLY;  /* 仅发送 */
        g_SPI2_handle.Init.CLKPhase                          = SPI_POLARITY_LOW;                             /* 配置时钟相位 */
        g_SPI2_handle.Init.CLKPolarity                       = SPI_PHASE_1EDGE;                           /* 配置时钟极性 */
        g_SPI2_handle.Init.DataSize                          = SPI_DATASIZE_16BIT;                       /* 设置数据宽度 */
        g_SPI2_handle.Init.FirstBit                          = SPI_FIRSTBIT_MSB;                 /* 数据传输先传高位 */
        g_SPI2_handle.Init.TIMode                            = SPI_TIMODE_DISABLE;                     /* 禁止TI模式  */
        g_SPI2_handle.Init.CRCCalculation                    = SPI_CRCCALCULATION_DISABLE;         /* 禁止CRC */
        g_SPI2_handle.Init.CRCPolynomial                     = 7;                                       /* 禁止CRC后,此位无效 */
        g_SPI2_handle.Init.CRCLength                         = SPI_CRC_LENGTH_8BIT;                     /* 禁止CRC后,此位无效 */
        g_SPI2_handle.Init.FifoThreshold                     = SPI_FIFO_THRESHOLD_04DATA;        /* 设置FIFO大小是一个数据项 */
       
        g_SPI2_handle.Init.NSS                                         = SPI_NSS_HARD_OUTPUT;                         /* 使用硬件方式管理片选引脚 */
        g_SPI2_handle.Init.NSSPMode                                    = SPI_NSS_PULSE_ENABLE;                            /* 使能脉冲输出 */
        g_SPI2_handle.Init.NSSPolarity                                 = SPI_NSS_POLARITY_LOW;               /* 低电平有效 */
        g_SPI2_handle.Init.MasterSSIdleness                = SPI_MASTER_SS_IDLENESS_00CYCLE;        /* MSS, 插入到NSS有效边沿和第一个数据开始之间的额外延迟,单位SPI时钟周期个数 */
        g_SPI2_handle.Init.MasterInterDataIdleness         = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE; /* MIDI, 两个连续数据帧之间插入的最小时间延迟,单位SPI时钟周期个数 */
       
        g_SPI2_handle.Init.MasterKeepIOState                 = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* 禁止SPI后,SPI相关引脚保持当前状态 */  
        g_SPI2_handle.Init.Mode                                          = SPI_MODE_MASTER;                     /* SPI工作在主控模式 */

                        /* 复位配置 */
        if (HAL_SPI_DeInit(&g_SPI2_handle) != HAL_OK)
        {}       

        /* 初始化配置 */
        if (HAL_SPI_Init(&g_SPI2_handle) != HAL_OK)
        {}       


       
}




void DAC8830_SPI2_init(void)
{
        bsp_InitSPI2_Param();

}



// DAC8830_DAC1写入函数
void DAC8830_DAC1_Write(uint16_t tx_data) {
//    // 拉低CS引脚,选择DAC_8830
       
        HAL_SPI_Transmit_DMA(&g_SPI2_handle, (uint8_t*)&tx_data, 1);
       
}




#if USE_DMA

/**
  * @brief Tx Transfer completed callback.
  * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
  *               the configuration information for SPI module.
  * @retval None
  */
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
        if(hspi->Instance == SPI2) LED0_TOGGLE();
}

/**
  * @brief This function handles SPI2 global interrupt.
  */
void SPI2_IRQHandler(void)
{
        HAL_SPI_IRQHandler(&g_SPI2_handle);
       
}

/**
  * @brief This function handles DMA2 stream3 global interrupt.
  */
void DMA2_Stream3_IRQHandler(void)
{
        HAL_DMA_IRQHandler(&g_DMA2_SPI2_handle);
       
       
}
#endif

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116196
QQ
发表于 前天 07:55 | 显示全部楼层
楼主方便的话,我看下你不使用DMA的正常发送代码,因为没用过这个DAC8830,  这样我就不应查阅这个芯片手册了,直接看下你的DMA配置问题即可-
回复

使用道具 举报

1

主题

1

回帖

4

积分

新手上路

积分
4
 楼主| 发表于 前天 11:26 | 显示全部楼层
eric2013 发表于 2025-6-7 07:55
楼主方便的话,我看下你不使用DMA的正常发送代码,因为没用过这个DAC8830,  这样我就不应查阅这个芯片手册 ...

正常的代码就是把代码中#if USE_DMA下面的部分去掉,因为我实际中用了两个DAC8830,所以使能了两个SPI,SPI2和SPI3,上面的代码有SPI3IO口的使能忘记剔除掉了,忽略即可,下面不使能DMA,spi的正常代码:
/*
*********************************************************************************************************
*        函 数 名: HAL_SPI_MspInit和HAL_SPI_MspDeInit
*        功能说明: 用于SPI底层的初始化和复位初始化
*        形    参: SPI_HandleTypeDef 类型指针变量
*        返 回 值: 无
*********************************************************************************************************
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *_hspi)
{
        GPIO_InitTypeDef  GPIO_InitStruct;
               
        /* SPI和GPIO时钟 */
        SPI2_CLK_ENABLE();
        SPI2_GPIO_CLK_ENABLE();

   
        /* SPI SCK */
        GPIO_InitStruct.Pin               = SPI2_CLK_GPIO_PIN;   
        GPIO_InitStruct.Mode              = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull              = GPIO_PULLUP;
        GPIO_InitStruct.Speed             = GPIO_SPEED_FREQ_MEDIUM;
        GPIO_InitStruct.Alternate         = SPI2_CLK_GPIO_AF;
        HAL_GPIO_Init(SPI2_CS_MOSI_CLK_GPIO_PORT, &GPIO_InitStruct);

        /* SPI MOSI */
        GPIO_InitStruct.Pin                 = SPI2_MOSI_GPIO_PIN;
        GPIO_InitStruct.Alternate         = SPI2_MOSI_GPIO_AF;
        HAL_GPIO_Init(SPI2_CS_MOSI_CLK_GPIO_PORT, &GPIO_InitStruct);
       
        /* SPI NSS */
        GPIO_InitStruct.Pin                 = SPI2_CS_GPIO_PIN;
        //GPIO_InitStruct.Mode                = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Alternate         = SPI2_CS_GPIO_AF;
        HAL_GPIO_Init(SPI2_CS_MOSI_CLK_GPIO_PORT, &GPIO_InitStruct);
       
       
}

/********************* 复位SPI函数 **********************/
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
{

}
void bsp_InitSPI2_Param(void)
{
       
        /* 设置SPI参数 */
        g_SPI2_handle.Instance                               = SPI2;                                   /* 例化SPI */
        g_SPI2_handle.Init.BaudRatePrescaler                 = SPI_BAUDRATEPRESCALER_4;             /* AHB时钟频率200MHz,4分频以后50MHz */
        g_SPI2_handle.Init.Direction                        = SPI_DIRECTION_2LINES_TXONLY;  /* 仅发送 */
        g_SPI2_handle.Init.CLKPhase                          = SPI_POLARITY_LOW;                             /* 配置时钟相位 */
        g_SPI2_handle.Init.CLKPolarity                       = SPI_PHASE_1EDGE;                           /* 配置时钟极性 */
        g_SPI2_handle.Init.DataSize                          = SPI_DATASIZE_16BIT;                       /* 设置数据宽度 */
        g_SPI2_handle.Init.FirstBit                          = SPI_FIRSTBIT_MSB;                 /* 数据传输先传高位 */
        g_SPI2_handle.Init.TIMode                            = SPI_TIMODE_DISABLE;                     /* 禁止TI模式  */
        g_SPI2_handle.Init.CRCCalculation                    = SPI_CRCCALCULATION_DISABLE;         /* 禁止CRC */
        g_SPI2_handle.Init.CRCPolynomial                     = 7;                                       /* 禁止CRC后,此位无效 */
        g_SPI2_handle.Init.CRCLength                         = SPI_CRC_LENGTH_8BIT;                     /* 禁止CRC后,此位无效 */
        g_SPI2_handle.Init.FifoThreshold                     = SPI_FIFO_THRESHOLD_04DATA;        /* 设置FIFO大小是一个数据项 */
       
        g_SPI2_handle.Init.NSS                                         = SPI_NSS_HARD_OUTPUT;                         /* 使用硬件方式管理片选引脚 */
        g_SPI2_handle.Init.NSSPMode                                    = SPI_NSS_PULSE_ENABLE;                            /* 使能脉冲输出 */
        g_SPI2_handle.Init.NSSPolarity                                 = SPI_NSS_POLARITY_LOW;               /* 低电平有效 */
        g_SPI2_handle.Init.MasterSSIdleness                = SPI_MASTER_SS_IDLENESS_00CYCLE;        /* MSS, 插入到NSS有效边沿和第一个数据开始之间的额外延迟,单位SPI时钟周期个数 */
        g_SPI2_handle.Init.MasterInterDataIdleness         = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE; /* MIDI, 两个连续数据帧之间插入的最小时间延迟,单位SPI时钟周期个数 */
       
        g_SPI2_handle.Init.MasterKeepIOState                 = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* 禁止SPI后,SPI相关引脚保持当前状态 */  
        g_SPI2_handle.Init.Mode                                          = SPI_MODE_MASTER;                     /* SPI工作在主控模式 */

                        /* 复位配置 */
        if (HAL_SPI_DeInit(&g_SPI2_handle) != HAL_OK)
        {}       

        /* 初始化配置 */
        if (HAL_SPI_Init(&g_SPI2_handle) != HAL_OK)
        {}       


       
}
void DAC8830_SPI2_init(void)
{
        bsp_InitSPI2_Param();

}

// DAC8830_DAC1写入函数
void DAC8830_DAC1_Write(uint16_t tx_data) {
//    // 拉低CS引脚,选择DAC_8830
       
        HAL_SPI_Transmit_DMA(&g_SPI2_handle, (uint8_t*)&tx_data, 1);
       
}
卡了好几天了,SPI2一加上DMA就不输出,我查看寄存器好像SPI没有产生DMA请求,麻烦了,感谢!
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116196
QQ
发表于 昨天 10:06 | 显示全部楼层
注意下这个问题

STM32H7的SPI DMA配置时,SPI硬件FIFO,DMA突发设置等几个重要注意事项
https://www.armbbs.cn/forum.php? ... 2944&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-6-9 19:11 , Processed in 0.355780 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表