OpenEdv-开源电子网

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

STM32F1 SPI DMA方式 发送完自动进入接收中断 不知道为何原因 找不出来来 求帮助

[复制链接]

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
发表于 2017-11-27 17:29:10 | 显示全部楼层 |阅读模式
10金钱
配置完SPI和DMA了,主发从,能接到,但是主机在发完进入完发送中断后,会立刻进入主机的接收中断,尽管从机没有数据发送回来,我做了实验排除了几个问题,从机是没有发送数据回来的,我直接把线拔了,也把接收缓存用串口显示,也没有数据,我把开发板的所有线拔了,排除外部干扰,我做了延时发送,排除初始化完立刻进入中断的可能,也就是说,我是在主机发送完之后,主机立刻进入的接收中断

#define SPI1_Tx_Buf_number 10
#define SPI1_Rx_Buf_number 10



[mw_shl_code=c,true]
int main(void)
{
       
/********************************Ïμí3ê±ÖóÅäÖÃ***********************************************/       
        SystemInit();
        Delay_Ms(1000);
       
/******************************½ûóÃJTAGμ÷êÔÅäÖÃ*********************************************/
        DISABLE_JTAG();      
       
/****************************3õê¼»ˉÖD¶ÏÏò῱íÅäÖÃ*******************************************/       
        Init_NVIC();               
       
/**********************************IO¿úÅäÖÃ*************************************************/       
        Init_IO();                         //°åÔØLED 3õê¼»ˉ
       
/***************************UART1′®¿úIO¿ú3õê¼»ˉÅäÖÃ*****************************************/       
        Init_Usart1();                                                  //óÃóúμ÷êÔ′®¿ú′òó¡êy¾Y
        Usart1_Configuration(115200);         
       
        Init_SPI_IO();
        Init_SPI1();
        Init_SPI1_DMA();
        Delay_Ms(200);
/*==============================================================================================================================*/       

        while(1)
        {
                main_temp_a++;
                SPI1_Tx_Buf[0]=(u8)main_temp_a;
                SPI1_Tx_Buf[1]=0x12;
                SPI1_Tx_Buf[2]=0x12;
                DMA_SPI1_Send_Data(SPI1_Tx_Buf_number);
                printf("%d\n\n",main_temp_b);
                for(main_temp_i=0;main_temp_i<SPI1_Rx_Buf_number;main_temp_i++)
                {
                        printf("%2x ",SPI1_Rx_Buf[main_temp_i]);
                }
                printf("\n\n");
                Delay_Ms(500);
        }        //while(1)
}         //main       
[/mw_shl_code]



[mw_shl_code=c,true]
void Init_NVIC(void)
{        
        NVIC_InitTypeDef NVIC_InitStructure;                        //定义一个NVIC向量表结构体变量

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //设置中断组 为2
  
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                                //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器
       
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;                                //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器
       
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;                                //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器
       
}

void Init_IO(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;                                                                                                                //定义一个GPIO结构体变量
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);                                                //使能各个端口时钟,重要!!!
       
  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2;                      //LED               
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                                           //通用输出推挽
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                                           //配置端口速度为50M
  GPIO_Init(GPIOD, &GPIO_InitStructure);                                                                                                   //根据参数初始化GPIOD寄存器
       
}
[/mw_shl_code]


[mw_shl_code=c,true]#include "DMA_SPI1.h"



void Init_SPI_IO(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;                                                                                                                                                                //GPIO初始化结构体
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);                        //GPIO、AFIO时钟使能
               
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                                                                                                                       
  GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                                                                                                        //将SCK和MOSI管脚设置为复用推挽输出   
  GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                                                                                                        //将SCK和MOSI管脚设置为复用推挽输出   
  GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                                                                                                        //将SCK和MOSI管脚设置为复用推挽输出   
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void Init_SPI1(void)
{
        SPI_InitTypeDef  SPI_InitStructure;                                                                                                                                                                                                //SPI初始化结构体
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);                                                                                                        //使能SPI2时钟
       
  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(SPI1, &SPI_InitStructure);
        SPI_Cmd(SPI1, ENABLE);
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);                       
        SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);                                                               
}


void Init_SPI1_DMA(void)
{
        extern u8 SPI1_Tx_Buf[SPI1_Tx_Buf_number];     
        extern u8 SPI1_Rx_Buf[SPI1_Rx_Buf_number];  
       
        DMA_InitTypeDef  DMA_InitStructure;                                                                                                                                                        //DMA初始化结构体
  
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);                                                                                                //使能DMA1时钟
       
        DMA_DeInit(DMA1_Channel3);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI1->DR));
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SPI1_Tx_Buf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = SPI1_Tx_Buf_number;
        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_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel3, &DMA_InitStructure);
  DMA_ClearFlag(DMA1_FLAG_GL3);                                 // 清除DMA所有标志
        DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);                                                                        //使能DMA1通道5中断,注意一定要是“DMA_IT_TC”,否则会出现进不了中断的问题。               
       
        DMA_DeInit(DMA1_Channel2);
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI1->DR));
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SPI1_Rx_Buf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = SPI1_Rx_Buf_number;
        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_Channel2, &DMA_InitStructure);
  DMA_ClearFlag(DMA1_FLAG_GL2);                                 // 清除DMA所有标志
        DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);                                                                        //使能DMA1通道5中断,注意一定要是“DMA_IT_TC”,否则会出现进不了中断的问题。
        DMA_Cmd(DMA1_Channel2, ENABLE);
}

