duvida de formação de estrutura em C

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

duvida de formação de estrutura em C

Mensagempor fabim » 27 Set 2008 22:10

Alguém poderia me explicar como funciona essas definições de união de variaveis ?

typedef struct
{
POV:4;
B4:1;
B5:1;
B6:1;
B7:1;
}byte_bits;

typedef union
{
unsigned char byte;
byte_bits bit;
}byte;

char read[64],write[64];
unsigned char temp,pov;
char x_axis,y_axis,throttle=0;
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor msamsoniuk » 27 Set 2008 23:18

opa!

union apenas faz as variaveis ocuparem a mesma posicao na memoria. no seu caso, vc esta dizendo que a variavel byte ocupa a mesma posicao de memoria que a variavel bit. assim vc pode acessar como byte ou como bit, vai estar acessando a mesma posicao de memoria de formas diferentes.

por exemplo:

byte.bit.B7 = 1; // seta o bit MSB
printf("byte = 0x%x ", byte.byte);

supondo que vc acertou para B7 ser o bit MSB, ele vai imprimir 0x80, certo ? :)
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor fabim » 28 Set 2008 18:30

ixi.. ta vendo os caras complicam esses fontes.
Manito.

Teria como você comentar e explicar mais profundamente..?

Estou olhando o fonte onde tem essa anarquia e estou perdidão.....

O que eu pude perceber que um array de 64 bytes.

Bom meió oce oiá..

Código: Selecionar todos
typedef struct
{
   POV:4;
   B4:1;
   B5:1;
   B6:1;
   B7:1;
}byte_bits;

typedef union
{
   unsigned char byte;
   byte_bits bit;
}byte;

char read[64],write[64];
unsigned char temp,pov;
char x_axis,y_axis,throttle=0;

void interrupt(void)
{
   HID_InterruptProc();
}

void main(void)
{
   byte buttons;
   
   buttons.byte=0;
   
   //Initialize ports
   TRISB=255;  //Set port b to inputs - Port b samples all the digital switches

   HID_Enable(read,write);
 
   while(1)
   {
       /////////////////////////////////
       //Joystick buttons
      /////////////////////////////////
      //Button 1
        if (PORTB.RB0)
           buttons.bit.B4=1;
      else
          buttons.bit.B4=0;
      //Button 2
       if (PORTB.RB1)
           buttons.bit.B5=1;
      else
          buttons.bit.B5=0;
      //Button 3
          if (PORTB.RB2)
           buttons.bit.B6=1;
      else
          buttons.bit.B6=0;
      //Button 4
          if (PORTB.RB3)
           buttons.bit.B7=1;
      else
          buttons.bit.B7=0;

      ///////////////////////////////////
      //POV Hat
      ///////////////////////////////////
      pov=Adc_Read(0)>>2;
      
      buttons.bit.POV=4;  //idle
      if (pov<=193 && pov>=176)   //Left
          buttons.bit.POV=3;
      if (pov<=175 && pov>=143)   //Down
          buttons.bit.POV=2;
      if (pov<=142 && pov>=61)    //Right
          buttons.bit.POV=1;
      if (pov<=60 && pov>=0)      //Up
          buttons.bit.POV=0;

      ///////////////////////////////
      //Joystick Axes
      x_axis=(Adc_Read(1)>>2)-128;      //Read only the top 8-bits of the ADC
      y_axis=(Adc_Read(2)>>2)-128;
      throttle=(Adc_Read(3)>>2)-128;
      //////////////////////////////
      //USB
      write[0]=throttle;
      write[1]=x_axis;
      write[2]=y_axis;
      write[3]=buttons.byte;
      write[4]=0xFF;
      
      while(!HID_Write(write,5));

   }
}


Observe que pelo que eu pude entender, eu não entendi!! praque aquelas duas funções
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor msamsoniuk » 28 Set 2008 23:06

