打印

STM32F103生成方波问题求教

[复制链接]
9213|72
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lixiaofengntsc|  楼主 | 2021-8-2 10:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近使用STM32F103RB做了个小东西,其中需要输出一路频率大约在1Hz左右的方波信号。我使用定时器3来产生,配置好定时器后,在中断里面使一个IO口的电平翻转,从而产生方波。但产生的方波总是会断一下,就是时不时电平就少翻转一次,即总是有连续两个的高电平或者连续连个的低电平。我在中断里面放了一个变量,发现每次中断是能进去的,方波断的地方是电平该翻转没有翻转。翻转电平的语句我也试几种,用变量判断,或者直接该位取反,都试过了,都是这个问题。IO口配置的是推挽输出,50MHz频率。请教各位有没有遇到过类似问题,或者帮我分析一下可能是什么原因,还能做什么测试?谢谢。

使用特权

评论回复
沙发
呐咯密密| | 2021-8-2 15:34 | 只看该作者
按道理说这个不该有问题的,你的逻辑没问题,考虑贴个代码给我们看看,包括定时器的初始化,中断处理函数,如果可以,直接用定时器的PWM模式输出方波可能会更好一些。

使用特权

评论回复
板凳
lixiaofengntsc|  楼主 | 2021-8-3 09:17 | 只看该作者
呐咯密密 发表于 2021-8-2 15:34
按道理说这个不该有问题的,你的逻辑没问题,考虑贴个代码给我们看看,包括定时器的初始化,中断处理函数, ...

初步判断是其他中断影响了,关闭其他中断就没问题了,我估计是样的:这个中断里面这条语句执行了,但单片机内部执行翻转还需要时间,等中断退出了,再执行翻转。恰巧这个中断退出了,下个中断就来了,于是电平翻转这个就不执行了。虽然指令执行了,但实际上并没有进行这个操作。但 不确定是不是这样的过程,并且解决方法还没有想好。

使用特权

评论回复
地板
呐咯密密| | 2021-8-3 09:20 | 只看该作者
lixiaofengntsc 发表于 2021-8-3 09:17
初步判断是其他中断影响了,关闭其他中断就没问题了,我估计是样的:这个中断里面这条语句执行了,但单片 ...

知道原因就很好解决了,你将定时器的中断优先级设为最高,然后在中断函数中进行IO翻转,翻转之后再清中断。

使用特权

评论回复
5
kiwis66| | 2021-8-3 09:49 | 只看该作者
时不时的就少翻转一次,
还是中断处理,
这就费解了

使用特权

评论回复
6
lixiaofengntsc|  楼主 | 2021-8-3 11:51 | 只看该作者
呐咯密密 发表于 2021-8-3 09:20
知道原因就很好解决了,你将定时器的中断优先级设为最高,然后在中断函数中进行IO翻转,翻转之后再清中断 ...

还真不好解决。有人说ODR寄存器可能被打断,用BSRR和BR寄存器操作,但我试了也不行。这个中断的优先级已经是最高了。代码没什么,我贴出来。
void Timer3_Config(void)
{
       TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
        TIM_DeInit(TIM3);
        TIM_TimeBaseStructure.TIM_Prescaler     = (32000-1);//计数频率1KHz,即周期1ms
        TIM_TimeBaseStructure.TIM_Period        = CURRENT_M_HALF_PERIOD-1;//500ms翻转一次
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
        TIM_ClearFlag(TIM3,TIM_FLAG_Update);
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
        TIM_Cmd(TIM3,ENABLE);
}

void NVIC_Config_TIM3(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
        {
                TIM_ClearITPendingBit(TIM3,TIM_IT_Update);               
        }
    if(CurrentStu == STOP)
    {
        GPIOA->BRR  = (0x0001<<12);//GPIO_ResetBits(GPIOA,GPIO_Pin_12);//GPIOA12 reset
        CurrentStu = RUN;
    }
    else if(CurrentStu == RUN)
    {
        GPIOA->BSRR = (0x0001<<12);  //GPIO_SetBits(GPIOA,GPIO_Pin_12);//GPIOA12 set
        CurrentStu = STOP;
    }
     __nop();__nop();__nop();__nop();__nop();
}

使用特权

评论回复
7
lixiaofengntsc|  楼主 | 2021-8-3 11:53 | 只看该作者
kiwis66 发表于 2021-8-3 09:49
时不时的就少翻转一次,
还是中断处理,
这就费解了

是的,问了很多人,试了很多方法,都不行。

使用特权

评论回复
8
呐咯密密| | 2021-8-3 12:03 | 只看该作者
lixiaofengntsc 发表于 2021-8-3 11:51
还真不好解决。有人说ODR寄存器可能被打断,用BSRR和BR寄存器操作,但我试了也不行。这个中断的优先级已 ...
试试这样
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
        {
    if(CurrentStu == STOP)
    {
        GPIOA->BRR  = (0x0001<<12);//GPIO_ResetBits(GPIOA,GPIO_Pin_12);//GPIOA12 reset
        CurrentStu = RUN;
    }
    else if(CurrentStu == RUN)
    {
        GPIOA->BSRR = (0x0001<<12);  //GPIO_SetBits(GPIOA,GPIO_Pin_12);//GPIOA12 set
        CurrentStu = STOP;
    }
     __nop();__nop();__nop();__nop();__nop();
       TIM_ClearITPendingBit(TIM3,TIM_IT_Update);               
        }

}

使用特权

