SAMC20 I2C SERCOM1

Gast #6408684
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
Gast #6408966
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.
Gast #6411663
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.
Gast #6413086
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren