Forum: Mikrocontroller und Digitale Elektronik SAMC20 I2C SERCOM1


von Simon (Gast)


Lesenswert?

Hallo Zusammen,
ich versuche bei einem SAMC20 MCU mittels des SERCOM1 I2C zu nutzen.
Der MCU soll als Master fungieren und es ist nur ein Slave am Bus.
Ich habe aber noch große Verständnissschwierigkeiten und hoffe hier auf 
Hilfe.

Konfiguriert habe ich den SERCOM wie folgt:
1
PORT->Group[0].PMUX[PIN_PA16/2].bit.PMUXE = MUX_PA16C_SERCOM1_PAD0;
2
PORT->Group[0].PINCFG[PIN_PA16].bit.PMUXEN = 1;
3
PORT->Group[0].PMUX[PIN_PA17/2].bit.PMUXO = MUX_PA17C_SERCOM1_PAD1;
4
PORT->Group[0].PINCFG[PIN_PA17].bit.PMUXEN = 1;
5
6
SERCOM1->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_INACTOUT(0x0) | SERCOM_I2CM_CTRLA_SPEED(0x0) | SERCOM_I2CM_CTRLA_SDAHOLD(0x0) | SERCOM_I2CM_CTRLA_MODE(0x5);
7
SERCOM1->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
8
9
static const uint32_t F_I2C = 100000;
10
SERCOM1->I2CM.BAUD.bit.BAUD = to_uint8(32e6/(2*F_I2C)-1);
11
12
SERCOM1->I2CM.CTRLA.bit.ENABLE = 1;

Nur wie schreibe und lese ich Register des Slaves?
Mir ist der Ablauf nicht ganz klar.

probiert habe ich folgendes:
1
volatile uint8_t bla;
2
SERCOM1->I2CM.ADDR.bit.ADDR = 0x1D;
3
SERCOM1->I2CM.DATA.reg = 0x00;
4
SERCOM1->I2CM.CTRLB.bit.CMD = SERCOM_I2CM_CTRLB_CMD(1);
5
bla = SERCOM1->I2CM.DATA.reg;
funktionieren tut das Ganze aber nicht.

Kann mir bitte jemand auf die Sprünge helfen?

Vielen Dank,
Simon

von oweiowei (Gast)


Lesenswert?

Simon schrieb:
> Mir ist der Ablauf nicht ganz klar.

Simon schrieb:
> Kann mir bitte jemand auf die Sprünge helfen?

Lies das Datenblatt deines Slave-Bausteins. Dort ist mit
Sicherheit der Ablauf eines Read- und eines Write-Vorgangs
klar dokumentiert.

Exemplarisch (für Write) sieht das verbal etwa so aus:

- Start-Condition erzeugen
- Address-Byte senden (evtl auch mehrere)
- warten auf ACK vom Slave
- Datum senden
- warten auf ACK vom Slave
- Stop-Condition erzeugen

Wenn dir das nicht geläufig ist dann musst du noch einiges
an I2C Prinzipien lernen.

Hier
https://www.mikrocontroller.net/articles/I%C2%B2C
gibt es ein Tutorial zum studieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simon schrieb:
> SERCOM1->I2CM.ADDR.bit.ADDR = 0x1D;

Das Register enthält übrigens die Adresse, wenn der SAMC20 als Slave 
adressiert werden soll. Für Master-Betrieb spielt das gar keine Rolle: 
die Slave-Adresse (und das R/¯W-Bit) werden dort ganz normal als 
Bustransaktion übertragen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

oweiowei schrieb:
> - Stop-Condition erzeugen

bzw. repeated start condition, wenn er vom Slave lesen will 
(Datenrichtungsumkehr).

von Simon (Gast)


Lesenswert?

