Forum: Mikrocontroller und Digitale Elektronik MCP23S17 an STM32F4 Problem


von Jo B. (bibu)


Lesenswert?

Hallo,

ich habe folgendes Problem:
Ich versuche gerade den MCP23S17 IO-Expander an meinem Discoveryboard zu 
betreiben. Leider tut sich garnichts. Ich möchte nur eine Ausgabe. Also 
die Pins an PortA des Controllers anschalten.
Das Ossi sagt, dass der SCK läuft, CS funktioniert und auch die 
Datenpakete gehen rüber.
Ich hab schon diverse Registereinstellungen des MCP durch, aber ich weiß 
leider nicht ob er das überhaupt annimmt. Der Resetpin ist auch auf 5V, 
bzw wurde auch shcon weg gelassen.
Eine Unbekannt: Der MCP läuft auf 5V und der STM auf 3. So weit ich aus 
dem Datenblatt entnehmen kann braucht der aber nur TTL-Logig von daher 
müsste es funktionieren.

http://www.adafruit.com/datasheets/mcp23017.pdf

IOCON.BANK hab ich schon auf 1 und 0 laufen lassen und dementsprechend 
die Adressen angepasst. Ich komm einfach nicht weiter.

Hier dann noch die Codes:
SPI-init:
1
void init_SPI1(void){
2
3
  GPIO_InitTypeDef GPIO_InitStruct;
4
  SPI_InitTypeDef SPI_InitStruct;
5
6
  // enable clock for used IO pins
7
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
8
9
  /* configure pins used by SPI1
10
   * PA5 = SCK
11
   * PA6 = MISO
12
   * PA7 = MOSI
13
   */
14
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
15
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
16
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
17
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
18
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
19
  GPIO_Init(GPIOA, &GPIO_InitStruct);
20
21
  // connect SPI1 pins to SPI alternate function
22
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
23
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
24
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
25
26
  // enable clock for used IO pins
27
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
28
29
  /* Configure the chip select pin
30
     in this case we will use PE7 */
31
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
32
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
33
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
34
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
35
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
36
  GPIO_Init(GPIOE, &GPIO_InitStruct);
37
38
  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high
39
40
  // enable peripheral clock
41
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
42
43
  /* configure SPI1 in Mode 0
44
   * CPOL = 0 --> clock is low when idle
45
   * CPHA = 0 --> data is sampled at the first edge
46
   */
47
  //SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
48
  SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx;
49
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
50
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
51
  SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle
52
  SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
53
  SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; // set the NSS management to internal and pull internal NSS high
54
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // SPI frequency
55
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
56
  SPI_Init(SPI1, &SPI_InitStruct);
57
58
  SPI_Cmd(SPI1, ENABLE); // enable SPI1
59
}

die Registereinstellung vom MCP:
1
void spi_setup(){
2
3
  Delay(10000000L);
4
  GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
5
  SPI_Xfer(0x40);
6
  SPI_Xfer(0x0A);        // IOCON
7
  test=SPI_Xfer(0xB8);
8
  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
9
  Delay(1000);
10
11
  GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
12
  SPI_Xfer(0x40);
13
  SPI_Xfer(0x00);        //IODIRA
14
  test=SPI_Xfer(0x00);
15
  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
16
  Delay(1000);
17
  GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
18
  SPI_Xfer(0x40);
19
  SPI_Xfer(0x10);        //IODIRB
20
  test=SPI_Xfer(0x00);
21
  GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
22
23
}

 die Senderoutine:
1
uint8_t SPI_Xfer(uint8_t data){
2
    /*!< Loop while DR register in not emplty */
3
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
4
      SPI_I2S_SendData(SPI1,data);
5
    return data;
6
    //return SPI1->DR;
7
}

und der relevante teil in der main:
1
    GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
2
    SPI_Xfer(0x40);  //Device Optcode
3
    SPI_Xfer(0x0A);  // OLATA, Adress
4
    test=SPI_Xfer(0xFF);  // Daten
5
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
6
                LD_4_EIN;  //Test LED
7
    Delay(100000000L);
8
               
9
10
    GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
11
    SPI_Xfer(0x40);  //Device Optcode
12
    SPI_Xfer(0x0A);  // OLATA, Adress
13
    test=SPI_Xfer(0x00);  // Daten
14
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high
15
16
    LD_4_AUS;  //Test LED
17
    Delay(100000000L);

Vielen Dank schonmal für Antworten

MfG
bibu

