32-разрядная целочисленная арифметика в 16-разрядной системе для PIC
Мне нужно реализовать 32-битную фиксированную точку в 16-битной системе. Кажется, мой компилятор выдает "предупреждение: целочисленное переполнение в выражении". Я не уверен, что мне чего-то не хватает:S . Ниже я приведу тупую версию моего кода. Любой совет был бы признателен:)
#include <stdint.h>
typedef int32_t Q22;
#define Q22base 512
#define Q22_Convert(_a) ((Q22)(_a*Q22base))
int main (){
// a bunch of code that does stuff goes here
Q22 variable1=0;
variable1 = Q22_Convert(some_value1) - Q22_Convert(some_value1);
return 0;
}
3 ответа
Решение
Ваш Q22base
16-битный на 16-битный int
система, вам нужно привести его к Q22
Так что ваши *
Выражение выполняется как минимум в 32-битном типе.
#define Q22_Convert(_a) ((Q22)(_a * (Q22) Q22base))
Существует существующий код, свободно доступный для реализации 32-битных операций в программном обеспечении. Это может быть достаточно для ваших целей.
PIC C code for the 32bit math functions.
////////////////////////////////////////////////////////////////////////////
// //
// This code is based on code by Vadim Gerasimov (vadim@media.mit.edu), //
// and extended skillfully by Mark Newman (newman@media.mit.edu) for the //
// Robotic F.A.C.E. project //
// //
// Copyright (C) 2001-2004 MIT Media Laboratory //
// //
////////////////////////////////////////////////////////////////////////////
// 32-bit arithmetic
#define move32(to,from) {to[0]=from[0];to[1]=from[1];to[2]=from[2];to[3]=from[3];}
#define zero32(n) {n[0]=0;n[1]=0;n[2]=0;n[3]=0;}
#define is_zero32(n) ((n[0]|n[1]|n[2]|n[3])==0)
#define inc32(n) {if(++n[0]==0)if(++n[1]==0)if(++n[2]==0)++n[3];}
void dec32 (char* n) {
if (n[0]--==0) if(n[1]--==0) if (n[2]--==0) --n[3];
}
void add32 (char* a, char* b)
{
byte r[4];
r[0] = *(b);
r[1] = *(b + 1);
r[2] = *(b + 2);
r[3] = *(b + 3);
#asm
movf a,w
movwf 4
movf r[0],w
addwf 0,f
movf r[1],w
incf 4,f
btfsc 3,0
incfsz r[1],w
addwf 0,f
movf r[2],w
incf 4,f
btfsc 3,0
incfsz r[2],w
addwf 0,f
movf r[3],w
incf 4,f
btfsc 3,0
incfsz r[3],w
addwf 0,f
#endasm
}
void sub32(char* a, char* b) { // a = a - b
byte r[4];
r[0] = *(b);
r[1] = *(b + 1);
r[2] = *(b + 2);
r[3] = *(b + 3);
#asm
movf a,w
movwf 4
movf r[0],w
subwf 0,f
movf r[1],w
incf 4,f
btfss 3,0
incfsz r[1],w
subwf 0,f
movf r[2],w
incf 4,f
btfss 3,0
incfsz r[2],w
subwf 0,f
movf r[3],w
incf 4,f
btfss 3,0
incfsz r[3],w
subwf 0,f
#endasm
}
int lt32(char *a, char *b) {
int i;
for (i = 3; i >= 0; i--) {
if (a[i] > b[i])
return 0;
if (a[i] < b[i])
return 1;
}
return 0;
}
int le32(char *a, char *b) {
int i;
for (i = 3; i >= 0; i--) {
if (a[i] < b[i])
return 1;
if (a[i] > b[i])
return 0;
}
return 1;
}
int gt32(char *a, char *b) {
int i;
for (i = 3; i >= 0; i--) {
if (a[i] < b[i])
return 0;
if (a[i] > b[i])
return 1;
}
return 0;
}
int ge32(char *a, char *b) {
int i;
for (i = 3; i >= 0; i--) {
if (a[i] > b[i])
return 1;
if (a[i] < b[i])
return 0;
}
return 1;
}
void shift32(char *n) {
char i, in, out;
in = 0;
for (i = 0; i < 4; i++) {
out = n[i] >> 7;
n[i] = in + (n[i] << 1);
in = out;
}
}
void mult32byte(char *a, char b) {
char i;
char r[4];
move32(r, a);
zero32(a);
for (i = 0; i < 8; i++) {
if (b & 1)
add32(a, r);
b = b >> 1;
shift32(r);
}
a[0] = a[1];
a[1] = a[2];
a[2] = a[3];
a[3] = 0;
}
Рекомендации
- "Код PIC C для 32-битных математических функций". http://web.media.mit.edu/~stefanm/yano/picc_Math32.html Получено 2013-11-07
Вам не нужно приводить константу. Вы можете просто написать #define Q22base 512L или #define Q22base 512UL