Skocz do zawartości

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


Pomocna odpowiedź

Napisano

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

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.

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.

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.

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.

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 ?

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.

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.

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 ....

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.

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?

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.

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)?

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);
}

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...