Textausgabe an das OLED-Display mit SH1106-Controller über SPI-Bus über HAL-Bibliothek

Hallo liebe Leser. Bei meinen Entwicklungen auf STM32-Mikrocontrollern verwende ich OLED-Displays auf dem SSD1306-Chip, um aussagekräftige Informationen anzuzeigen. Das letzte Mal, als ein 1,3-Zoll-Display zu einem demokratischen Preis zu mir kam - ungefähr 200 Rubel. Das erste, was mir auffiel, war die Inschrift SH1106 anstelle von SSD1306. Eine Suche im Internet machte deutlich, dass dies fast das gleiche ist, nur der einzige Seitenadressierungsmodus ist noch vorhanden Es wird in dieser Veröffentlichung versuchen zu erklären, wie man damit arbeitet.

Vor ungefähr einem Jahr begann ich, die Fähigkeiten der blauen Pille (STM32F103) zu vermissen, und das chinesische Entwicklungsboard STM32F407VE wurde bestellt. Zum Debuggen reichen oft zwei LEDs nicht aus. Deshalb verbinde ich in jedem Projekt die OLED SSD1306 über den I2C-Bus, um Informationen anzuzeigen, in die ich mich seit den Tagen von Arduino verliebt habe. Da ich keine Grafiken darauf anzeige, hauptsächlich Zahlen und Text, und die Größe der fertigen Bibliotheken und deren Inhalt meine Fantasie verblüffte, wurde eine kleine Bibliothek geschrieben, die ich leicht an SH1106 angepasst habe und die ich Ihnen beim Schreiben mitteilen möchte. Anzeige angekommen 7pin SPI:

sh1106

Ich habe ein solches Entwicklerboard, aber nichts hindert Sie daran, eine Verbindung zu einem anderen herzustellen, selbst auf STM32F103, für das HAL erfunden wurde (nicht wahr?):

F407board

CubeMX STM32F407VE , , UART1. Clock Configuration 8MHz 168MHz HSE. PA6 PA7, D2 D3 ( «0») :

RccDebug

SPI1 NRF24L01 ESP-PSRAM64H, SPI3. DMA , :

SpiAll

DC (/), RESET ( ) CS ( ) :

Gpio

:

SH1106 — STM32F407
  1. GND — GND
  2. VDD — 3V3
  3. SCK — PC10
  4. SDA — PC12
  5. RES — PD0
  6. DC — PC11
  7. CS — PA15

Heap Stack 2 Atollic, . , . Src File->Source File, spi1106.c File->Header File spi1106.h. Src Inc , #define ic1306_H_ #endif /* ic1306_H_ */ CD, RESET CS :

#define SPI1106_H_
#include "main.h"
void sh1106Init (uint8_t contrast, uint8_t bright, uint8_t mirror);
#define SH_Command HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET)
#define SH_Data HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_SET)
#define SH_ResHi HAL_GPIO_WritePin(RES_GPIO_Port, RES_Pin, GPIO_PIN_SET)
#define SH_ResLo HAL_GPIO_WritePin(RES_GPIO_Port, RES_Pin, GPIO_PIN_RESET)
#define SH_CsHi HAL_GPIO_WritePin(GPIOA, CS_Pin, GPIO_PIN_SET)
#define SH_CsLo HAL_GPIO_WritePin(GPIOA, CS_Pin, GPIO_PIN_RESET)
#endif /* SPI1106_H_ */

spi1106.c , main.h, SPI :

#include "main.h"
#include <spi1106.h>
extern SPI_HandleTypeDef hspi3;

SPI HAL:

void SH1106_WC (uint8_t comm)
{
uint8_t temp[1];
SH_Command;
SH_CsLo;
temp[0]=comm;
HAL_SPI_Transmit(&hspi3,&temp,1,1);
SH_CsHi;
}

:

void sh1106Init (uint8_t contrast, uint8_t bright,uint8_t mirror)
{
SH_ResLo;
HAL_Delay(1);
SH_ResHi;
HAL_Delay(1);
SH1106_WC(0xAE); //display off
SH1106_WC(0xA8); //--set multiplex ratio(1 to 64)
SH1106_WC(0x3F); //
SH1106_WC(0x81); //--set contrast control register
SH1106_WC(contrast);
if (mirror) {SH1106_WC(0xA0);
SH1106_WC(0xC0);}
else {SH1106_WC(0xA1);
SH1106_WC(0xC8); }
SH1106_WC(0xDA);
SH1106_WC(0x12);
SH1106_WC(0xD3);
SH1106_WC(0x00);
SH1106_WC(0x40);
SH1106_WC(0xD9); //--set pre-charge period
SH1106_WC(bright);
SH1106_WC(0xAF); //--turn on SSD1306 panel
}

