Могут ли объявленные переменные в моей структуре иметь разный размер - PullRequest
0 голосов
/ 13 января 2012

Почему я спрашиваю об этом, потому что происходит следующее:

Определено в заголовке:

typedef struct PID
{
// PID parameters
uint16_t Kp; // pGain
uint16_t Ki; // iGain
uint16_t Kd; // dGain

// PID calculations OLD ONES WHERE STATICS
int24_t pTerm;
int32_t iTerm;
int32_t dTerm;
int32_t PID;

// Extra variabels
int16_t CurrentError;

// PID Time
uint16_t tick;

}_PIDObject;

В источнике C:

static int16_t PIDUpdate(int16_t target, int16_t feedback)
{
      _PIDObject PID2_t;

  PID2_t.Kp = pGain2; // Has the value of 2000

      PID2_t.CurrentError = target - feedback; // Has the value of 57

      PID2_t.pTerm = PID2_t.Kp * PID2_t.CurrentError; // Should count this to (57x2000) = 114000

Что происходит, когда яотладка в том, что это не так.Самое большое значение, которое я могу определить (своего рода) в pGain2 - это 1140. 1140x57 дает 64980.

Почему-то кажется, что программа думает, что PID2_t.pTerm - это uint16_t.Но это не так;в структуре он объявлен больше.

Имеет PID2_t.pTerm каким-то образом получил значение uint16_t из первых объявленных переменных в структуре или что-то не так с вычислениями, у меня uint16_t раз a int16_t?Этого не произойдет, если я объявлю их вне структуры.

Кроме того, вот мое int def (никогда раньше не было проблем:

#ifdef __18CXX
typedef signed char int8_t;                 // -128 -> 127               // Char & Signed Char
typedef unsigned char uint8_t;              // 0 -> 255                  // Unsigned Char
typedef signed short int int16_t;           // -32768 -> 32767           // Int
typedef unsigned short int uint16_t;        // 0 -> 65535                // Unsigned Int
typedef signed short long int int24_t;      // -8388608 -> 8388607       // Short Long
typedef unsigned short long int uint24_t;   // 0 -> 16777215             // Unsigned Short Long
typedef signed long int int32_t;            // -2147483648 -> 2147483647 // Long
typedef unsigned long int uint32_t;         // 0 -> 4294967295           // Unsigned Long
#else
#   include <stdint.h>
#endif

Ответы [ 3 ]

5 голосов
/ 13 января 2012

Попробуйте

PID2_t.pTerm = ((int24_t) PID2_t.Kp) * ((int24_t)PID2_t.CurrentError);

Комментарий Иоахима объясняет, почему это работает. Компилятор не переводит мультипликаторы в int24_t перед умножением, поэтому существует переполнение. Если мы вручную продвигаем использование приведений, переполнение не происходит.

1 голос
/ 13 января 2012

В моей системе нет int24_t, поэтому, как было сказано в некоторых комментариях, откуда это взялось?

После комментария Иоахима я написал короткий тест:

#include <stdint.h>
#include <stdio.h>

int main() {
        uint16_t a = 2000, b = 57;
        uint16_t c = a * b;
        printf("%x\n%x\n", a*b, c);
}

Вывод:

1bd50
bd50

Итак, вы получаете первые 2 байта, в соответствии с int16_t.Таким образом, проблема, похоже, в том, что ваш int24_t не определен правильно.

0 голосов
/ 13 января 2012

Как уже отмечали другие, ваш int24_t представляется равным 16 битам.Помимо того, что он слишком мал, вы должны быть осторожны с этим определением типа в целом.stdint.h определяет типы uint_Nt, которые должны быть ровно N битами.Таким образом, предполагая, что ваш процессор и компилятор на самом деле не имеют 24-битного типа данных, вы нарушаете стандартное соглашение.Если вы в конечном итоге определите его как 32-битный тип, было бы более разумно назвать его uint_least24_t, что соответствует шаблону целочисленных типов, которые по крайней мере достаточно великидержать N бит.Различие важно, потому что кто-то может ожидать, что uint24_t будет перенесен выше 16777215.

...