oweiowei schrieb:
>
> Exemplarisch (für Write) sieht das verbal etwa so aus:
>
> - Start-Condition erzeugen
> - Address-Byte senden (evtl auch mehrere)
> - warten auf ACK vom Slave
> - Datum senden
> - warten auf ACK vom Slave
> - Stop-Condition erzeugen
>
Herzlichen Dank, das war mir grob schon soweit klar, das ging auch aus 
dem Datenblatt des ICs hervor. Ich hatte nur gehofft, dass der SAMC20 
mir da einiges abhnemen kann.

Jörg W. schrieb:
> Simon schrieb:
>> SERCOM1->I2CM.ADDR.bit.ADDR = 0x1D;
>
> Das Register enthält übrigens die Adresse, wenn der SAMC20 als /Slave/
> adressiert werden soll. Für Master-Betrieb spielt das gar keine Rolle:
> die Slave-Adresse (und das R/¯W-Bit) werden dort ganz normal als
> Bustransaktion übertragen.
>
Vielen Dank! Auch das war der Hoffnung geschuldete, dass der MCU vieles 
automatisch generiert.

von Simon (Gast)


Lesenswert?

Ich habe es jetzt wie folgt gelöst:
Es ist der erste Versuch, ohne Timeout und sonstige Fehlerbehandlung.
1
void init_i2c(void)
2
{
3
  SERCOM1->I2CM.CTRLA.reg = 
4
       SERCOM_I2CM_CTRLA_SPEED(0x0) // Normal speed
5
     | SERCOM_I2CM_CTRLA_MODE(0x5); // Master Mode
6
  SERCOM1->I2CM.CTRLB.reg =
7
       SERCOM_I2CM_CTRLB_ACKACT     // Nach Lesen von DATA -> NAK
8
     | SERCOM_I2CM_CTRLB_SMEN;      Smart-Mode
9
10
  static const uint32_t F_CPU = 32000000;
11
  static const uint32_t F_I2C = 100000;
12
  SERCOM1->I2CM.BAUD.bit.BAUD = to_uint8(F_CPU/(2*F_I2C)-1);
13
14
  SERCOM1->I2CM.CTRLA.bit.ENABLE = 1;
15
16
  SERCOM1->I2CM.STATUS.bit.BUSSTATE = 0x01; // Force Idle State
17
}
18
19
uint8_t IIC_RegRead(uint8_t address, uint8_t reg)
20
{
21
  SERCOM1->I2CM.CTRLB.bit.ACKACT = 1; // Nach Lesen von DATA -> NAK
22
  while (SERCOM1->I2CM.STATUS.bit.BUSSTATE != SERCOM_I2CM_STATUS_BUSSTATE_IDLE) {}; // warte auf Idle-State
23
  SERCOM1->I2CM.ADDR.bit.ADDR = (0x1D << 1) | 0x00; // Erzeugt Start-Condition und überträgt Addresse sowie "Schreib-Bit"
24
25
  while (SERCOM1->I2CM.INTFLAG.bit.MB != 1) {}; // Warte auf Ende der Übertragung
26
  SERCOM1->I2CM.DATA.bit.DATA = reg; // Übertrage Register Adresse
27
  
28
  while (SERCOM1->I2CM.INTFLAG.bit.MB != 1) {}; // Warte auf AK von Slave
29
  SERCOM1->I2CM.ADDR.bit.ADDR = (0x1D << 1) | 0x01; // Erzeugt Repeatet-Start-Condition und überträgt Addresse sowie "Lese-Bit"
30
31
  while (SERCOM1->I2CM.INTFLAG.bit.SB != 1) {}; // Warte auf AK vom Slave
32
  reg = SERCOM1->I2CM.DATA.bit.DATA; // Lese Empfangene Daten und erzeuge NAK
33
34
  while (SERCOM1->I2CM.INTFLAG.bit.SB != 1) {}; // Warte auf Ende der Übertragung
35
  SERCOM1->I2CM.CTRLB.bit.CMD = SERCOM_I2CM_CTRLB_CMD_STOP_CONDIT; //  Sende Stop-Condition
36
37
  return reg;
38
}

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.