hehehe duvida no programa *inteiro* ? bom, vamos lah...botei comentarios quase que linha a linha e joguei fora os originais, pois estavam meio toscos demais :D hahaha... eu na verdade nao conheco as funcoes da API USB dele, entao, claro, vou meio no chute! mas em C fica bem facil supor como as coisas funcionam, se vc tiver alguma duvida mais especifica, eh soh detalhar melhor o que quer saber :)

Código: Selecionar todos
/* cria um typedef para os bits em um byte */
typedef struct {
    POV:4;
    B4:1;
    B5:1;
    B6:1;
    B7:1;
} byte_bits;

/* cria um typedef juntando os bits com um byte */
typedef union {
    unsigned char byte;
    byte_bits bit;
} byte;

char read[64];                  /* buffer de recepcao */
char write[64];                 /* buffer de transmissao */
unsigned char temp;             /* temporario qq */
unsigned char pov;              /* um potenciometro qq */
char x_axis;                    /* potenciometro do eixo x */
char y_axis;                    /* potenciometro do eixo y */
char throttle = 0;              /* *outro* potenciometro aleatorio... tu tem um joystick fashion hein! */

/* deve ser tratamento de alguma interrupcao, nao conheco essa mcu */
void interrupt(void)
{
    HID_InterruptProc();
}

/* programa principal */
void main(void)
{
    /* cria uma variavel com o byte e os bits lah */
    byte buttons;
    /* zera todos os bits */
    buttons.byte = 0;

    /* inicializa porta B como entrada para switchs digitais */
    TRISB = 255;

    /* soh deus sabe! */
    HID_Enable(read, write);

    /* loop infinito comeca aqui */
    while (1) {
        /* testa os botaozinho nas portas RB e seta os bits de acordo */
        /* testa botao 1 */
        if (PORTB.RB0)
            buttons.bit.B4 = 1;
        else
            buttons.bit.B4 = 0;

        /* testa botao 2 */
        if (PORTB.RB1)
            buttons.bit.B5 = 1;
        else
            buttons.bit.B5 = 0;

        /* testa botao 3 */
        if (PORTB.RB2)
            buttons.bit.B6 = 1;
        else
            buttons.bit.B6 = 0;

        /* testa botao 4 */
        if (PORTB.RB3)
            buttons.bit.B7 = 1;
        else
            buttons.bit.B7 = 0;

        /* le o AD, provavelmente de 10 bits e pega os 8 bits MSB */
        pov = Adc_Read(0) >> 2;

        /* separa o valor de 8 bits em 4 faixas diferentes e seta os bits POV, seguindo uma logica maluca qq */

        buttons.bit.POV = 4;    //idle

        if (pov <= 193 && pov >= 176)   //Left
            buttons.bit.POV = 3;

        if (pov <= 175 && pov >= 143)   //Down
            buttons.bit.POV = 2;

        if (pov <= 142 && pov >= 61)    //Right
            buttons.bit.POV = 1;

        if (pov <= 60 && pov >= 0)      //Up
            buttons.bit.POV = 0;

        /* isso deve ser as coordenadas x/y do joystick, pegando 8 de 10 bits
        e subtraindo 128 p/ tornar sinalizado (-127 a +127) */

        x_axis = (Adc_Read(1) >> 2) - 128;
        y_axis = (Adc_Read(2) >> 2) - 128;
        throttle = (Adc_Read(3) >> 2) - 128;

        /* monta uma mensagem de 5 bytes com os dados que capturou */
        write[0] = throttle;
        write[1] = x_axis;
        write[2] = y_axis;
        write[3] = buttons.byte;
        write[4] = 0xFF;

        /* envia a mensagem de 5 bytes... pela cara do loop, ele tenta varias vezes ateh conseguir mandar! */
        while (!HID_Write(write, 5));

    }                           /* loop infinito termina aqui */
}
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor fabim » 29 Set 2008 07:55

ááátá tchelo.
Parte do main, sem problemas...
O q eu não estou conseguingo entender são aquelas 2 primeiras rotinas...

Mas pelo que eu observei no seu comentario.
Eu posso fazer tudo no main, sem criar aquelas frescurites né ?

