你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 OLED显示程序

[复制链接]
STMCU小助手 发布时间:2022-3-29 10:11
01. OLED概述
# c7 x+ ~% E2 g: i3 n2 |, @OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(OrganicElectroluminesence Display, OELD)。OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。
9 b5 ~. t: D5 ~' e9 ?2 k6 k* w
- a9 h4 {3 X! E6 F% R$ XLCD 都需要背光,而 OLED 不需要,因为它是自发光的。这样同样的显示,OLED 效果要来得好一些。以目前的技术,OLED 的尺寸还难以大型化,但是分辨率确可以做到很高。; V( w3 L: l# R. J' H! g
* [, u# s. H- R9 S% x: i
02. OLED初始化
  z+ S/ j; t3 a& M1 V/ a1 ^( k. e" Z" y; \$ d' V0 ~- {" P" C
0_31)3}(R7UW4572507357F.png
& a) o% G) K' O+ w  Q* ]8 s: w  v: r8 X$ t# d5 ~1 t! ~4 H
驱动 IC 的初始化代码,我们直接使用厂家推荐的设置就可以了,只要对细节部分进行一些修改,使其满足我们自己的要求即可,其他不需要变动。
  R5 Y" O& e( b/ q/ t+ d* I, i, c: ]1 D+ s
OLED 显示需要的相关设置步骤如下:
! g2 _2 {, E! t# W" X2 c- {2 T3 V, a: T9 g+ }2 f  |' r& ?3 c1 ^
1 )设置 STM32F4 与 与 OLED 模块相连接的 IO 。
( D' p9 p( d  F+ X: a- U; _这一步,先将我们与 OLED 模块相连的 IO 口设置为输出,具体使用哪些 IO 口,这里需要根据连接电路以及 OLED 模块所设置的通讯模式来确定。+ z" D( H7 ?& Q% W/ Z/ O- p* p$ F& j
  J; O; W5 h2 D* z1 w1 t2 K
2 )初始化 OLED 模块。
% D; ?, p, m0 J( }其实这里就是上面的初始化框图的内容,通过对 OLED 相关寄存器的初始化,来启动 OLED的显示。
: t5 A* w% Y& X  A- l# ^" X6 L3 a4 D0 j7 H1 z7 k2 \0 c) S
3 )通过函数将字符和数字显示到 OLED 模块上。+ Z4 S( _; E1 c0 h" B6 U; E
这里就是通过我们设计的程序,将要显示的字符送到 OLED 模块就可以了
5 |/ D4 O# ]/ s6 P2 S* b! G0 ~( P; {) {7 b0 f
通过以上三步,我们就可以使用 ALIENTEK OLED 模块来显示字符和数字了。
' q7 ]) Q$ w) U; u: v6 t/ {' U
' u) `5 t# e' R1 ^03. 硬件设计
2 k/ l. p- }7 n& K5 T3 w' y用到的硬件资源有:
: r9 `% j6 r4 {) \+ P- w7 w( Y1) 指示灯 DS00 U6 I+ l& L! v9 k; I$ z
2) OLED 模块
6 F8 M+ J/ X+ ]4 u! P6 {+ `, F+ m
) E' F0 D2 b$ r2 M, Y& j5 A硬件上,OLED 与探索者 STM32F4 开发板的 IO 口对应关系如下:
6 _* t5 p, C- U* U' y  x4 f9 pOLED_CS 对应 DCMI_VSYNC,即:PB7;
( b1 u2 t$ L0 j0 [* q/ bOLED_RS 对应 DCMI_SCL,即:PD6;
* T& u, t6 `" b# S% K" ]  SOLED_WR 对应 DCMI_HREF,即:PA4;
7 K: ~: N1 \. [# Q4 N& q5 uOLED_RD 对应 DCMI_SDA,即:PD7;
- {6 G7 ]( }/ p8 c; ~1 k1 c1 yOLED_RST 对应 DCMI_RESET,即:PG15;
# h# _, Q  R8 I# |* lOLED_D[7:0]对应 DCMI_D[7:0],即:PE6/PE5/PB6/PC11/PC9/PC8/PC7/PC6;4 ?0 v0 Q) C( t1 d
- I. F' P; \6 F* R$ ]# ]- _
04. 程序示例
( `; _4 w: F: \4 D7 d, U) aoled.h: H+ |$ Y  |' X; P% Y: ~1 H
  1. #ifndef __OLED_H+ D1 x; e# p7 H: S3 r
  2. #define __OLED_H                                   
    8 R9 u3 y$ e% ?
  3. #include "sys.h"
    5 _+ m: m1 v! X
  4. #include "stdlib.h"            - T0 D6 U: S% X
  5. ; V, z3 w; s3 s
  6. //OLED模式设置
    . v. ^; K5 e6 R
  7. //0: 4线串行模式  (模块的BS1,BS2均接GND), n5 a0 H) j" D. e9 G7 D
  8. //1: 并行8080模式 (模块的BS1,BS2均接VCC)/ V- i$ K- i" N5 R* i9 t8 P
  9. #define OLED_MODE         1
    - p8 U* r# ~- }& a/ }
  10.                                                                       ! J# n5 Y! S- @: V, o# |
  11. //-----------------OLED端口定义----------------                                             
    : M  t# m% ^7 i8 _, ?; [! Q8 T5 b* e. I
  12. #define OLED_CS         PBout(7)' z9 M8 H) g6 v. o1 p1 j% ~
  13. #define OLED_RST  PGout(15)        ! i( z0 I2 {; h( S& H
  14. #define OLED_RS         PDout(6)
    - U$ R) ]3 [. g2 i
  15. #define OLED_WR         PAout(4)                    r' u! G% X: V' ^) ~
  16. #define OLED_RD         PDout(7)
    ' t- W% C. V: l. y  W
  17. $ f# B2 ~  c+ S3 m7 g# r
  18. //使用4线串行接口时使用
    5 P& `! o; I9 c" J/ C5 a) g6 S" `
  19. #define OLED_SCLK         PCout(6)
    ) ^9 V/ U# S; q
  20. #define OLED_SDIN         PCout(7)
    - }, H# Q3 Z) B- O
  21.                      ' {* {. s( Q2 j- S9 K9 [
  22. #define OLED_CMD          0                //写命令
    " k) _5 V/ P( {& o# K0 K6 f2 r
  23. #define OLED_DATA         1                //写数据
      `1 \0 n6 W! B! f* a0 ?7 F$ l, y! m
  24. //OLED控制用函数
    7 a, a& Z2 P+ I2 q3 L- H- U9 n
  25. void OLED_WR_Byte(u8 dat,u8 cmd);            
    $ Y; f! g, u2 [) M  j" D! H
  26. void OLED_Display_On(void);
    9 y) ?" ?% o/ ?7 C; i7 @7 ?
  27. void OLED_Display_Off(void);
    ; G) A7 l) x/ l( t1 H3 g
  28. void OLED_Refresh_Gram(void);                  
    % n6 G, {. d- e; T# ~
  29.                                                                                6 r+ T; X" R. c5 |
  30. void OLED_Init(void);
    2 R, E% W7 b/ d- U% h/ ]" g* |
  31. void OLED_Clear(void);, f& Y5 J. ~4 w: ?0 U
  32. void OLED_DrawPoint(u8 x,u8 y,u8 t);3 s& B$ i5 O9 o# ]
  33. void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
    . V, Y8 L; _/ R
  34. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);
    5 r" G2 F5 ^, `) {, C* F
  35. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);& U7 K! X- G! w9 K: O. g8 l0 o
  36. void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size);         1 c1 v- R0 g* P/ m9 e" S
  37. #endif  0 U) c; K/ S# a- S9 y$ T
