通过HAL库通过SPI总线使用SH1106控制器将文本输出到OLED显示屏

尊敬的读者您好。在我对STM32微控制器的开发中,为了显示有意义的信息,我在SSD1306芯片上使用了OLED显示器。上次以民主的价格向我展示1.3英寸显示屏-大约200卢布。引起我注意的第一件事是题字SH1106而不是SSD1306,在互联网上的搜索表明,这几乎是相同的,只剩下唯一的页面寻址模式,并且它仅限于一行。在本出版物中,我将尝试解释如何使用它。

大约一年前,我开始怀念蓝丸(STM32F103)的功能,并订购了中国开发板STM32F407VE。为了进行调试,通常两个LED是不够的,因此在每个项目中,我都通过I2C总线连接OLED SSD1306以显示信息,这是我从Arduino时代起就爱上的。由于我没有在其上显示图形,主要是数字和文本,并且制成的库的大小及其内容令人惊讶,因此我编写了一个小库,我为SH1106做了一些改动,并希望与您分享编写它的过程。显示到货的7pin SPI:

sh1106

我有这样的开发板,但是没有什么可以阻止您连接到另一个,即使是在发明HAL的STM32F103上(不是吗?):

F407板

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

Rcc调试

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

:

噪声

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");
你好

, , 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 */
速度

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

.




All Articles