## Probably a bit banging-101 question...

8 posts / 0 new
Author
Message

I have a function I use to switch the ADC MUX. It looks like so:

```void ADC_MUX_control(uint8_t channel)
{

switch(channel)
{
case 0:                                       break;
case 1: ADMUX|=(1<<MUX0);                     break;
case 2: ADMUX|=(1<<MUX1);                     break;
case 3: ADMUX|=(1<<MUX1)|(1<<MUX0);           break;
case 4: ADMUX|=(1<<MUX2);                     break;
case 5: ADMUX|=(1<<MUX2)|(1<<MUX0);           break;
case 6: ADMUX|=(1<<MUX2)|(1<<MUX1);           break;
}
}```

However, can I write it as:

```void ADC_MUX_control(uint8_t channel)
{
switch(channel)
{
case 0: ADMUX=0;                             break;
case 1: ADMUX=(1<<MUX0);                     break;
case 2: ADMUX=(1<<MUX1);                     break;
case 3: ADMUX=(1<<MUX1)|(1<<MUX0);           break;
case 4: ADMUX=(1<<MUX2);                     break;
case 5: ADMUX=(1<<MUX2)|(1<<MUX0);           break;
case 6: ADMUX=(1<<MUX2)|(1<<MUX1);           break;
}
}```

So this will not OR the ADMUX register with a mask, rather define it explicitly?

Or another approach:

```void ADC_MUX_control(uint8_t channel)
{
}```

Quote:

Or another approach

As you can see that certainly looks simplest and simplest is usually the best. However that line seems to be composed on the premise of no AREF bits and no ADLAR. So you may want to consider adding those to the assignment.

Why do you even need a function call?

Remember that there are other bits in ADMUX besides the channel.

There are many threads on ADMUX and |=. Try to search some out. My typical setup...

```// Read the AD conversion result

// Select next ADC input
{
}

// Start the AD conversion
```

"ADC_VREF_TYPE" is a constant in most of my apps. Something like

```// VREF
// ====
//	Note that in ADMUX, bit 7 is REFS1; bit 6 is REFS0; bit 4 is REFS2.

//	------- 	----------		-----------
//	0 			0x00			External AREF pin level used as Vref
//	1			0x40			Use Vcc as Vref with cap on AREF pin
//	2			0x80			Internal 1.1V bandgap with cap on AREF pin
//	3			0xc0			Internal 2.56V w/ cap on AREF pin

// MUX
// ===
//	MUX4..0
//	-------
//	0000 		0 -- ADC0 (PA0)
//	0001 		1 -- ADC1 (PA1)
//	...
//	0111 		7 -- ADC7 (PA7)
//	...			(added combinations for differential, BG, & GND--n/a in this app)

```

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

In your first example bits 0/1/2 are ANDed with 0 to be cleared (set to 0) and then depending on the case some of the cleared bits are ORed with 1 to be set, the contents of bits 7/6/5/4/3 are preserved.

On the other hand in the second example you overwrite the complete register with a new value which means that you mess with bits of the register that you don't have an intension to change like the reference voltage bits

Alex

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

Yes, I'm aware of that. I use Vcc as reference. However, both of the above functions are correct? With no regard to their efficiency.

You say you are aware of what your code does but since you use Vcc as ADC Vref bit 6 of ADMUX is 1 and will be cleared as soon as you execute the code as given in your second example so you will get wrong results.

Alex

"For every effect there is a root cause. Find and address the root cause rather than try to fix the effect, as there is no end to the latter."
Author Unknown

alexan_e wrote:
You say you are aware of what your code does but since you use Vcc as ADC Vref bit 6 of ADMUX is 1 and will be cleared as soon as you execute the code as given in your second example so you will get wrong results.

Alex

Thanks, you're 1st post answered my question. On Tiny24 the top two MSB cleared means Vcc as ref.