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

【经验分享】STM32实战应用(一)——1602蓝牙时钟1液晶的显示测试

[复制链接]
STMCU小助手 发布时间:2022-2-7 20:41
前言
从51到STM32F4学习这么久了,总算找到点头绪了,目前学习了GPIO,中断,定时器,看门狗的基本使用,所以想试着看看能不能做个什么东西,就是想复习一下最近学习的知识。正好上学期单片机课程设计做过一个可以蓝牙、按键校准、带温度显示的时钟,所以我想看能不能将程序移植到STM32上呢?说做就做,经过三天的时间,几次的程序修改和调试,终于成功了!

" ~" ]& M: _6 m2 G1 {+ z& x$ X
由于STM32内部定时器的精度还是很高的(一小时慢1s),所以就没有使用DS1302时钟芯片(关键是手里没有),显示上和课程设计做的有些不一样,没有增加日期和星期显示,就时间、闹钟和温度的显示。

7 B: A1 Z5 ?+ r- V1 D3 \今天先学习一下1602液晶的显示,那么如何用STM32控制LCD1602显示字符,字符串或数字呢?( i4 X. ^- z. T6 s) T! Z7 U
1602液晶介绍
工业字符型液晶,能够同时显示16x02即32个字符。1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。市面上字符液晶大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。

  E7 G: N% \5 \; k2 u4 p+ J& x由于1602液晶是5V供电,引脚高电平为5v。不像51单片机IO输出高电平5v,STM32高电平只有3.3v,低电平0v,找到了1602的数据手册,里面居然没有说明高电平电压范围,到底能不能驱动呢?我又查找了1602驱动芯片HD44780的数据手册,其中有一个电压特性,如下图  m" J/ a+ Y1 B# h7 E
1124009-20170423131826726-1458841834.png " Y. |+ i1 q# _1 q

' @+ l2 G1 }+ P9 X2 ^
可见用STM32的3.3v电平驱动显示完全没问题,看到这我就放心了,代码经过多次的修改后,终于成功显示了,所以还是要多看看数据手册。

  }/ `4 o* X( X# _* l2 `硬件电路连接
