Forum: Mikrocontroller und Digitale Elektronik Kann mir jemand erklären was in diesem Code passiert (Beispiel Atmel AtXmega128A1 TWI)


von Denis (Gast)


Lesenswert?

Hallo,

ich habe hier diesen Beispiel Code von Atmel. Habe versucht ihn zu 
verstehen, bin aber noch sehr unerfahren und komme nicht weiter. Kann 
mir hier einer helfen?

Danke im Vorraus

Gruß Denis

#include "avr_compiler.h"
#include "twi_master_driver.h"
#include "twi_slave_driver.h"

/*! Defining an example slave address. */
#define SLAVE_ADDRESS    0x55

/*! Defining number of bytes in buffer. */
#define NUM_BYTES        8

/*! CPU speed 2MHz, BAUDRATE 100kHz and Baudrate Register Settings */
#define CPU_SPEED       2000000
#define BAUDRATE  100000
#define TWI_BAUDSETTING TWI_BAUD(CPU_SPEED, BAUDRATE)


/* Global variables */
TWI_Master_t twiMaster;    /*!< TWI master module. */
TWI_Slave_t twiSlave;      /*!< TWI slave module. */


/*! Buffer with test data to send.*/
uint8_t sendBuffer[NUM_BYTES] = {0x55, 0xAA, 0xF0, 0x0F, 0xB0, 0x0B, 
0xDE, 0xAD};


/*! Simple function that invert the received value in the sendbuffer. 
This
 *  function is used in the driver and passed on as a pointer to the 
driver.
 */
void TWIC_SlaveProcessData(void)
{
  uint8_t bufIndex = twiSlave.bytesReceived;
  twiSlave.sendData[bufIndex] = (~twiSlave.receivedData[bufIndex]);
}


/*! /brief Example code
 *
 *  Example code that reads the key pressed and show a value from the 
buffer,
 *  sends the value to the slave and read back the processed value which 
will
 *  be inverted and displayed after key release.
 */
int main(void)
{
  /* Initialize PORTE for output and PORTD for inverted input. */
  PORTE.DIRSET = 0xFF;
  PORTD.DIRCLR = 0xFF;
  PORTCFG.MPCMASK = 0xFF;
  PORTD.PIN0CTRL |= PORT_INVEN_bm;
//      PORTCFG.MPCMASK = 0xFF;
//      PORTD.PIN0CTRL = (PORTD.PIN0CTRL & ~PORT_OPC_gm) | 
PORT_OPC_PULLUP_gc;

//Enable internal pull-up on PC0, PC1.. Uncomment if you don't have 
external pullups
PORTCFG.MPCMASK = 0x03; // Configure several PINxCTRL registers at the 
same time
PORTC.PIN0CTRL = (PORTC.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLUP_gc; 
//Enable pull-up to get a defined level on the switches



  /* Initialize TWI master. */
  TWI_MasterInit(&twiMaster,
                 &TWIC,
                 TWI_MASTER_INTLVL_LO_gc,
                 TWI_BAUDSETTING);

  /* Initialize TWI slave. */
  TWI_SlaveInitializeDriver(&twiSlave, &TWIC, TWIC_SlaveProcessData);
  TWI_SlaveInitializeModule(&twiSlave,
                            SLAVE_ADDRESS,
                            TWI_SLAVE_INTLVL_LO_gc);

  /* Enable LO interrupt level. */
  PMIC.CTRL |= PMIC_LOLVLEN_bm;
  sei();

  uint8_t BufPos = 0;
  while (1) {
                while(!PORTD.IN); /* Wait for user to press button */

    switch(PORTD.IN){
      case (PIN0_bm):  BufPos = 0; break;
      case (PIN1_bm):  BufPos = 1; break;
      case (PIN2_bm):  BufPos = 2; break;
      case (PIN3_bm):  BufPos = 3; break;
      case (PIN4_bm):  BufPos = 4; break;
      case (PIN5_bm):  BufPos = 5; break;
      case (PIN6_bm):  BufPos = 6; break;
      case (PIN7_bm):  BufPos = 7; break;
      default:    break;
    }

    /* Show the byte to send while holding down the key. */
    while(PORTD.IN != 0x00){
      PORTE.OUT = sendBuffer[BufPos];
    }

    TWI_MasterWriteRead(&twiMaster,
                        SLAVE_ADDRESS,
                        &sendBuffer[BufPos],
                        1,
                        1);


    while (twiMaster.status != TWIM_STATUS_READY) {
      /* Wait until transaction is complete. */
    }

    /* Show the sent byte received and processed on LEDs. */
    PORTE.OUT = (twiMaster.readData[0]);

                while(PORTD.IN); /* Wait for user to release button */
  }
}

/*! TWIC Master Interrupt vector. */
ISR(TWIC_TWIM_vect)
{
  TWI_MasterInterruptHandler(&twiMaster);
}

/*! TWIC Slave Interrupt vector. */
ISR(TWIC_TWIS_vect)
{
  TWI_SlaveInterruptHandler(&twiSlave);
}

von Oliver J. (skriptkiddy)


Lesenswert?

Die XMEGA-Firmware-Library ist dokumentiert. In der Doku müssen wohl 
alle, die die Library verwenden wollen (früher oder später) mal drin 
schmökern. Das Datenblatt des verwendeten Controllers ist da unter 
Umständen auch ganz hilfreich.

Gruß Oliver

von Denis (Gast)


Lesenswert?

Hallo, ja Danke für die Antwort. Ich habe mich natührlich mit der 
Dokumentation auseinander gesetzt. Habe trotzdem ein Problem!

Wenn ich zum Beispiel für Slave folgendes parametriere:

#define SLAVE_ADDRESS    0xA0

Dieses Byte soll der Master als erstes an den Slave eigentlich 
rausschicken, jedoch kippt er es aus irgend einem grund um und schickt 
0x40 raus und ich verstehe nicht warum!!!!

Kann mir da jemand helfen?


Dieser Beispielcode ist von der Atmelseite für AtXmega128A1:

http://www.atmel.com/dyn/resources/prod_documents/AVR1308.zip

von Krapao (Gast)


Lesenswert?

TWI_SlaveInitializeModule() scheint sein drittes Argument als 
TWI-Adresse im 7-bit Format anzusehen und shiftet die Adresse für das 
anzuhängende LSB Bit R/W eins nach links.

Siehe z.B.
http://www.mikrocontroller.net/attachment/125829/twi_bus.c
1
 twi->interface->SLAVE.ADDR = (address << 1) | (general_call << 0);//(1<<0) gerneral call enable/disable

Wenn du wirklich 0xA0 als SLAVE ADDRESS benutzen willst, musst du 
(0xA0>>1) übergeben.

von Denis (Gast)


Lesenswert?

Danke versuche ich heute Abend zu realisieren!!

von Denis (Gast)


Lesenswert?

Hallo,

habe es ausprobiert und es funktioniert. Danke

Habe jetzt aber zwei weitere Probleme und zwar:


1) wenn ich z.B. ein Feld definiere

   uint8_t sendBuffer[2] = {0x55, 0xAA};

   und dieser Funktion übergebe

   TWI_MasterWriteRead(&twiMaster,
                        SLAVE_ADDRESS,
                        &sendBuffer[BufPos],
                        2,
                        2);
