Forum: PC-Programmierung SPI Master STM32F4


von Jonathan S. (broky)


Lesenswert?

Hallo Leute,
ich versuche jetzt schon mehrere Tage verzweifelt einen SPI Master auf 
einem STM32F4 zum Laufen zu bekommen. Auf der anderen Seite der 
Kommunikation ist ein Digital Analog Converter. Das Problem wenn ich 
über eine Schleife eine Sägezahnspannung erzeuge funktioniert alles 
bestens.
Wenn ich aber ein einzelnes Kommando schicke z.B. Reset Input Registers 
passiert nichts. Meine Vermutung ist: Ich bekomme in unregelmäßigen 
Abständen ein MODF Fehler. Diesen versuche ich zurückzusetzen. Was mir 
nur mit mäßigem Erfolg gelingt. Bei einem MODF wird das SPI abeschaltet.
Das komische ist er verlässt die Schleife die den MODF zurücksetzt. Kurz 
danach ist er aber wieder aktiv. Hat jemand von euch einen Tipp oder 
kann mir einen beispiel Code für einen SPI Master zeigen? Ich wäre euch 
furchbar dankbar :-)

Hier meine SPI-Master Senderoutine:
1
  volatile uint32_t delayCounter = 0;
2
  while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET && delayCounter < SPI_ERROR_DELAY)
3
  {
4
    //Handle Mode Fault
5
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_MODF))
6
    {
7
      volatile int temp1, temp2; //Clear MODF and enable SPI again
8
      temp1=SPI1->CR1;
9
      temp2=SPI1->SR;
10
      SPI1->CR1=temp1;
11
      SPI_Init(SPI1,&(conf->SPI_InterfaceConfig));
12
      SPI_Cmd(SPI1,ENABLE);
13
    }
14
    delayCounter ++;
15
  }
16
  if(delayCounter == SPI_ERROR_DELAY)
17
    return DEVICE_UNREAD;
18
19
        //set chip select low
20
  GPIO_ResetBits(GPIOA,GPIO_Pin_4);
21
  volatile uint32_t delay;
22
  for(delay = 0; delay < 10; delay ++){}
23
24
  if (SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_MODF))
25
    LED_On(LED3); // MODF schon wieder???????????????????
26
27
  SPI_I2S_SendData(conf->SPIx, (data>>24) & 0xFF);
28
  // be sure that the character goes to the shift register
29
  if(controlledWaiting() != OK)
30
    return TIME_OUT;
31
32
  SPI_I2S_SendData(conf->SPIx, (data>>16) & 0xFF);
33
    // be sure that the character goes to the shift register
34
  if(controlledWaiting() != OK)
35
    return TIME_OUT;
36
37
  SPI_I2S_SendData(conf->SPIx, (data>>8) & 0xFF);
38
  // be sure that the character goes to the shift register
39
  if(controlledWaiting() != OK)
40
    return TIME_OUT;
41
42
  SPI_I2S_SendData(conf->SPIx, data & 0xFF);
43
  if(controlledWaiting() != OK)
44
    return TIME_OUT;
45
46
  GPIO_SetBits(GPIOA,GPIO_Pin_4); //Set chip select high
47
48
  return OK;
49
}

Hier wird das SPI Initalisiert
1
void initDAC()
2
{
3
  configureSPI1(&spi1Config);
4
5
  spi1Config.GPIO_MyConfig.GPIO_PuPd = GPIO_PuPd_UP;
6
  spi1Config.GPIO_MyConfig.GPIO_Pin = spi1Config.GPIO_NSS_Pin;
7
  spi1Config.GPIO_MyConfig.GPIO_Mode = GPIO_Mode_OUT;
8
  GPIO_Init(spi1Config.NSS_PORT,&(spi1Config.GPIO_MyConfig));
9
  GPIO_SetBits(spi1Config.NSS_PORT,spi1Config.GPIO_NSS_Pin);
10
11
  SPI_Ini(&spi1Config);
12
13
  SPI1->CR1 &= ~(1<<8);  //reset SSI flag
14
  SPI1->CR2 |= (1<<2);  //Set slave select output
15
}

Hier meine SPI Parameter für die Konfiguration
1
  conf->NSS_Source = GPIO_PinSource4;
2
  conf->SCK_Source = GPIO_PinSource5;
3
  conf->MISO_Source = GPIO_PinSource6;
4
  conf->MOSI_Source = GPIO_PinSource7;
5
  conf->LowSpeed_APB_PeripheralClock = RCC_APB2Periph_SPI1;
6
  conf->PeripheralClock_NSS = RCC_AHB1Periph_GPIOA;
7
  conf->PeripheralClock_SCK = RCC_AHB1Periph_GPIOA;
8
  conf->PeripheralClock_MISO = RCC_AHB1Periph_GPIOA;
9
  conf->PeripheralClock_MOSI = RCC_AHB1Periph_GPIOA;
10
  conf->GPIO_NSS_Pin = GPIO_Pin_4;
11
  conf->GPIO_SCK_Pin = GPIO_Pin_5;
12
  conf->GPIO_MISO_Pin = GPIO_Pin_6;
13
  conf->GPIO_MOSI_Pin = GPIO_Pin_7;
14
  conf->GPIO_AlternativeFunction = GPIO_AF_SPI1;
15
  conf->NSS_PORT = GPIOA;
16
  conf->SCK_PORT = GPIOA;
17
  conf->MISO_PORT = GPIOA;
18
  conf->MOSI_PORT = GPIOA;
19
  conf->SPIx = SPI1;
20
    SPI_StructInit(&(conf->SPI_InterfaceConfig));
21
  conf->SPI_InterfaceConfig.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
22
  conf->SPI_InterfaceConfig.SPI_CPHA = SPI_CPHA_1Edge;
23
  conf->SPI_InterfaceConfig.SPI_CPOL = SPI_CPOL_Low;
24
  conf->SPI_InterfaceConfig.SPI_CRCPolynomial = 0;
25
  conf->SPI_InterfaceConfig.SPI_DataSize = SPI_DataSize_8b;
26
  conf->SPI_InterfaceConfig.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
27
  conf->SPI_InterfaceConfig.SPI_FirstBit = SPI_FirstBit_MSB;
28
  conf->SPI_InterfaceConfig.SPI_Mode = SPI_Mode_Master;
29
  conf->SPI_InterfaceConfig.SPI_NSS = SPI_NSS_Hard;
30
31
  conf->GPIO_MyConfig.GPIO_Mode = GPIO_Mode_AF;
32
  conf->GPIO_MyConfig.GPIO_OType = GPIO_OType_PP;
33
  conf->GPIO_MyConfig.GPIO_PuPd = GPIO_PuPd_NOPULL;
34
  conf->GPIO_MyConfig.GPIO_Speed = GPIO_Speed_50MHz;

von Gnubbel (Gast)


Lesenswert?

Hallo,

ich habe gerade ein ähnliches Problem mit dem SPI1.
Der TXE kommt zu früh.

Das ganze passiert erst ab einem Vorteiler von 32. Versuch doch mal 
einen anderen Vorteilerwert z.B. SPI_BaudRatePrescaler_8 oder 
SPI_BaudRatePrescaler_16.

In der Doku zur StdPeriphLibrary ist ein Beispiel drin.

von Jonathan S. (broky)


Lesenswert?