- f# M6 h9 R; X, t, T6 h# B: D5 G) o# C+ K0 u5 n4 s. D% Q! i
, V) w2 O0 Q; }: {
1124009-20170423132248601-1684036602.png 5 X3 S0 M8 k& K# F

. Z9 L) W. }/ t5 j, }# g4 K4 ]
' u3 e- f& d4 D9 J. @
程序设计
/ ?/ C5 j2 r: t5 n8 o% N1.控制线宏定义,通过位带操作,以后就可以像51那样RS=1来操作了,是不是很熟悉呢?这里还将数据线的8个端口定义为了一个LCD_DB6 z, M) z* i3 B4 `4 M$ ]3 S! i
$ m! U; f- [4 J, K  g( w" i
  1. #define LCD_RS PAout(1)3 Z' ^2 G+ b# W$ C8 u2 O
  2. #define LCD_RW PAout(4)
    1 V0 `. @: P; {: r
  3. #define LCD_EN PAout(6)3 q% F/ I' [, r4 [) M' \. N
  4. #define LCD_DB GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15
复制代码

, g" v7 e+ F1 i, z, ]* H* ?3 |2.LCD相连的GPIO配置,将数据线端口配置为OD(开漏)输出模式,可以做双向IO使用,在检测LCD是否忙时,需要读取D7位的状态! t& M( i3 p+ p
  1. void LCD_GPIO_Config(void)
    * y, O0 c+ T1 O" w/ A) Q
  2. {9 J, ?) i! G+ {3 S% k7 `
  3.     GPIO_InitTypeDef  IO_Init;- P7 `' C' S) s5 U* R# a$ @
  4.     * E) n. H9 A1 X- u: l: P
  5.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE,ENABLE);8 m3 {# J* w  S  U5 k" R. d. a0 q
  6.     & S% W& t) L! _! J5 W& t% X
  7.     /*控制线初始化 : */
    2 B) R  q6 {0 V1 d5 F" [5 y3 w
  8.     IO_Init.GPIO_Mode=GPIO_Mode_OUT;        //输出$ c7 h! Q4 C8 L( R! _; T- j2 k5 p0 _
  9.     IO_Init.GPIO_OType=GPIO_OType_PP;        //推挽模式
    ; B' ^5 R9 C  y" x5 y3 Z
  10.     IO_Init.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_6;
    1 H6 v- h/ l! i3 u& [
  11.     IO_Init.GPIO_PuPd=GPIO_PuPd_UP;            //% e# R7 X- _; U9 x, a- J
  12.     IO_Init.GPIO_Speed=GPIO_Speed_2MHz;        //GPIO_Speed_2MHz/ Y& R5 }& }/ P" L6 O/ L
  13.     GPIO_Init(GPIOA,&IO_Init);+ E- [4 {$ p% i; W" z
  14.     0 u2 [' z8 |( Z: T2 A
  15.     /*数据线初始化*/
    , Z4 I. O5 `( g- O. Y
  16.     IO_Init.GPIO_Mode=GPIO_Mode_OUT;
      |- ~" i; p8 e% ]
  17.     IO_Init.GPIO_OType=GPIO_OType_OD;        //开漏输出可双向5 F. ]/ {' m+ g3 }: ?
  18.     IO_Init.GPIO_Pin=LCD_DB;
    ! ^- {' H( p4 `( Q& f$ k8 C3 y
  19.     IO_Init.GPIO_PuPd=GPIO_PuPd_UP;            //上拉9 [; O' ?- s. [7 M* T* |. O
  20.     IO_Init.GPIO_Speed=GPIO_Speed_2MHz;        
    $ h  K; u5 f( k1 M! J3 |
  21.     GPIO_Init(GPIOE,&IO_Init);                        + Y/ U  M& g% a9 G( v% ^: Z( `( F
  22.     /*测试 : 高电平3.3v
    - x" y) d3 l4 d* y) L# o: L
  23.     LCD_RS=1;
      a# q: l1 p: l, u1 a
  24.     LCD_RW=1;
    ( n& J& f  w1 A1 A" P6 V4 s# j
  25.     LCD_EN=1;
    * v# `+ I4 {; q: d" {; x
  26.     GPIO_SetBits(GPIOE,LCD_DB); */! w- D6 o% l. k4 K# {/ N) N
  27. }
复制代码
; _7 T! }0 M- |8 E
* E3 \* f) D$ Y9 A7 Z+ i1 Q; i; H
3.实现P1=0xff功能的函数,带参数
+ \! v, M" y# r7 w: k
  1. void GPIO_OutData(u8 Dat)
    / Z3 |% P3 U4 K# B: ]7 |
  2. {
    5 f! ]1 x& H7 I6 {5 [8 p6 i
  3.     u16 tmp;
    ) b1 F, ^  }7 y  a' S
  4.     tmp = 0;
      A; \& x- W6 m0 E, h' @
  5.     tmp =Dat;
    - j0 y, k3 y) l
  6.     tmp <<= 8;            //数据左移到高8位
    9 |! [( m4 ~" X* ]; s) o( n8 j# \
  7.     GPIO_Write(GPIOE,tmp);        //数据写入到GPIOE高8位
    ! m3 C: h# z7 ~; [6 l! q
  8. }
复制代码
+ @$ Q1 z5 \0 {
4.检测LCD是否忙. f5 R' S5 E& R& ~/ f
  1. void LCD_CheckBusy(void)# z, e( M; j2 O1 ^4 |+ M
  2. {
    ) X; C2 T0 q0 I: d
  3.     u8 sta;. ]; M5 J9 H$ z7 g( S6 s' J, n
  4.     GPIO_OutData(0xff);# a* C* T2 e3 e) I
  5.     LCD_RS=0;! A/ {& e4 K6 ?: q8 ^& _- q
  6.     LCD_RW=1;
    * A5 ?* W# ^& z, L$ a" o0 C( _
  7.     do{6 _3 S6 Z$ v2 l- @% e  G- x) I
  8.         LCD_EN=1;; a9 p: m( ^  K7 S4 R
  9.         delay_ms(5);) X: Q  W9 m  G
  10.         sta = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);
    / m' Z/ e" d2 s* {5 F" i8 W
  11.         LCD_EN =0;/ K0 E8 F. _* G7 v+ E0 q
  12.     }while(sta & 0x80);6 S- h. x' W: b# E0 L
  13. }
复制代码

& k4 J/ T$ F# F3 b9 o' _
0 w9 L' g! ]/ A, O5.向LCD写一字节数据
+ U- L! X' C  L4 T2 l
  1. /* LCD_RS = 1, LCD_RW = 0 */" }4 Z) |9 X. o: F! N
  2. void LCD_WriteData(u8 Dat)2 y3 \" }- ?. ^7 J
  3. {
    4 b6 J$ s, r$ T

  4.   H- d8 [$ N4 A5 n0 a
  5.     LCD_CheckBusy(); //忙则等待
    7 ]2 M/ ]# a7 Z+ ]2 ?7 W
  6.     LCD_RS=1;
      c9 x1 q- G: D9 B' k
  7.     LCD_RW=0;5 r& m, h  p0 `( }
  8.     GPIO_OutData(Dat);
    2 x0 f2 k3 Q- G7 o9 n' M
  9.     LCD_EN=1;
    3 b) ]: W. V: a9 g! u; J( [7 W& R+ _1 s
  10.     delay_ms(1);
    # m# Z$ j2 e& z8 v* t& G" [6 U. W
  11.     LCD_EN = 0;
    - v$ Q8 K$ v. A! E2 e8 K" Q
  12.     9 D8 m3 i0 l- L, l/ ]! p7 `8 O0 u
  13. }
复制代码

& T* ~8 j+ R  Z 6.向LCD写一字节命令
2 o8 }7 ?8 v2 u, Z8 c/ t6 j9 |" w
  1. /*LCD_RS = 0, LCD_RW = 0*/
    , A* r" p$ l. y& _& Q$ T) e
  2. void LCD_WriteCmd(u8 Cmd)) S# R; \  O% S5 u& u; j8 e
  3. {6 E% w! T0 T2 E  U5 p  {- X6 f
  4.     LCD_CheckBusy(); //忙则等待+ h2 z+ `7 b3 V3 [1 m' I6 E
  5.     LCD_RS = 0;
    $ c0 [- g4 h. }% @' i4 O: H3 S/ i
  6.     LCD_RW = 0;
    % ~) I5 C% q8 p
  7.     GPIO_OutData(Cmd);   
    ; D1 S8 Z! O2 C
  8.     LCD_EN = 1;/ E: e$ X* H. q
  9.     delay_ms(1);1 O; ?# h) V6 Q' i1 {9 t
  10.     LCD_EN = 0;     8 ?" K5 K+ Z( `8 `' T3 T5 N
  11. }
复制代码

7 [) k4 A3 ^# ?; c4 Q/ n/ a# d! `. z7.LCD初始化8 T- e  ?) b; d. w
  1. void LCD_Init(void)
    6 U/ P# A" d! o1 B
  2. {9 ?7 B2 A* g. e  o
  3.     LCD_WriteCmd(0x38);
    * E: W' a: h; Y+ N( U6 i; {
  4.     LCD_WriteCmd(0x0C);9 t' r+ J& I, d8 _8 w% G! {
  5.     LCD_WriteCmd(0x06);    /*显示光标移动设置*/    delay_ms(1);
    3 L) m# K$ X9 t, `; o* p
  6.     LCD_WriteCmd(0x01);    /*显示清屏*/
    ' b$ t1 d0 O$ h) D+ n
  7. }
复制代码
) H) }- P$ h  G& C
8.LCD清屏% |& c( ~+ J: K
  1. <div>void LCD_ClearScrren(void)</div><div>{</div><div>    LCD_WriteCmd(0x01);</div><div>}</div>
复制代码

! l0 r: ^9 e" H% u; Z8 G- |0 `
* Y1 h  M: m4 Q" r, r/ X8 e! W' X2 x
9.根据xy坐标,写入对应的数据位置& p; y; K8 l& p, Y- j: L+ Q
  1. void LCD_SetCursor(u8 x, u8 y), q/ J- Q- H# R# u+ s
  2. {
    3 h; L) Y; ]+ @  F- G; D# k$ e' m
  3.     u8 addr;
      P) \8 t9 ^6 c) C6 F1 `. ^
  4.     if (y == 0)
    0 w: f+ S7 N. a( ]' R$ S3 I  W+ Y8 ^
  5.         addr = 0x00 + x;
    * X5 j: z4 [- u5 e
  6.     else: I2 y) H: w& N; n
  7.         addr = 0x40 + x;& t  @& k$ k! x
  8.     LCD_WriteCmd(addr | 0x80);! Z7 u" p" w3 z  w- x
  9. }
复制代码

9 k$ Y1 P6 K$ ~- s% Z7 p6 X 10.根据xy坐标显示一个字符
1 P7 f% b6 h0 X, b9 g
  1. void LCD_DisChar(u8 x,u8 y,u8 ch)# f' T. o/ X, o7 T. a' P7 }
  2. {
    ! I2 H/ x* D1 F: M* w2 J& o
  3.     LCD_SetCursor(x,y);        //字符显示位置设定
    ; P7 F. O8 d4 m  V' P
  4.     LCD_WriteData(ch);
    , i' N" b/ c" S) K9 n8 l1 W
  5. }
复制代码
) w& E/ u1 ~+ C( f& F, o
11.显示两位的数字% x# N. T) G/ Q3 x: n* d( K
  1. void LCD_DisNumber(u8 x,u8 y,u8 Num)
    4 X: |: U( }, |
  2. {; K- O- s7 b* o6 B9 W
  3.     LCD_SetCursor(x,y);. Y4 ~, }7 [* _1 V1 a
  4.     LCD_WriteData(0x30+Num/10);! }- |4 x+ y3 |/ p- H/ L7 E" v
  5.     LCD_SetCursor(x+1,y);
    3 d" T+ \5 z5 R$ @6 A6 l
  6.     LCD_WriteData(0x30+Num%10);. {- J, ~' h4 u; r& p2 u! c
  7. }
复制代码

6 [. [* |5 _# b/ i
" z$ I( ]2 b0 C! Q12.显示字符串+ o& w/ \' a0 @( c7 a5 c$ N
  1. void LCD_DisString(u8 x,u8 y,u8 *str)
    % `. V& p" W( |* I; D
  2. {
    3 {. N+ y: |4 U5 L7 z* b# q
  3.     LCD_SetCursor(x, y);8 [# A4 g3 F5 G4 W# G0 R
  4.     while(*str != '\0')5 ~  w& ~8 Q# R
  5.     {
    ; a8 f9 I% S# z8 J, W+ h" m
  6.         LCD_WriteData(*str++);
    ! b7 k: \: K6 r1 v3 _& N) N
  7.     }( _9 K0 h% n3 g5 ]7 x" A) l
  8. }
复制代码
( A- @# u4 L* Y# q$ A, w1 p# }
主函数
4 @) I& Q$ V. Z: `) j( `# j) y; k
  1. int main(void)  O! H9 ]5 e# E4 Q- J2 ]
  2. {
    5 j6 }2 J) D) s" _; t5 M, K
  3.     delay_init(168);. y& b* w5 g. c& z2 S8 X+ C& C
  4.     LED_Init();
    / D. [- t4 a6 j* m9 b" n
  5.     3 O& g  H8 k. F* \, M' A
  6.     LCD_GPIO_Config();+ c' q4 N2 k) T+ c; d  N* C
  7.     LCD_Init();* h7 X# ]0 h3 T7 a+ x9 A
  8.     LCD_ClearScrren();; C. r+ t8 q  `% G: _% K
  9.     while(1)
    ) I( u1 h( r9 M2 W9 G" z* e1 m
  10.     {/ H& l4 H1 m6 V. N& ?/ Y4 S
  11.         delay_ms(500);
    0 Y7 Q( a$ q9 C: M; E- q
  12.         LED1_ON;! t4 P4 D  z& {2 ~) ]
  13.         LCD_DisString(0,0,"abcdefghijklmnop");. C/ P4 U- Y5 V! T7 w* |
  14.         delay_ms(500);
    ! k- s$ n' S' j7 J7 D
  15.         LED1_OFF;: ^. ]" b9 L9 g: ?/ w9 b
  16.         LCD_DisNumber(0,1,56);# {; |; q4 `+ z( ?$ ]9 [
  17.         LCD_DisChar(2,1,'a');
    7 _' G* [2 K) u5 e) y
  18.         LCD_DisString(3,1," Hello World!");  l& B% T$ J# C; V
  19.     }    ' @8 d+ m/ B) W+ \) }$ W
  20. }
复制代码

) M5 W0 `0 z  W4 j$ {5 E& `( Q" E$ c7 b' S$ \7 N) |
实际显示效果:1 g8 `5 x- d* N$ y) D1 n7 a
# C, }; x) A* L  v, x, x1 Y
1124009-20170423140758382-1252243185.jpg
$ j( }: V, R4 M' t2 g( x5 f6 |% m3 }8 s& f) ]  l
显示非常完美,和51驱动没有什么区别
' N7 L5 ]1 _) @( c% O3 W  J
( h3 n: Y1 l5 g7 S+ n% Y  n
总结:
7 }2 B* |6 I' d: {实际运行时,不使用检测忙函数也行,1602显示正常了,接下来就是增加定时器显示时钟了。在设置IO口模式时,可以将模式设置为开漏模式,就可以实现双向IO的目的,即可输出,又可以读取外部输入。通过位带操作和宏定义就可以像51那样直接操作IO口输出高低电平了。
- r' B1 \& {( l) r+ B# d7 B6 L/ c* o6 Q# n3 b1 J8 i

# y0 {6 }3 {5 l' W( r3 ^! _
& T) P) z6 T, n7 D
收藏 评论0 发布时间:2022-2-7 20:41

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版