Switch /case with pointer to structure

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys,

I have defined a global struct for my ADC values (ATMEGA328)  like

	struct ADCint
	{ 
		uint8_t ADC_No;
		uint16_t ADC_Value ;
		uint16_t ADC_VoltX100;
	};

	extern struct ADCint ADC_1, ADC_2, ADC_3, ADC_4, ADC_5, ADC_6, ADC_7;

In the function  I want to access on of the structure variables (ADC_1,  ADC_2, ...) depending on the ADC_No passed to the function, like this:

void ADC_VrefInt(uint8_t ADC_No)  // writes values to the desired ADCint structure
{
    // struct ADCint *ADCvaluesPTR = &ADC_6;  //-> this alone works fine

    struct ADCint ADCvaluesPTR;

    switch(ADC_No)
    {
        case 1: *ADCvaluesPTR = &ADC_1; break;  //-> this doesn't work
        case 2: *ADCvaluesPTR = &ADC_2; break;
        case 3: *ADCvaluesPTR = &ADC_3; break;
        case 4: *ADCvaluesPTR = &ADC_4; break;
        case 5: *ADCvaluesPTR = &ADC_5; break;
        case 6: *ADCvaluesPTR = &ADC_6; break;
        case 7: *ADCvaluesPTR = &ADC_7; break;
    }
    
    // Read ADC 
    // 	        7 bit 	6 bit 	5 bit 	4 bit 	3 bit 	2 bit 	1 bit 	0 bit 
    //  ADMUX	REFS1	REFS0 	ADLAR 	- 	     MUX3 	MUX2 	MUX1 	MUX0 

    ADMUX = ADCvaluesPTR->ADC_No;         // reading the desired ADC channel
    
    //.... and so on

Using for example

struct ADCint *ADCvaluesPTR = &ADC_6;

works fine.

But the use with switch /case does always process errors.

 

Any help would appreciated, maybe how to solve this more elegant, selecting structur variables depending on numbers.

 

Many thanks!

BEXX

 

 

Last Edited: Wed. Jun 20, 2018 - 04:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 3

Umm why not an array of struct? Whenever you start naming objects var1, var2, var3 it's just crying out for var[n]. Obviously your channel number becomes your array index. In which case you can drop all the switch() stuff.

Last Edited: Wed. Jun 20, 2018 - 05:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, you are right! Thanks!

This would be the easiest way and i will do that!

 

But just to learn something, can you tell me, what I did wrong in the switch statement above?

 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The reason that this works...

struct ADCint *ADCvaluesPTR = &ADC_6;

is becuase ADCvaluesPTR is of type struct ADCint *.

 

struct ADCint ADCvaluesPTR;
*ADCvaluesPTR = &ADC_1;

This doesn't work because now ADCvaluesPTR is of type struct ADCint - note not a pointer to struct ADCint, but also because of the asterix used in the assignment. So the simple fix is to put an asterix between the variable name and type in the declaration, and to remove the asterix from the assigning statement.

 

struct ADCint *ADCvaluesPTR;
ADCvaluesPTR = &ADC_1;
Last Edited: Wed. Jun 20, 2018 - 08:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Howard_Smith wrote:

So the simple fix is to put an asterix between the variable name and type in the declaration, and to remove the asterix from the assigning statement.

 

Yup, declare a pointer then do pointer assignment.  It looks like this:

void ADC_VrefInt(uint8_t ADC_No)  // writes values to the desired ADCint structure
{
    struct ADCint *ADCvaluesPTR;    // declares the pointer

    switch(ADC_No)
    {
        case 1: ADCvaluesPTR = &ADC_1; break;  // assigns the pointer
        case 2: ADCvaluesPTR = &ADC_2; break;
        case 3: ADCvaluesPTR = &ADC_3; break;
        case 4: ADCvaluesPTR = &ADC_4; break;
        case 5: ADCvaluesPTR = &ADC_5; break;
        case 6: ADCvaluesPTR = &ADC_6; break;
        case 7: ADCvaluesPTR = &ADC_7; break;
    }
    
    // Read ADC 
    // 	        7 bit 	6 bit 	5 bit 	4 bit 	3 bit 	2 bit 	1 bit 	0 bit 
    //  ADMUX	REFS1	REFS0 	ADLAR 	- 	     MUX3 	MUX2 	MUX1 	MUX0 

    ADMUX = ADCvaluesPTR->ADC_No;         // reading the desired ADC channel
    
    //.... and so on

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In C the struct syntax becomes clearer if you typedef them so the only place "struct" then appears is during the typedef. And only use struct tags if you need self reference.

 

The code in #1 would then become:

	typedef struct
	{
		uint8_t ADC_No;
		uint16_t ADC_Value ;
		uint16_t ADC_VoltX100;
	} ADCint;

	extern ADCint ADC_1, ADC_2, ADC_3, ADC_4, ADC_5, ADC_6, ADC_7;
void ADC_VrefInt(uint8_t ADC_No)  // writes values to the desired ADCint structure
{
    // ADCint *ADCvaluesPTR = &ADC_6;  //-> this alone works fine

    ADCint ADCvaluesPTR;

    switch(ADC_No)
    {
        case 1: *ADCvaluesPTR = &ADC_1; break;  //-> this doesn't work
        case 2: *ADCvaluesPTR = &ADC_2; break;
        case 3: *ADCvaluesPTR = &ADC_3; break;
        case 4: *ADCvaluesPTR = &ADC_4; break;
        case 5: *ADCvaluesPTR = &ADC_5; break;
        case 6: *ADCvaluesPTR = &ADC_6; break;
        case 7: *ADCvaluesPTR = &ADC_7; break;
    }
    
    // Read ADC 
    // 	        7 bit 	6 bit 	5 bit 	4 bit 	3 bit 	2 bit 	1 bit 	0 bit 
    //  ADMUX	REFS1	REFS0 	ADLAR 	- 	     MUX3 	MUX2 	MUX1 	MUX0 

    ADMUX = ADCvaluesPTR->ADC_No;         // reading the desired ADC channel

As this "cleans up" the syntax then the missing '*' becomes more obvious.

Last Edited: Thu. Jun 21, 2018 - 08:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As explained in #2, an array of struct is the way to go. But regarding your question:

 

The reason this works:

struct ADCint *ADCvaluesPTR = &ADC_6;

 

and this doesn't:

        case 1: *ADCvaluesPTR = &ADC_1; break;  //-> this doesn't work

 

is because the first "*" is different from the 2nd "*". The first one is part of the declaration, it means the variable being declared is a pointer type. In the second case, the "*" is a derreference operator, it means the value will not go to ADCvaluesPTR, as you intend, but instead to the address pointed to by ADCvaluesPTR (that is, the starting address of the structure). The variable types will not match, so the compiler will give an error, or at least a warning.

Last Edited: Thu. Jun 21, 2018 - 08:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

...many thanks for the detailed explanation!

Really great community! ;-)