STM32F103C8T6 + SSD1306 OLED

Tu możesz pisać o swoich problemach z pisaniem programów w języku C/C++ dla STM.
Awatar użytkownika
acid3
User
User
Posty: 466
Rejestracja: czwartek 03 wrz 2015, 22:42
Lokalizacja: Kłopoty-Stanisławy
Kontaktowanie:

STM32F103C8T6 + SSD1306 OLED

Postautor: acid3 » niedziela 15 sty 2017, 20:29

Post ten (pseudo-artykuł) będzie traktował o uruchomieniu magistrali I2C na mikrokontrolerze STM32F103 na malutkiej, taniutkiej, chińskiej płyteczce ewaluacyjnej w połączeniu z malutkim, chińskim ekranikiem OLED o wymiarach 128x32. Z racji tego, że ekran nie lubi komunikować się z uC, a jedynie przyjmuje dane ( no może oprócz odpowiedzi w formie ACK ), zajmiemy się tylko konfiguracja i wysyłaniem danych.

Do pisania używać będziemy środowiska Atollic 7.0.1 Lite. Kwestie ściągnięcia, instalacji i uruchomienia nie będą tu poruszane.

Obsługa wyświetlacza zostanie uruchomiona z wykorzystaniem bibliotek SPL. Dlaczego nie HAL? SPL wciąż cieszy się sporą popularnością, poza tym kod jest, wbrew pozorom, łatwiejszy do zrozumienia.


Poniżej linki do ebay.com do użytych w tym materiale narzędzi: (proszę zgłaszać nie działające linki)

http://www.ebay.ca/itm/STM32F103C8T6-ARM-STM32-Minimum-System-Development-Board-Module-For-Arduino-D-/112035273840?hash=item1a15d29c70:g:CioAAOSwMNxXaqSp

http://www.ebay.com/itm/IIC-I2C-0-91-128x32-white-OLED-LCD-Display-Module-3-3v-5v-For-Arduino-PIC-/152106706368?hash=item236a4425c0:g:BHQAAOSw6btXSWm3


Podstawowa konfiguracja i rozpoczęcie projektu.


Na poczatku wybieramy opcję FILE->NEW->C PROJECT
01_nowy_projekt.jpg
klikamy NEXT

Następnie nadajemy nazwę dla naszego projektu i wybieramy EMBEDDED C PROJECT z ramki po lewej i ATOLLIC ARM TOOLS z prawej strony
02_nazwa_projektu.jpg

klikamy NEXT

Teraz wybieramy procek z jakim mamy do czynienia. Żeby było szybciej, górze mamy okno filtra i wpiszemy tam nazwę naszego kontrolera, czyli STM32F103c8, w tym czasie w oknie DEVICE powinien pojawić się właściwy i na niego klikamy. Automatycznie wypełnią się podstawowe dane łącznie z informacją o dostępnej ilości pamięci FLASH i RAM.
03_wybor_procka.jpg
klikamy NEXT

Następna opcja to wybór biblioteki i opcje optymalizacji, niczego tu nie zmieniamy
04_opcje_toolchaina.jpg
klikamy NEXT

Wybieramy programator. Z racji, że używam J-LINK'a (w sumie jego klona) na obrazku własnie ten jest wybrany, ale są tam inne opcje i należy wybrać własciwą i odpowiednią dla nas i naszego sprzętu.
05_programator.jpg
klikamy NEXT

I na koniec możemy wybrać konfiguracje z jakimi będziemy pracować, ja zawszę zostawiam jak jest, czyli opcje Debug oraz Release. Z reguły używam tylko opcji Debug, dlatego że tylko pracuję nad projektem, a nie wcielam go w życie w jakimś urządzeniu. :D
06_wynik_kompilacji.jpg
klikamy FINISH

