2017-09-04 1 views
-3

C 언어의 모듈러스 산술에 문제가 있습니다. 이 1ms마다 증가하는 전역 변수 uint16_t Tmr_1ms를 정의했습니다. 제가 에서 발진 상태는 아래 구조 여기C 언어의 모듈로 산법

// 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; 

인스턴스에 저장

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 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 오버 플로우 전에 만 기능합니다. 나는 왜 그런지 이해하지 못한다. 아무도 내게 어떤 안내를 줄 수 있습니까? 미리 감사드립니다.

+1

[mcve]를 입력하고 [ask [. "funcional"이란 무엇을 의미합니까? Negation 연산자는 없으며 NegLogicSignal은 표준 함수가 아닙니다. 디버거 사용법을 익히십시오. – Olaf

+0

코드에 모듈러스 연산자가 없으므로 어떤 모듈러스 산술 연산에 문제가 있는지 확실하지 않습니까? –

+0

귀하의 질문/문제가 무엇인지 전혀 확신하지 못합니다. Tmr_1ms가 돌아 가면 다시 "if"문으로 들어가서 "NegLogicSignal (output)"을 호출하지 않는다는 것을 의미합니까? – Basya

답변

1

작업 시간에서 시작 시간을 뺀 동작 시간이 끝나면 문제가 발생합니다. 더 작은 부호없는 숫자에서 더 큰 부호가없는 숫자를 뺀 것이므로 원하는 것을주지 못할 수 있습니다. 이들 숫자가 부호있는 숫자의 차이는 음수입니다. 부호없는 숫자에서 부호가없는 큰 숫자가 될 음수와 비트 동등한 것을 얻을 수 있습니다 (그러나 이전에 저장된 시작 값보다 여전히 작음).

둘러 감을 감지하고 처리해야합니다. 랩 어라운드 (읽기를 지우거나 읽을 때 지워짐)를 나타내는 다른 레지스터 유형 값을 갖거나 시작 값이 최대 값에 대한 델타보다 가깝다는 델타 노트를 계산하는 함수가 있어야합니다. 그런 다음 차이를 계산하는 함수가 정확한 차이를 계산합니다.

당신은 플로트 변수의 값을 넣어 가지고 있기 때문에, 당신은 서명되지 않은 int와하지 캐스트, 다음 랩 어라운드 후 음수, 명확하게 랩 어라운드를 표시하고 정확한 차이를 계산 수를 얻을 수 있습니다 수 있습니다.

this discussion of unsigned subtraction을 살펴보면 자세한 설명과 제안 사항이 있습니다.

가장 좋은 해결책은 old_timer가 의견에서 제안한 것입니다 (old_timer, 답을 만들고 싶다면 받아 들여야 함, 대답에서 이것을 제거하겠습니다). 16 비트 부호없는 값을 32 비트 부호없는 값으로 올리십시오 (float은 원래 코드에서와 같이 가능하지만 필요하지 않거나 권장하지 않음). 32 비트 (또는 부동 소수점) 값으로 빼기를 수행하십시오. 뺄셈 후 비트를 16 비트 (비트 단위 -와 0xFFFF 또는 부호없는 16 비트 변수에 할당)로 마스킹합니다. 산술 연산이 32 비트 (또는 부동)로 수행되기 때문에 뺄셈이 적용됩니다. "모듈로"효과는 상위 비트를 마스킹하여 얻습니다.

+0

답변을 주신 Basy Perlman에게 감사드립니다. Tmr_1ms 변수가 16 비트 하드웨어 타이머/카운터의 상태로 대체 된 비슷한 프로그램을 작성했습니다. 일부 작업 (uint16_t prev_state 변수에 저장된 값)의 시작 부분에서 카운터 값을 읽은 다음 uint16_t cur_state 변수에 저장된 작업의 끝에서 카운터 값을 읽습니다. 다음 명령문은 적절한 결과를 반환합니다. diff = cur_state - prev_state (여기서 diff는 uint16_t 임). 이 경우 뺄셈이 적절한 결과를 반환하는 이유를 말씀해주십시오. 감사. 나는 autodidact입니다. – Steve

+0

나는 그것에 대해 좀 더 생각해 볼 것이나, 언뜻보기에는, 아니, 나는 그것이 왜 작동 하는지를 말할 수 없다 :-) 나는 그것을 기대하지 않을 것이다. – Basya

+0

하드웨어 타이머/카운터의 결과를 바탕으로 "소프트웨어 타이머"Tmr_1ms와 동일한 접근 방식을 사용했습니다. 예를 들어, 부호없는 변수로 인해 12-65528 = 20이라고 예상했습니다. 하드웨어 타이머/카운터가 자유 실행으로 구성되었습니다. 이제 나는 혼란 스럽다. – Steve