Programming Atmega1284p

Go To Last Post
74 posts / 0 new

Pages

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

Thanks for the help guys, stupid software bugs. Now i understand and the 0.3s difference is no big deal right.

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

I presume that you mean PCINT3_vect.

You still need to do an sei()
And of course examine the state of your PCMSK3 pins.

You get an interrupt regardless of which edge has caused a change on any of the enabled pins.

You would be better off starting with an INT0 interrupt.

And explaining exactly what your intentions are, and adding this in your commented code.

Then you can copy-paste real-life code. Otherwise we have to read 'PCINT32_vect' typos.

David.

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

Hey again,

I just stumbled across a wall with the pin interrupts.

Each port is assigned a pin interrupt register, PCINT(3:0)

What If I want several pin interrupts on the same port,
yes it is possible to initialise them.

But the problem, when they are activated they will start the same ISR.
because the vector is checking all the pins of the port

ISR(PCINT3_vect) THEY ARE NOT SEPERATED.

Is there a solution around this?

Any help is much appreciated :D

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

Yes.

   ...
   PCMSK3 = 0b00001011;  // enable IRQ on 3 pins
   ...

ISR(PCINT3_vect)
{
   static uint8_t prev;
   uint8_t current = PIND & PCMSK3;
   uint8_t changed = current ^ prev;
   prev = current;
   if (changed & 0b00001000) do_pin3(); 
   if (changed & 0b00000010) do_pin1(); 
   if (changed & 0b00000001) do_pin0(); 
}

The bits will be set in 'changed' on both edges.
If you want the rising / falling edge:

   if (changed & 0b00000010 & current) do_up_pin1();
   if (changed & 0b00000010 & ~current) do_down_pin1(); 

Untested. You can probably be a little neater.

David.

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

Nice, too bad I don't get it

From my understanding

Current gives the pin that is pressed out of the selected for IRQ.

Changed gives a 1 if different and 0 if same [fixed]

00001011(pcmask) & 00000010(PinD) = 00000010 (Current)
00000010 ^ 00001000 = 00001010 (changed)
00000010 (now prev)
if(00001010 & 0b00001000) do_pin3();
   00001010 & 00001000 = 00001000

I AM CONFUSED AT THIS POINT

Last Edited: Tue. Mar 13, 2012 - 12:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Current gives the pin that is pressed out of the selected for IRQ.
Yes .
Quote:
Changed gives a 0 if different and 1 if same...
Nope, the ^ is the XOR operator, so it does the opposite of what you wrote .
Quote:
...but what is the initial value of prev?
From the definition of a static var -> It's zero . You need to review a C book and check out the "Bit Manipulation 101" tutorial .

Don't forget, you can/should try such code sections that you don't get in the simulator ( a non-ISR version of course ) . You can put what David P. gave you near the top of your code in main(), so it gets down soon enough in the start of the simulation . Init. vars and play with it until you get it ( with an open C book, pencil and paper ) .

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

I second indiana's advice. Open your Boolean textbook on the XOR page. Trace different values with pencil and paper.

XOR is a difficult concept for people. However it just behaves simple Boolean rules, and is really useful. Work through the values bit by bit with the XOR truth table.

Note that my example was untested. If you find something wrong, shout.

'prev' starts off as 0. So you will get 'changed' bits immediately. If you use regular active-low pushbuttons, you set prev to 0b00001011. i.e. the un-pushed value of the buttons.

David.

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

I will use the external interrupt int2:0 instead, don't have much time to mess with these things, just spent hours trying to figure out why 0<<SOMEBITINREGISTER, affected my code.

I read somewhere you can use it to make it obvious for others reading your code that a particular bit in register is set to zero.

DOING SO MESSED UP MY CODE, NOW I KNOW BETTER.

EXTRA:

Can I use the SCK, MISO, MOSI pins when the programmer is not programming and only connected for power supply?

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

Quote:

just spent hours trying to figure out why 0<<SOMEBITINREGISTER, affected my code.

I read somewhere you can use it to make it obvious for others reading your code that a particular bit in register is set to zero.