Na naszym ekranie powinno pojawić się coś w ten desń
07_restore.jpg
klikamy RESTORE, tam gdzie wskazuje strzałka i powinno pojawić się nam to:
08_organizacja_srodowiska.jpg
Strzałkami zaznaczone jest:
1 - Outline, to możemy zminimalizować, raczej nam to nie będzie potrzebne
2 - Information Center, to polecam zamknąć, bo raczej przeglądarka ze stroną informacyjną Atollica nam się nie przyda
3 - Tu przełączamy na CONSOLE, jest to najważniejsze miejsce zawierające wszystko o wynikach naszej kompilacji, czyli błędy, ostrzeżenia
4 - Build Analyzer, .. to niestety nie będzie nam potrzebne, dlatego, że jest to opcja działająca w wersji PRO Atollica.

W edytorze pliku main.c ja z reguły pozbywam się całej wygenerowanej automatycznie zawrtości, dlatego że w większości zawiera dane debbugera i opcje dla zestawów, których nie posiadamy.
09_main_clean.jpg
CTRL-A i DEL :D


plik main.c

I tu się wszystko zaczyna. Na początek zaczynamy od “inkludowania” najpotrzebniejszych plików systemowych.

Kod: Zaznacz cały

#include <string.h>   //zawiera memset
#include <stm32f10x.h> // to wszystkie podstawowe (i nie tylko) "cechy" naszego mikrokontrolera
#include <ssd1306.h>   // a to pliczek zawierający komendy dzięki którym możemy sterować ekranem


Teraz kolej na definicje funkcji które będziemy konstruować

Kod: Zaznacz cały

void oled_init(void);   // funkcja inicjalizująca nasz ekran
void oled_cls(void);   // funkcja czyszcząca
void update_screen(void);   // funkcja wysyłająca zawartość bufora do sterownika ekranu



Teraz zajmiemy się utworzeniem tabeli zawierającej zestaw komend odpowiedzialnych za inicjalizację wyświetlacza. ( i tu należą się wielkie podziękowania koledze Antystatycznemu za znalezienie i optymalizację sekwencji inicjalizującej ten wyświetlacz ). Tablica jest static, by była widoczna tylko w tej jednostce kompilacji:

Kod: Zaznacz cały

static uint8_t Init_Table[]=
{
      SSD1306_DISPLAYOFF,
      SSD1306_SETLOWCOLUMN,
      SSD1306_SETHIGHCOLUMN,
      SSD1306_SETPAGESTARTADDRESS,
      SSD1306_SETSTARTLINE,
      SSD1306_SEGREMAP | 0x01,
      SSD1306_SETCOMPINS,
      0x02,   /* Set com pins data. */
      SSD1306_SETDISPLAYOFFSET,
      0x00,   /* Set display offset data. No offset. */
      SSD1306_COMSCANDEC,
      SSD1306_NORMALDISPLAY,
      SSD1306_DISPLAYALLON_RESUME,
      SSD1306_SETCONTRAST,
      0x01,   /* Set contrast data. */
      SSD1306_MEMORYMODE,
      0x00,   /* Memory addressing mode data. Horizontal addressing. */
      SSD1306_SETMULTIPLEX,
      0x1F,   /* Set MUX ratio data. 1/32 duty cycle. */
      SSD1306_SETPRECHARGE,
      0xF1,   /* Set pre-charge period data. */
      SSD1306_SETVCOMDESELECT,
      0x40,   /* Set V com deselect data. */
      SSD1306_CHARGEPUMP,
      0x14,   /* Charge pump setting data. */
      SSD1306_DISPLAYON,
}



Zadeklarujmy jeszcze bufor, który odzwierciedla całą pamięć graficzną naszego wyświetlaczyka. SSD1306_Width, SSD_Height to makra zdefiniowane w pliku SSD1306.h i definiują szerokość i wysokość ekranu.

Kod: Zaznacz cały

static uint8_t buffer [ SSD1306_Width * SSD_Height / 8 ];


Ekran składa się z czterech stron ułożonych poziomo. Każda strona składa się ze 128-miu bajtów. Każdy bajt strony to osiem pikseli (bitów) na ekranie ułożonych w pionie.

ekran.jpg

Jak widzimy na obrazku wpisanie do pierwszego bajtu bufora liczby 1 zaświeci nam punkt w lewym górnym rogu
ekran_0x01.jpg
a jeżeli wpiszemy 0xFF (255, czyli wypełnimy bajt jedynkami) zaświeci się nam pionowa linia po lewej stronie ekranu. Linia ta symbolizuje też wysokość pierwszej strony pamięci wyświetlacza.
ekran_0xFF.jpg

----------------------------------------------------------------------------------------------

Zaczynamy z właściwym programem.

Na początek trzeba zainicjalizować piny odpowiedzialne za I2C. Dla F103 są to PB6 i PB7 - SCL,SDA. Zaczynamy więc od przypisana Definicji Typu Inicjalizacyjnego dla portów wejścia-wyjścia ogólnego przeznaczenia:

Kod: Zaznacz cały

GPIO_InitTypeDef gpio;


Aby móc korzystać z portów GPIO [ i nie tylko ] na mikrokontrolerach z rdzeniem Cortex-M3 [ i nie tylko ] koniecznie trzeba (należy?) zacząć konfigurację portu od uruchomienia sygnału zegarowego dla danego peryferium. W tym przypadku będzie to:

Kod: Zaznacz cały

RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB);


Kolejną rzeczą jaką musimy zrobić to “odblokować” alternatywne funkcje pinów. Jest to nam niezbędne do uruchomienia wbudowanego, sprzętowego I2C:

Kod: Zaznacz cały

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);


Następnym krokiem jest uruchomienie magistrali I2C:

Kod: Zaznacz cały

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);


I teraz, kiedy mamy już włączone podstawowe elementy uC, możemy skonfigurować właściwe piny. Najpierw struktura inicjalizacji GPIO (ta, którą powołaliśmy do życia chwilę wcześniej):

Kod: Zaznacz cały

GPIO_StructInit(&gpio);


Ustalmy, z którymi pinami chcemy pracować:

Kod: Zaznacz cały

gpio.GPIO_pin = GPIO_Pin_6 | GPIO_Pin_7;       // SCL, SDA odpowiednio



Następnie podajemy informację o tym, że w/w piny będą pracować ze swoją alternatywną funkcją:

Kod: Zaznacz cały

gpio.GPIO_Mode = GPIO_Mode_AF_OD;      // alternatywna funkcja, Open Drain


(*OD oznacza Open Drain, I2C wymaga aby jego piny pracowały w ten sposób)...to chyba kazdy wie, co? A jeśli nie wie, to RTFM


Kolejnym krokiem konfiguracji pinów jest określenie maksymalnej prędkości, z jaką mogą pracować:

Kod: Zaznacz cały

gpio.GPIO_Speed = GPIO_Speed_50MHz;


(umawiamy się na 50 MHz, czyli maksimum dla tego procesora. Nie zasilamy układu bateryjnie, więc nie musimy się zbytnio przejmować oszczędzaniem energii).
I na koniec wstępu do początku wcielimy w życie strukturę, którą właśnie skonfigurowaliśmy:

Kod: Zaznacz cały

GPIO_Init(GPIOB, &gpio);


Kolejny etap to konfiguracja I2C.

Jak przy konfiguracji pinów powołujemy do życia strukturę inicjalizacyjną magistralę.

Kod: Zaznacz cały

I2C_InitTypeDef i2c;
I2C_StructInit(&i2c);


Tak samo jak w przypadku GPIO będziemy ustawiać teraz parametry pracy I2C.

Ustalimy tutaj coś, co możemy nazwać wypełnieniem zegara. Mamy do wyboru dwie opcje 2 i 16/9. Chodzi o stosunek długości stanu niskiego do stanu wysokiego na wyjściu zegarowym szyny. Nas interesuje opcja 2, czyli stosunek stanów zegara wynosi 1:1..

Kod: Zaznacz cały

   i2c.I2C_DutyCycle = I2C_DutyCycle_2;


Przypisanie adresu układu MASTER (W naszym przypadku nieistotne):

Kod: Zaznacz cały

   i2c.I2C_OwnAddress1 = 0x00;


Włączenie żądania (oczekiwania) na odpowiedź od urządzenia

Kod: Zaznacz cały

   i2c.I2C_Ack = I2C_Ack_Enable;


