SaĂ­da de texto para display OLED com controlador SH1106 via barramento SPI via biblioteca HAL

Olá queridos leitores. Em meus desenvolvimentos em microcontroladores STM32, para exibir informações significativas, eu uso telas OLED no chip SSD1306. A última vez que um display de 1,3 "veio a mim a um preço democrático - cerca de 200 rublos. A primeira coisa que chamou minha atenção foi a inscrição SH1106 em vez de SSD1306, uma pesquisa na Internet deixou claro que é quase o mesmo, apenas o único modo de endereçamento de página restante, e está limitado a uma linha. Tentarei explicar como trabalhar com isso nesta publicação.

Há cerca de um ano, comecei a sentir falta dos recursos do comprimido azul (STM32F103) e a placa de desenvolvimento chinesa STM32F407VE foi encomendada. Para depuração, muitas vezes, dois LEDs não são suficientes, então em cada projeto eu conecto o OLED SSD1306 via barramento I2C para exibir informações, pelas quais me apaixonei desde os dias do Arduino. Como não exibo gráficos nele, principalmente números e texto, e o tamanho das bibliotecas concluídas e seu conteúdo espantou minha imaginação, uma pequena biblioteca foi escrita, que adaptei ligeiramente para SH1106 e quero compartilhar com vocês o processo de escrevê-la. A tela chegou 7 pinos SPI:

sh1106

Eu tenho essa placa de desenvolvedor, mas nada vai impedir vocĂŞ de se conectar a outra, mesmo na STM32F103, para a qual o HAL foi inventado (nĂŁo Ă©?):

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 */

:

ruĂ­do

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");
Olá

, , 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 */
Rapidez

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

.




All Articles