Surely it depends what you were doing with it. 0<<anything is 0. It is completely benign to OR or XOR with 0 as nothing changes. It is totally fatal to AND with 0 (unless you really mean to clear the target to 0 in which case you might as well just use "= 0;").

So how were you using (0 << something) ?

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

Quite honestly, most projects only need a few pin-change inputs. So you can use INT0, INT1, INT2 pins. The INTn pins have the advantage of selecting edge or level separately.

OTOH, the INTn pins are not always convenient. The PCINTn_vect interrupts of the modern AVRs can work on any pin.

The first stage of any design is to write down your requirements. Preferably on disk so that you can print on paper.

If you have a clear description of what you want to do, the implementation is easier. Especially because you can ask others to inspect or advise. And when you come back to your project in a year's time, you can understand what you were doing.

David.

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

Yh i understand as it was OR it shouldnt change the value. But.it.certainly has an affect on the prog

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

Quote:

Yh i understand as it was OR it shouldnt change the value. But.it.certainly has an affect on the prog


No it does not - in fact the optimiser in the compiler will likely recognise that it does nothing and not generate code. If the behaviour changes you are misunderstanding something else.

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

I don't know how I can explain it better,

When initialising the ADC you have to set the control registers
like ADMUX

I had it set as ADMUX |= 1<<REFS0

and the code works fine, displays conversion results as predicted

however

When Later I though to maker it more clear to readers

I set ADMUX |= 0<<REFS1 | 1<<REFS0;

The prog still works but there is a delay on the conversion results, it will display a Zero Value and then update after just over a second.

All that just because I put 0<<REFS1,

I checked all my code every last bit of it and found that removing the 0<<REFS1, fixed my problem.

Bear in mind REFS1 is assigned to Zero by default,
and the initialisation was not in a loop.

Strange, I think it is a compiler Issue.

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

Quote:

I set ADMUX |= 0<<REFS1 | 1<<REFS0;

I cannot see the fascination that people seem to have with |= and AVR I/O registers. In particular with ADMUX we see threads over and over with garbage ADMUX.

Is it >>that<< hard to just rebuild it each time? Pseudo code when getting ready for a conversion:
"ADMUX = (reference selection) | (channel selection); "

Now indeed there may be ADLAR or other special-purpose in there. The point is with an AVR app it is rare (at least for my apps) to have more than one reference V for an app.

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

//	REFS2:0		ADMUX Mask		Description
//	------- 	----------		-----------
//	0 			0x00			Use Vcc as Aref
//	1			0x40			External AREF on PB0
//	2			0x80			Internal 1.1V bandgap
//	3							n/a
//	6			0x90			Internal 2.56V w/ capacitor on PB0
//	7			0xd0			Internal 2.56V; no connection to PB0
#define	ADC_VREF_VCC	0x00
#define	ADC_VREF_AREF	0x40
#define	ADC_VREF_BG		0x80
#define	ADC_VREF_INTCAP	0x90
#define	ADC_VREF_INT	0xd0

#define ADC_VREF_TYPE ADC_VREF_VCC
...
// **************************************************************************
// *
// *		R E A D _ A D C
// *
// **************************************************************************
//
// Read the AD conversion result
unsigned int	read_adc			(unsigned char adc_input)
{
	ADMUX=adc_input|ADC_VREF_TYPE;
	// Start the AD conversion
	ADCSRA|=0x40;
	// Wait for the AD conversion to complete
	while ((ADCSRA & 0x10)==0);
	ADCSRA|=0x10;
	return ADCW;
}

No |= or &=~ in sight. Short/fast code sequence and no RMW possible issues. Plain to read.

Quote:

All that just because I put 0<<REFS1,

I checked all my code every last bit of it and found that removing the 0<<REFS1, fixed my problem.
...
Strange, I think it is a compiler Issue.


Let's see the generated code fragments. Then we don't have to "think".

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

Quote:

I set ADMUX |= 0<<REFS1 | 1<<REFS0;