Habs hin bekommen. Hier mal mein Code. Hoffe das ich dir helfen kann 
damit.
1
void initDAC()
2
{
3
  configureSPI1(&spi1Config);
4
5
  GPIO_InitTypeDef nss;
6
  nss.GPIO_Mode = GPIO_Mode_OUT;
7
  nss.GPIO_PuPd = GPIO_PuPd_UP;
8
  nss.GPIO_Pin = spi1Config.GPIO_NSS_Pin;
9
  GPIO_Init(spi1Config.NSS_PORT,&nss);
10
  GPIO_SetBits(spi1Config.NSS_PORT,spi1Config.GPIO_NSS_Pin);
11
12
  SPI_Ini(&spi1Config);
13
14
  SPI1->CR1 |= (1<<8);  //set SSI flag
15
  //SPI1->CR2 |= (1<<2);  //Set slave select output
16
}
17
18
19
20
void SPI_Ini(SPI_ExtConfig* conf)
21
{
22
  //Enable clocks
23
  if(conf->SPIx == SPI1)
24
    RCC_APB2PeriphClockCmd(conf->LowSpeed_APB_PeripheralClock, ENABLE);
25
  else
26
    RCC_APB1PeriphClockCmd(conf->LowSpeed_APB_PeripheralClock, ENABLE);
27
28
  RCC_AHB1PeriphClockCmd(conf->PeripheralClock_NSS, ENABLE);
29
  RCC_AHB1PeriphClockCmd(conf->PeripheralClock_SCK, ENABLE);
30
  RCC_AHB1PeriphClockCmd(conf->PeripheralClock_MISO, ENABLE);
31
  RCC_AHB1PeriphClockCmd(conf->PeripheralClock_MOSI, ENABLE);
32
33
  //Configure GPIO Pins
34
  GPIO_PinAFConfig(conf->NSS_PORT, conf->NSS_Source, conf->GPIO_AlternativeFunction);
35
  GPIO_PinAFConfig(conf->SCK_PORT, conf->SCK_Source, conf->GPIO_AlternativeFunction);
36
  GPIO_PinAFConfig(conf->MISO_PORT, conf->MISO_Source, conf->GPIO_AlternativeFunction);
37
  GPIO_PinAFConfig(conf->MOSI_PORT, conf->MOSI_Source, conf->GPIO_AlternativeFunction);
38
39
  if(conf->SPI_InterfaceConfig.SPI_Mode != SPI_Mode_Master)
40
  {
41
    conf->GPIO_MyConfig.GPIO_Pin = conf->GPIO_NSS_Pin;
42
    GPIO_Init(conf->NSS_PORT,&(conf->GPIO_MyConfig));
43
  }
44
  conf->GPIO_MyConfig.GPIO_Pin = conf->GPIO_SCK_Pin;
45
  GPIO_Init(conf->SCK_PORT,&(conf->GPIO_MyConfig));
46
  conf->GPIO_MyConfig.GPIO_Pin = conf->GPIO_MISO_Pin;
47
  GPIO_Init(conf->MISO_PORT,&(conf->GPIO_MyConfig));
48
  conf->GPIO_MyConfig.GPIO_Pin = conf->GPIO_MOSI_Pin;
49
  GPIO_Init(conf->MOSI_PORT,&(conf->GPIO_MyConfig));
50
51
    SPI_I2S_DeInit(conf->SPIx);
52
    SPI_Init(conf->SPIx,&(conf->SPI_InterfaceConfig));
53
  SPI_Cmd(conf->SPIx,ENABLE);
54
55
  if(conf->precondition != 0)
56
    conf->precondition();
57
}
58
59
static inline void configureSPI1(SPI_ExtConfig* conf)
60
{
61
  conf->NSS_Source = GPIO_PinSource4;
62
  conf->SCK_Source = GPIO_PinSource5;
63
  conf->MISO_Source = GPIO_PinSource6;
64
  conf->MOSI_Source = GPIO_PinSource7;
65
  conf->LowSpeed_APB_PeripheralClock = RCC_APB2Periph_SPI1;
66
  conf->PeripheralClock_NSS = RCC_AHB1Periph_GPIOA;
67
  conf->PeripheralClock_SCK = RCC_AHB1Periph_GPIOA;
68
  conf->PeripheralClock_MISO = RCC_AHB1Periph_GPIOA;
69
  conf->PeripheralClock_MOSI = RCC_AHB1Periph_GPIOA;
70
  conf->GPIO_NSS_Pin = GPIO_Pin_4;
71
  conf->GPIO_SCK_Pin = GPIO_Pin_5;
72
  conf->GPIO_MISO_Pin = GPIO_Pin_6;
73
  conf->GPIO_MOSI_Pin = GPIO_Pin_7;
74
  conf->GPIO_AlternativeFunction = GPIO_AF_SPI1;
75
  conf->NSS_PORT = GPIOA;
76
  conf->SCK_PORT = GPIOA;
77
  conf->MISO_PORT = GPIOA;
78
  conf->MOSI_PORT = GPIOA;
79
  conf->SPIx = SPI1;
80
    SPI_StructInit(&(conf->SPI_InterfaceConfig));
81
  conf->SPI_InterfaceConfig.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
82
  conf->SPI_InterfaceConfig.SPI_CPHA = SPI_CPHA_1Edge;
83
  conf->SPI_InterfaceConfig.SPI_CPOL = SPI_CPOL_Low;
84
  conf->SPI_InterfaceConfig.SPI_CRCPolynomial = 0;
85
  conf->SPI_InterfaceConfig.SPI_DataSize = SPI_DataSize_8b;
86
  conf->SPI_InterfaceConfig.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
87
  conf->SPI_InterfaceConfig.SPI_FirstBit = SPI_FirstBit_MSB;
88
  conf->SPI_InterfaceConfig.SPI_Mode = SPI_Mode_Master;
89
  conf->SPI_InterfaceConfig.SPI_NSS = SPI_NSS_Soft;
90
91
  conf->GPIO_MyConfig.GPIO_Mode = GPIO_Mode_AF;
92
  conf->GPIO_MyConfig.GPIO_OType = GPIO_OType_PP;
93
  conf->GPIO_MyConfig.GPIO_PuPd = GPIO_PuPd_NOPULL;
94
  conf->GPIO_MyConfig.GPIO_Speed = GPIO_Speed_50MHz;
95
96
  conf->precondition = 0;
97
};
98
99
inline SendErrorCode SPI_Send32Bit(uint32_t data,SPI_ExtConfig* conf)
100
{
101
  volatile uint32_t delayCounter = 0;
102
  while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET && delayCounter < SPI_ERROR_DELAY)