评论回复
9
呐咯密密| | 2021-8-3 12:07 | 只看该作者
我突然想起来了,你是有其他中断的干扰,你这个不要用定时器进行IO翻转,用定时器的PWM功能是最好的。或者你还是用这个,在进入定时器中断后第一时间关闭其他中断,等你把IO翻转回来再打开其他中断,但是这个操作可能会造成其他的中断无法响应,谨慎使用

使用特权

评论回复
10
lixiaofengntsc|  楼主 | 2021-8-3 13:41 | 只看该作者
呐咯密密 发表于 2021-8-3 12:07
我突然想起来了,你是有其他中断的干扰,你这个不要用定时器进行IO翻转,用定时器的PWM功能是最好的。或者 ...

按你的写法也是老样子。我是想用PWM的,不过我硬件用的IO口,PWM输出是映射不到的,还得跳线。关中断的操作我 试过了,也是一样。

使用特权

评论回复
11
呐咯密密| | 2021-8-3 13:52 | 只看该作者
lixiaofengntsc 发表于 2021-8-3 13:41
按你的写法也是老样子。我是想用PWM的,不过我硬件用的IO口,PWM输出是映射不到的,还得跳线。关中断的操 ...

你关了其他中断就可以,这个有点奇怪,你的定时器的优先级是最高的,其他的程序不可能打断你定时器中断。不知是否方便再贴一点其他中断看看

使用特权

评论回复
12
lixiaofengntsc|  楼主 | 2021-8-3 13:59 | 只看该作者
呐咯密密 发表于 2021-8-3 13:52
你关了其他中断就可以,这个有点奇怪,你的定时器的优先级是最高的,其他的程序不可能打断你定时器中断。 ...

这个是timer3中断,另外一个是timer2中断,一个是串口接收中断。串口目前没有接收数据,打开也确实没影响。timer2中断是打开就有影响,关闭就没有这个现象。我试过把timer3中断的语句转移到timer2里面实现,结果更乱。
void TIM2_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)
        {
                TIM_ClearITPendingBit(TIM2,TIM_IT_Update);               
        }
        ADC_Start_Counter++;
    StuLed_Counter++;
//   GasMeasCntr++;
//    GasRoomTempCntr++;
    BuckUpCntr++;
    if(BuckUpCntr >= CURRENT_M_HALF_PERIOD)
    {
        BuckUpCntr = 0;
        if(CurrentStu == STOP)
        {
            GPIOA->BRR  = (0x0001<<12);//GPIO_ResetBits(GPIOA,GPIO_Pin_12);//GPIOA12 reset
            CurrentStu = RUN;
        }
        else if(CurrentStu == RUN)
        {
            GPIOA->BSRR = (0x0001<<12);  //GPIO_SetBits(GPIOA,GPIO_Pin_12);//GPIOA12 set
            CurrentStu = STOP;
        }
    }
        
}
这样出来的波形连方波都不是了,就是高电平时间比低电平时间多两倍的样子的一个波形。

使用特权

评论回复
13
呐咯密密| | 2021-8-3 15:25 | 只看该作者
lixiaofengntsc 发表于 2021-8-3 13:59
这个是timer3中断,另外一个是timer2中断,一个是串口接收中断。串口目前没有接收数据,打开也确实没影响 ...

你把你的代码里面重要的东西删除,发给我,我试试,

使用特权

评论回复
14
lixiaofengntsc|  楼主 | 2021-8-3 15:45 | 只看该作者
这是全部程序,没什么重要的东西,您帮忙看看,谢谢。
链接:https://pan.baidu.com/s/1qGX6UqBYwqsPk72vl2gv9g
提取码:5toy

使用特权

评论回复
15
GlenX| | 2021-8-4 08:35 | 只看该作者

STM32F103生成方波问题求教

直接用PWM很简单、实用、准确!搜索
复制

使用特权

评论回复
16
lixiaofengntsc|  楼主 | 2021-8-4 09:16 | 只看该作者
问题解决了。是程序里面的一个大数组搞的鬼。好像是STM32对这种大数组支持的有点差,我定义了一个800个值的数组来做数据分析。把这个数据禁用了,就没问题了。楼上说的PWM是我再画硬件的时候没有打算这么做,用的IO口不能映射的PWM的输出上。

使用特权

评论回复
17
呐咯密密| | 2021-8-4 09:22 | 只看该作者
lixiaofengntsc 发表于 2021-8-4 09:16
问题解决了。是程序里面的一个大数组搞的鬼。好像是STM32对这种大数组支持的有点差,我定义了一个800个值的 ...

果然还是其他问题导致的,看你的代码实在找不出问题了,不是STM32对大数组的支持差,是你这款支持差,换高速的大储存的MCU就没问题了。不过也是一个经验,以后我遇到也会惊醒,

使用特权

评论回复
18
lixiaofengntsc|  楼主 | 2021-8-4 09:26 | 只看该作者
呐咯密密 发表于 2021-8-4 09:22
果然还是其他问题导致的,看你的代码实在找不出问题了,不是STM32对大数组的支持差,是你这款支持差,换 ...

是的,我这是第二次因为大数组出问题了。以后这种嵌入式还是尽量避免这种大数组。还是同样感谢您,也耽误您不少时间,谢谢!

使用特权

评论回复
19
kiwis66| | 2021-8-4 15:13 | 只看该作者
大数组,定时器,IO
倒是给以后留个警醒
感谢楼上的各种讨论

使用特权

评论回复
20
SantaBunny| | 2023-3-6 20:28 | 只看该作者
检查一下你的示波器是不是正常的

使用特权

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

本版积分规则

7

主题

22

帖子

0

粉丝