OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5327|回复: 7

新手求助:SPI2怎么使用DMA发送数据

[复制链接]

3

主题

16

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2021-7-11
在线时间
11 小时
发表于 2021-9-27 23:36:03 | 显示全部楼层 |阅读模式
5金钱
我现在不用DMA的话,SPI2是可以用的,但是就是速度太慢了,所以想启用DMA(用来驱动ILI9341)。现在碰到的问题是我DMA配置完之后,屏幕完全没有刷新,用示波器看了SPI的发送端口,发送数据只持续了120uS就停止了。
倒腾了几天没有进展,哪位大佬帮忙看下。
  1. //****************************************************************************
复制代码

  1. //****************************************************************************
复制代码

  1. //****************************************************************************
复制代码












正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2021-7-11
在线时间
11 小时
 楼主| 发表于 2021-9-28 08:12:56 | 显示全部楼层
为什么我的代码贴上来就只有一行***
早上躺床上突然想到了,DMA缓存最大只能设置65535,我设置的缓存超标了。
晚上把这个地方改一下,在测试一遍。
回复

使用道具 举报

6

主题

890

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1477
金钱
1477
注册时间
2020-8-19
在线时间
335 小时
发表于 2021-9-28 09:43:51 | 显示全部楼层
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2021-7-11
在线时间
11 小时
 楼主| 发表于 2021-9-28 23:26:21 | 显示全部楼层
void  SPI2_DMA_TxInit(DspRAMStruct  PicTableStruct)
{
        DMA_InitTypeDef  DMA_InitStruct;
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//        delay_ms(1);
        DMA_DeInit(DMA1_Channel5);
       
//        DMA_InitStruct.DMA_PeripheralBaseAddr = PicTableStruct.PeripheralAddr;                                //设定外设地址
        DMA_InitStruct.DMA_PeripheralBaseAddr = 0x4000380C;                                                                        //设定外设地址
        DMA_InitStruct.DMA_MemoryBaseAddr = PicTableStruct.MemoryAddress;                                        //内存地址       
        DMA_InitStruct.DMA_BufferSize =(u32)PicTableStruct.TxBuffSize;                                                //DMA缓存大小(240*320)
        DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;                                                                                //传输方向:内存到外设
        DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                                //外设地址寄存器不变
        DMA_InitStruct.DMA_MemoryInc = DMA_PeripheralInc_Enable;                                                        //内存地址递增
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;                                //外设数据宽度为8Bit
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                                                //内存数据宽度为8Bit       
        DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;                                                                                        //刷新1次
        DMA_InitStruct.DMA_Priority = DMA_Priority_High;                                                                        //DMA优先级为高
        DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                                                                                        //除能内存到内存传输
        DMA_Init(DMA1_Channel5,&DMA_InitStruct);

        SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);                                                                                //选择 Tx 缓存 DMA 传输请求
                                                                                                                                                                                //选择 Rx 缓存 DMA 传输请求       
       
        DMA_ClearFlag(DMA1_FLAG_TC5);
        DMA_ClearFlag(DMA1_FLAG_TE5);
        DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);                                                                                //传输完成中断
        DMA_ITConfig(DMA1_Channel5,DMA_IT_TE,ENABLE);                                                                                //传输错误中断
}
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2021-7-11
在线时间
11 小时
 楼主| 发表于 2021-9-28 23:34:13 | 显示全部楼层
放弃抵抗了,那个大佬能帮忙看下。在调用TurnONSPI2DMATx后DMA传输报错了(DMA SendData Error TE)。
我在开启DMA之前是先设置好片选端口和数据命令端口,设想是传输完成后再将片选端口拉高。
        LCD_CS_CLR;
        LCD_RS_SET;  
       
