Sida 1 av 2

USART med MPCM på en AVR

Postat: 22 juli 2010, 12:59:44
av davrex
Håller nu på med att försöker att få MPCM att funkar mellan just nu 2 st avr:er har fått det att funka utan MPCM men efter som jag ska ha flera sedan så börja jag kolla på MPCM. Problmet jag har är att jag tar en en knapp tryckning på mastern och skickar den till slaven som sak skiva ut det till PORTB men det som kommer ut på PORTB är adressen inte data. Så skulle behöva lite hjälp med att fatt vad jag har missuppfattat.

MASTER koden:

Kod: Markera allt

#include <avr/io.h>
#include <util/delay.h> 

#define F_CPU 8000000
#define USART_BAUDRATE 9600 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) 

int main (void) 
{ 
   DDRC = 0x00;
   DDRB = 0xFF;
   UCSRC = (1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
   UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<TXCIE)|(1<<RXCIE)|(1<<UCSZ2); 

   UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register 
   UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register 

   for (;;) // Loop forever 
   { 

  
      while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 
      
      UCSRB |= (1<<TXB8); 
      UDR = 0x02;
      
      while ((UCSRA & (1 << UDRE)) == 0) {}; 
      PORTB = PINC;
      UCSRB &= ~(1<<TXB8); 
      UDR = PINC; 
   }    

}

SLAVE kod :

Kod: Markera allt

#include <avr/io.h> 
#include <avr/interrupt.h> 

#define bit_on(BYTE, BIT)  BYTE |= 1 << BIT
#define bit_off(BYTE, BIT) BYTE &= ~(1 << BIT)

#define F_CPU 8000000
#define USART_BAUDRATE 9600 
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) 
#define rx_address 0x02


int main (void) 
{ 
   DDRB = 0xFF;
   DDRC = 0xFF;
   UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register 
   UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register 

   UCSRC = (1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
   UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(1<<UCSZ2); 
   UCSRA |= (1<<MPCM); 
    sei();
    PORTB = 0xFF;
    PORTC = 0x00;
   for (;;) // Loop forever 
   { 
         // Do nothing - echoing is handled by the ISR instead of in the main loop 

   }    
} 

ISR(USART_RXC_vect) 
{ 
   unsigned char inData; 
   inData = UDR;    //Read data register    
   if(UCSRB & (1<<RXB8)) //Address frame? 
   { 
      if((inData) == rx_address)    //Verify address 
      { 
         UCSRA &= ~(1<<MPCM);//Disable MPCM filtering 
         bit_on(PORTC,4);
      } 
      else // not our address, ignore any data 
      { 
         UCSRA |= (1<<MPCM);//Enable MPCM filtering 
         bit_off(PORTC,4);
 
      } 
    bit_off(PORTC,3);
   } 
   else                   //Data Frame received 
   { 
        bit_on(PORTC,3);
        PORTB = inData; 
        UCSRA |= (1<<MPCM); //Enable MPCM 

   } 
} 

Tack på förhand.

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 16:25:41
av davrex

Kod: Markera allt

  if(UCSRA & (1<<MPCM)) //Address frame? 
Kör jag med nu istället vilket det då funkar mellan mina 2 avr som jag som test. Fast jag blir inte klok på hur det är tänkt har läst mycket på http://www.avrfreaks.net och där säger folk olika. http://www.avrfreaks.net/index.php?name ... 334#644334 där skriver han att man inte ska använda som jag gör nu utan dom jag hade innan. Någon som har koll och kan förklara för mig vilket det är som gäller och varför det "korrekta" sättet inte funkar för mig.

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 16:33:11
av sodjan
I första posten, du har inte någon interrupt-flagga man ska stängas av i ISR(USART_RXC_vect) ?
Jag tänkte om din rutin blir anropad två gånger direkt efter varandra (innan data byten
har kommit på USART linan) så kommer kanske inData = UDR att läsa adressen två gånger ?
D.v.s samma data från UDR. Du stänger av MPCM filtering första gången så andra gången
kommer väl den att trilla igenom ner till där du sätter PORTB... ?

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 17:07:41
av davrex
hmm intressant tänkte USART_RXC_vect ska ju dock bara anropas när en byte är framme. Och har inte läst något om att man måste noll ställa det.

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 17:16:33
av sodjan
Nej, och jag vet inte riktigt hur det fungerar på AVR med C heller... :-)

På andra processorer sätts en flagga (och ett interrupt genereras om det
är enablat). Om man inte clearar flaggan innan man gör "return-from-interrupt"
så kommer interruptet att anropas direkt igen. Men som sagt, kanske att
C-kompilatorn tar han om det.

Hur som helst, din beskrivning på symptomet skulle stämmer med dubbelt anrop.

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 17:24:40
av davrex
Dock efter min ändring i min andra post så funkar det som det är tänkt :/ det som gör mig lite förvirrad. Då jag har löst att det är "fel" sätt att göra på.

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 17:35:06
av jesse
har du nån länk till definitionen av MCPM, med beskrivning av dataprotokollet?

