Forum: Mikrocontroller und Digitale Elektronik Stm32f103 Problem mit Spi2


von grundschüler (Gast)


Lesenswert?

ich versuche inzwischen schon länger, bei einem stm32f103VET8 spi2 in 
Gang zu setzen. Diese thread nicht weiter: 
Beitrag "STM32 - SPI2 will nicht"

Ich habe den code alternativ auf spi1 umgestellt und umgelötet - das lcd 
läuft auf anhieb.

Was ist an meinem spi2-code falsch bzw. anders als am spi1-code, der 
funktioniert?
1
#define xspi2 0
2
void lcd_spi_write(u8 dat){
3
#if xspi2
4
  SPI2->DR=dat;
5
  while (SPI2->SR & 1<<(7)) ;
6
  return SPI2->DR;
7
#else
8
  SPI1->DR=dat;
9
  while (SPI1->SR & 1<<(7)) ;
10
  return SPI1->DR;
11
#endif
12
}
13
14
void lcd_spi_init()
15
{
16
  SPI_InitTypeDef  SPI_InitStructure;
17
  GPIO_InitTypeDef GPIO_InitStructure;
18
19
  /* Configure SPI1 pins: SCK and MOSI with default alternate function (not remapped) push-pull */
20
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
21
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
22
#if xspi2
23
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
24
  GPIO_Init(GPIOB, &GPIO_InitStructure);
25
#else
26
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
27
  GPIO_Init(GPIOA, &GPIO_InitStructure);
28
#endif
29
30
  /* Configure MISO as Input with internal pull-up */
31
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
32
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
33
34
#if xspi2
35
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
36
  GPIO_Init(GPIOB, &GPIO_InitStructure);
37
#else
38
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
39
 GPIO_Init(GPIOA, &GPIO_InitStructure);
40
#endif
41
42
      SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
43
      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
44
      SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
45
      SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
46
      SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
47
      SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
48
      SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
49
      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
50
      SPI_InitStructure.SPI_CRCPolynomial = 7;
51
52
53
#if xspi2
54
 SPI_Init(SPI2, &SPI_InitStructure);
55
 SPI_CalculateCRC(SPI2, DISABLE);
56
 SPI_Cmd(SPI2, ENABLE);
57
#else
58
SPI_Init(SPI1, &SPI_InitStructure);
59
 SPI_CalculateCRC(SPI1, DISABLE);
60
 SPI_Cmd(SPI1, ENABLE);
61
 #endif
62
}
63
64
65
int main(void){
66
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
67
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
68
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
69
70
#if xspi2
71
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
72
#else
73
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
74
#endif
75
    lcd_CS_INIT();
76
    lcd_CS_HIGH();
77
    lcd_spi_init();
78
    lcd_init();
79
    lcd_clear(RED);
80
81
82
    while(1){
83
84
 /*   nur zum testen
85
  lcd_CS_HIGH();
86
      lcd_spi_write(0x0f);
87
      wait;
88
      lcd_CS_LOW();
89
         lcd_spi_write(0xf0);
90
     wait;*/
91
    }
92
}

von hp-freund (Gast)


Lesenswert?

#define xspi2 0
und
#if xspi2

kontrollier das mal.

von Martin (Gast)


Lesenswert?

