打印
[STM32F1]

用DMA实现SPI通信进不了DMA中断

[复制链接]
2676|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wenqin1002|  楼主 | 2014-4-11 09:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 airwill 于 2014-4-11 20:44 编辑

我的配置如下,为什么程序进不了DMA中断呢,设置buffersize大小为6,调试中监控DMA通道2和通道3的剩余数据数目一直为6
#define SPI1_DR_Addr ( (u32)0x40013000 )
u16 ReceivedD[6] = {0,0,0,0,0,0};
u16 SendD[6] = {0,0,0,0,0,0};
/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
  ErrorStatus HSEStartUpStatus;
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();                                                                                                //时钟控制寄存器全部恢复默认值
  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);                                                                //外部高速时钟源开启(8M晶振)
  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();                                //等待外部时钟就绪
  if(HSEStartUpStatus == SUCCESS)                                                        //如果时钟启动成功
  {
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                //定义AHB设备时钟为系统时钟1分频
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1);                                                        //定义APB2设备时钟为HCLK时钟1分频
    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);                                                        //定义APB1设备时钟为HCLK时钟2分频
    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);                                                //设定内部FLASH的的延时周期为2周期
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);        //使能FLASH预存取缓冲区
    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);        //配置PLL时钟为外部高速时钟的9倍频,8MHz * 9 = 72 MHz
    /* Enable PLL */
    RCC_PLLCmd(ENABLE);                                                                                //使能PLL时钟
    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)                //等待PLL时钟设置完成准备就绪
    {
    }
    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                //使用PLL时钟作为系统时钟源
    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)                                        //返回系统所用时钟源确认为外部高速晶振,8M晶振。
    {
    }
  }
  /* 设备时钟控制 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                //使能由APB2时钟控制的PB端口
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 , ENABLE);
         /* 设备时钟控制 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                //使能由APB2时钟控制的PA端?
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5 , ENABLE);
        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);                //使能SPI1
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  
}                                                                                                                        //使能由APB1时钟控制的TIM2、TIM3端口

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

   /*配置LED对应位IO口*/
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6 | GPIO_Pin_7;                  //选择IO端口的第6和第7位
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                          //时钟速度为50M
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                          //端口模式为输入方?
        GPIO_Init(GPIOB, &GPIO_InitStructure);                                          //用以上几个参数初始化PC口
          GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_1;                  //选择IO端口的第6和第7位
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                          //时钟速度为50M
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                          //端口模式为输入方式?
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                          //用以上几个参数初始化PC口
        
        /* 配置SPI1引脚配置: SCK, MISO and MOSI ---------------------------------*/
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;         //IO端口第6位
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                   //端口模式为推免复用输出方式
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);                                                   //用以上几个参数初始化PA口
        
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;         //IO端口的第4位
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                          //端口模式为输入方?
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                                   //用以上几个参数初始化PA口

//GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_TIM4);
//GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_TIM4);
}


                                          
/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures NVIC.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 选择中断分组 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                                 //选择中断分组2(主优先级2位,从优先级2位)
  
  /* 配置TIM4中断线 */
  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;                             //选择定时器4中断线
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;                 //主优先级为0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                         //从优先级为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                 //使能中断通道
  NVIC_Init(&NVIC_InitStructure);                                                                 //用以上参数初始化TIM4

/* 配置TIM5中断线 */
  NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;                             //选择定时器4中断线
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;                 //主优先级为1
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                         //从优先级为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                 //使能中断通道
  NVIC_Init(&NVIC_InitStructure);                                                                 //用以上参数初始化TIM5
        
        
        /*配置SPI1通接收中断*/
  NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;                             //SPI1接收中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;                 //主优先级为2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                         //从优先级为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                 //使能中断通道
  NVIC_Init(&NVIC_InitStructure);                                                                 //用以上参数初始化TIM5
        
        /*配置DAM中断*/
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;                             //DMA通道2中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;                 //主优先级为2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                         //从优先级为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                 //使能中断通道
  NVIC_Init(&NVIC_InitStructure);                                                                 //用以上参数初始化TIM5
                /*配置DAM中断*/
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;                             //DMA通道3中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;                 //主优先级为2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                         //从优先级为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                 //使能中断通道
  NVIC_Init(&NVIC_InitStructure);                                                                 //用以上参数初始化TIM5
        
}

/*******************************************************************************
* Function Name  : TIM_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void TIM_Configuration(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;
  
  /* TIM4 configuration */
        TIM_DeInit(TIM4);
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;                            //设置定时器重载值,计算时应加1
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;                         //无分频,计算时应加1
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;                      //时钟分割,用于滤波器
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //选择向上计数模式
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;                  //重载次数计数器,计数到0便产生中断事件
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);                          //以上参数初始化TIM4
        TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);                          //以上参数初始化TIM8
  
  TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);        //编码器接口初始化
        TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = 6; //6
  TIM_ICInit(TIM4, &TIM_ICInitStructure);
// Clear all pending interrupts
  TIM_ClearFlag(TIM4, TIM_FLAG_Update);
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
  //Reset counter
  TIM4->CNT = 0;   //0
  TIM_Cmd(TIM4, ENABLE);                //使能TIM4
        
        TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);        //编码器接口初始化
        TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = 6; //6
  TIM_ICInit(TIM5, &TIM_ICInitStructure);
// Clear all pending interrupts
  TIM_ClearFlag(TIM5, TIM_FLAG_Update);
  TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
  //Reset counter
  TIM5->CNT = 0;   //0
  TIM_Cmd(TIM5, ENABLE);                //使能TIM5

  TIM_ClearFlag(TIM4, TIM_FLAG_Update);                                                  //清除更新事件标志位(防止启动便中断)
  
  /* 开中断 */
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);                                  //打开重载更新中断
        
  TIM_ClearFlag(TIM5, TIM_FLAG_Update);                                                  //清除更新事件标志位(防止启动便中断)
  
  /* 开中断 */
  TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);                                  //打开重载更新中断

  
  

}