Teraz decydujemy o długości adresów układów , z którymi będziemy się komunikować. Możliwe opcje to adres 7 bitowy lub 10 bitowy. Większość układów SLAVE posiada 7 bitowy adres. Aby uniknąć pomyłki, zawsze należy zajrzeć do dokumentacji wykorzystywanego układu SLAVE.

Kod: Zaznacz cały

   i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;


W tym miejscu decydujemy w jakim trybie będzie pracowała nasza magistrala ( do wyboru jest jeszcze SMBus_Host i SMBus_Device, ale to nas nie interesuje)

Kod: Zaznacz cały

   i2c.I2C_Mode = I2C_Mode_I2C;


… oraz, co bardzo ważne, ustalamy prędkość z jaką nasze urządzenia będą się komunikować (tu też bardzo ważne jest dokładne przeczytanie Datasheeta naszego wyświetlacza, czy czegokolwiek innego, bo właśnie tam producent podaje wartości z jakimi układ może pracowac. W naszym przypadku jest również ważna errata do DS, gdzie dowiadujemy się, iż nasz oledzik pracuje poprawnie tylko z prędkością 400KHz)

Kod: Zaznacz cały

   i2c.I2C_ClockSpeed = 400000;


Inicjalizujemy strukturę

Kod: Zaznacz cały

   I2C_Init(I2C1, &i2c);


i włączamy “peryferium” (cudne słowo)

Kod: Zaznacz cały

   I2C_Cmd(I2C1, ENABLE);



KONIEC CZĘŚCI PIERWSZEJ, NIE OSTATNIEJ.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
acid3
User
User
Posty: 466
Rejestracja: czwartek 03 wrz 2015, 22:42
Lokalizacja: Kłopoty-Stanisławy
Kontaktowanie:

Re: STM32F103C8T6 + SSD1306 OLED

Postautor: acid3 » sobota 21 sty 2017, 20:08

Druga część “kursu” (fakt, to wielkie słowo) opisywać będzie inicjalizację ekranu.

Na początek drobne uzupełnienie części pierwszej. Aby ułatwić sobie życie i za każdym razem nie pisać serii bajtów chcąc wyświetlić literę, stwórzmy sobie tablicę znaków (konkretnie liter) do późniejszego wykorzystania. Znaki zawierają się w matrycy 5x8 i są stałej szerokości.


Kod: Zaznacz cały

static uint8_t litery [26][5] = {
      {0xFE,0x11,0x11,0x11,0xFE},      // A - 0
      {0xFF0x89,0x89,0x89,0x76},      // B - 1
      {0x7E,0x81,0x81,0x81,0x42},      // C - 2
      {0xFF,0x81,0x81,0x42,0x0c},      // D - 3
      {0xFF,0x89,0x89,0x81,0x81},      // E - 4
      {0xFF,0x09,0x09,0x01,0x01},      // F - 5
      {0x7E,0x81,0x81,0x91,0x72},      // G - 6
      {0xFF,0x08,0x08,0x08,0xFF},      // H - 7
      {0x00,0x00,0xFF,0x00,0x00},      // I - 8
      {0x41,0x81,0x81,0x41,0x3F},      // J - 9
      {0xFF,0x18,0x24,0x42,0x81},      // K - 10
      {0xFF,0x80,0x80,0x80,0x80},      // L - 11
      {0xFF,0x02,0x04,0x02,0xFF},      // M - 12
      {0xFF,0x0c,0x18,0x30,0xFF},      // N - 13
      {0x7E,0x81,0x81,0x81,0x7E},      // O - 14
      {0xFF,0x09,0x09,0x09,0x06},      // P - 15
      {0xFF,0x11,0x31,0x51,0x8E},      // R - 16
      {0x86,0x89,0x89,0x89,0x71},      // S - 17
      {0x01,0x01,0xFF,0x01,0x01},      // T - 18
      {0x7F,0x80,0x80,0x80,0x7F},      // U - 19
      {0xFF,0x30,0x18,0x30,0xFF},      // W - 20
      {0x03,0x0c,0xf0,0x0c,0x03},      // Y - 21
      {0xE1,0x91,0x89,0x85,0x83},      // Z - 22
      {0x00,0xc0,0xc0,0x00,0x00}      // kropka - 23
};


