野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15333|回复: 8

F4定时器的诡异情况

[复制链接]
发表于 2017-3-8 17:14:59 | 显示全部楼层 |阅读模式
100火花
我最近在写定时器使能SPI-DMA传输的实验,一开始测PWM信号频率和脉宽都没有错误,但是SPI数据总是会在中间出现那么几个错误的,经过调试发现是定时器有时进中断不及时导致后面传输的数据错位了,下面贴上定时器的配置代码,用的是100K的PWM频率,请大神帮忙看看

//配置定时器中断,在中断中使能SPI1-TX-DMA 触发SPI1SCLK时钟信号
void TIM_NVIC_Config(void)
{
    NVIC_InitTypeDef    NVIC_InitStructure;
    //设置中断组为0
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    //设置中断源
    NVIC_InitStructure.NVIC_IRQChannel                                         = TIM8_UP_TIM13_IRQn;
    //设置抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    =    0;
    //设置子优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority                 = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd                                 = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/**
    * period  :设置30以1MHz采样,
    *                        设置300以100KHz采样,
    *                        设置3000以10KHz采样,
    *                        设置30000以1KHz采样
    *                        默认采用100KHz采样
    **/
void TIM1_Init(u16 period)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
   
    TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
    TIM_OCInitTypeDef    TIM_OCInitStructure;
   
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);
   
    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode     = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed    =    GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd    =    GPIO_PuPd_UP;
    GPIO_Init(GPIOC,&GPIO_InitStructure);
   
    GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM8);
   
    TIM_TimeBaseStructure.TIM_ClockDivision         = TIM_CKD_DIV1;            //时钟分频
    TIM_TimeBaseStructure.TIM_CounterMode             = TIM_CounterMode_Up;    //计数模式向上计数
    TIM_TimeBaseStructure.TIM_Prescaler                 = 6-1;                                    //Timer Clock = 180 / (TIM_Prescaler + 1) = 30M
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;                        //重复计数器,计数器产生TIM_RetitionCounter+1次置位时产生一次中断,这里一次PWM进一次中断
    TIM_TimeBaseStructure.TIM_Period                         = period - 1;                            //定时器周期,即设定自动重载值
    TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);
   
    TIM_OCInitStructure.TIM_OCMode                             = TIM_OCMode_PWM2;                        //PWM2为反相占空比模式
    TIM_OCInitStructure.TIM_OutputState                 = TIM_OutputState_Enable;    //TIM8_CH1输出使能
    TIM_OCInitStructure.TIM_OutputNState                 = TIM_OutputNState_Disable;    //TIM8_CH1N不使能
    TIM_OCInitStructure.TIM_OCPolarity                     = TIM_OCPolarity_High;            //高电平有效
    TIM_OCInitStructure.TIM_OCNPolarity                 = TIM_OCNPolarity_High;    //输出反相TIM_OCNPolarity_Low;//输出同相
    TIM_OCInitStructure.TIM_OCIdleState                 = TIM_OCIdleState_Set;    //空闲状态是通道输出电平
    TIM_OCInitStructure.TIM_OCNIdleState                 = TIM_OCNIdleState_Reset;
   
    TIM_OCInitStructure.TIM_Pulse                             = period*2/3;                //PC6作为AD的convst信号
    TIM_OC1Init(TIM8,&TIM_OCInitStructure);
   
   
        // 清除定时器更新中断标志位
    TIM_ClearFlag(TIM8, TIM_FLAG_Update);
   
    // 开启定时器更新中断
    TIM_ITConfig(TIM8,TIM_IT_Update,ENABLE);
    TIM_Cmd(TIM8,ENABLE);
    TIM_CtrlPWMOutputs(TIM8,ENABLE);
   
}

void  TIM8_UP_TIM13_IRQHandler (void)
{
    static    uint32_t time;
    SPI_AD7608_CS_HIGH();
    if ( TIM_GetITStatus( TIM8, TIM_IT_Update) != RESET )
    {   
        
        DMA_ClearITPendingBit(DMA2_Stream3,DMA_IT_TCIF3);   //清除DMA2_Stream3中断标记位
        DMA_Cmd(DMA2_Stream3,ENABLE);                     //使能DMA2_Stream3
        SPI_DMACmd(SPI1,SPI_DMAReq_Tx,ENABLE);          //使能SPI_TX DMA
        TIM_ClearITPendingBit(TIM8 , TIM_IT_Update);           //清除定时器中断标记位
        SPI_AD7608_CS_LOW();
    }            
}

下面是测得的PWM信号波形
PWM.jpg

下面是测得的CS脚波形
CS.jpg

回复

使用道具 举报

发表于 2017-3-8 18:35:31 | 显示全部楼层
IO是不是有用到其他的外设上,换一个纯净的IO。
回复

使用道具 举报

发表于 2017-3-8 18:39:05 | 显示全部楼层
不用DMA 不在中断设置,直接用spi正常嘛?
回复

使用道具 举报

 楼主| 发表于 2017-3-8 19:45:21 | 显示全部楼层
fire 发表于 2017-3-8 18:35
IO是不是有用到其他的外设上,换一个纯净的IO。

没有,这个IO什么也没接,也没有其他地方用到,初始化后就中断里面拉高拉低,外设SPI的CS脚直接接地,没有接芯片上
回复

使用道具 举报

 楼主| 发表于 2017-3-8 19:49:54 | 显示全部楼层
flyleaf 发表于 2017-3-8 18:39
不用DMA 不在中断设置,直接用spi正常嘛?

不再中断里不论用不用DMA SPI都正常,定时器中断什么都不写,只剩控制IO拉高拉低也是会出现进中断异常,算较长时间进中断次数是正确的
回复

使用道具 举报

 楼主| 发表于 2017-3-9 11:57:22 | 显示全部楼层
测试了只跑裸机不跑UCOS,进中断就正常,一跑UCOS,定时器进中断就会出现前面所说的情况,有没有大神对UCOS和定时器还有中断了解比较深的帮忙分析下原因
回复

使用道具 举报

 楼主| 发表于 2017-5-9 15:16:52 | 显示全部楼层
搞了一半手头有另外的项目去做了其它项目,现在回来重新调了后发现了问题所在,都是SDRAM惹的祸,当配置成自动分配变量到SDRAM的时候,进入定时器中断就会出现这种情况,中断越频繁现象会越明显,需要把配置成默认分配变量到内部SRAM,指定的再分配到SDRAM,减少对SDRAM的读写就不会出现了,至于还有没有其它更好的解决方法目前还没有找到,希望看到的大神们能多提提建议
回复

使用道具 举报

发表于 2017-5-10 20:30:44 | 显示全部楼层
能自己发现错误,厉害厉害
回复

使用道具 举报

 楼主| 发表于 2017-5-17 16:32:24 | 显示全部楼层
陈加勇 发表于 2017-5-10 20:30
能自己发现错误,厉害厉害

都是调试偶然发现的
回复

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-2 05:34 , Processed in 0.048315 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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