Lite svårt att hitta på Google:
MPCM Evangelism Ministry
Marco Polo Capital Markets (MPCM)
MicroParticles in Cerebral Malaria
Massive Passive Cash Machine. MPCM
*Multichannel Pulse Code Modulation* (men ingen förklaring)

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 17:41:55
av davrex
Multi-processor Communication mode (MPCM)

EDIT:bara det jag har läst i atmega8 datablad har inte mycket hitta så mycket mer vettig info än det.

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 17:43:12
av sodjan
Som jag fattade det så är det en bit i något kontrollregister
som väljer om man ska ha USART adressering (med en nioende
bit sannolikt) påslaget eller inte...

Re: USART med MPCM på en AVR

Postat: 23 juli 2010, 21:04:04
av jesse
aha.. ok :idea:

Re: USART med MPCM på en AVR

Postat: 24 juli 2010, 16:27:45
av davrex
sodjan skrev:Nej, och jag vet inte riktigt hur det fungerar på AVR med C heller... :-)

På andra processorer sätts en flagga (och ett interrupt genereras om det
är enablat). Om man inte clearar flaggan innan man gör "return-from-interrupt"
så kommer interruptet att anropas direkt igen. Men som sagt, kanske att
C-kompilatorn tar han om det.

Hur som helst, din beskrivning på symptomet skulle stämmer med dubbelt anrop.
Hitta detta i ATmega8 datablad så jag antar att den 0 ställs själv efter läsning.
RXC: USART Receive Complete
This flag bit is set when there are unread data in the receive buffer and cleared when the receive
buffer is empty (i.e. does not contain any unread data). If the Receiver is disabled, the receive
buffer will be flushed and consequently the RXC bit will become zero. The RXC Flag can be
used to generate a Receive Complete interrupt (see description of the RXCIE bit).

Re: USART med MPCM på en AVR

Postat: 24 juli 2010, 16:48:49
av sodjan
OK. Så läsningen av mottagningsregistret clearar också flaggan. Rimligt.

Hm, antagligen är det mågot annat logiskt fel i hur koden hanterar MPCM flaggan o.s.v.
Spontant ser det lite konstigt ut att läsa UDR innan man har kollat adressbiten t.ex.

Re: USART med MPCM på en AVR

Postat: 24 juli 2010, 17:04:46
av davrex
TACK! Nu funkar det som det ska efter du sa det där så satte jag mig med databladet igen... och läst allt från början. Hitta då detta stycket:
Receiving Frames with 9 Data Bits
If 9-bit characters are used (UCSZ=7) the ninth bit must be read from the RXB8 bit in UCSRB
before reading the low bits from the UDR. This rule applies to the FE, DOR and PE Status Flags
as well. Read status from UCSRA, then data from UDR. Reading the UDR I/O location will
change the state of the receive buffer FIFO and consequently the TXB8, FE, DOR, and PE bits,
which all are stored in the FIFO, will change.
Så koden vart då såhär och det verkar funka som det ska:

Kod: Markera allt

ISR(USART_RXC_vect) 
{ 
 unsigned char status, control, inData; 
   status=UCSRA;    //Read register A 
   control=UCSRB;   //Read register B -- incl. RXB8 
   inData = UDR;    //Read data register      
   if(control & (1<<RXB8)) //Address frame? 
   { 
      if((inData) == rx_address)    //Verify address 
      { 
         UCSRA &= ~(1<<MPCM);//Disable MPCM filtering 
         bit_on(PORTC,4);
      } 
      else // not our address, ignore any data 
      { 
         UCSRA |= (1<<MPCM);//Enable MPCM filtering 
         bit_off(PORTC,4);
 
      } 
    bit_off(PORTC,3);
   } 
   else                   //Data Frame received 
   { 
        bit_on(PORTC,3);
        PORTB = inData; 
        UCSRA |= (1<<MPCM); //Enable MPCM 

   } 
} 

Så nu återstår bara problemet med att lyckas då den att skicka något tillbaka till master med.

Re: USART med MPCM på en AVR

Postat: 24 juli 2010, 17:13:34
av sodjan
OK, trevligt... :-)
Jag hade inte sett just det där, det bara kändes mer naturligt att
kolla flaggor och statusbitar först och sedan läsa själva datat.
Verkar ju som att det stämde... :-)

Jag ser att du löste det via ett par temp-variabler, min tanke var mer
att flytta in läsningen UDR *efter* kontrollen av RXB8, men det där
fungerar väl också.

Varför läser du UCSRA ? Du använder ju inte "status" någonstans.

Re: USART med MPCM på en AVR

Postat: 24 juli 2010, 17:19:15
av davrex
Körde med variabler för att slippa ha på 2 ställen att läsa av UDR är nog mer bara en sak jag brukar göra. Och status tog jag med bara i alla fall att jag skulle behöva kolla MPCM eller likande, har ju error flaggor där och så. Hellre en kod rad extra en en för lite :P