复制代码

8 T* Y' d, m/ q# H2 C" coled.c  j+ ]  v, i3 v* o; P- S
! i7 }% t" k9 O6 @: E
  1. #include "oled.h"
    / N' K( H& s9 a4 `7 n" f0 k
  2. #include "stdlib.h"
    & A) q3 L& n* h& h7 d" d
  3. #include "oledfont.h"           
    : k- @; Y+ _, A3 M  E
  4. #include "delay.h"0 S4 L+ M2 r" h+ y
  5. $ c/ a. p  M% O# _& e9 T/ C
  6. //OLED的显存
    * m, h0 l! I3 K" ?% s* ?, O7 I7 ^
  7. //存放格式如下.* }' v2 I6 T/ T) ~. a9 B
  8. //[0]0 1 2 3 ... 127        + S4 V3 j  Q" j3 H5 d9 C4 @
  9. //[1]0 1 2 3 ... 127        " J1 t. ^  p* j: _
  10. //[2]0 1 2 3 ... 127        
    . b8 ^- Z) `- `( N0 t! A
  11. //[3]0 1 2 3 ... 127        ( c. K7 v( ]+ Y& d6 m$ W  g
  12. //[4]0 1 2 3 ... 127        
    : q, M0 n; P' O6 A
  13. //[5]0 1 2 3 ... 127        
    ' b# l( y, m! j- R: T  l8 X: `7 k% T
  14. //[6]0 1 2 3 ... 127        
    : b+ V$ ~& }) l( ^
  15. //[7]0 1 2 3 ... 127                    6 q. `4 @% ?9 ^9 t
  16. u8 OLED_GRAM[128][8];         2 Z) [3 o, s- p0 R, L% ]
  17. 5 c; S7 o: e& ?1 z- ?
  18. //更新显存到LCD                 
      w4 |( O6 A" L' G7 a) m( v
  19. void OLED_Refresh_Gram(void)
    - u. x2 j: F& G0 ?# {8 m
  20. {
    " J% ^, [  e! i! `  R% @
  21.         u8 i,n;                    8 ]( N8 l" h7 O; `& p" W
  22.         for(i=0;i<8;i++)  
      J1 N  ?8 D' b2 ^7 \* n
  23.         {  
      k! V+ p6 @6 r* }
  24.                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)( ^/ e. u7 d* M7 ]9 F+ e1 V
  25.                 OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址- i3 ?+ @1 o& i$ Q6 V8 Q
  26.                 OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   # W+ ~: s6 p- u5 c- n$ A: K; J
  27.                 for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n],OLED_DATA); " o, a& z: O0 g3 l0 h2 @
  28.         }   - {. r/ o. H2 Q: q8 S
  29. }5 H7 P# @# N8 u# u  Q# C8 ^' V
  30. //8080并口) m( M3 a, K# _7 p; y8 y
  31. //通过拼凑的方法向OLED输出一个8位数据
    * I: j8 c. D' H% l5 ?, |+ @
  32. //data:要输出的数据
    6 y+ ?9 [! a2 N& V: L# s
  33. void OLED_Data_Out(u8 data)3 W, F8 Z% e# z% f  h9 P% }
  34. {
    * E( Z7 n  ]1 e; F+ ^* T7 I
  35.         u16 dat=data&0X0F;0 h6 g" @4 ~" q; v# E
  36.         GPIOC->ODR&=~(0XF<<6);                //清空6~9
    ; j1 f8 T+ p7 D3 h4 p/ Q5 Y* `
  37.         GPIOC->ODR|=dat<<6;                        //D[3:0]-->PC[9:6]
    ! q8 Y7 x! U" f1 z
  38.         GPIO_Write(GPIOC,dat<<6);
    - u" [! w6 D6 z
  39.         PCout(11)=(data>>4)&0X01;        //D4
    3 ]" ~9 U% r/ }' u' |3 ^
  40.         PBout(6)=(data>>5)&0X01;        //D5" u6 X3 a+ R8 E& i* c6 i
  41.         PEout(5)=(data>>6)&0X01;        //D6
    6 M9 I- X( U# Y8 p- [
  42.         PEout(6)=(data>>7)&0X01;        //D7 ! Z8 L3 o4 W" @9 y9 B0 @3 ~. f
  43. } , i- l1 S( C  _  q- E2 Q$ \
  44. //向SSD1306写入一个字节。
    # t) O7 H0 E, W$ [: p( o
  45. //dat:要写入的数据/命令% O( h6 r! k1 t2 a2 S
  46. //cmd:数据/命令标志 0,表示命令;1,表示数据;* x; Q. ]0 b5 u, a
  47. void OLED_WR_Byte(u8 dat,u8 cmd)
    + X' {$ M/ I4 K) ^1 b! v3 E
  48. {, e3 j8 K' x& h& r
  49.         OLED_Data_Out(dat);            
    ! m  c0 k' H2 h8 E
  50.          OLED_RS=cmd;, v& M4 k& f8 S3 I
  51.         OLED_CS=0;           : }( x0 g; F2 H5 i( e# ?
  52.         OLED_WR=0;         0 X2 ~  C. Z& H
  53.         OLED_WR=1;
    1 t8 }' ]3 l2 e) ~
  54.         OLED_CS=1;          ( `6 S) R, |; \/ C  f/ e
  55.         OLED_RS=1;         
    % x( }& r, Q5 J; w* s
  56. }                        
    ! ?# f$ ]: r% Z( X5 M0 X
  57.                     
    " N- J# m, V* ]$ N  B3 H" h
  58. //开启OLED显示    1 F9 E$ v9 h; q3 k8 A; w7 C# |
  59. void OLED_Display_On(void)- M' k0 o) G$ G: Q  E) j& R) F
  60. {* |- X) I+ h  @2 {7 K1 V
  61.         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    ' p8 K! W/ M7 \' X
  62.         OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON; N' L" X# a( v/ F! u
  63.         OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON5 a4 j# o3 d0 s" W+ g3 T2 ?7 N) b" U
  64. }5 g+ w+ a* ]9 n5 w5 Z
  65. //关闭OLED显示     
    & w! p4 J; _1 N' e& |: o
  66. void OLED_Display_Off(void)" h( L' y5 W: M3 v
  67. {
    / R/ H" x- A. {8 P% B; Y: m
  68.         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令8 b1 W5 p- f8 V0 K0 c  u, x6 ^$ G  I
  69.         OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF& {. v: `* _3 O  l7 v
  70.         OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
    ( _! y" C* s; @/ z6 N
  71. }                                            
    3 ~: O* P; P/ a7 ?; G4 f2 Y' y. @
  72. //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!          , U$ `: B5 f0 v4 V: K, M7 R
  73. void OLED_Clear(void)  0 ~  [2 O# Q& z" g# `* [. `# |
  74. {  
    - ]! n9 G& U: s) r& ^+ X
  75.         u8 i,n;  
    , a2 B. u3 n. P2 F  Y9 w* \& _
  76. for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n]=0X00;  * W! P# V% t; J
  77.         OLED_Refresh_Gram();//更新显示* H% R5 F- L" p! N& w0 D- E
  78. }
    " p) V: A, P/ [- G, l! X, B
  79. //画点   C5 O2 e# y* W+ ~* g
  80. //x:0~127
    , m6 s- i$ g9 A9 p$ {# B
  81. //y:0~63
    ! ^5 S5 w# S8 t) T/ ~
  82. //t:1 填充 0,清空                                   - v4 F7 M2 Y; m
  83. void OLED_DrawPoint(u8 x,u8 y,u8 t)
    " |, {' v  g) Y
  84. {
    " p( L% I4 w# v/ j+ j- p  f6 A2 ^
  85.         u8 pos,bx,temp=0;
    + f7 r2 P" ]5 W  z  F
  86.         if(x>127||y>63)return;//超出范围了.3 {2 j8 c7 m, U
  87.         pos=7-y/8;
    + T$ B2 y0 n% Q
  88.         bx=y%8;
    1 R+ u) Y. E( l' v$ _( h# [
  89.         temp=1<<(7-bx);4 V5 {' J5 T3 B0 B/ |; P
  90.         if(t)OLED_GRAM[x][pos]|=temp;3 i2 |( R% u' W  e
  91.         else OLED_GRAM[x][pos]&=~temp;            4 W5 v+ u% n# P" L6 l" z2 L8 f
  92. }
    : z( W, d$ c# b- `4 I
  93. //x1,y1,x2,y2 填充区域的对角坐标
    9 L' O! Y2 r+ K! f7 }3 I
  94. //确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63                  
    : E# e1 {$ @  M! D1 n9 E0 E) I
  95. //dot:0,清空;1,填充          # b6 C9 m8 q- N. j4 K
  96. void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)  
      W) _! P- c( c& U2 ]
  97. {  
    # U  Q# u9 d; i; M/ o
  98.         u8 x,y;  & `+ S# Y$ _; A4 C2 u
  99.         for(x=x1;x<=x2;x++)1 v$ \( p- h4 ~1 k( I4 [5 F
  100.         {$ c) C5 x) o' ?1 A2 y. T
  101.                 for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);' d" L+ l7 ^8 n
  102.         }                                                                                                            ; |; @3 A6 _" m" z  @9 v
  103.         OLED_Refresh_Gram();//更新显示
    & n8 i* b; L! _5 {! W
  104. }
    / h+ G0 X, z0 X/ F3 L; ~' f. _. J
  105. //在指定位置显示一个字符,包括部分字符
    4 G: d% Y& W  R/ ^
  106. //x:0~127
    3 P! w( c0 y; L0 b
  107. //y:0~63
    2 k2 g% n, W/ u% ~- J( m
  108. //mode:0,反白显示;1,正常显示                                 
    0 z, B0 @4 \! l$ ]
  109. //size:选择字体 12/16/24" r' U9 Y. F1 j6 B- \- ~3 u, ^
  110. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
    ; K8 Z+ S; N8 n
  111. {                                  ' \: Z7 h& e) Q) T( X
  112.         u8 temp,t,t1;  D% [: k" u" a7 N+ b; f0 X
  113.         u8 y0=y;
    $ Q0 Q; k4 C' l7 v
  114.         u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数( M$ {* U" k. J* c
  115.         chr=chr-' ';//得到偏移后的值                 5 _+ `/ f7 N& i1 Y; ^2 L! b% l2 H
  116.     for(t=0;t<csize;t++)
    ' l  }6 v, h) {8 b
  117.     {   ! r  \! ]6 g$ [. m  J' i
  118.                 if(size==12)temp=asc2_1206[chr][t];                  //调用1206字体) q3 \* t+ l5 V/ `( N+ K. h6 f' S
  119.                 else if(size==16)temp=asc2_1608[chr][t];        //调用1608字体
      l) m8 A( P4 Y
  120.                 else if(size==24)temp=asc2_2412[chr][t];        //调用2412字体
    - m, L: D, i5 L. U. z: V
  121.                 else return;                                                                //没有的字库
    : |  l/ Y: `0 S
  122.         for(t1=0;t1<8;t1++)
    ' R# ~$ A( p7 q" f$ H
  123.                 {7 o( B' B' l& X& r' \0 r8 R
  124.                         if(temp&0x80)OLED_DrawPoint(x,y,mode);
    * s* h! R9 P6 P7 e6 @6 f$ F
  125.                         else OLED_DrawPoint(x,y,!mode);
    + H3 n4 m8 m6 r4 d/ J
  126.                         temp<<=1;
    1 n$ f9 i; a" k7 Y& Z6 ^3 a- r
  127.                         y++;
    0 f$ q3 {+ X8 W5 m$ w
  128.                         if((y-y0)==size)
      a- Z1 r6 a/ X' y
  129.                         {
    ! N, s* u( H5 ^
  130.                                 y=y0;
    ! f3 x! ?/ C1 m: d9 d
  131.                                 x++;: G" v2 k9 ?* \5 a( T
  132.                                 break;
    7 r$ J  d/ d# y1 W6 H
  133.                         }
    8 T7 x( u3 a( `# G
  134.                 }           
    7 `$ y3 X* f/ C9 F
  135.     }          ' V+ p+ v  l; E  u& U6 a, e$ V8 m
  136. }
    6 _% `/ M, l3 ]% L! c2 `, s
  137. //m^n函数
    3 ~- y5 V  l. @- A
  138. u32 mypow(u8 m,u8 n)
    % R  r8 X( l+ @+ C" r' G4 I
  139. {; p" ~, }) V# L4 M) ~) O* g
  140.         u32 result=1;         2 i; B0 q( o9 n2 R) C6 R* p
  141.         while(n--)result*=m;   
    5 g3 |, p7 u! ]8 |3 q; ?6 x" P
  142.         return result;
    2 r  V) X- u& U* Y1 f
  143. }                                  0 @* n* f3 x: n, @0 @
  144. //显示2个数字
    - |; y( v* g" u  i9 s8 h
  145. //x,y :起点坐标         
      w: i% V% f' P+ [; ?3 V( Q
  146. //len :数字的位数  x/ A. Y8 P; O+ r' Y# z0 F
  147. //size:字体大小& ~# R( f& e. Q2 {8 ^3 o7 N+ o1 S
  148. //mode:模式        0,填充模式;1,叠加模式
    , t- e; y1 `+ C; U( p
  149. //num:数值(0~4294967295);                           
    9 _# ^, X4 |& P& q
  150. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)4 Y( A( K! N' g) _# q8 r
  151. {                 
    * [# f6 s$ V7 ]$ K  L9 s( A
  152.         u8 t,temp;
    ( z* f9 D6 w6 t: S
  153.         u8 enshow=0;                                                   # t( C' c" Q, ^+ W+ g/ {4 U& }
  154.         for(t=0;t<len;t++)
    / Z. P  C; M2 o6 Z& F% N1 u  P
  155.         {! M) G+ i- C; S. X; }) Q/ {
  156.                 temp=(num/mypow(10,len-t-1))%10;* ^1 @$ T* d# X5 b% h, R0 O' |
  157.                 if(enshow==0&&t<(len-1))* @0 t. r6 G9 Y! ]& o# H" D
  158.                 {
    3 g$ `( g% S; S
  159.                         if(temp==0)/ C. E+ n7 }' p' j, q" E( A
  160.                         {0 b; a0 }- @7 c- b9 P7 E
  161.                                 OLED_ShowChar(x+(size/2)*t,y,' ',size,1);8 x9 c. C0 V" M) d% L: V, H7 ~
  162.                                 continue;
    2 f! W6 V1 R+ _$ q6 M. O* [/ n
  163.                         }else enshow=1;
    % U- m. I6 r8 ~# j# a1 U# y
  164.                             Z* c: K5 i+ c; F0 J; Q% _7 U- o
  165.                 }! t( J$ f' \/ P: K. ^  W) }3 E
  166.                  OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);
    2 M) ]. |; r, P4 g# ?  R
  167.         }
    , k- R( E' s9 r% n( c6 Y
  168. } 1 f7 T2 |' E$ i4 m" x
  169. //显示字符串
    2 w5 M8 A/ ^8 Y+ D
  170. //x,y:起点坐标  + K; o3 E7 H# ^2 D1 h0 ?) p4 A+ w
  171. //size:字体大小
    6 K) h# z7 K" z! I
  172. //*p:字符串起始地址
    + P1 m/ a) S" B# o) s' e
  173. void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size)9 t3 N+ F- [  |: T+ [3 q7 O9 ?6 k
  174. {        
    5 E. x4 {; M& t/ R+ i: a
  175.     while((*p<='~')&&(*p>=' '))//判断是不是非法字符!1 y& l8 b6 l. z4 ^8 J4 X; M2 ~
  176.     {       : ]9 G" |+ a% x: t7 s/ @
  177.         if(x>(128-(size/2))){x=0;y+=size;}
    / w1 b$ Z& J5 u: O
  178.         if(y>(64-size)){y=x=0;OLED_Clear();}
    7 x& h( j* Z6 {# v$ D) m( s
  179.         OLED_ShowChar(x,y,*p,size,1);         
    ( p* A2 D# k) H: h  }4 ?, S
  180.         x+=size/2;
    4 o, R$ p5 m* A' p8 k# C
  181.         p++;
    8 S3 y, F' u4 x: @
  182.     }  
    - t4 A* A6 l7 U( [2 a
  183.         
    4 ]- ?8 x! G3 c# K: o
  184. }        
    ) z( X) c; z4 X) [3 Q
  185. //初始化SSD1306                                            9 J' ^0 i' F$ A& o7 A
  186. void OLED_Init(void)! F3 i9 i% _; H' `3 i
  187. {                           
    ( E& t4 @1 h* U* ]3 n: V
  188.   GPIO_InitTypeDef  GPIO_InitStructure;
    4 ]1 |* L9 j% c! U9 e
  189.         % Z+ B% Z2 e; \4 a$ z
  190.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOG, ENABLE);//使能PORTA~E,PORTG时钟5 q* u8 }/ _/ {& Q% X
  191. % y. |/ D7 q9 E2 h
  192. //使用8080并口模式               
    ! L3 Q, v9 {; R$ Q) ~' w! ^
  193.         $ _4 N" I, u/ @1 D/ Z
  194.         //GPIO初始化设置, T" W8 Q& c4 y; r! A) \  Z
  195.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;
    " I( w8 d" Y( I0 L/ t) m2 K
  196.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
    / G  w+ J" {9 j
  197.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出1 f1 \$ u" c0 ^  R6 x$ A/ r
  198.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz/ o! b- e1 d/ G% I
  199.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉7 Q2 i+ g1 _! o# |0 ~& k5 J
  200.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化& t* }! P/ U6 Q! q# [6 q
  201.         
    & N' `. S9 J. Q6 x
  202.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7 ;        $ H7 ~* A$ O9 i- N# K
  203.         GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化; L  L2 h7 @% _5 g* a( d5 w

  204. ' h8 J9 s7 m/ r0 {3 Z0 S0 Q
  205.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_11;        
    8 o) p" O: b# r6 \# C7 L, `7 U* }
  206.         GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化        
    7 `1 S) x9 Y( V+ H& y

  207. 0 d7 r$ Q% B2 r) N. I& T2 W$ R3 @
  208.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;        - U1 p. D$ j& ~9 {# C
  209.         GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化        
    0 c" {9 N* N0 W1 j' k
  210.         9 x* X0 V2 z- T: n# \" n
  211.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_5;        
    9 T* `7 u! L: o
  212.         GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化        
    ) B) O/ z0 G5 Q5 Z" Y  @
  213.         4 g! Q; A. g, {5 X' {2 O
  214.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;        8 V( i% x: P# d
  215.         GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化        
    1 H+ H) ?/ x# O
  216. 0 \; o1 w5 J- j8 C( D4 \
  217.         
    ' r5 ^" w, X7 I9 y. H
  218.          OLED_WR=1;
    & N- u; Q, X2 b; q# E5 A4 o4 m' s
  219.         OLED_RD=1;
    4 m! V: [% I6 v  p( D% ~) O

  220. * W+ _7 {8 ~  j! h/ ?
  221.         OLED_CS=1;
      a0 k  V7 y5 o9 {# G6 s( {
  222.         OLED_RS=1;         
      M; \% u  K/ Y
  223.         
    4 h1 N" e& y- }1 T) a) Y
  224.         OLED_RST=0;9 P3 G" W7 |  r& c% l4 x7 I! S
  225.         delay_ms(100);- J1 S- I; m! z$ R* Y
  226.         OLED_RST=1;
    + P$ X9 p/ [& X/ s
  227.                                           ; n9 Y) D+ e. w, H5 `' p
  228.         OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示( h+ Y% ?, I( }4 {
  229.         OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
    . u& h) B7 p( I! y4 U
  230.         OLED_WR_Byte(80,OLED_CMD);   //[3:0],分频因子;[7:4],震荡频率, l, [' u* L& _
  231.         OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数
    ' s5 Q) L! d5 L, Z. K- C: Y2 d
  232.         OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64)
    1 v! I! z! o1 B: M. Z3 v
  233.         OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移
    , F' n. o7 [3 {0 D7 z
  234.         OLED_WR_Byte(0X00,OLED_CMD); //默认为0
    5 K+ O! M- g. i. @9 Q  `# g
  235. % @- J" }% q6 c" j* r5 `$ R
  236.         OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.% \% E0 m, w, N  K1 E+ e
  237.                                                                                                             
    3 {7 M% H: Z2 i& G/ V" F, r1 e1 F- }
  238.         OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置/ I8 B/ g, t7 J$ K9 s
  239.         OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭. f* s7 C7 D) L* B
  240.         OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式- z, w6 s+ A9 \/ I  t; _
  241.         OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;8 D/ J2 I* v/ c/ [" @+ d/ R/ C
  242.         OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;; e' F, B1 v& f" C
  243.         OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
    + A  L" {& _1 c9 S2 m5 d- D
  244.         OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置
      V( c* [  e* m, p/ w  S
  245.         OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置$ x4 i9 U5 Q4 k0 d) q( Q
  246.                  
    8 Q! \$ n- L- ?3 |' {
  247.         OLED_WR_Byte(0x81,OLED_CMD); //对比度设置
    7 U2 w' |3 \2 h: Z. t
  248.         OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)
      \8 X) g; M. C
  249.         OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期
    4 |1 G+ D* F4 _* Y- E6 Q9 ^5 P
  250.         OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
    3 I0 N+ n0 @9 Z
  251.         OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率
    7 ~4 U; {- i6 p& w7 f3 e7 N# t
  252.         OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
    % i' W, f1 Y& F% ~, t
  253. ; S% X* ~9 u  A! Q
  254.         OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
    # @0 e9 i& a3 u/ P  n% p$ |
  255.         OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示                                                               
    " J$ ^7 \  X  W2 _( J# u
  256.         OLED_WR_Byte(0xAF,OLED_CMD); //开启显示         
    + M3 U& T) ~$ _1 |
  257.         OLED_Clear();! P+ e( h, H# N8 L3 [( h
  258. }  
复制代码
7 {  a! J3 g+ ^% [& b" l& t
main.c& y8 o& Y9 u' \0 m$ R# I* ~
" {. ~8 @* V  ]0 n+ z& u: X
  1. #include "sys.h": X0 m4 ?7 x3 c0 B
  2. #include "delay.h"4 b$ V5 a% h  z. x; v& L
  3. #include "usart.h"& }' \) O  I" a) {# j
  4. #include "led.h"0 A+ g. q9 f, R
  5. #include "oled.h"
    5 j! A" g9 r. E1 _, b8 H! T5 ?: V
  6. 5 b$ K( O- i: Q+ a0 B% B8 [

  7. 8 Q/ j0 x. l- {
  8. int main(void)
    + g& R, I2 y3 c- h# Q- v
  9. {   C5 x/ f' ?. J  c, R1 O
  10.         u8 t=0;
    - b3 k4 m2 j/ x2 I" {
  11.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    4 s- z2 a8 o! R  t
  12.         delay_init(168);     //初始化延时函数
    6 N  W( C2 g7 M" o" i6 S* |0 y
  13.         uart_init(115200);        //初始化串口波特率为115200
    * {2 \" P% `/ n0 ~8 d6 g: y7 N# Q
  14.         LED_Init();                                        //初始化LED
      {- `  I8 T% ]' G. O( q: J
  15.          OLED_Init();                                //初始化OLED
    + t8 g/ K$ [( E4 v9 ^! }
  16.   OLED_ShowString(0,0,"ALIENTEK",24);  
    / |5 m5 A5 z2 @/ a
  17.         OLED_ShowString(0,24, "0.96' OLED TEST",16);  9 m; r8 V. P2 V* Z$ h* T( I2 G
  18.          OLED_ShowString(0,40,"ATOM 2014/5/4",12);  + r, S; Q) _5 H7 n+ f0 V2 [
  19.          OLED_ShowString(0,52,"ASCII:",12);  
    : g& }. h" _+ g6 Q3 B+ E
  20.          OLED_ShowString(64,52,"CODE:",12);  
    : E9 }+ X  Q+ ~* V$ a
  21.         OLED_Refresh_Gram();//更新显示到OLED         ( M1 X; D8 z( Z% f
  22.         t=' ';  
    ; N$ z) j% h: L+ {1 W
  23.         while(1)
    & z& }3 N/ G5 {
  24.         {               
    7 I# e5 d' L4 i
  25.                 OLED_ShowChar(36,52,t,12,1);//显示ASCII字符        : v7 u" {% e8 W
  26.                 OLED_ShowNum(94,52,t,3,12);        //显示ASCII字符的码值    5 n- ^. x* G. ~: Z4 e
  27.                 OLED_Refresh_Gram();        //更新显示到OLED
    % D- q6 q# J3 ^, p5 L
  28.                 t++;
    8 x5 q# L  b3 M8 j/ P, p% h
  29.                 if(t>'~')t=' ';  
    - {" a; t* L6 x- ~( W& ^: r5 W! k
  30.                 delay_ms(500);
    6 l" s! E# _" U
  31.                 LED0=!LED0;! L! o+ [1 a+ I9 ~) Y& K% R0 j* J" q
  32.         }
    : g1 H# y3 t+ p/ N" P4 p6 ]) W
  33. }: s) _9 ~/ i2 B

  34. ; C- T+ o" C8 G9 z# \! f. X  }' n! ]
复制代码
( E4 R/ O" l$ J) o0 k, N

  q7 |/ @/ P, z8 w
赞 收藏 评论0 发布时间:2022-3-29 10:11

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版