由C251控制pwm引伸重入函数的一点疑问
本帖最后由 陌风 于 2024-5-30 22:10 编辑在使用stc32fk54时,我遇到了这一个问题,我在定时器1的中断和主函数都调用了这一个函数。(比较新手,谢谢大神的解答)
void pwm_duty(PWMCH_enum pwmch, uint32 duty)
{
uint32 match_temp;
//读取ARR寄存器值
uint32 arr = ((*(unsigned char volatile far *) (PWM_ARR_ADDR))<<8) | (*(unsigned char volatile far *) (PWM_ARR_ADDR + 1 ));
//arr寄存器和频率有关
// P_SW2 |= 0x80;
if(duty != PWM_DUTY_MAX)
{
match_temp = arr * ((float)duty/PWM_DUTY_MAX); //占空比
}
else
{
match_temp = arr + 1;
}
//用这个值设置比较寄存器CCR寄存器,当达到ccr寄存器的值时,输出0,没达到输出1
//设置捕获值|比较值
(*(unsigned char volatile far *) (PWM_CCR_ADDR)) = match_temp>>8; //高8位
(*(unsigned char volatile far *) (PWM_CCR_ADDR + 1))= (uint8)match_temp; //低8位
// P_SW2 &= ~0x80;
}
主函数用了while(1){pwm_duty(PWMB_CH3_P33, 5250);}定时器1放了pwm_duty(P13,1000);已知这两个通道不冲突,但是现在出现了主函数的pwm_duty(PWMB_CH3_P33, 5250),会影响P13的输出,如图是P13的波,
可是我在网络上了解到,中断时,数据会被储存到堆栈中断退出时,自动恢复这些寄存器原本的值,那么为啥定时器的函数运行,会影响到主函数呢?是形参不堆栈吗?只有形参引脚变了才会影响P13??
第二次编辑:
类比C51,我想我可能知道了大概是,C251在重入中,把局部变量重新赋值,并没有堆栈,所以导致主函数的引脚错误,而在最后设置比较值时,将match_temp也就是5250赋值给了,PWM_CCR_ADDR但是注意,这个pwmch时重写的,也就是P13。
但是说法还是有一些问题 为什么局部变量match_temp;没有改变。2 在我将这两个函数分别放在不同定时中断内,运行两分钟 没出现冲突。 希望大家能给出更具体的解答
我问别人说是同一函数调用,在运行过程中触发中断,改变了变量,但是还是不懂具体原因 C51里会有这种问题,,,C251还不太清楚,, 陌风 发表于 2024-5-29 22:32
我问别人说是同一函数调用,在运行过程中触发中断,改变了变量,但是还是不懂具体原因 ...
所谓“重入”,即重复进入函数处理,同一个函数,如果外部程序正在调用一个函数处理,执行到中途,进入某个中断,中断又调用这个函数,则中断返回后从刚才的断点继续执行函数,此时一些变量肯恩更衣镜倍中断调用时改变了,会得到错误的结果。
处理方法:
1、程序定义为重入函数。
2、互斥调用。 梁工 发表于 2024-5-30 12:04
所谓“重入”,即重复进入函数处理,同一个函数,如果外部程序正在调用一个函数处理,执行到中途,进入某 ...
是的,我查询了重入函数的相关概念,发现网上有很多说法,而对于c51(虽然这是C251)如果你不特别设计你的函数,它就是不可重入的。引起这个差别的原因在于:一般的 C 编译器(或者更确切点地说:基于一般的处理器上的 C 编译器),其函数的局部变量是存放于堆栈中的,而 C51 是存放于一个可覆盖的(数据)段中的。我想应该是他将局部变量的内存覆盖了,并没有堆栈。虽然没有更明确的C251定义。 _奶咖君_ 发表于 2024-5-30 08:50
C51里会有这种问题,,,C251还不太清楚,,
是的,我有查询了资料,在这一篇文章提到了这个问题,http://blog.chinaunix.net/uid-27675161-id-3458297.html,我想可能C251中,他把局部变量重新赋值了 勾选产生重入函数选项
另外如果函数使用了公共变量或其它公共资源,一般是没法重入的,此情况不会警告或错误
页:
[1]