103
  {
104
    //Handle Mode Fault
105
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_FLAG_MODF))
106
    {
107
      volatile int temp1, temp2; //Clear MODF and enable SPI again
108
      temp1=SPI1->CR1;
109
      temp2=SPI1->SR;
110
      SPI1->CR1=temp1;
111
      SPI_Init(SPI1,&(conf->SPI_InterfaceConfig));
112
      SPI_Cmd(SPI1,ENABLE);
113
    }
114
    delayCounter ++;
115
  }
116
  if(delayCounter == SPI_ERROR_DELAY)
117
    return DEVICE_UNREAD;
118
119
  GPIO_ResetBits(GPIOA,GPIO_Pin_4);
120
  volatile uint32_t delay;
121
  for(delay = 0; delay < 10; delay ++){}
122
123
  SPI_I2S_SendData(conf->SPIx, (data>>24) & 0xFF);
124
  // be sure that the character goes to the shift register
125
  if(controlledWaiting() != OK)
126
    return TIME_OUT;
127
128
  SPI_I2S_SendData(conf->SPIx, (data>>16) & 0xFF);
129
    // be sure that the character goes to the shift register
130
  if(controlledWaiting() != OK)
131
    return TIME_OUT;
132
133
  SPI_I2S_SendData(conf->SPIx, (data>>8) & 0xFF);
134
  // be sure that the character goes to the shift register
135
  if(controlledWaiting() != OK)
136
    return TIME_OUT;
137
138
  SPI_I2S_SendData(conf->SPIx, data & 0xFF);
139
  if(controlledWaiting() != OK)
140
    return TIME_OUT;
141
142
  GPIO_SetBits(GPIOA,GPIO_Pin_4);
143
144
  return OK;
145
};

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.