, , — (0-255), — ( , 0xX0 0x0X ), — (0/1). « . 1. OLED 0.96» (12864) SSD1306" SSD1306.

main.c :

/* USER CODE BEGIN 2 */
sh1106Init (40,0x22,0);
/* USER CODE END 2 */

:

Lärm

spi1106.h — , :

void sh1106Clear(uint8_t start, uint8_t stop);
void sh1106SmallPrint(uint8_t posx, uint8_t posy, uint8_t *str);
void sh1106MediumPrint(uint8_t posx, uint8_t posy,uint8_t *str);

spi1106.c 0- 7- 0xB0...0xB7 :

void sh1106Clear(uint8_t start, uint8_t stop)
{ uint32_t *adrclear;
uint32_t timep,timec;
uint8_t dt[128];
adrclear=(uint32_t *)dt;
for(uint8_t i=0;i<32;i++) {*adrclear++=0x00;}
for (uint8_t m = start; m <= stop; m++)
{
SH1106_WC(0xB0+m);
SH1106_WC(2);
SH1106_WC(0x10);
SH_Data;
SH_CsLo;
HAL_SPI_Transmit_DMA(&hspi3,dt,128);
timec=HAL_GetTick();
timep=timec+50;
while ((HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)&&(timec<timep))
{timec=HAL_GetTick();}
SH_CsHi;
}
}

main.c, , :

sh1106Clear(0,7);

, , , spi1106.c DefaultFonts.c ( - ). , ( SSD1306/SH1106). 4- . , , :

SmallFont
const uint8_t SmallFont[] =  //    SmallFont
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //	001)	0x20=032	
0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, //	002)	0x21=033	!
0x00, 0x00, 0x07, 0x00, 0x07, 0x00, //	003)	0x22=034	"
0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, //	004)	0x23=035	#
0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, //	005)	0x24=036	$
0x00, 0x23, 0x13, 0x08, 0x64, 0x62, //	006)	0x25=037	%
0x00, 0x36, 0x49, 0x55, 0x22, 0x50, //	007)	0x26=038	&
0x00, 0x00, 0x05, 0x03, 0x00, 0x00, //	008)	0x27=039	'
0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, //	009)	0x28=040	(
0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, //	010)	0x29=041	)
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, //	011)	0x2A=042	*
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, //	012)	0x2B=043	+
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, //	013)	0x2C=044	,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, //	014)	0x2D=045-
0x00, 0x00, 0x60, 0x60, 0x00, 0x00, //	015)	0x2E=046	.
0x00, 0x20, 0x10, 0x08, 0x04, 0x02, //	016)	0x2F=047	/
//
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, //	017)	0x30=048	0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, //	018)	0x31=049	1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46, //	019)	0x32=050	2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, //	020)	0x33=051	3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, //	021)	0x34=052	4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39, //	022)	0x35=053	5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, //	023)	0x36=054	6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03, //	024)	0x37=055	7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36, //	025)	0x38=056	8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, //	026)	0x39=057	9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00, //	027)	0x3A=058	:
0x00, 0x00, 0x56, 0x36, 0x00, 0x00, //	028)	0x3B=059	;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00, //	029)	0x3C=060	<
0x00, 0x14, 0x14, 0x14, 0x14, 0x14, //	030)	0x3D=061 =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08, //	031)	0x3E=062	>
0x00, 0x02, 0x01, 0x51, 0x09, 0x06, //	032)	0x3F=063	?
//
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, //	033)	0x40=064	@
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, //	034)	0x41=065	A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, //	035)	0x42=066	B
// ...
}

( 6, 8 ), posx , 6 , posy (0 — , 7 — ):

void sh1106SmallPrint(uint8_t posx, uint8_t posy, uint8_t *str)
{
uint8_t dt[128];
uint16_t posfont, posscr;
uint32_t *adrclr;
uint16_t *adrdst,*adrsrc;
uint32_t timer,timec;
adrclr=(uint32_t *)&dt;
uint8_t code;
code=*str++;
for(uint8_t i=0;i<32;i++) { *adrclr++=0; }
posscr=posx*6;
while (code>31)
{
if(code==32) {posscr+=2;}
else
{posfont=6*(code-32);
adrdst=(uint16_t *)&dt[posscr];
adrsrc=(uint16_t *)&SmallFont[posfont];
*(adrdst++)=*(adrsrc++);
*(adrdst++)=*(adrsrc++);
*(adrdst++)=*(adrsrc++);
posscr+=6;
}
code=*str++;
if (posscr>122) break;
}
SH1106_WC(0xB0+posy);
SH1106_WC(2);
SH1106_WC(0x10);
SH_Data;
SH_CsLo;
HAL_SPI_Transmit_DMA(&hspi3,dt,128);
timec=HAL_GetTick();
timer=timec+50;
while ((HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)&&(timec<timer))
{timec=HAL_GetTick();}
SH_CsHi;
}

, spi1106.c ( 16, 12 ) DefaultFonts.c ( 4 ) , posx , 12 , posy :

void sh1106MediumPrint(uint8_t posx, uint8_t posy, uint8_t *str)
{
uint8_t dt[256];
uint16_t posfont, posscr;
uint32_t *adrdst, *adrsrc;
uint32_t timer,timec;
adrdst=(uint32_t *)&dt;
uint8_t code;
code=*str++;
for(uint8_t i=0;i<64;i++) { *adrdst++=0; }
posscr=posx*12;
while (code>31)
{posfont=24*(code-32);
adrsrc=(uint32_t *)&MediumFont[posfont];
adrdst=(uint32_t *)&dt[posscr];
*(adrdst++)=*(adrsrc++);
*(adrdst++)=*(adrsrc++);
*(adrdst++)=*(adrsrc++);
adrsrc=(uint32_t *)&MediumFont[posfont+12];
adrdst=(uint32_t *)&dt[posscr+128];
*(adrdst++)=*(adrsrc++);
*(adrdst++)=*(adrsrc++);
*(adrdst++)=*(adrsrc++);
code=*str++;
posscr+=12;
if (posscr>116) break;
}
SH1106_WC(0xB0+posy);
SH1106_WC(2);
SH1106_WC(0x10);
SH_Data;
SH_CsLo;
HAL_SPI_Transmit_DMA(&hspi3,dt,128);
timec=HAL_GetTick();
timer=timec+50;
while ((HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)&&(timec<timer))
{timec=HAL_GetTick();}
SH1106_WC(0xB0+posy+1);
SH1106_WC(2);
SH1106_WC(0x10);
SH_Data;
SH_CsLo;
HAL_SPI_Transmit_DMA(&hspi3,dt+128,128);
timec=HAL_GetTick();
timer=timec+50;
while ((HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY)&&(timec<timer))
{timec=HAL_GetTick();}
SH_CsHi;
}

main.c :

sh1106SmallPrint(0,0,(uint8_t *) "Hello SH1106_1234567890");
sh1106MediumPrint(0,1,(uint8_t *) "Hi SH1106");
sh1106MediumPrint(0,3,(uint8_t *) "Hello SH1106");
Hallo

, , HardFault . , , , .

, , 7 :

/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t buf[128*8];
char str[32];
uint16_t count;
uint8_t x,y,b;
uint32_t timep,timec;
while (1)
{
count++;
b=count&0x07;
x=(count>>3)&0x7f;
y=(count>>10)&0x07;
buf[y*128+x]=buf[y*128+x]|(1<<b);
timec=HAL_GetTick();
for (uint8_t m = 0; m < 7; m++)
{SH1106_WC(0xB0+m);
SH1106_WC(2);
SH1106_WC(0x10);
SH_Data;
SH_CsLo;
HAL_SPI_Transmit_DMA(&hspi3,buf+m*128,128);
while ((HAL_SPI_GetState(&hspi3) != HAL_SPI_STATE_READY))
{__NOP();}
SH_CsHi;
}
timep=HAL_GetTick();
sprintf(str, "%d", timep-timec);
sh1106SmallPrint(0,7,str);
/* USER CODE END WHILE */
Geschwindigkeit

— "0" "1" , 1ms, .. 1000fps. , , . SPI SPI DMA.

.




All Articles