matryca5x8.jpg


Jak widać na załączonym obrazku wzór litery składa się z pięciu bajtów. Każdy z nich odpowiada za pionową linię o wysokości 8 punktów (bitów). I tak 5 bajtów = 5 pionowych linii składających się na literę.


A teraz przejdźmy do bardziej twórczych rzeczy i napiszmy funkcję oled_init.

Kod: Zaznacz cały

void oled_init(){       // początek funkcji
unit8_t i;      // deklarujemy sobie zmienną pomocniczą, która będzie nam potrzebna do wysyłania danych


Na początku musimy wysłać sygnał START

Kod: Zaznacz cały

I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);


Zgodnie z protokołem następny musi być adres urządzenia odbierającego nasze dane

Kod: Zaznacz cały

I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);


Teraz musimy wysłać informację czy wysyłane dane będą komendą, czy danymi

Kod: Zaznacz cały

I2C_SendData(I2C1, 0x80);            // 0x80 to informacja dla sterownika ekranu, że dane, które będą za chwilę wysyłane, są komendami konfiguracyjnymi (ustawieniami) i tak należy je traktować


Teraz możemy wysyłać dane(komendy) do sterownika

Kod: Zaznacz cały

for (i = 0; i < sizeof(Init_Table); i++) {      // pętla, w której wyślemy dane zawarte w tablicy inicjalizacyjnej
I2C_SendData(I2C1, Init_Table[i]);      // wysyłanie właściwe
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
    };


i na koniec, zgodnie z protokołem, generujemy sygnał STOP

Kod: Zaznacz cały

I2C_GenerateSTOP(I2C1, ENABLE);


Po takim zestawie instrukcji nasz ekran jest gotowy do przyjmowania danych i wyświetlania tego, co się nam zamarzy.

Najpierw jednak musimy nauczyć się czyścić (usuwać) zawartość ekranu. Musimy, dlatego że tuż po inicjalizacji na ekranie (z reguły) pojawią się bliżej nieokreślone hieroglify. Spowodowane jest to tym, że po włączeniu zasilania w pamięci naszego sterownika znajdują się losowe dane.

Kod: Zaznacz cały

void oled_cls(void){
memset (buffer, 0x00, sizeof(buffer));
}


i tyle …
Nasza funkcja czyszcząca ekran, za pomocą instrukcji memset wpisuje do naszego bufora zera (0x00) i skutkuje to tym, że wszystkie nasze piksele nie są podświetlone, a więc ekran jest czarny i “wyczyszczony”,

Zostaje to wszystko jednak tylko w naszym programie(w zmiennej buffer w pamięci naszego procka), a na ekranie wciąż są śmieci. Należy teraz uzbroić się w funkcję update_screen(). Będzie ona wysyłać zawartość zmiennej buffer do pamięci sterownika naszego wyświetlacza.

Kod: Zaznacz cały

void update_screen(void){
uint16_t o;
    I2C_GenerateSTART(I2C1, ENABLE);      // jak przy każdej transmisji generujemy START
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

    I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);    // wysyłamy ADRES urządzenia
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);

    I2C_SendData(I2C1, 0x80);       // wysyłamy informację, że za chwilę będą komendy

    I2C_SendData(I2C1, 0x00);      // dolna połówka licznika kolumn (zerowanie)
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);

    I2C_SendData(I2C1, 0x10);      // górna połówka licznika kolumn (zerowanie)
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);

    I2C_SendData(I2C1, 0xB0);      // licznik  stron pamięci (zerowanie tegoż licznika)
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);

    I2C_GenerateSTOP(I2C1, ENABLE);    // teraz STOP

    I2C_GenerateSTART(I2C1, ENABLE);   // i znowu START
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

    I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);      // ADRES
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);

    I2C_SendData(I2C1, 0x40);      // informacja, że tym razem wysyłamy dane
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);

    for (o=0; o < sizeof(buffer); o++){      // i pętla o wielkości naszego bufora
       I2C_SendData(I2C1, buffer[o]);   // wysyłanie kolejnych bajtów bufora (pamięci ekranu?)
       while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
    };

    I2C_GenerateSTOP(I2C1, ENABLE);   // i generujemy STOP
}