What is the order of precendence of those operators? (personally I don'tknow and would have to look it up - using parentheses avoids a lot of manual reading!)

OK, I couldn't help myself so I had to check:

	ADMUX |= 1<<REFS0;
  3c:	3e 9a       	sbi	0x07, 6	; 7
	ADMUX |= 0<<REFS1 | 1<<REFS0; 
  3e:	3e 9a       	sbi	0x07, 6	; 7

Those lines are logically identical so cannot possibly have changed the program behaviour.

Oh and just to check this is the dog's breakfast you get fro -O0:

	ADMUX |= 1<<REFS0;
  74:	a7 e2       	ldi	r26, 0x27	; 39
  76:	b0 e0       	ldi	r27, 0x00	; 0
  78:	e7 e2       	ldi	r30, 0x27	; 39
  7a:	f0 e0       	ldi	r31, 0x00	; 0
  7c:	80 81       	ld	r24, Z
  7e:	80 64       	ori	r24, 0x40	; 64
  80:	8c 93       	st	X, r24
	ADMUX |= 0<<REFS1 | 1<<REFS0; 
  82:	a7 e2       	ldi	r26, 0x27	; 39
  84:	b0 e0       	ldi	r27, 0x00	; 0
  86:	e7 e2       	ldi	r30, 0x27	; 39
  88:	f0 e0       	ldi	r31, 0x00	; 0
  8a:	80 81       	ld	r24, Z
  8c:	80 64       	ori	r24, 0x40	; 64
  8e:	8c 93       	st	X, r24

But still identical.

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

Sorry they had parentheses around them like (0<<REFS1)|(1<<REFS0)

If you saying they are identical then are really don't know.

Try 01 optimization, with avr studio 5.1

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

Hello,

I need help with serial interface USART0, can anyone show me how to initiliase with 1284p using internal 8mhz oscilator?

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

There are articles about this in the tutorial forum. It can be as simply as setting UBRR and the TXEN/RXEn bits and then for transmit waiting for UDRE and flling UDR and for reception waiting for RXC and reading UDR.

Using the internal oscillator is not a great idea - I'd pay $0.25 for a crystal if I were you to rule out one of the likely problems you'll face.

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

I tried to simulate the serial port using VSPE and Proteus but it does not work.

I just want to test it using a simple program that transmits a string of characters to the pc.

Can't find a code for the 1284p. I even tried the code from the usart tutorial and it didn't work.

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

We are very kind and helpful to those students that show some effort.

The USART of a mega1284P is the same as the mega88/168/328 used in the Arduino or the 164/324/644/1284 family or most modern AVRs. You can see many examples.

It is slightly different to the old mega8/16/32 chips. Compare the differences by looking at URSEL in the mega32 data sheet.

But you can use .
Look it up in the Studio Help->avr-libc.a docs

Show what effort you have made.
Describe your symptoms / problems.
Ask specific questions.

There is no problem in students posting their code and asking for help. If it means that you understand how and why anything works, not only does your project succeed but you can do the next one yourself

David.

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

If you ask several AVR programmers what steps will get the serial port talking, I bet most would say: 1)write a function to init the uart. Name it void inituart(void); 2)Write a function to send a char parameter to the uart. Name it void putchar(char c); 3) Write a function to return a char from the uart. Name it char getchar(void); 4)Write a main program that calls inituart() then calls putchar('U'); in a loop. Plug the AVR RS232 transmit pin into your PC RS232 receive pin, and see if you can read the UUUUUUUU from the AVR. If you can't then the 8MHz RC oscillator in the AVR is not within the required 2% accuracy for serial comms. It is usually within 10%, but if it is greter than 2%, I'd expect to see garbage on the serial port. Perform these steps and report your results. Hurry. This is urgent. You have a dozen engineers with 30 years of experience on 5 continents on planet earth waiting for your next message.

Imagecraft compiler user

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

OP's saying the simulation's not working, it seems to me since the sentence before it not working was about Proteus . Try it on the hardware, the tutorial UART code WORKS ( after adjusting UART registers for a different MCU than in the tut. ) .

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Yo Jolly... your problem is either hardware or software. Post a picture of the mega1284p board you are using. We will look to see if it has an RS232 voltage level translator chip on it like a MAX232. Your multimeter should see -7V sitting on the pin2 from the AVR DB9. The PC DB9 should have -7V on pin3. These are the tx lines passing each other on their way to and from the AVR and PC. It won't work if you try to make PC tx talk to AVR tx.

Imagecraft compiler user

Pages