Gebe meinem Vorredner recht:
1
#define xspi2
2
void lcd_spi_write(u8 dat){
3
#ifdef xspi2
4
  SPI2->DR=dat;
5
  while (SPI2->SR & 1<<(7)) ;
6
  return SPI2->DR;
7
#else
8
  SPI1->DR=dat;
9
  while (SPI1->SR & 1<<(7)) ;
10
  return SPI1->DR;
11
#endif
12
}
13
14
void lcd_spi_init()
15
{
16
  SPI_InitTypeDef  SPI_InitStructure;
17
  GPIO_InitTypeDef GPIO_InitStructure;
18
19
  /* Configure SPI1 pins: SCK and MOSI with default alternate function (not remapped) push-pull */
20
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
21
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
22
#ifdef xspi2
23
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
24
  GPIO_Init(GPIOB, &GPIO_InitStructure);
25
#else
26
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
27
  GPIO_Init(GPIOA, &GPIO_InitStructure);
28
#endif
29
30
  /* Configure MISO as Input with internal pull-up */
31
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
32
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
33
34
#ifdef xspi2
35
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
36
  GPIO_Init(GPIOB, &GPIO_InitStructure);
37
#else
38
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
39
 GPIO_Init(GPIOA, &GPIO_InitStructure);
40
#endif
41
42
      SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
43
      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
44
      SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
45
      SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
46
      SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
47
      SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
48
      SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
49
      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
50
      SPI_InitStructure.SPI_CRCPolynomial = 7;
51
52
53
#ifdef xspi2
54
 SPI_Init(SPI2, &SPI_InitStructure);
55
 SPI_CalculateCRC(SPI2, DISABLE);
56
 SPI_Cmd(SPI2, ENABLE);
57
#else
58
SPI_Init(SPI1, &SPI_InitStructure);
59
 SPI_CalculateCRC(SPI1, DISABLE);
60
 SPI_Cmd(SPI1, ENABLE);
61
 #endif
62
}
63
64
65
int main(void){
66
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
67
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
68
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
69
70
#ifdef xspi2
71
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
72
#else
73
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
74
#endif
75
    lcd_CS_INIT();
76
    lcd_CS_HIGH();
77
    lcd_spi_init();
78
    lcd_init();
79
    lcd_clear(RED);
80
81
82
    while(1){
83
84
 /*   nur zum testen
85
  lcd_CS_HIGH();
86
      lcd_spi_write(0x0f);
87
      wait;
88
      lcd_CS_LOW();
89
         lcd_spi_write(0xf0);
90
     wait;*/
91
    }
92
}

von hp-freund (Gast)


Lesenswert?

oder auch xspi2 ungleich 0 definieren...

von grundschüler (Gast)


Lesenswert?

hp-freund schrieb:
> #define xspi2 0
> und
> #if xspi2
>
> kontrollier das mal.

das ist nur das define, um zwischen spi1 und spi2 umzuschalten:

#define xspi2 0 => führt den code für SPi1 aus
#define xspi2 1 => führt den code für SPi2 aus

Irgendwo muss ein Fehler im code für Spi2 sein, obwohl er entsprechend 
dem spi1-code aufgebaut ist. Es kommen zwar Signale auf sck, mosi und 
cs, aber das lcd wird nicht initialisiert.

von hp-freund (Gast)


Lesenswert?

Wissen auch alle deine lcd_xx Funktionen das sie auf SPI2 zugreifen 
sollen?

von grundschüler (Gast)


Lesenswert?

hp-freund schrieb:
> Wissen auch alle deine lcd_xx Funktionen das sie auf SPI2 zugreifen
sollen

Es ist doch nur eine einzige lcd-Funktion, die auf Spi zugreift, nämlich 
"lcd_spi_write(dat)", Lesefunktionen gibt es nicht, Miso ist nicht 
verbunden. lcd_spi_write sollte das eigentlich wissen.

von hp-freund (Gast)


Lesenswert?

Was ist mit:
lcd_CS_INIT();
lcd_CS_HIGH();
lcd_CS_LOW();
lcd_init();
?

von grundschüler (Gast)


Lesenswert?

hp-freund schrieb:
> lcd_CS_INIT();
> lcd_CS_HIGH();
> lcd_CS_LOW();
> lcd_init();

1
#define lcd_CS_port     B
2
#define lcd_CS_pin      6
3
#define lcd_CS_INIT()    pinDIRout(lcd_CS_port,lcd_CS_pin)  
4
#define lcd_CS_HIGH()    pinSET(lcd_CS_port,lcd_CS_pin);spimode_0
5
#define lcd_CS_LOW()    pinCLR(lcd_CS_port,lcd_CS_pin);spimode_3