Z grubsza mamy już większość rzeczy jakie są nam potrzebne i możemy przejść do właściwego programu i zacząć coś wyświetlać. Po konfiguracji GPIO i I2C powinniśmy wywołać funkcję inicjującą

Kod: Zaznacz cały

oled_init();


następnie wstępnie wyczyśćmy bufor ekranu

Kod: Zaznacz cały

oled_cls();


A więc czas na jakieś bardziej “widowiskowe” działanie.


( to co teraz nastąpi może być szkodliwe dla zdrowia psychicznego programistów, może skutkować zaplutym monitorem i mieć inne negatywne skutki — ale zostało to popełnione z pełną świadomością, że tak się nie robi, że tak się nie pisze i nie powinno tak być )

Wyświetlimy teraz “jakiś” napis na pierwszej stronie wyświetlacza.

Kod: Zaznacz cały

   uint8_t i;
   uint8_t u;

   u = 0;
   for (i=0; i<5; i++) buffer[i] = litery[12][u++];
   u = 0;
   for (i=6; i<11; i++) buffer[i] = litery[8][u++];
   u = 0;
   for (i=12; i<17; i++) buffer[i] = litery[2][u++];
   u = 0;
   for (i=18; i<23; i++) buffer[i] = litery[16][u++];
   u = 0;
   for (i=24; i<29; i++) buffer[i] = litery[14][u++];
   u = 0;
   for (i=30; i<35; i++) buffer[i] = litery[6][u++];
   u = 0;
   for (i=36; i<41; i++) buffer[i] = litery[4][u++];
   u = 0;
   for (i=42; i<47; i++) buffer[i] = litery[4][u++];
   u = 0;
   for (i=48; i<53; i++) buffer[i] = litery[10][u++];
   u = 0;
   for (i=54; i<59; i++) buffer[i] = litery[23][u++];
   u = 0;
   for (i=60; i<65; i++) buffer[i] = litery[4][u++];
   u = 0;
   for (i=66; i<71; i++) buffer[i] = litery[19][u++];



:D

KONIEC CZĘŚCI DRUGIEJ … NIE OSTATNIEJ
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: STM32F103C8T6 + SSD1306 OLED

Postautor: Antystatyczny » sobota 21 sty 2017, 20:14

Super artykuł! A będziesz opisywał skalowanie czcionek?
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
acid3
User
User
Posty: 466
Rejestracja: czwartek 03 wrz 2015, 22:42
Lokalizacja: Kłopoty-Stanisławy
Kontaktowanie:

Re: STM32F103C8T6 + SSD1306 OLED

Postautor: acid3 » sobota 21 sty 2017, 20:22

Antystatyczny pisze:A będziesz opisywał skalowanie czcionek?


Nie przewidywałem tego (na obecną chwilę), dlatego że mam inne plany. A nie chcę tu podawać gotowców, a jedynie pokazać kierunek działań w celu uruchomienia i dalszej pracy już we własnym zakresie. Przy czym niczego nie można wykluczyć ... ( no i Ty musiałbyś mieć czas i cierpliwość na pomoc dla mnie w tym temacie :D )

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: STM32F103C8T6 + SSD1306 OLED

Postautor: Antystatyczny » sobota 21 sty 2017, 20:24

No dobra, to może coś wspólnie wykombinujemy. Wszystko rozbija się o ilość wolnego czasu i uruchomionych projektów.
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
acid3
User
User
Posty: 466
Rejestracja: czwartek 03 wrz 2015, 22:42
Lokalizacja: Kłopoty-Stanisławy
Kontaktowanie:

Re: STM32F103C8T6 + SSD1306 OLED

Postautor: acid3 » środa 25 sty 2017, 20:01

W części trzeciej trochę się wytłumaczę ….