Tipo só acessar o byte do array, que eu estou interessado... correto ?

Fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor Sergio38br » 29 Set 2008 08:01

bom dia, fabim, o acesso por bit em C só é possivel pela montagem da struct, caso queira deixa-la, vai ter de usar operações booleanas, fazendo um and ou or ( & ou |) com a variavel desejada.

[ ]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor Sergio38br » 29 Set 2008 08:15

deve ser segunda, ainda não acordei, melhor lhe dar um exemplo... :roll:
Veja esta parte do codigo:

Código: Selecionar todos
      /* testa botao 1 */
        if (PORTB.RB0)
            buttons.bit.B4 = 1;
        else
            buttons.bit.B4 = 0;


caso não queira montar a struct

Código: Selecionar todos

     if (PORTB.RB0)
        buttons |= 0B00010000; // seta o bit 4 da variavel
     else
        buttons &= 0B11101111; // reseta o bit 4 da variavel


[ ]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor fabim » 29 Set 2008 08:47

ááá´´áááá saquei..
O C ANSI também não permite acesso de bit´s a não ser que sejam definidos en estruturas de macro...
BASIC< PASCA< ASM PERMITEM :( rsrs

vamos ver se eu entendi..

typedef struct
{
POV:4; // POV ocupa bits 0...3
B4:1; // ocupa bit 4
B5:1; // bit 5
B6:1; // bit 6
B7:1; // bit 7
}byte_bits;
??????????????????????? certo ?
LSB PARA MSB? ou contrario ?

typedef union
{
unsigned char byte; // criei um tipo de variavel definida como
byte_bits bit; // byte.. poderia ser Tconfs por exemplo ?
}byte;


void main(void)
{
byte buttons; // falei pro comp que a struct BYTE vai workar
// com uma var buttons que tem 8 bits
buttons.byte=0; // limpa registrador geral
éissu mêmu /;????

Fabim
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor Sergio38br » 29 Set 2008 08:52

8) cierto 8)

[ ]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor fabim » 29 Set 2008 09:37

Retiro o que eu disse.
MikroC é uma bosta para ASM. AFF
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor Sergio38br » 29 Set 2008 09:42

Pelo tamanho do codigo gerado?
[]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor ze » 29 Set 2008 10:36

hitech c: permite variável tipo bit
ex:
static bit b; //tem que ser global
b^=1;//inverte

mikroc: permite acesso e manipulação aos bits de variáveis tipo char (somente)
ex:
unsigned char c;
c.f0=1;
c.f2=c.f3;

ccs: va tománocuidado com ele.

Mas os 2 casos não são recomendados pra não perder a portabilidade. Se não vislumbrar upgrade de uC e/ou compilador não deixa de ser opções curiosas.
abs.....
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor msamsoniuk » 29 Set 2008 12:01

fabim escreveu:ááátá tchelo.
Parte do main, sem problemas...
O q eu não estou conseguingo entender são aquelas 2 primeiras rotinas...

Mas pelo que eu observei no seu comentario.
Eu posso fazer tudo no main, sem criar aquelas frescurites né ?

Tipo só acessar o byte do array, que eu estou interessado... correto ?

Fabim


os typedefs ? nao sao rotinas, sao declaracoes que "ensinam" o compilador como acessar a variavel... pura frescura! vc poderia usar mascaras de bits:

Código: Selecionar todos
#define POV_MASK (0xf)
#define B4_MASK (1<<4)
#define B5_MASK (1<<5)
#define B6_MASK (1<<6)
#define B7_MASK (1<<7)

char read[64];                  /* buffer de recepcao */
char write[64];                 /* buffer de transmissao */
unsigned char buttons; /* variavel legal indicando o botao */
unsigned char temp;             /* temporario qq */
unsigned char pov;              /* um potenciometro qq */
char x_axis;                    /* potenciometro do eixo x */
char y_axis;                    /* potenciometro do eixo y */
char throttle = 0;              /* *outro* potenciometro aleatorio... tu tem um joystick fashion hein! */

