2017-08-11 7 views
0

J'ai un micro-contrôleur atMega1281 en utilisant C. J'ai une routine pour tirer 4 octets hors d'un bus CAN pour lire un SPN. Je suis en mesure d'obtenir les 4 octets, mais je ne peux pas imprimer le numéro de 4 octets parce qu'il tronque les 2 premiers octets, ce qui en fait un nombre de 16 bits. J'ai essayé d'utiliser unsigned long comme la déclaration sans succès. Quel est le truc lorsque vous utilisez des nombres de 32 bits avec un AVR?Comment combiner 4 octets et faire des calculs mathématiques en C en utilisant AVR

unsigned long engine_hours_raw; 
float engine_hours_uint; 

engine_hours_raw = (OneMessage.Msg.Data[3] << 24) | (OneMessage.Msg.Data[2] << 16) | (OneMessage.Msg.Data[1] << 8) | OneMessage.Msg.Data[0]); 
engine_hours_uint = engine_hours_raw * 0.05; 

ftoa(engine_hours_uint, engHours, 1); 
UART1_Printf("Engine Hours: %s ", engHours); 
+0

Juste pour être sûr: comment allez-vous l'impression du numéro 4 octets? –

+0

En fait, je convertis le flottant en une chaîne en utilisant ftoa et ensuite imprimer comme une chaîne. – Eddie

+0

@Eddie Sur les systèmes embarqués en métal nu, il n'était pas nécessaire de respecter la norme car nous savons que le pointeur est une adresse réelle dans la mémoire :) –

Répondre

1

(OneMessage.Msg.Data[3] << 24) sera de 0 comme la taille par défaut pour une expression est un entier. à moins qu'il ne soit lancé. Au lieu de cela, chargez les données dans le long int, puis effectuez le décalage.

engine_hours_raw = OneMessage.Msg.Data[3]; 
engine_hours_raw <<= 8; 
engine_hours_raw |= OneMessage.Msg.Data[2]; 
engine_hours_raw <<= 8; 
engine_hours_raw |= OneMessage.Msg.Data[1]; 
engine_hours_raw <<= 8; 
engine_hours_raw |= OneMessage.Msg.Data[0]; 

Vous pouvez aussi jeter les expressions intermédiaires comme journal ou uint32_t non signé, mais tout aussi désordonné et peut prendre plus de temps.

engine_hours_raw = ((unit32_t)(OneMessage.Msg.Data[3]) << 24) | ((unit32_t)(OneMessage.Msg.Data[2]) << 16) | ((unit32_t)(OneMessage.Msg.Data[1]) << 8) | (unit32_t)(OneMessage.Msg.Data[0]); 
+0

pourquoi le compliquer? nous sommes dans le monde embarqué du métal nu. les pointeurs et les adresses sont bien connus :) –

+0

Cette solution a fonctionné. J'ai trouvé un document expliquant plus de détails sur les déclarations. Merci UncleO! – Eddie

0

Il y a beaucoup plus facile et simple :)

uint32_t *engine_hours_raw = (uint32_t *)OneMessage.Msg.Data; 
float engine_hours_uint = *engine_hours_raw * 0.05;