//        SPI2_DMA_TxInit(PicSturct);
        TurnONSPI2DMATx();



  1. *********************************************************************************************/
  2. void  SPIModeInit(void)
  3. {
  4.         DspRAMStruct  PicSturct;
  5.        
  6.         SPI_InitTypeDef     SPIInitStatus;                                                                        //定义SPI结构体
  7.         GPIO_InitTypeDef        GPIO_InitStructure;                                                                //定义GPIO初始化结构体
  8.        
  9.        
  10.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);        //配置SPI2管脚
  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  14.         GPIO_Init(GPIOB, &GPIO_InitStructure);

  15.         GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14;   
  16.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  17.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  18.         GPIO_Init(GPIOB, &GPIO_InitStructure);         
  19.         //*********************************************************************
  20.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);                                        //使能SPI时钟
  21.         SPI_I2S_DeInit(SPI2);                                                                                                //恢复SPI为缺省状态
  22.        
  23.         SPIInitStatus.SPI_Direction = SPI_Direction_2Lines_FullDuplex;                //SPI 设置为双线双向全双工
  24.         SPIInitStatus.SPI_Mode = SPI_Mode_Master;                                                        //设置为SPI主机
  25.         SPIInitStatus.SPI_DataSize = SPI_DataSize_8b;                                                //收发数据为8位
  26.         SPIInitStatus.SPI_CPOL = SPI_CPOL_Low;                                                                //时钟悬空低
  27.         SPIInitStatus.SPI_CPHA = SPI_CPHA_1Edge;                                                        //数据捕获于第一个时钟沿,即上升沿
  28.         SPIInitStatus.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;                //波特率预分频值为2
  29.         SPIInitStatus.SPI_NSS = SPI_NSS_Soft;                                                                //内部NSS信号由SSI位控制
  30.         SPIInitStatus.SPI_FirstBit = SPI_FirstBit_MSB;                                                //数据传输从高位开始
  31.         SPIInitStatus.SPI_CRCPolynomial = 7;
  32.         SPI_Init(SPI2,&SPIInitStatus);                                                                                //初始化SPI接口

  33.         SPI_Cmd(SPI2,ENABLE);                                                                                                //使能 SPI
  34.         //*********************************************************************       
  35. //        SPI_SetSpeed(SPI2,1);
  36.         //*********************************************************************               
  37.         DMA1_NVIC_Config();
  38.        
  39.         PicSturct.MemoryAddress = (u32)&gImage_Pic4;
  40.         PicSturct.PeripheralAddr = (u32)&SPI2->DR;                                //#define SPI2_BASE     (APB2PERIPH_BASE + 0x3800)
  41.                                                                                                                         //0x0C 对应SPI_DR地址
  42.         PicSturct.TxBuffSize = 65500;
  43.         PicSturct.DataSizeType = DMA_MemoryDataSize_Byte;                //数据宽度8Bit
  44.         PicSturct.RefreshMode = DMA_Mode_Normal;
  45.         SPI2_DMA_TxInit(PicSturct);
  46.         //*********************************************************************               
  47. }
  48. //****************************************************************************