void DMA1_Channel2_IRQHandler(void)
{
        extern u8 main_temp_b;
       
        main_temp_b++;
        if(DMA_GetITStatus(DMA1_IT_TC2)==SET)
        {
                //DMA1_Channel2->CNDTR =SPI1_Rx_Buf_number;
    //DMA_Cmd(DMA1_Channel2,DISABLE);
                DMA_Cmd(DMA1_Channel2,ENABLE);
                DMA_ClearITPendingBit(DMA1_IT_TC2);
        }
}

void DMA1_Channel3_IRQHandler(void)
{
  if(DMA_GetITStatus(DMA1_FLAG_TC3))
        {
    DMA_Cmd(DMA1_Channel3,DISABLE);
                DMA_ClearFlag(DMA1_FLAG_GL3);         // 清除标志
        }
}


void DMA_SPI1_Send_Data(u32 size)
{
  DMA1_Channel3->CNDTR =size;
  DMA_Cmd(DMA1_Channel3, ENABLE);        
}




[/mw_shl_code]



最佳答案

查看完整内容[请看2#楼]

因为发一个数据,就肯定会收到一个数据。所以不管你怎么搞,都会进入。 最好就别开这个中断。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2017-11-27 17:29:11 | 显示全部楼层
因为发一个数据,就肯定会收到一个数据。所以不管你怎么搞,都会进入。  最好就别开这个中断。
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 09:59:16 | 显示全部楼层
正点原子 发表于 2017-11-27 17:29
因为发一个数据,就肯定会收到一个数据。所以不管你怎么搞,都会进入。  最好就别开这个中断。

我主机发送端发送一个数据    在发送端进入接收中断哦   不是在接收端进入的接收中断哦   但是只有第一次发送数据才会进入接收中断哦    是主机发送,主机进入接收中断,只有第一次会这样
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 10:01:16 | 显示全部楼层
正点原子 发表于 2017-11-27 17:29
因为发一个数据,就肯定会收到一个数据。所以不管你怎么搞,都会进入。  最好就别开这个中断。

原子哥  求助啊   查了很多百度    没人有这样的情况   帮忙查错   第一次用SPI的DMA模式  我之前是用UART的DMA模式的   没问题   用到SPI上就有这样的错了
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 10:29:42 | 显示全部楼层
换了SPI2也一样    第一次主机发送完后,立即进入主机的接收中断,我把所有外设都拔了的哦,但是只有第一次发送完才会进入接收中断,后面的发送就不会了
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 10:40:37 | 显示全部楼层
刚刚又调出了一个线索了,我主机发送完后,打印DMA的接收缓存发现里面有发送的数据
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 10:54:40 | 显示全部楼层
意思就是我  主机发送数据,主机能够立即接收到发送的数据  但是硬件中没有连接的,应该是软件没有配置好,但是只有第一次会这样,从机能够接收到此数据,但是主机不应该接收到的啊
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2017-11-28 10:59:36 | 显示全部楼层
aa27838955 发表于 2017-11-28 10:54
意思就是我  主机发送数据,主机能够立即接收到发送的数据  但是硬件中没有连接的,应该是软件没有配置好, ...

没解决怎么结贴了.
自己选择的路,成家前走完。
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 11:10:05 | 显示全部楼层
aiyeba 发表于 2017-11-28 10:59
没解决怎么结贴了.

。。。。。我没按结帖啊   我的天
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 11:10:53 | 显示全部楼层
aiyeba 发表于 2017-11-28 10:59
没解决怎么结贴了.

兄弟,能否帮忙看下小弟的错误所在
回复

使用道具 举报

28

主题

133

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
323
金钱
323
注册时间
2016-11-22
在线时间
66 小时
发表于 2017-11-28 14:40:38 | 显示全部楼层
朋友你基础还不够扎实呀,去认真了解一下SPI的通信过程,和DMA工作的整个过程,你就不会有这么多问题了。不要浮躁,一步一步来。
回复

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
38
金钱
38
注册时间
2017-11-7
在线时间
6 小时
 楼主| 发表于 2017-11-28 18:07:23 | 显示全部楼层
ARM学员 发表于 2017-11-28 14:40
朋友你基础还不够扎实呀,去认真了解一下SPI的通信过程,和DMA工作的整个过程,你就不会有这么多问题了。不 ...

兄弟  能否指出我的错误  还是说这是正常的   主机发送数据 主机会自动进入接收中断
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2020-2-10
在线时间
2 小时
发表于 2020-2-11 01:44:35 | 显示全部楼层
2楼已给出答案了:SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ;
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-20 13:18

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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