Closed. This question is off-topic。它当前不接受答案。
想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
2年前关闭。
我对C语言的模运算有疑问。
我定义了全局变量uint16_t Tmr_1ms这是
每1毫秒递增一次。我想在
在下面实现的软件振荡器实现
给定功能
振荡器状态存储在以下给定结构的实例中
这是代码
问题在下面的代码中
输出取反仅在Tmr_1ms溢出之前有效。我不明白为什么。请有人可以给我任何指导吗?提前致谢。
想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
2年前关闭。
我对C语言的模运算有疑问。
我定义了全局变量uint16_t Tmr_1ms这是
每1毫秒递增一次。我想在
在下面实现的软件振荡器实现
给定功能
void OSC(uint32_t output, Osc_t *p){
float act_time;
if(p->start){
taskENTER_CRITICAL();
act_time = Tmr_1ms;
taskEXIT_CRITICAL();
if(p->init){
SetLogicSignal(output);
p->start_time = act_time;
p->delta = ((p->period)/(2*p->T));
p->init = FALSE;
}
if(((uint16_t)act_time - (uint16_t)(p->start_time)) >= ((uint16_t)(p->delta))){
NegLogicSignal(output); // my defined function for negation of a bit variable
p->start_time = act_time;
}
}else{
ClearLogicSignal(output);
p->init = TRUE;
}
}
振荡器状态存储在以下给定结构的实例中
// oscillator state (oscillator with fixed duty cycle)
typedef struct{
float period; // period of the oscillations (ms)
float T; // function execution period (ms)
BOOL start; // oscillator start signal (start==TRUE, stop==FALSE)
BOOL init; // initiate the oscillator state
float delta; // time after which expiration the oscillator output is negated
float start_time; // captured Tmr_1ms value
}Osc_t;
这是代码
// oscillator instance init
Test_Oscillator_state.T = 20;
Test_Oscillator_state.period = 1000;
Test_Oscillator_state.init = TRUE;
// calling the function
Test_Oscillator_state.start = TRUE;
OSC(LTestBlink, &Test_Oscillator_state);
问题在下面的代码中
if(((uint16_t)act_time - (uint16_t)(p->start_time)) >= ((uint16_t)(p->delta))){
NegLogicSignal(output);
p->start_time = act_time;
}
输出取反仅在Tmr_1ms溢出之前有效。我不明白为什么。请有人可以给我任何指导吗?提前致谢。
最佳答案
当动作时间结束时,从动作时间中减去开始时间是有问题的。您正在从较小的数字中减去较大的无符号数字,这不太可能为您提供所需的信息。如果这些是带符号的数字,则差异为负。在无符号数字中,您将得到一些与负数等效的东西,该负数将是一个较大的无符号数字(但显然仍小于以前保存的起始值)。
您需要检测并处理环绕。可以使用另一个寄存器类型值来指示回绕(在读取时清除,或者在读取时清除),或者具有一个计算增量的函数,请注意起始值比增量更接近最大值。然后,用于计算差异的函数将得出正确的差异。
由于已将值放在float变量中,因此无法将其强制转换为unsigned int,然后在折回之后您将得到一个负数,清楚地表明折回并允许您计算正确的差值。
看一下this discussion of unsigned subtraction,它有进一步的解释和建议。
注释中建议的最佳解决方案old_timer(old_timer,如果您想使其成为答案并被接受,我将其从答案中删除)。将16位无符号值提升为32位无符号值(可以按照原始代码中的说明进行浮点操作,但不是必需的或不建议使用的)。用32位(或浮点)值进行减法。减法后,将位屏蔽回16位(逐位并使用0xFFFF或分配给无符号的16位变量)。然后进行减法运算,因为算术是以32位(或浮点数)完成的,该位不会回绕。通过屏蔽较高的位可获得“模”效果。