kann nicht Fehlerursache sein, weil durch den Wechsel von spi1 auf spi2 
nicht beeinflusst. cs funktioniert,  lcd_init ist für spi1 u. spi2 
identisch.

Ich muss wohl das Signal, das bei spi2/mosi/sck rauskommt, genauer 
untersuchen. Mit meinem china-dso geht das leider nicht. Vielleicht ein 
zweiter uc als slave.

von hp-freund (Gast)


Lesenswert?

grundschüler schrieb:
> lcd_init ist für spi1 u. spi2 identisch.

Wirklich? Zeig mal.
Ist da nicht etwas in der Art von Display_IoInit_If() drin?

von Jojo S. (Gast)


Lesenswert?

Martin schrieb:
> while (SPI2->SR & 1<<(7)) ;

#define  SPI_SR_TXE  ((uint8_t)0x02)      /*!< Transmit buffer Empty */

Bit7 ist das Busy Flag, vor dem Senden soll aber das TX Empty abgefragt 
werden.

von grundschüler (Gast)


Lesenswert?

hp-freund schrieb:
> Display_IoInit_If

Jojo S. schrieb:
> Bit7 ist das Busy Flag, vor dem Senden soll aber das TX Empty abgefragt
> werden.

das ist zutreffend. Mit dem busy-flag ist der code mglw. langsamer, 
funktioniert aber sicher. Wenn es mal geht, kann man das optimieren.

hp-freund schrieb:
> Wirklich? Zeig mal.

gerne:
1
void lcd_init(void)
2
{
3
lcd_spi_init();
4
//Portrait//landscape
5
6
#if ( DISP_ORIENTATION == 0 )//0° grad
7
    lcd_write_reg(0x0003,(1<<12) );   /* importance */
8
#endif
9
#if ( DISP_ORIENTATION == 1 )//90°
10
    lcd_write_reg(0x0003,(1<<12)|(1<<5)|(1<<3) );   /* importance */
11
#endif
12
#if ( DISP_ORIENTATION == 2 )//180°
13
    lcd_write_reg(0x0003,(1<<12)|(1<<4)|(1<<5) );   /* importance */
14
#endif
15
#if ( DISP_ORIENTATION == 3 )//270°
16
    lcd_write_reg(0x0003,(1<<12)|(1<<4)|(1<<3) );   /* importance */
17
#endif
18
19
    lcd_write_reg(0x04,0x0000); /* Scalling Contral */
20
    lcd_write_reg(0x08,0x0202); /* Display Contral 2 */
21
    lcd_write_reg(0x09,0x0000); /* Display Contral 3 */
22
    lcd_write_reg(0x0a,0x0000); /* Frame Cycle Contal */
23
    lcd_write_reg(0x0c,(1<<0)); /* Extern Display Interface Contral 1 */
24
    lcd_write_reg(0x0d,0x0000); /* Frame Maker Position */
25
    lcd_write_reg(0x0f,0x0000); /* Extern Display Interface Contral 2 */     
26
    _delay_ms(50); 
27
    lcd_write_reg(0x07,0x0101); /* Display Contral */
28
    _delay_ms(50);    
29
    lcd_write_reg(0x10,(1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4)); /* Power Control 1 */
30
    lcd_write_reg(0x11,0x0007);                              /* Power Control 2 */
31
    lcd_write_reg(0x12,(1<<8)|(1<<4)|(0<<0));                /* Power Control 3 */
32
    lcd_write_reg(0x13,0x0b00);                              /* Power Control 4 */
33
    lcd_write_reg(0x29,0x0000);                              /* Power Control 7 */
34
    lcd_write_reg(0x2b,(1<<14)|(1<<4)); 
35
  
36
    lcd_write_reg(0x50,0);       /* Set X Start */
37
    lcd_write_reg(0x51,239);      /* Set X End */
38
    lcd_write_reg(0x52,0);      /* Set Y Start */
39
    lcd_write_reg(0x53,319);      /* Set Y End */
40
  _delay_ms(50);
41
    lcd_write_reg(0x60,0x2700); /* Driver Output Control */
42
    lcd_write_reg(0x61,0x0001); /* Driver Output Control */
43
    lcd_write_reg(0x6a,0x0000); /* Vertical Srcoll Control */
44
    
45
    lcd_write_reg(0x80,0x0000); /* Display Position? Partial Display 1 */
46
    lcd_write_reg(0x81,0x0000); /* RAM Address Start? Partial Display 1 */
47
    lcd_write_reg(0x82,0x0000); /* RAM Address End-Partial Display 1 */
48
    lcd_write_reg(0x83,0x0000); /* Displsy Position? Partial Display 2 */
49
    lcd_write_reg(0x84,0x0000); /* RAM Address Start? Partial Display 2 */
50
    lcd_write_reg(0x85,0x0000); /* RAM Address End? Partial Display 2 */
51
    
52
    lcd_write_reg(0x90,(0<<7)|(16<<0)); /* Frame Cycle Contral */
53
    lcd_write_reg(0x92,0x0000);         /* Panel Interface Contral 2 */
54
    lcd_write_reg(0x93,0x0001);         /* Panel Interface Contral 3 */
55
    lcd_write_reg(0x95,0x0110);         /* Frame Cycle Contral */
56
    lcd_write_reg(0x97,(0<<8)); 
57
    lcd_write_reg(0x98,0x0000);         /* Frame Cycle Contral */    
58
    lcd_write_reg(0x07,0x0133); 
59
//  }    
60
    _delay_ms(100);   /* delay 50 ms */    
61
}

von hp-freund (Gast)


Lesenswert?

Wenn das richtige lcd_spi_init(); aufgerufen wird ist das ja schon mal 
in Ordnung.
lcd_write_reg wäre dann die nächste Frage. Geht mir jetzt aber ein wenig 
zu weit.

Ich würde jetzt als Nächstes das lcd_init(); in eine Endlosschleife 
legen und die Ausgaben prüfen.

von grundschüler (Gast)


Lesenswert?

hp-freund schrieb:
> Ich würde jetzt als Nächstes das lcd_init(); in eine Endlosschleife
> legen und die Ausgaben prüfen.

danke erstmal für die Unterstützung. Ich habe für heute genug von STM. 
Ich lass das ganze zunächst auf spi1. Vielleicht probier ich das ganze 
mit ein paar Tagen Abstand noch einmal mit spi2.

von Jojo S. (Gast)


Lesenswert?

Laut Doku ist das Busy für den Slavemode, der Slave soll das Ende 
signalisieren wenn Busy aus ist.

von grundschüler (Gast)


Lesenswert?

Jojo S. schrieb:
> Laut Doku ist das Busy für den Slavemode, der Slave soll das Ende
> signalisieren wenn Busy aus ist.

Der verwendete code stammt von Fat-Elm-Chan, der fragt das bsy-flag ab. 
Müsste eigentlich auch so funktionieren.

Nachdem auch spi1 nicht mehr zuverlässig lief, habe ich die Stm-Vorlage 
ausprobiert:
1
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
2
{
3
  /* Check the parameters */
4
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
5
  
6
  /* Write in the DR register the data to be sent */
7
  SPIx->DR = Data;
8
}

Diese ist etwa 10% langsamer, der Chip lässt sich aber mit hw-spi - 
zumindest spi1 - wieder programmieren.  Möglicherweise ist dieses 
merkwürdige stm-assert_param für den zuverlässigen Betrieb erforderlich.

von Jojo S. (Gast)


Lesenswert?

das assert prüft nur ob der parameter ein gültiger Pointer ist, also 
&SPI1, 2 oder 3.
ST erwähnt im Handbuch mehrfach das TXE Flag zu verwenden, warum sollen 
die lügen?
'Note: Do not use the BSY flag to handle each data transmission or 
reception. It is better to use the
TXE and RXNE flags instead.'
'Note: The software must ensure that the TXE flag is set to 1 before 
attempting to write to the Tx
buffer. Otherwise, it overwrites the data previously written to the Tx 
buffer.'

Ein Unterschied ist ja noch das SPI1/2 um den Faktor 2 unterschiedlich 
schnell sind, da kann das durchaus ein Timingproblem sein. Du hast ja 
geschrieben das auch Daten gesendet werden, aber falsche. Das wäre der 
Effekt wenn die Daten schon während der Übertragung verändert werden.
Hast du denn schon probiert das TXE Flag anstelle des BSY abzufragen?

von grundschüler (Gast)


Lesenswert?

Jojo S. schrieb:
> TXE Flag anstelle des BSY

Ich habe alle erdenklichen Variationen TXE RXNE BSY ausprobiert. 
Prescaler zwischen 2 und 256.

Das Problem ist, dass der Fehler nicht 100% reproduzierbar ist. D.h. 
identischer code geht mal, beim nächsten Flashen dann wieder nicht. 
Gerade funktioniert das LCD mit Prescaler_2/kompletter Bildaufbau 
0,17sec recht ordentlich. Als nächstes werde ich den enc28j60 
anschließen. Probleme gibts dann wahrscheinlich mit dem Wechsel zwischen 
Spimode_0 und Spimode_3.

von grundschüler (Gast)


Lesenswert?

habe das Projekt noch mal neu aufgesetzt. Auf einmal gehts. Bildaufbau 
0,11sec mit optimiertem code:
1
#if STM32F103==1 && use_bitbang==0
2
  SPI2->CR1 |=  _BV(11);  /* Set SPI to 16-bit mode */
3
4
  for( index = 0; index < ((uint32_t)lcd_max_width*lcd_min_width); index++ )  {
5
      while ((SPI2->SR & _BV(1))) ;//0_rxne 1_txe 7_bsy
6
      SPI2->DR = Color;
7
    }
8
    SPI2->DR;//fifo leeren
9
10
  SPI2->CR1 &= ~ _BV(11);  /* Set SPI to 8-bit mode */
11
#else
12
...

von hp-freund (Gast)


Lesenswert?

Schön.
Auch wenn das mit dem code von oben recht wenig zu tun hat :-)

von grundschüler (Gast)


Lesenswert?

Das Problem war, dass sich
     SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
nicht mit der txe/rxne-abfrage verträgt.

     while ((SPI2->SR & _BV(1))) ;//0_rxne 1_txe 7_bsy
ist offensichtlich falsch. gewartet werden soll, solange tx not empty 
ist.

er funktionierte zeitweilig aber trotzdem: Stm-Mysterium

Im fullduplex-modus funktioniert es dann einwandfrei. Entschädigt wird 
man durch eine enorme spi-Geschwindigkeit: 100-facher Bildaufbau in 
7sec.

von Jojo S. (Gast)


Lesenswert?

Wäre vielleicht noch durch DMA zu toppen? Allerdings sind 36 MHz SPI 
auch schon recht zügig, wieviel verträgt das Display denn?
Jedenfalls danke für die Auflösung. Wenn ich meinen STM mal wieder 
rauskrame erinnere ich mich hoffentlich noch an diesen Thread :-)

von grundschüler (Gast)


Lesenswert?

Jojo S. schrieb:
> 36 MHz SPI

240x320x2Bytesx100/7sec ~=2,2 Mbyte/sec. Ein bischen 
TFT-Register-Überbau ist noch dabei. Der Stm ist jedenfalls deutlich 
schneller als ein 100-Mhz LPC1768 mit dem gleichen Code (10sec per SSP).

DMA ist der übernächste Schritt, jetzt kommt erstmal sdio.

von Jojo S. (Gast)


Lesenswert?

grundschüler schrieb:
> Der Stm ist jedenfalls deutlich
> schneller als ein 100-Mhz LPC1768 mit dem gleichen Code (10sec per SSP).

Das passt, der LPC kann max 12,5 MHz, der STM 18 MHz. Ist also 44 % 
schneller und damit werden aus 7 s dann 10 s.
Mehr geht also nicht, beim STM und SPI1 musst du min. einen Teiler von 4 
einstellen um nicht über die 18 MHz zu kommen. Die ~2,2 MB/s sind ~17,6 
MHz, also schon am Limit. Die CPU ist jetzt allerdings nur mit dem 
Display beschäfftigt, wäre die beim DMA frei für andere Rechnerei oder 
wird der Bus trotzdem (teilweise) blockiert?
Beim SPI Takt ist mir noch aufgefallen das tw (Pulsweite SCK) mit 50-60 
ns angegeben ist, wie geht das bei 18 MHz Takt (= 55 ns Periodendauer)?

Nachtrag:
wobei die 12,5 MHz beim LPC nur für die SPI Schnittstelle gelten, die 
SSP die auch SPI kann soll 50 MBit/s schaffen. Ganz schön verwirrend das 
SPI Zeugs.

von grundschüler (Gast)


Lesenswert?

Jojo S. schrieb:
> SPI1 musst du min. einen Teiler von 4

das mit den unterschiedlichen Geschwindigkeiten zwischen spi1 und spi2 
habe ich im manual nicht gefunden. Das TFT hängt jetzt an spi2. Ich 
werde das aber noch einmal wechseln und bei spi1 verschiedene 
Geschwindigkeiten ausprobieren. Vielleicht geht die Begrenzung aber auch 
über die Stm-assert-Parameter. Für irgendwas müssen die ja nützlich 
sein.

> wäre die beim DMA frei für andere Rechnerei
müsste eigentglich so sein, es gibt ja auch mehrere AHB-Busse.

> 12,5 MHz beim LPC nur für die SPI Schnittstelle
Kann ich nicht bestätigen. LPC-Spi ist gefühlt deutlich langsamer. SSP 
war bei 10sec. Wenn ich mein Projekt fertig habe, werde ich mal die 
verschiedenen Geschwindigkeiten bitbang/hwSpi für avr stm und lpc 
gegenüberstellen.

Weißt du wie das mit spi3 und der SWD-Programmierschnittstelle -beide 
A13,A14 - läuft? Kann man dann nicht mehr programmieren?

An spi3 soll ein At45DB32MBit-Speicher, der würde das Board deutlich 
aufwerten:
http://www.ebay.de/itm/291221786470?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

von grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

Mysterium spi2: Mit einem mal ging nichts mehr auf spi2. Mittels 
spi-Selbsttestprogramm konnte festgestellt werden, dass spi2 erst dann 
anläuft, wenn nach der Initialisierung nochmals die spi2-Geschwindigkeit 
mit
SPI2->CR1|=7<<3;// /256
eingestellt wird. Warum, ist für mich nicht nachvollziehbar, denn in der 
Initialisierung war das schon genau so drin:
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;

Der Spi-Selbsttest:
1
#if zucSTM32
2
//input-Register
3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
4
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
6
GPIO_InitStructure.GPIO_Pin = 0xffff;
7
GPIO_Init(GPIO(E), &GPIO_InitStructure);
8
9
10
u8 r=0;
11
n=0;
12
SPI2->CR1&=~(7<<3);
13
lcd_clear(GRAY0);
14
//spi_SLOW();
15
16
//SPI_Cmd(SPI2, DISABLE);
17
SPI1->CR1|=7<<3;// /256 fullspeed==0<<3
18
SPI2->CR1|=7<<3;// /256 fullspeed==0<<3
19
//SPI_Cmd(SPI2, ENABLE);
20
21
//while(PIND&0x10);//warten auf cs low
22
while(GPIOE->IDR&_cs);
23
24
25
//cli();
26
27
//SPDR=0b01010101;
28
SPI1->DR=0b01010101;
29
SPI2->DR=0b01010101;
30
while(
31
//!cs_val &&
32
n < maxarray){//beschreiben des Speichers
33
//array[n]=PIND;
34
array[n]=GPIOE->IDR;
35
n++;
36
}
37
38
//sei();
39
40
//spi_FAST();
41
SPI1->CR1&=~(7<<3);// /4 fullspeed
42
SPI2->CR1&=~(7<<3);SPI2->CR1|=(1<<3);// 
43
for (i=0;i<120;i++){
44
tmp=array[i];
45
  ck=(tmp&(_ck))<<4;//16
46
  lcd_pixel(i+1,150-ck,BLACK);
47
  if (old_ck!=ck){//bei Sprung
48
    for(j=0;j<16+1;j++)lcd_pixel(i,150-j,BLACK);
49
  }//sprung
50
  old_ck=ck;
51
52
53
  mosi=(tmp&(_mosi));//16
54
  lcd_pixel(i+1,170-mosi,RED);
55
  if (old_mosi!=mosi){//bei Sprung
56
    for(j=0;j<16+1;j++)lcd_pixel(i,170-j,RED);
57
  }
58
  old_mosi=mosi;
59
60
  cs=(tmp&(1<<0));//16
61
  lcd_pixel(i+1,190-cs,GREEN);
62
}//for
63
64
//Auswertung
65
old_ck=255;
66
for (n=0;n<120;n++)
67
{
68
tmp=array[n];
69
ck=tmp&_ck;
70
mosi=(tmp&(_mosi));
71
//lgi(1+n%25,14,n);lw("-");lcd_bitweise(tmp);
72
  if (old_ck<ck){//bei Sprung aufwärts ->2.edge
73
  r<<=1;  if (mosi) r++;
74
    for(j=0;j<5+1;j++)lcd_pixel(n,157-j,BLACK);
75
  }//sprung
76
  old_ck=ck;
77
}//for
78
79
lg(9,1);lcd_bitweise(r);
80
#endif

von holger (Gast)


Lesenswert?

>Mysterium spi2:

SPI2 läuft ohne Probleme auch ohne Tricks.

von grundschüler (Gast)


Lesenswert?

holger schrieb:
>>Mysterium spi2:


es kommt zu Überlagerungen zwischen den spi-Registern. Die 
Geschwindigkeit Spi1 ändert sich über das SPI2-Register:

lcd_init();
SPI2->CR1&=~(7<<3);SPI2->CR1|=(2<<3);// spi2 schnell, spi1 schnell
//SPI1->CR1&=~(7<<3);// spi2 langsam, spi1 langsam
lcd_clear(RED);

von ismaell (Gast)


Lesenswert?

holger schrieb:
> Mysterium spi2:
>
> SPI2 läuft ohne Probleme auch ohne Tricks.

So siehts aus.
Ich nutze bei SPI1 eeprom und den enc28j60 und beim spi2 den Touch, ich 
arbeite mit dem STM32F103ZET6.


solche Probleme wie grundschüler hat naja...  .

von grundschüler (Gast)


Lesenswert?

ismaell schrieb:
> solche Probleme wie grundschüler hat naja...  .

Danke für diesen Beitrag.

Inzwischen läuft spi2 wieder. Das Problem lag an der Schreibsequenz:
1
u8 xlcd_spi_write ( u8 dat ){
2
3
SPI2->DR = dat;
4
//_delay_us(50);//ok
5
while (!(SPI2->SR & 1<<0));//0_rxne 1_txe 7_bsy// ok
6
//while (!(SPI2->SR & 1<<1));//0_rxne 1_txe 7_bsy//not ok
7
//  while ((SPI2->SR & _BV(7))) ;//0_rxne 1_txe 7_bsy//not ok
8
return (u8)SPI2->DR;/**/
9
//SPI1->DR = dat;
10
//while (SPI1->SR & _BV(7)) ;
11
//return (u8)SPI1->DR;
12
}

Während bei spi1 bsy- und tx-Flag so funktionieren wie man das erwartet, 
geht bei spi2 nur mit dem rx-Flag. Warum, ist mir unerklärlich.

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.