To co nastąpiło powyżej, cały ten chaos i brak organizacji jest celowym zabiegiem. Tak samo pewne niedopowiedzenia lub brak w elementach kodu pewnych strategicznych wpisów. Chciałem zmusić pokolenie Copy&Paste (bez urazy) do samodzielnego myślenia lub do drążenia tematu na forum za pomocą postów... Wyszłoby to wszystkim na dobre, tak dla mnie(też się dopiero uczę), dla pytającego jak i dla wszystkich, którzy w przyszłości trafią na ten temat, próbując bezskutecznie uruchomić taki wyświetlacz na takim lub podobnym “procesorku” (wiem, że to jest mikrokontroler, ale lubię to określenie). Dzięki różnym pytaniom różnych ludzi wyjaśniło by się pewnie wiele drobnych ludzkich pomyłek, “niezrozumień” bądź zwykłych niedopatrzeń i błędów typu rc=-1...

Moim celem jest pokazanie jak zacząć, a nie dostarczyć gotową bibliotekę. Jeśli ktoś ma ochotę pracować z gotowcami to gorąco polecam Arduino lub mbed. Są to bardzo fajne środowiska, których sam czasem używam i dzięki którym można zbudować bardzo ciekawe urządzenia w relatywnie krótkim czasie (prościej mówiąc – bardzo szybko ).

Tutaj chciałbym, razem z Wami, czegoś się nauczyć.

Jeśli będzie taka potrzeba i pomoc na forum nie przyniesie efektu, udostępnię cały projekt z Atollic’a jako paczkę do pobrania. Będzie to dokładnie to samo co powstało podczas pisania tego artykułu, więc z założenia powinno działać bez najmniejszych problemów.

Poniżej zawartość pliku SSD1306.h, potrzebna do uruchomienia.

Kod: Zaznacz cały

#define SLAVE_ADDRESS                        0x78

#define SSD1306_WIDTH                           128
#define SSD1306_HEIGHT                           32

#define SSD1306_COLOR_BRIGHT                     0xFF
#define SSD1306_COLOR_DARK                        0x00

/* SSD1306 commands. */
#define SSD1306_SETLOWCOLUMN                      0x00
#define SSD1306_EXTERNALVCC                         0x01
#define SSD1306_SWITCHCAPVCC                      0x02
#define SSD1306_SETHIGHCOLUMN                      0x10
#define SSD1306_MEMORYMODE                         0x20
#define SSD1306_COLUMNADDR                         0x21
#define SSD1306_PAGEADDR                           0x22
#define SSD1306_RIGHT_HORIZONTAL_SCROLL                0x26
#define SSD1306_LEFT_HORIZONTAL_SCROLL                0x27
#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL       0x29
#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL       0x2A
#define SSD1306_DEACTIVATE_SCROLL                   0x2E
#define SSD1306_ACTIVATE_SCROLL                      0x2F
#define SSD1306_SETSTARTLINE                      0x40
#define SSD1306_SETCONTRAST                      0x81
#define SSD1306_CHARGEPUMP                         0x8D
#define SSD1306_SEGREMAP                         0xA0
#define SSD1306_SET_VERTICAL_SCROLL_AREA                0xA3
#define SSD1306_DISPLAYALLON_RESUME                   0xA4
#define SSD1306_DISPLAYALLON                      0xA5
#define SSD1306_NORMALDISPLAY                      0xA6
#define SSD1306_INVERTDISPLAY                      0xA7
#define SSD1306_SETMULTIPLEX                      0xA8
#define SSD1306_DISPLAYOFF                         0xAE
#define SSD1306_DISPLAYON                         0xAF
#define SSD1306_SETPAGESTARTADDRESS                  0xB0
#define SSD1306_COMSCANINC                         0xC0
#define SSD1306_COMSCANDEC                         0xC8
#define SSD1306_SETDISPLAYOFFSET                      0xD3
#define SSD1306_SETDISPLAYCLOCKDIV                   0xD5
#define SSD1306_SETPRECHARGE                      0xD9
#define SSD1306_SETCOMPINS                         0xDA
#define SSD1306_SETVCOMDESELECT                     0xDB


Wróć do „Programowanie STM w C/C++”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości