Ce code est destiné à un pilote pour un DAC puce.
J'ai un Bitfield ci-dessous qui représente un registre 24 bits. Donc, ce que je dois faire, c'est peupler le bitfield et l'écrire sur SPI à la puce. p> dans ma fonction d'initialisation, je crée un syndicat comme ci-dessous. p> union{
GAIN_REG_st GAIN_st;
uint32_t G_32;
} G_u;
5 Réponses :
prototype: La fonction peut accéder aux champs de structure à l'aide de -> code> opérateur: p>
G_u g;
...
populateGainRegSt( &(g.GAIN_st));
union G_u the_union; the_union.GAIN_st.address_u8 = 0x4; function_call( &the_union ); void function_call( union G_u *the_union ) { uint8 address; address = the_union->GAIN_st.address_u8; return; } Do you mean this? it's a union, so why pass an internal member? it won't make any difference. They all start at the same memory offset.
#include <stdint.h> #include <stdio.h> typedef struct { uint8_t rdwr_u8: 1; uint8_t not_used_u8: 3; uint8_t address_u8: 4; uint8_t reserved_u8: 8; uint8_t data_u8: 8; uint8_t padding_u8: 8; } GAIN_REG_st; union G_u { GAIN_REG_st GAIN_st; uint32_t G_32; }; static void foo (GAIN_REG_st *data) { printf ("%x %x %x\n", data->rdwr_u8, data->not_used_u8, data->address_u8); } int main () { union G_u udata; udata.G_32 = 1986; foo (&udata.GAIN_st); return 0; }
Le titre consiste à adopter le syndicat, mais la question pose la question de la structure de passage. Vous pouvez le faire soit, vous déclarez simplement l'argument de la fonction en conséquence et laissez-passer soit le membre, soit l'ensemble de l'union.
Toutes les réponses actuelles démontrent le passage par référence, mais il n'est pas nécessaire de le faire, vous pouvez passer par copie, qui Pour une structure ou une union qui est finalement une valeur de 32 bits n'est plus coûteuse et enregistre une déséroférance dans la fonction appelée, peut donc être plus efficace; p> ou pour passer la structure : p> Notez que vous pouvez typuref the Union comme vous avez la structure: p> alors le premier exemple serait Simplement; p> void fn( G_u arg );
int main()
{
G_u param;
...
fn( param );
}
C89 n'a aucune disposition réelle d'initialisation et de passage des syndicats en tant qu'arguments directement. Dans C89, les syndicats ne peuvent être déclarés que des références variables ou variables, puis doivent être initialisées à l'aide de la variable. Cependant, vous pouvez ensuite passer et renvoyer ces variables par valeur, donc sans utiliser de pointeurs.
Les structures retournées et les syndicats ne doivent pas nécessairement s'intégrer dans des registres comme des paramètres de retour normaux. Dans ce cas, le compilateur fait tout pour vous (sur la pile), et s'il est en profondeur d'optimisation et d'inline, cela n'implique généralement pas beaucoup de frais généraux (lire: le code C optimisé avec soigneusement à la main peut être plus rapide, mais souvent l'optimiseur bon travail). p>
ci-dessous est exemple de code. p>
avec les fonctions utilitaires Veuillez noter que cela ne fonctionne que pour des types de pointeur de cette manière, car le pointeur doit pointez quelque part. Si vous utilisez des pointeurs, vous devez maintenant, vous pouvez appeler directement votre fonction create_gain_reg_st code> et
gain_reg_st_to_g_u code> Vous pouvez créer la structure / Union sur la volée sur la liste des arguments à l'appel de votre fonction, qui les accepte comme paramètre (s). p>
MALLOC CODE> /
GRATUIT code>. Mais avec le retour de l'ensemble du type de données, vous n'avez pas besoin de cela. Une chose importante est que vous pouvez obtenir un pointeur sur les données créées à la volée, mais que les données ne vivent que lors de l'appel, comme d'habitude pour les variables sur la pile - cela peut rapidement conduire à "utiliser après libre" ou des pointeurs aliasés sur - utilisées des régions de pile. (Ainsi, évitez toujours les pointeurs aux structures / unions qui sont transmis comme des arguments, qui sont retournés ou qui sont des variables temporaires.) P>
SPI CODE>: P>
void
spi_bits(uint8_t rdwr, uint8_t address, uint8_t data)
{
spi(GAIN_REG_st_to_G_u(create_GAIN_REG_st(rdwr, address, data)));
}
int
main()
{
spi_bits(1,19,255);
return 0;
}
Essayez-vous de contourner le problème que vous avez rencontré ici: Stackoverflow.com/questions/5675299/... ? Avez-vous trouvé des informations sur votre système qui indique que vous devez avoir une union de la structure avec un int 32 bits?
NE PAS I> Utilisez des champs de bits pour cartographier les protocoles de données. Vous ne connaissez pas l'alignement, ni l'ordre des bits, ni l'endianesse: rien de tout cela n'est défini par la norme. En outre, le compilateur est libre d'ajouter un nombre quelconque d'octets de rembourrage au champ de bit, puis il est également libre d'ajouter un nombre quelconque d'octets de rembourrage à votre syndicat. La solution appropriée consiste à utiliser un simple uint32_t avec des masques de bits et des opérateurs bit-sis. Ensuite, votre code sera déterministe et 100% portable. Comme les choses se tiennent maintenant, personne ne peut dire ce qui se passera lorsque vous envoyez ce morceau à SPI à SPI, à moins qu'ils ne connaissent les détails de la mise en œuvre spécifique du compilateur.
Soyez très prudent des champs de bits d'emballage, vous devez utiliser des attributs spéciaux de votre compilateur. C'est une manière peu incournAte, vous devez donc envelopper ce code dans les définitions de préprocesseur. Vérification C COMPILER.
Pour GNU GCC, certaines macros doivent être utilisées:
__ attribut__ (((Emballé)) code> et
__ attribut__ ((((((((type> code> pris en charge à partir de GCC V.6