Forum: Mikrocontroller und Digitale Elektronik STM32 SPI (Anfänger-)problem


von Cube_S (Gast)


Lesenswert?

Hallo liebe Gemeinde,

ich versuche meinen AVR-geprägten Horizont zu erweitern und 
experimentiere mit einem STM32 Discovery-Board (STM32F407) erweiteret 
mit einem Mikroelektronika "STM32F4 Discovery Shield" und dazu passendem 
"7 seg click" (http://www.mikroe.com/click/7seg/). Die darauf 
befindlichen 74HC595 tun mit Bit-Bangingen was sie sollen.

Mit SPI bekomme ich die Geschichte aber nicht hin. Symptom: Manchmal 
funktionierts, meistens jedoch nicht. Es sieht so aus als gelänge es 
nach Debug-Start genau einmal die richtigen Daten (2-Bytes) 
"rauszuschieben" und danach immer nur noch das Höchste Bit der beiden 
Datenbytes.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include "diag/Trace.h"
4
#include "stm32f4xx_hal.h"
5
#include "stm32f4xx_hal_spi.h"
6
7
#pragma GCC diagnostic ignored "-Wunused-parameter"
8
9
static int volatile tick_count;
10
static volatile bool tick;
11
12
extern "C" void SysTick_Handler(void)
13
{
14
  HAL_IncTick();
15
16
  if (tick_count==0)
17
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
18
  else if (tick_count==666)
19
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
20
21
  if (++tick_count==1000)
22
  {
23
    tick_count = 0;
24
    tick = true;
25
  }
26
}
27
28
extern "C" void HAL_SPI_MspInit(SPI_HandleTypeDef *sh)
29
{
30
   GPIO_InitTypeDef s;
31
32
  __SPI2_CLK_ENABLE();
33
  __GPIOB_CLK_ENABLE();
34
35
  s.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
36
  s.Mode = GPIO_MODE_AF_PP;
37
  s.Speed = GPIO_SPEED_FAST;
38
  s.Pull = GPIO_NOPULL;
39
  s.Alternate = GPIO_AF5_SPI2;
40
  HAL_GPIO_Init(GPIOB, &s);
41
42
  s.Pin = GPIO_PIN_12;
43
  s.Mode = GPIO_MODE_OUTPUT_PP;
44
  s.Speed = GPIO_SPEED_FAST;
45
  s.Pull = GPIO_NOPULL;
46
  HAL_GPIO_Init(GPIOB, &s);
47
48
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
49
}
50
51
int main(int argc, char* argv[])
52
{
53
  HAL_Init();
54
  trace_printf("System clock: %uHz\n", SystemCoreClock);
55
56
  __GPIOD_CLK_ENABLE();
57
58
  GPIO_InitTypeDef GPIO_InitStructure;
59
  GPIO_InitStructure.Pin = GPIO_PIN_12;
60
  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
61
  GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
62
  GPIO_InitStructure.Pull = GPIO_NOPULL;
63
  HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
64
65
  SPI_HandleTypeDef sh;
66
  sh.Instance = SPI2;
67
  sh.Init.Mode = SPI_MODE_MASTER;
68
  sh.Init.Direction = SPI_DIRECTION_2LINES;
69
  sh.Init.DataSize = SPI_DATASIZE_8BIT;
70
  sh.Init.CLKPolarity = SPI_POLARITY_LOW;
71
  sh.Init.CLKPhase = SPI_PHASE_1EDGE;
72
  sh.Init.NSS = SPI_NSS_SOFT;
73
  sh.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
74
  sh.Init.FirstBit = SPI_FIRSTBIT_MSB;
75
  sh.Init.TIMode = SPI_TIMODE_DISABLE;
76
  sh.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
77
  sh.Init.CRCPolynomial = 1;
78
79
  HAL_SPI_Init(&sh);
80
81
  static uint8_t buffer[] = { 0xB6, 0x0A };
82
  static uint8_t rbuf[2];
83
84
  HAL_StatusTypeDef s = HAL_SPI_TransmitReceive(&sh, buffer, rbuf, 2, 100);
85
  HAL_Delay(10);
86
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
87
  HAL_Delay(10);
88
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
89
90
  trace_printf("SPI Status = %d (%02x, %02x)\n", s, rbuf[0], rbuf[1]);
91
92
  while(1)
93
  {
94
    if (tick)
95
    {
96
      tick = false;
97
98
      uint8_t h = buffer[0];
99
      buffer[0] = buffer[1];
100
      buffer[1] = h;
101
102
      s = HAL_SPI_TransmitReceive(&sh, buffer, rbuf, 2, 100);
103
      HAL_Delay(10);
104
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
105
      HAL_Delay(10);
106
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
107
108
      trace_printf("SPI Status = %d (%02x, %02x)\n", s, rbuf[0], rbuf[1]);
109
    }
110
  }
111
}

Der Output der 74HC595 ist wieder mit MISO verbunden so dass ich immer 
die letzten Werte der beiden 74HC595 wieder auslesen kann. Diese stimmen 
auch immer mit der Anzeige überein.

Was könnte ich hier übersehen haben?

von Ich selber (Gast)


Lesenswert?

Cube_S schrieb:
> Was könnte ich hier übersehen haben?

Ich gehe mal davon aus, das du das Datenblatt deiner SPI Komponenten 
gelesen hast.

 - SPI Mode
 - SPI Geschwindigkeit


Allgemein empfehle ich die Anschaffung eine Protokoll Analysers, sofern 
nicht schon vorhanden (etwa Zeroplus logicube).

Mann kommt sonst schnell ins Raten


Zur Cube/HAL Methoden.
Bei mir haben die Methoden TransmitReceive()
Und Transmit(), receive() .
Nicht immer die gleichenergebnisse gebracht.

Heißt:
Bei Baustein A hat TransmitReceive wunderbar funktioniert.
Ein anderes mal musste ichtrennen in expliziet, Transmit und Receive,
ausbrobieren;_)

