Skocz do zawartości
Vroobee

[STM32] STM32F3x problem z uruchomieniem wyświetlacza graficznego - SPI

Pomocna odpowiedź

Witam,
chciałem dzisiaj podłączyć wyświetlacz z kursu STM32 pod Nucleo F303K8x. Kod spróbowałem pisać sam, jednak sprawdzając wielokrotnie z kodem z kursu (oczywiście z pozamienianymi rejestrami GPIO itp.) powinno być tak samo i działać, a nie działa. Może ktoś próbował np. na Discovery uruchamiać (podobne procki) i połapie gdzie jest błąd. Mi skończyły się pomysły :/

#include "stm32f30x.h"
#include <stdint.h>
#include <stdio.h>

#define LCD_DC GPIO_Pin_0
#define LCD_CE GPIO_Pin_7
#define LCD_RST GPIO_Pin_6
#define LCD_BL GPIO_Pin_12

const unsigned char logo_mini_mono [] = {
0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x7F, 0x7F, 0x7F, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0x3F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x01, 0x01, 0x02, 0x00, 0x04, 0x08, 0xF8,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF9, 0xFB, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0xE0, 0x0C, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03,
0x03, 0x81, 0x81, 0x81, 0xC1, 0xC0, 0xC0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xFC,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F,
};

uint8_t spi_sendrecv(uint8_t byte){
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData16(SPI1, byte);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData16(SPI1);
}

void lcd_reset(){
GPIO_ResetBits(GPIOB, LCD_RST);
GPIO_SetBits(GPIOB, LCD_RST);
}

void lcd_cmd(uint8_t cmd){
GPIO_ResetBits(GPIOB, LCD_CE|LCD_DC);
spi_sendrecv(cmd);
GPIO_SetBits(GPIOB, LCD_CE);
}

void lcd_data(const uint8_t* data, int size){
int i;
GPIO_SetBits(GPIOB, LCD_DC);
GPIO_ResetBits(GPIOB, LCD_CE);
for (i = 0; i < size; i++) {spi_sendrecv(data[i]);}
GPIO_SetBits(GPIOB, LCD_CE);
}

int main(void){
GPIO_InitTypeDef gpio;
SPI_InitTypeDef spi;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

GPIO_StructInit(&gpio);
SPI_StructInit(&spi);

//BL
gpio.GPIO_Pin = GPIO_Pin_12;
gpio.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOA, &gpio);

//MOSI, SCK
gpio.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_3;
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_PuPd = GPIO_PuPd_UP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_5);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_5);

//MISO
gpio.GPIO_Pin = GPIO_Pin_4;
gpio.GPIO_Mode = GPIO_Mode_IN;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
gpio.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &gpio);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_5);

gpio.GPIO_Pin = LCD_DC|LCD_RST|LCD_CE;
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio);
GPIO_SetBits(GPIOB, LCD_CE|LCD_RST);

spi.SPI_Mode = SPI_Mode_Master;
spi.SPI_NSS = SPI_NSS_Soft;
spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_Init(SPI1,&spi);
SPI_Cmd(SPI1,ENABLE);


GPIO_SetBits(GPIOA, LCD_BL);

lcd_reset();
lcd_cmd(0x21);
lcd_cmd(0x14);
lcd_cmd(0x80 | 0x35); //Ustawienie kontrastu
lcd_cmd(0x20);
lcd_cmd(0x0c);

lcd_data(logo_mini_mono, sizeof(logo_mini_mono));

while(1){

}
}

Dodam, że wyświetlacz coś wyświetla tylko nie jest to logo Forbota. Zmiana kontrastu działa, więc nie jest to wina wyświetlacza.

__________

Komentarz dodany przez: Treker

Udostępnij ten post


Link to post
Share on other sites

Próbowałeś wyświetlać coś innego ? Sam kiedyś uruchamiałem ten wyświetlacz, ale było to dawno. Jednak nadal pamiętam, że miałem podobne białe rzędy pikseli odstępu przy wyświetlaniu. Chyba wtedy szukałem rozwiązania w inicjalizacji wyświetlacza. Dlatego na początku spróbuj wyświetlić np dwie skrzyżowane linie i zobacz czy jedna będzie poprzecinana tymi białymi odstępami.

Nie wiem jak dokładnie jest z tym wyświetlaczem, ale o ile coś wyświetla znaczy to, że poprawnie się zainicjował. Tak więc SPI powinno być w porządku.

Udostępnij ten post


Link to post
Share on other sites

Wyświetlać wyświetla ale mam wrażenie, że tylko co drugą linijkę. Dla potwierdzenia - miał wyświetlać tablicę z samymi 0xFF. A wyświetla kreski.

Udostępnij ten post


Link to post
Share on other sites

A widzisz, czyli Twój wyświetlacz ma tę samą przypadłość co mój. Na pewno znajdziesz rozwiązanie w internecie, bo po wpisaniu hasła do wyszukiwarki widzę, że nie my jedyni mieliśmy taki problem.

Udostępnij ten post


Link to post
Share on other sites

Dodam jeszcze, że ten sam program wrzucony na Nucleo F103RB działa normalnie i wyświetla dobrze....

[ Dodano: 24-03-2016, 20:52 ]

Poza tym już próbowałem chyba wszystkiego. Zmieniałem konfigurację SPI, typy zmiennych, próbowałem zmieniać coś w funkcjach wyświetlania i nic.

Udostępnij ten post


Link to post
Share on other sites

Masz może pod ręką analizator stanów logicznych ? Wtedy można by było porównać obie inicjalizacje i zobaczyć co jest nie tak z drugą. Jak to jest z prędkościami SPI - są jednakowe dla obu zestawów ?

Udostępnij ten post


Link to post
Share on other sites

Analizatora nie mam. Prędkość SPI w F103RB jest do 18 Mbit/s, dla F303K8 nie mogę znaleźć prędkości. Podejrzewam, że może być taka sama.

Udostępnij ten post


Link to post
Share on other sites
Podejrzewam, że może być taka sama.

No niestety, ale samo podejrzewanie nie pomoże nam rozwiązać problemu 😉

Sprawdź na jakiej prędkości chodzi ( nie jaka jest maksymalna ) SPI w jednym i w drugim zestawie. Jak nie zadziała zmiana prędkości SPI, spróbuj poczytać dokumentację PCD8544 i zobacz czy nie ma tam nic o zwiększaniu adresów kolumn i wierszy.

Udostępnij ten post


Link to post
Share on other sites

Zmieniałem prescaler od 2 do 256 i nic. Adresowanie kolumn jest od 0-83, wierszy od 0-5. Nic się nie zmienia w kodzie zarówno na F3x jak i na F1x. Inne są tylko rejestry GPIO i funkcji alternatywnych. A wyświetlacz jakby wciąż wyświetlał obraz w kolumnach 0,2,4 ....

Udostępnij ten post


Link to post
Share on other sites
Nic się nie zmienia w kodzie zarówno na F3x jak i na F1x

Ale rozumiem na F1x wszystko jest w porządku niezależnie od prędkości ?

Co do tych adresów, nie chodziło mi o ich ilość, tylko żeby zobaczyć czy przypadkiem nie masz zamienionych x z y. Pomyślałem że sterownik mógłby chcieć "rozciągnąć" te 48 linii na 84 linie i dlatego co druga jest biała. Spróbuj zamienić x z y przy inicjalizacji ( powinien być do tego rejestr ) i zobacz czy linie będą poziome, czy może wszystko będzie w porządku.

Jeszcze użyj inicjalizacji z wątku : http://forum.atnel.pl/topic2115.html

z komentarza kolegi savian86. Jak widzę jest tam coś o adresowaniu.

Udostępnij ten post


Link to post
Share on other sites

O ile pamiętam, STM32F1 mają prostsze SPI i tam ramka ma zawsze 8 bitów. F3x mają fajniejszy SPI z ramką programowaną od 4 do 16 bitów. Jeżeli tutaj domyślnie jest np. 16 bitów, to za każdym razem wysyłasz dwa bajty. Może inicjalizacji to nie przeszkadza, a przy zapisie do pamięci obrazu robi się kaszana?

Udostępnij ten post


Link to post
Share on other sites

Próbowałem już też z taką inicjalizacją SPI bo też zauważyłem, że F303 ma 16 bitowe wysyłanie, i dalej nic:

    spi.SPI_Mode = SPI_Mode_Master;
   spi.SPI_NSS = SPI_NSS_Soft;
   spi.SPI_DataSize = SPI_DataSize_8b;
   spi.SPI_FirstBit = SPI_FirstBit_MSB;
   spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
   SPI_Init(SPI1,&spi);
   SPI_Cmd(SPI1,ENABLE);

Wszelkie możliwe full duplexy, polaryzację zegara, reakcję na zbocze itp. itd też wypróbowałem.

Przy okazji sprawdziłem jeszcze funkcję wysyłającą. Zauważyłem, że jest tam zapis:

SPI_I2S_SendData16(SPI1, byte);

,
a przecież funkcja wysyła uint8_t. Zmieniłem na:

SPI_SendData8(SPI1, byte);

no i niestety pudło. Na ekranie już zupełnie nic się nie pokazywało.

Udostępnij ten post


Link to post
Share on other sites

Ja bym nie odpuszczał tylko podrążył temat. To że nic nie widać nie oznacza, ze jest gorzej. W kodzie może być więcej błędów i jeden przykrywa drugi. Czy ta funkcja jest jedynym sposobem wysłania wszystkiego co LCD, czy np. komendy są wysyłane inaczej a dane inaczej (tj. w innym miejscu biblioteki)?

Udostępnij ten post


Link to post
Share on other sites

Jeśli chodzi o wysyłanie komend na wyświetlacz to wykorzystuję funkcję:

void lcd_cmd(uint8_t cmd){
GPIO_ResetBits(GPIOB, LCD_CE|LCD_DC);
spi_sendrecv(cmd);
GPIO_SetBits(GPIOB, LCD_CE);
}

która z kolei wykorzystuje funkcję wysyłania pojedynczego bajtu przez SPI:

uint8_t spi_sendrecv(uint8_t byte){
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData16(SPI1, byte);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData16(SPI1);
}

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...