打印
[STM32F0]

STM32F051C8程序为什么卡死在这里了 求大神指教

[复制链接]
1243|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
还我今生|  楼主 | 2016-5-16 14:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序是用SPI2  通过DMA发送数据到外部FLASH

以下是时钟初始化程序
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOF , ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_SPI2 , ENABLE);

以下是IO口初始化
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_0);//SPI NSS   
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0);//SPI NCK  
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_0);//SPI MISO     
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0);//SPI MOSI  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);



以下是SPI2 DMA初始化
        void SPI2_DMA_Configuration( void )
{
       
        DMA_InitTypeDef DMA_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
       
       
        DMA_DeInit(DMA1_Channel4);/* DMA1 Channel4 (triggered by SPI2 Rx event) Config */
        DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_Address;//设置 SPI1 发送外设(0x4001300C) 地址(目的地址)
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_RX_Buff;//设置 SRAM 存储地址(目的地址)
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向 外设-内存
        DMA_InitStructure.DMA_BufferSize =1;//SPI2_ReciveBufferSize;SPI的字节数
        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_Channel4, &DMA_InitStructure);
        DMA_Cmd(DMA1_Channel4, ENABLE);       

       
       
/* DMA1 Channel5 (triggered by SPI2 Tx event) Config */
        DMA_DeInit(DMA1_Channel5);  
        DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_Address;                       //设置  接收外设(0x4001300C) 地址(源地址)
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_TX_Buff;                    //设置 SRAM 存储地址(源地址)
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                //传输方向 内存-外设
        DMA_InitStructure.DMA_BufferSize = 1;//SPI2_SendBufferSize;               //设置 SPI1 接收长度
        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_Channel5, &DMA_InitStructure);




        DMA_Cmd(DMA1_Channel5, ENABLE);                                                  //开启 DMA 通道 DMA1_Channel5
       


//SPI初始化
  SPI_I2S_DeInit(SPI2);                        //SPI初始化//SPI1->CR1复位
        SPI_StructInit(&SPI_InitStructure);     //恢复默认值
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工模式       
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI主机       
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ;//软件nss管理       
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;//这句有啥用
  SPI_Init(SPI2, &SPI_InitStructure);       //SPI参数载入
  
        SPI2->CR2 |= 1<<1  ;                //发送缓冲区DMA使能
        SPI2->CR2 |= 1<<0  ;                //接收缓冲区DMA使能
  
  SPI_Cmd(SPI2, ENABLE);                       //使能SPI
       
       
}

沙发
还我今生|  楼主 | 2016-5-16 14:07 | 只看该作者
问题出在下面这段调用程序
void SPI2_ReceiveSendByte( uint16 num )
{
        u8 retry=0;
        DMA1_Channel4->CNDTR = 0x0000   ;           //传输数量寄存器清零
        DMA1_Channel4->CNDTR = num ;         //传输数量设置为buffersize个

        DMA1_Channel5->CNDTR = 0x0000   ;           //传输数量寄存器清零
        DMA1_Channel5->CNDTR = num ;         //传输数量设置为buffersize个

        DMA1->IFCR = 0xF000 ;                         //清除通道4的标志位
        DMA1->IFCR = 0xF0000 ;                        //清除通道5的标志位
       
       
//while( ( SPI2->SR & 0x02 ) == 0 );          //(SPI2->SR==1)的时候跳出循环 等待SPI发射缓冲区为空       
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
                {
                retry++;
                if(retry>200)return;//重试200次  这样写就会200次跳出循环,不写这段可能会卡在无限循环//用break试试
                }

                DMA1_Channel5->CCR |= 1 << 0 ;              //开启DMA通道5       
                while( ( DMA1->ISR & (1<<17) ) == 0  ); //while( ( DMA1->ISR & 0x20000 ) == 0 );      //DMA1通道5 DMA传输完毕 跳出循环

                DMA1_Channel5->CCR &= ~(1 << 0) ;         //关闭DMA通道5
                retry=0;


//        SPI2->DR ;                                                                                         //接送前读一次SPI1->DR,保证接收缓冲区为空       
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
                {
                retry++;
                if(retry>200)return;//重试200次  这样写就会200次跳出循环,不写这段可能会卡在无限循环//用break试试
                }          
                DMA1_Channel4->CCR |= 1 << 0 ;              //开启DMA通道4               
                while( ( DMA1->ISR & (1<<13) ) == 0  ) ;//while( ( DMA1->ISR & 0x2000 ) == 0 );       //DMA1通道4 DMA传输完毕 跳出循环
                DMA1_Channel4->CCR &= ~( 1 << 0 ) ;         //关闭DMA通道4

}

使用特权

评论回复
板凳
还我今生|  楼主 | 2016-5-16 14:08 | 只看该作者
while( ( DMA1->ISR & (1<<17) ) == 0  );    //DMA1通道5 DMA传输完毕 跳出循环
就是这段永远跳不出来了,相当于传输一直没完成吧。求大神指教!拜谢!

使用特权

评论回复
地板
cnb12345| | 2016-5-16 17:15 | 只看该作者
学习

使用特权

评论回复
5
airwill| | 2016-5-16 18:22 | 只看该作者
不知道你为什么要测试  TCIF 标志?

TCIFx: 通道 x (x = 1 ..5) 传输完成标志
该位由硬件设置。由软件对 DMA_IFCR 寄存器的相应位写1清除。
0: 在通道x上无传输完成 (TC) 的事件发生
1: 在通道x上发生了传输 (TC) 的事件

最好先参考例程, 使用库函数来编程

使用特权

评论回复
6
734774645| | 2016-5-16 22:44 | 只看该作者

那你别死等待啊,弄个倒计时在while里面,比如说1000个计数周期,用逻辑与。

使用特权

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

本版积分规则

217

主题

1381

帖子

1

粉丝