von Justus S. (jussa)


Lesenswert?

schon versucht, das Senden & Empfangen 'per Hand' zu machen? Ich hatte 
bei beim STM32F3 Discovery das Problem, dass die HAL-Funktion bei 
niedrigen Baudraten gut funktioniert hat, bei höheren aber immer doppelt 
so viele CLK-Pulse ausgegeben hat wie eigentlich nötig...

von Cube_S (Gast)


Lesenswert?

Vielen Dank für die Anregungen. Vor allem das Spielen mit den 
Geschwindigkeiten brachte Erfolg. Mit lausigen 160Hz SPI Frequenz ging 
dann alles, was natürlich keine Lösung ist.

Protokoll habe ich dann auch mit dem Oszi angesehen, sah eigentlich 
(gemessen an den Pins des Discovery-Boards) gut aus, direkt am Board mit 
den 74HC595 weniger.

Moral von der Gesicht: Es war eine kalte Lötstelle an einem Pin-Header 
des "7 seg click" den ich selbst angelötet hatte. Echter Anfängerfehler 
obwohl ich nicht das erste mal löte und auch nicht nur Buchsenleisten.

von hiero (Gast)


Lesenswert?

Magst du den funktionierenden Code nochmal hier posten? Danke.

von Cube_S (Gast)


Lesenswert?

Der Code sollte in Ordnung sein, soweit ich mich erinnere. Es war 
wirklich nur ein Hardwareproblem (kalte Lötstelle)

von Ert (Gast)


Lesenswert?

GPIO_PinAFConfig(xxxxx xxxx xxxx)
fehlt doch doch

hier ein Code für SPI3 der funktioniert
1
SPI_InitTypeDef         SPI_InitStruct;
2
SPI_InitTypeDef         SPI_InitStructure;
3
GPIO_InitTypeDef         GPIO_InitStructure_SPI;
4
5
6
//Clock
7
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC,  ENABLE);
8
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
9
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3  | RCC_APB1Periph_TIM13, ENABLE);
10
  //*********************************************************************************
11
//GPIO
12
//Chip Selsct Ausgang Init  
13
  GPIO_StructInit(&GPIO_InitStructure_SPI);
14
  GPIO_InitStructure_SPI.GPIO_Pin = GPIO_Pin_2;
15
  GPIO_InitStructure_SPI.GPIO_Mode = GPIO_Mode_OUT;
16
  GPIO_InitStructure_SPI.GPIO_PuPd = GPIO_PuPd_DOWN;
17
  GPIO_InitStructure_SPI.GPIO_Speed = GPIO_Speed_50MHz;
18
  GPIO_Init(SPI_CS_PORT, &GPIO_InitStructure_SPI);
19
  
20
  
21
//SCK, MISO, MOSI
22
  GPIO_StructInit(&GPIO_InitStructure_SPI);
23
  GPIO_InitStructure_SPI.GPIO_Pin = SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN;
24
  GPIO_InitStructure_SPI.GPIO_Mode = GPIO_Mode_AF;
25
  GPIO_InitStructure_SPI.GPIO_OType = GPIO_OType_PP;
26
  GPIO_InitStructure_SPI.GPIO_PuPd = GPIO_PuPd_NOPULL;
27
  GPIO_InitStructure_SPI.GPIO_Speed = GPIO_Speed_50MHz;
28
  GPIO_Init(SPI_PORT, &GPIO_InitStructure_SPI);    
29
  
30
  GPIO_PinAFConfig(SPI_PORT, GPIO_PinSource10, GPIO_AF_SPI3);
31
  GPIO_PinAFConfig(SPI_PORT, GPIO_PinSource11, GPIO_AF_SPI3);
32
  GPIO_PinAFConfig(SPI_PORT, GPIO_PinSource12, GPIO_AF_SPI3);
33
  
34
35
36
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
37
SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // transmit in master mode, NSS pin has to be always high
38
SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b; // one packet of data is 8 bits wide
39
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; // clock is low when idle
40
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge; // data sampled at first edge
41
//SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high
42
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; // SPI frequency is APB2 frequency / 4
43
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
44
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
45
SPI_Init(SPI3, &SPI_InitStruct);
46
SPI_Cmd(SPI3, ENABLE); // enable SPI3

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.