sendet der Master erst mal die Slave Adresse dann die beiden Bytes aus 
dem Feld und soll dann zwei Bytes vom Slave auslesen jedoch liest er nur 
ein Byte aus. Muss ich den ersten Byte (speziell) erstmal aus dem 
Register abholen, damit er den zweiten auslesen kann??

2) Ich wollte ja eigentlich mit Hilfe von TWI ein EEPROM auslesen und 
beschreiben. Wenn ich zum Beispiel mehrere Bytes(oder auch eins) 
hintereinander auslese, muss ich beim letzten Byte NO ACK setzen
 (siehe diesen Link Seite 12: 
http://www.atmel.com/dyn/resources/prod_documents/doc0670.pdf ).
Wo kann ich es bei Atmel Quellcode setzen???



Vielen Dank im Voraus!!!!!


Denis

von fdssd (Gast)


Lesenswert?

dann schnapp dir die vorhandene lib und bau dir daraus ne eigene 
schreib/lesefunktion die so arbeitet wie gewünscht

von Gerhard G. (xmega)


Lesenswert?

Hallo,

>> hintereinander auslese, muss ich beim letzten Byte NO ACK setzen

das ist bereits in deinem Befehl TWI_MasterWriteRead... implmementiert
Da musst du garnichts machen. Nur die Befehle Startadressen usw. richtig 
behandeln.

Bei meinem Beispiel ist der Schreib- und Lesebefehl getrennt.


siehe Beispiel:

void mcp3421_eingabe(void) // schreiben Befehl
{
uint8_t buffer[1];

buffer[0]= 0x88; // Startadresse
TWI_MasterWriteRead(&twiMaster,SLAVE_ADDRESS,buffer,1,0);

while (twiMaster.status != TWIM_STATUS_READY) {}
/* Wait until transaction is complete. */

}


void mcp3421_auslesen(TWI_Master_t *twi) //  auslesen Daten
{


TWI_MasterWriteRead(&twiMaster,SLAVE_ADDRESS,0,0,3);

while (twiMaster.status != TWIM_STATUS_READY) {}
/* Wait until transaction is complete. */

h_byte = twi->readData[0x00];
l_byte = twi->readData[0x01];
conf_reg = twi->readData[0x02];

}


Gruß xmega

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.