Probably a bit banging-101 question...

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

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

void ADC_MUX_control(uint8_t channel)
{
	ADMUX&=~((1<<MUX2)|(1<<MUX1)|(1<<MUX0));
	
	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;
		case 7: ADMUX|=(1<<MUX2)|(1<<MUX1)|(1<<MUX0);
	}
}

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;
		case 7: ADMUX=(1<<MUX2)|(1<<MUX1)|(1<<MUX0);
	}
}

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)
{	
	ADMUX=channel;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

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

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
	adc_raw[ad_index] = ADCW;

// Select next ADC input
	if (++ad_index >= ADC_CHANNELS)
		{
		ad_index=0;
		}

	ADMUX = ADC_VREF_TYPE + ad_index;

// Start the AD conversion
	ADCSRA |= BIT_ADCSRA_ADSC;

"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.

//	REFS1:0		ADMUX Mask		Description
//	------- 	----------		-----------
//	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
#define	ADC_VREF_AREF	0x00
#define	ADC_VREF_VCC	0x40
#define	ADC_VREF_BG		0x80
#define	ADC_VREF_INT	0xc0

// 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)

#define ADC_VREF_TYPE ADC_VREF_AREF

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.

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

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

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

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.

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

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

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

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.

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

Well you never mentioned the model you were using so I based my reply on a mega8.

So basically your question was which way of the two to use since the high bits will be 0 anyway either if you overwrite them or preserve them.
My opinion to this is don't get used to bad habits because sooner or later they 'll get you in trouble when you overwrite something you shouldn't.

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