复制代码

  1. //****************************************************************************
  2. void  SPI2_DMA_TxInit(DspRAMStruct  PicTableStruct)
  3. {
  4.         DMA_InitTypeDef  DMA_InitStruct;
  5.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  6. //        delay_ms(1);
  7.         DMA_DeInit(DMA1_Channel5);
  8.        
  9. //        DMA_InitStruct.DMA_PeripheralBaseAddr = PicTableStruct.PeripheralAddr;                                //设定外设地址
  10.         DMA_InitStruct.DMA_PeripheralBaseAddr = 0x4000380C;                                                                        //设定外设地址
  11.         DMA_InitStruct.DMA_MemoryBaseAddr = (u32)PicTableStruct.MemoryAddress;                                        //内存地址       
  12.         DMA_InitStruct.DMA_BufferSize =(u32)PicTableStruct.TxBuffSize;                                                //DMA缓存大小(240*320)
  13.         DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;                                                                                //传输方向:内存到外设
  14.         DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                                                //外设地址寄存器不变
  15.         DMA_InitStruct.DMA_MemoryInc = DMA_PeripheralInc_Enable;                                                        //内存地址递增
  16.         DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;                                //外设数据宽度为8Bit
  17.         DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                                                //内存数据宽度为8Bit       
  18.         DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;                                                                                        //刷新1次
  19.         DMA_InitStruct.DMA_Priority = DMA_Priority_High;                                                                        //DMA优先级为高
  20.         DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;                                                                                        //除能内存到内存传输
  21.         DMA_Init(DMA1_Channel5,&DMA_InitStruct);

  22.         SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);                                                                                //选择 Tx 缓存 DMA 传输请求
  23.                                                                                                                                                                                 //选择 Rx 缓存 DMA 传输请求       
  24.        
  25.         DMA_ClearFlag(DMA1_FLAG_TC5);
  26.         DMA_ClearFlag(DMA1_FLAG_TE5);
  27.         DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);                                                                                //传输完成中断
  28.         DMA_ITConfig(DMA1_Channel5,DMA_IT_TE,ENABLE);                                                                                //传输错误中断
  29. }
  30. //****************************************************************************



  31. //****************************************************************************
  32. void  TurnONSPI2DMATx(void)
  33. {
  34. //        DMA_Cmd(DMA1_Channel5,DISABLE);
  35. //    DMA1_Channel5->CNDTR=65500;                         //设置要传输的数据长度
  36. //    DMA1_Channel5->CMAR=(u32)&gImage_Pic4;         //设置RAM缓冲区地址

  37. //        SPI2->CR2 |= 1<<1;
  38.         DMA_Cmd(DMA1_Channel5,ENABLE);
  39. }
  40. //****************************************************************************
复制代码

  1. //****************************************************************************
  2. void DMA1_Channel5_IRQHandler(void)
  3. {
  4.         if(DMA_GetFlagStatus(DMA1_FLAG_TC5) == SET)
  5.         {
  6.                 printf("\r\nDMA SendData Over\r\n");

  7.                 DMA_ClearFlag(DMA1_FLAG_TC5);
  8.                 LCD_CS_SET;                        //传输完成后将片选脚拉高
  9.         }
  10.        
  11.         if(DMA_GetFlagStatus(DMA1_FLAG_TE5) == SET)
  12.         {
  13.                 printf("\r\nDMA SendData Error TE \r\n");

  14.                 DMA_ClearFlag(DMA1_FLAG_TE5);               
  15.         }
  16.        
  17.         if(DMA_GetFlagStatus(DMA1_FLAG_GL5) == SET)
  18.         {
  19.                 DMA_ClearFlag(DMA1_FLAG_GL5);
  20.         }       
  21.        
  22.         if(DMA_GetFlagStatus(DMA1_FLAG_HT5) == SET)
  23.         {
  24.                 DMA_ClearFlag(DMA1_FLAG_HT5);
  25.         }       
  26.        
  27.        
  28. }
  29. //****************************************************************************
复制代码
回复

使用道具 举报

3

主题

16

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2021-7-11
在线时间
11 小时
 楼主| 发表于 2021-9-28 23:36:08 | 显示全部楼层
bin133 发表于 2021-9-28 09:43
配置可以看看这个https://www.cnblogs.com/ctu11/p/11510481.html

感谢回复,你这个是完全操作寄存器的了。我对比了下我的配置流程,也没有发现问题啊,要哭了
回复

使用道具 举报

0

主题

8

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2020-3-12
在线时间
7 小时
发表于 2022-2-25 14:09:40 | 显示全部楼层
我看了你的关于spi的发帖  我想咨询一下关于spi的 dma操作,
回复

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2020-12-8
在线时间
9 小时
发表于 2022-3-7 18:32:03 | 显示全部楼层
兄弟你搞好了么,我也在弄这个
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-28 03:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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