von holger (Gast)


Lesenswert?

SPI_I2S_SendData(SPI1,data);

Die Funktion wartet nicht bis die Daten gesendet wurden.
Mit dieser Erkenntnis schaust du hier rein:

    test=SPI_Xfer(0xFF);  // Daten
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high

CS geht hoch bevor die letzten Bits gesendet wurden.
Noch Fragen?

von Jo B. (bibu)


Lesenswert?

Müsste dann ca. so sein!?:

    test=SPI_Xfer(0xFF);  // Daten
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high

Hatte ich, glaube ich schonmal ausprobiert. Ich werd es morgen nochmal 
testen. Vielleicht läufts dann. Danke schonmal.

von holger (Gast)


Lesenswert?

>Müsste dann ca. so sein!?:

Nein, TXE sagt nicht das die Übertragung beendet ist.

von Jo B. (bibu)


Lesenswert?

So es lang an zwei Sachen. 1. Die Spannung am MCP war zu hoch, 2. Er hat 
nicht gewartet. Ein Delay hat die Lösung gebracht.

Danke für die Antworten.

MfG
bibu

von Jo B. (bibu)


Lesenswert?

So, nächstes Problem. Diesmal mit dem Auslesen.

Eingefügter Code:

Auslesen:
1
    GPIOE->BSRRH |= GPIO_Pin_7; // set PE7 (CS) low
2
    SPI_Xfer(0x41);  //Device Optcode --Lesen
3
    SPI_Xfer(0x13);  // GPIOB, Adress
4
    mcpregister=SPI_RXfer(0x00);  //Dummybyte
5
    Delay(1000);
6
    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 (CS) high

Leseroutine:
1
uint8_t SPI_RXfer(uint8_t data){
2
  /*!< Loop while DR register in not emplty */
3
4
    SPI_I2S_SendData(SPI1,data);
5
    //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
6
    while (!(SPI1->SR & SPI_I2S_FLAG_TXE));
7
    //while (!(SPI1->SR & SPI_I2S_FLAG_RXNE));
8
    while (SPI1->SR & SPI_I2S_FLAG_BSY);
9
  //return data;
10
    Delay(1000);
11
  return SPI1->DR;
12
}

Wenn ich //while (!(SPI1->SR & SPI_I2S_FLAG_RXNE)); (also warten bis 
empfangen) wieder rein nehme, geht es nicht weiter.

SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex
ist jetzt eingestellt.

: Bearbeitet durch User
von Putin (Gast)


Lesenswert?

void Spi2Tx8b (uint8_t Daten)
{
  while(!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
  SPI_I2S_SendData(SPI2, Daten);
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY));
}

uint8_t Spi2TxRx8b (uint8_t Daten)
{
  while(!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE));
  SPI_I2S_SendData(SPI2, Daten);
  while(!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE));
  Daten = SPI_I2S_ReceiveData(SPI2);
  return Daten;
}

von Jo B. (bibu)


Lesenswert?

Leider das selbe: bleibt in while(!SPI_I2S_GetFlagStatus(SPI1, 
SPI_I2S_FLAG_RXNE)); hängen.

von Jo B. (bibu)


Lesenswert?

Das problem konnte behoben werden. Zwar nicht bei dem MCP, aber bei 
einem andern IC. Die Spannungsversorgung war anscheinend zu ungefiltert. 
So dass es manchmal funktionierte und manchmal nicht...

von holger (Gast)


Lesenswert?

>Die Spannungsversorgung war anscheinend zu ungefiltert.
>So dass es manchmal funktionierte und manchmal nicht.

Wie schön das du deine Schaltungen nicht zeigst.
Wahrscheinlich müsste dann jeder der nur halbwegs
was auf dem Kasten hat kotzen.

Ich danke dir dafür das du das uns allen ersparst;)

von Jo B. (bibu)


Lesenswert?

Langweilig?
Ich hatte vorher ein 0815 Netzteil dran und jetzt ein Labornetzteil und 
da funktionierts... Soll ich dir davon den Schaltplan raus suchen?

von holger (Gast)


Lesenswert?

>Langweilig?
>Ich hatte vorher ein 0815 Netzteil dran und jetzt ein Labornetzteil und
>da funktionierts... Soll ich dir davon den Schaltplan raus suchen?

Nein, manchmal muss man etwas provozieren bevor man mal
ne wichtige Information bekommt die man vorher nicht hatte.

Dann können wir den Thread ja jetzt schliessen.

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.