/*******************************************************************************
* Function Name  : SPI_Configuration
* Description    : Configures the SPI.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_Configuration(void)
{
  SPI_InitTypeDef SPI_InitStructure;
  /* SPI1 Config -------------------------------------------------------------*/
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置为双向双线全双工
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;                                                 //从模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;                                         //16位数据格式
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                                                 //SCK在空闲时为低电平
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                                                 //在SCK时钟的第一个边沿接收数据
  SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;                                                         //NSS硬件控制模式
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //总线时钟8分频为SPI时钟,72/8=9
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                 //传输数据低位在前
  SPI_InitStructure.SPI_CRCPolynomial = 7;                                                         //CRC7校验
  SPI_Init(SPI1, &SPI_InitStructure);                                                                 //用以上参数初始化SPI1
  /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);                                                                                         //打开SPI1
  
        //SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);        //使能SPI1接收中断
//SPI_ClearITPendingBit(SPI1,SPI_I2S_IT_RXNE);          //清除中断标志位
   
}

/*******************************************************************************
2 * Function Name  : SPI1_DMA_Configuration
3 * Description    : ??SPI1_RX?DMA??2,SPI1_TX?DMA??3
4 * Input          : None
5 * Output         : None
6 * Return         : None
7 * Attention             :
8 *******************************************************************************/
void SPI1_DMA_Configuration(void)
{

DMA_InitTypeDef DMA_InitStructure;
   
   /* DMA1 Channel2 (triggered by SPI1 Rx event) Config */
DMA_DeInit(DMA1_Channel2);  
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;                          
// DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SRC_Buffer;                    
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceivedD;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                
DMA_InitStructure.DMA_BufferSize = buffersize;                        
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //接收一次数据后,设备地址禁止后移
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 //内存地址允许后移
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;     //数据宽度16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;             //工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);            //不设置为内存到内存传输
  
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);           //开启接收完成中断
  /* Enable SPI1 DMA RX request */
//SPI1->CR2 |= 1<<0;                                                                 //接收缓冲区DMA使能
DMA1_Channel2->CCR |= 1 << 0 ;               //开启DMA通道2
DMA_Cmd(DMA1_Channel2, ENABLE);        
CurrdataCounter=DMA_GetCurrDataCounter(DMA1_Channel2);
   
/* DMA1 Channel3 (triggered by SPI1 Tx event) Config */
DMA_DeInit(DMA1_Channel3);   
//DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;                          //SPI地址(0x40013000)
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Addr;  
// DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DST_Buffer;                    //?? SRAM ????(???)
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendD;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                              
DMA_InitStructure.DMA_BufferSize = buffersize;                           //?? SPI1数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                  
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                           
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;           
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                   //16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                    
DMA_InitStructure.DMA_Priority = DMA_Priority_High;                           
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                    
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
  
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);                                   //开启发送完成中断
//DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE);                                   //开启发送错误中断
/* Enable SPI1 DMA TX request */
//SPI1->CR2 |= 1<<1;                                                                //发送缓冲区DMA使能
DMA1_Channel3->CCR |= 1 << 0 ;               //开启DMA通道3
DMA_Cmd(DMA1_Channel3, ENABLE);                                                  //使能DMA
}


/*******************************************************************************
* Function Name  : TIM4_IRQHandler
* Description    : TIM4 interrupt.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/

void TIM4_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {
                TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
                if(TIM4->CR1 & 0x0010)
                        CNT1_High16 --;
                else
                        CNT1_High16++;
        }
        
}


/*******************************************************************************
* Function Name  : TIM5_IRQHandler
* Description    : TIM5 interrupt.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/

void TIM5_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM5, TIM_IT_Update) == SET)
        {
                TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
                if(TIM5->CR1 & 0x0010)
                        CNT2_High16 --;
                else
                        CNT2_High16 ++;
        }
        
}

/*******************************************************************************
* Function Name  : SPI1_IRQnHandler
* Description    : SPI1 interrupt.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI1_IRQnHandler(void)
{
        
                                                                        
        if( SPI_I2S_GetITStatus( SPI1, SPI_I2S_IT_RXNE ) == RESET )          //接收数据
        {                                                         
                ReceivedD[spicount] = SPI_I2S_ReceiveData(SPI1);
                spicount++;
        }  
       if( spicount >= 6 )
        {
                spicount = 0;
        }                                
       //SPI_ClearITPendingBit(SPI1,SPI_I2S_IT_RXNE);            
}

/*******************************************************************************
* Function Name  : DMA1_Channel2_IRQn
* Description    : DMA1 interrupt.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void DMA1_Channel2_IRQnHandler(void)
{
  /*u8 i=0;
        for(i=0;i<6;i++)
        {
         SPI_I2S_SendData(SPI1,SendD);
        }*/
        DMA_ClearITPendingBit(DMA1_IT_TC2);          /*清除DMA全局中断挂起标志*/
}

/*******************************************************************************
* Function Name  : DMA1_Channel2_IRQn
* Description    : DMA1 interrupt.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void DMA1_Channel3_IRQnHandler(void)
{
/* u8 i=0;
        for(i=0;i<6;i++)
        {
         ReceivedD = SPI_I2S_ReceiveData(SPI1);
        }*/
        DMA_ClearITPendingBit(DMA1_IT_TC3);          /*清除DMA全局中断挂起标志*/
}
沙发
airwill| | 2014-4-12 12:24 | 只看该作者
SPI_Mode_Slave 这样的传输是被动的, 总线上有没有主机给目标板发数据呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

13

帖子

0

粉丝