/* deve ser tratamento de alguma interrupcao, nao conheco essa mcu */
void interrupt(void)
{
    HID_InterruptProc();
}

/* programa principal */
void main(void)
{
    /* zera todos os bits */
    buttons = 0;

    /* inicializa porta B como entrada para switchs digitais */
    TRISB = 255;

    /* soh deus sabe! */
    HID_Enable(read, write);

    /* loop infinito comeca aqui */
    while (1) {
        /* testa os botaozinho nas portas RB e seta os bits de acordo */
        /* testa botao 1 */
        if (PORTB.RB0)
            buttons |= B4_MASK;
        else
            buttons &= ~B4_MASK;

        /* testa botao 2 */
        if (PORTB.RB1)
            buttons |= B5_MASK;
        else
            buttons &= ~B5_MASK;

        /* testa botao 3 */
        if (PORTB.RB2)
            buttons |= B6_MASK;
        else
            buttons &= ~B6_MASK;

        /* testa botao 4 */
        if (PORTB.RB3)
            buttons |= B7_MASK;
        else
            buttons &= ~B7_MASK;

        /* le o AD, provavelmente de 10 bits e pega os 8 bits MSB */
        pov = Adc_Read(0) >> 2;

        /* separa o valor de 8 bits em 4 faixas diferentes e seta os bits POV, seguindo uma logica maluca qq */

        buttons &= ~POV_MASK; /* limpa campo POV */

        if (pov <= 193 && pov >= 176)   //Left
            buttons |= (POV_MASK & 3);

        else if (pov <= 175 && pov >= 143)   //Down
            buttons |= (POV_MASK & 2);

        else if (pov <= 142 && pov >= 61)    //Right
            buttons |= (POV_MASK &  1);

        else if (pov <= 60 && pov >= 0)      //Up
            buttons |= (POV_MASK & 0);

        else buttons |= (POV_MASK &  4);    //idle


        /* isso deve ser as coordenadas x/y do joystick, pegando 8 de 10 bits
        e subtraindo 128 p/ tornar sinalizado (-127 a +127) */

        x_axis = (Adc_Read(1) >> 2) - 128;
        y_axis = (Adc_Read(2) >> 2) - 128;
        throttle = (Adc_Read(3) >> 2) - 128;

        /* monta uma mensagem de 5 bytes com os dados que capturou */
        write[0] = throttle;
        write[1] = x_axis;
        write[2] = y_axis;
        write[3] = buttons.byte;
        write[4] = 0xFF;

        /* envia a mensagem de 5 bytes... pela cara do loop, ele tenta varias vezes ateh conseguir mandar! */
        while (!HID_Write(write, 5));

    }                           /* loop infinito termina aqui */
}


acho ateh mais recomendavel, pois raramento vejo usarem unions de bitmasks, provavelmente em funcao que a ordem dos bits misteriosamente reverte em maquinas big-endian e little-endian.
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor msamsoniuk » 29 Set 2008 12:07

Sergio38br escreveu:
Código: Selecionar todos

     if (PORTB.RB0)
        buttons |= 0B00010000; // seta o bit 4 da variavel
     else
        buttons &= 0B11101111; // reseta o bit 4 da variavel



opa! dae eh melhor chutar o balde e usar direto assembler! hehehe

nao vejo dificuldade alguma na notacao hexadecimal do C... vc bate o olho e visualiza de cara neh, por exemplo 0xA5 nao tem como nao ver que eh 10100101. mas melhor mesmo eh fazer um #define para melhorar a legibilidade, por exemplo #define BOTAO_1 0xA5, fica mais facil depois para entender o que um button |= BOTAO_1 faz.

apesar de que vc poderia fazer algo como:

#define 0B00000000 0x00
#define 0B00000001 0x01
...
#define 0B11111111 0xff

mas fica meio esquisito, tipo coisa de pic! pff! :)
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor Sergio38br » 29 Set 2008 14:51

Era só, para mostrar qual bit ia ser setado ou resetado.....gosto mais de usar struct

[ ]'s
Sergio
Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Próximo

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

x