完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1)实验平台:【正点原子】 NANO STM32F103 开发板
2)摘自《正点原子STM32 F1 开发指南(NANO 板-HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子 第十七章 数码管显示实验 前面几章的实例,均没涉及到显示,这一章,我们将向大家介绍数码管的使用。在本章中,我们将使用 NANO STM32F103 V1 开发板上的数码管模块,来点亮数码管,并实现字符的显示。本章分为如下几个部分: 17.1 数码管/74HC595D/74HC138D 简介 17.2 硬件设计 17.3 软件设计 17.4 下载验证 17.1 数码管/74HC595D/74HC138D 简介 1)数码管 数码管,也称 LED 数码管,按发光二极管单元连接方式可分为“共阳极数码管”和“共阴极数码管”。而开发板板载的数码管为四位共阴极数码管,实物图与内部引脚图,如图 17.1.1所示: 图 17.1.1 四位数码管实物与内部引脚结构图 共阳极数码管是指将所有发光二极管的阳极接到一起,而共阴极数码管则是发光二极管的阴极连到一起,连接方式如图 17.1.2 所示: 图 17.1.2 数码管的连接方式 从上图可以看到,数码管为共阴时,当某一字段的发光二极管阳极为高电平时,响应字段就点亮,为共阳时,当某一字段的发光二极管阴极为低电平时,相应字段则点亮。所以通过点亮相对应的字段就可以显示我们需要的字符。数码管要正常显示,就要用驱动电路来驱动数码管的各个端码,从而显示出我们要的字符,因此根据数码管的驱动方式不同,可以分为“静态式”和“动态式”两类。静态显示驱动,也称为直流驱动。静态驱动是指每个数码管的每一个端码都有一个单片机的 I/O 端口进行驱动,或者使用如 BCD 码二-十进制译码进行驱动。静态驱动的优点是编程简单,显示亮度高,缺点是占用 I/O 端口多,如驱动 5 个数码管静态显示则需要 5×8=40 个 I/O 端口来驱动,要知道 STM32 单片机可用的 IO 端口是有限的,实际应用时必须增加译码器进行驱动,但会增加电路的复杂性。动态显示驱动,是单片机应用中最为广泛的显示方式,动态驱动是将所有数码管的 8 个显示笔划“a,b,c,d,e,f,g,dp”的同名端连载一起,另外为每个数码管的公共级 COM 增加位选通控制电路,位选通由各自独立 IO 线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通 COM 端电路的控制,所有我们只要将需要显示的数码管的选通控制打开,改为就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的 COM 端,就可以使各个数码管轮流显示。在轮流显示过程中,每位数码管的点亮时间为 1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,只要扫描的速度够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静止显示是一样的,能够节省大连的 IO端口,功耗降低。本实验我们将使用动态驱动的方式驱动数码管,为了节省 IO,使用到驱动电路,段选数据使用 74HC595D 串行数据转并行数据输出芯片,位选数据使用 74HC138D 三-八译码器芯片。下面将介绍这两款芯片。 2)74HC595D 74HC595D 是恩智浦 NXP 公司推出的一款低噪声、低功耗、高速的 CMOS 移位寄存器, 能够驱动 15 个 LS-TTL 的负载。该器件包含一个 8 位串行输入、并行输出的移位寄存器及带有 三态输出控制的 8 位 D 型存储器。74HC595D 的特点如下: ①、带存储功能的 8 位串行输入,并行输出的移位寄存器 ②、工作电压范围宽:2V-6V ③、可级联使用 74HC595D 广泛应用于点阵屏和主控 IO 较少数据串行转并行的场合,74HC595D 的框图如 图 17.1.1 所示: 图 17.1.1 74HC595D 框图 1,引脚说明 74HC595D 的引脚说明如表 17.1.2 所示: 表 17.1.2 74HC595 引脚说明 我们使用的 74HC595D 采用 SO16 封装,总共 16 个脚,其中包括 8 个三态输出 IO 口、1 个串行数据输出端,1 个移位寄存器清零端,1 个数据输入时钟,1 个输出存储器锁存时钟,1 个输出使能端,1 个串行数据输入端,等其他引脚。下面我们分别以数据端和控制端讲解下引 脚的作用: 数据端: Q0-Q7:八位并行数据输出端,可以直接控制数码管的 8 个段。 Q7’:级联输出端。它可接入下一个 74HC595 的 DS 端。 DS:串行数据输入端,级联的话接上一级的 Q7’。 控制端: /MR(10 脚):低电平时将移位寄存器的数据清零。一般情况下接 VCC。 SH_CP(11 脚):上升沿时数据寄存器的数据移位。传输方向:Q0->Q1->Q2->Q3->...->Q7; 下降沿移位寄存器数据不变。 ST_CP(12 脚):上升沿时移位寄存器的数据进入数据存储器,下降沿时存储器数据不变。 通常将 ST_CP 置为低电平,当移位结束后,在 ST_CP 端产生一个正脉 冲,更新显示数据。 /OE(13 脚):高电平时禁止输出(高组态)。可以用一个引脚控制它,可以方便地产生 闪烁和熄灭效果。 2,时序图 数据的串行输入需要按照规定的时间才能正常写入,根据上面讲解,我们要知道的是 SH_CP 上升沿高电平和 ST_CP 正脉冲保持的时间,如图 17.1.3 所示: 图 17.1.3 SHCP 和 STCP 时序图 从上图可以看到时序的时间都是 ns 级别的,在写软件时我们只需要几 us 的时间就可以了。 通过 74HC595D 的使用,我们就可以以串行数据输入,并行数据输出控制数码管的端选段, 从而显示对应的字符。 3)74HC138D 74HC138D 是恩智浦 NXP 公司推出的一款高速 CMOS、低功耗的 3-8 译码器。通过三个地 址的输入设置,可选择对应八种的状态输出。74HC138D 的特点如下: 1)低功耗。 2)工作电压范围宽:3V-5V。 74HC138D 广泛应用于消费类电子产品,74HC138D 的框图如图 17.1.4 所示: 图 17.1.4 74HC138D 引脚和功能框图 1,引脚说明 74HC138D 的引脚说明如表 17.1.5 所示: 表 17.1.5 所示 74HC138D 引脚说明 2,真值表 Y0~Y7 的输出是 A0~A2 的设置的,而它们是依照 3-8 译码形式设置,以下是它们工作的 真值表,如图 17.1.6 所示: 图 17.1.6 74HC138D 真值表 从图可以看到,当/E1、/E2、E3 使能端使能后,设置 A0、A1、A2 的输入(高电平有效), /Y0~/Y7 都会有对应的状态输出(低电平),例如 A0、A1、A2 设置的是(A2=0,A1=1,A2=1), 根据 BCD-421 码的换算,代表是 3,则 Y3 输出有效电平 L,其他的都输出为无效电平 H。设 置(A2=1,A1=1,A0=1),代表是 7,则 Y7 输出有效电平 L,其他的都输出为无效电平 H。 通过 74HC138D 的使用,我们就可以控制对应数码管的位选端了。 17.2 硬件设计 本实验用到的硬件资源有: 1) 指示灯 DS0 2) 74HC595D、74HC138D 3) 数码管 数码管、74HC595D、74HC138D 电路连接如图 17.2.1-1 和图 17.2.1-2 所示: 图 17.2.1-1 开发板连接示意图 图 17.2.1-2 开发板连接示意图 原理图中 74HC595D 芯片标的引脚标号名称可能与芯片手册标的有点不一样,以下是引脚 对应标号关系,如表 17.2.2 所示: 表 17.2.2 引脚标号关系 从图 17.2.1 原理图可以看到,74HC138D 的使能端引脚默认已上拉或下拉硬件使能, 74HC595D 的 RST 复位引脚与开发板的复位线相连接,当按下开发板的复位按键或首次上电即 可对 74HC595D 的芯片的数据清零,以到达复位的作用。由于没有做级联的功能,SDO 引脚上 做了悬空处理。而使能端引脚也同样做了默认硬件使能。 在数码管中,两个数码管的 A~DOT 段选段都与 74HC595D 芯片的 QA~QH 相连接,而数 码管的 CH1~CH4 位选端则单独分别与 74HC138D 芯片的 Y0~Y7 引脚相连接。通过控制 74HC595D 输出的段码和控制 74HC138D 输出的位选就可以实现选择点亮数码管。 本节,我们将实现 8 位数码管的动态显示,通过 tiMER3 定时器 2ms 时间来刷新显示,1S 时间更新显示字符,下面我们开始软件设计。 17.3 软件设计 我们直接打开数码管显示实验可以发现 HARDWARE 下面有一个 smg.c 和 timer 文件,同 时包含了头文件 smg.h 和 timer.h。 timer.c 文件下的代码,是关于定时器的初始化配置,在第十三章定时器中断实验我们有比 较详细的讲解,这里就不做介绍了。这里我们主要讲解下 smg.c 的代码,首先是 LED_SMG_Init 函数,该函数比较简单,对使用到的 IO 口初始化,由于某些 IO 口是默认 JTAG 功能,这里调 用了 HAL 库函数,关闭 JTAG 功能,使能其作为普通 IO 口使用,LED_SMG_Init 函数代码如 下: //数码管驱动 IO 初始化 void LED_SMG_Init(void) { GPIO_InitTypeDef GPIO_Initure; __HAL_RCC_GPIOB_CLK_ENABLE(); //开启 GPIOB 时钟 __HAL_RCC_GPIOC_CLK_ENABLE(); //开启 GPIOC 时钟 __HAL_RCC_AFIO_CLK_ENABLE(); //开启 AFIO 时钟 __HAL_AFIO_REMAP_SWJ_NOJTAG(); //关闭 jtag,使能 SWD,可以用 SWD 模式调 试 PB4 做普通 IO 口使用,否则不能当 IO 使用 //74HC595 DS-PB3 LCLK-PB4 SCK-PB5 GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;//PB3~5 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速 HAL_GPIO_Init(GPIOB,&GPIO_Initure); //74HC138 A0-PC10 A1-PC11 A2-PC12 GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;//PC10~12 HAL_GPIO_Init(GPIOC,&GPIO_Initure); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_RESET); } 接着,要介绍的是 LED_Wei 函数。这函数实现控制 74HC138D 的 A0~A2 地址,将入口参 数通过转换设置 LED_A0~LED_A2 的宏定义 IO 位带操作,LED_Wei 函数代码如下: //74HC138 驱动 //数码管位选 //num:要显示的数码管编号 0-7(共 8 个数码管) void LED_Wei(u8 num) { LED_A0=num&0x01; LED_A1=(num&0x02)>>1; LED_A2=(num&0x04)>>2; } LED_Write_Data 函数,该函数实现了段码数据以 8 个上升沿的时钟先低位后高位的串行输 入形式,传输给 74HC595D,然后调用 LED_Wei 函数控制位选需要显示的数码管, LED_Write_Date 函数代码如下: //74HC595 驱动 //数码管显示 //duan:显示的段码 //wei:要显示的数码管编号 0-7(共 8 个数码管) void LED_Write_Data(u8 duan,u8 wei) { u8 i; for( i=0;i<8;i++)//先送段 { LED_DS=(duan>>i)&0x01; LED_SCK=0; delay_us(5); LED_SCK=1; } LED_Wei(wei);//后选中位 } 最后要介绍的是 LED_Refresh 函数,该函数实现对 74HC595D 串行输入的数据,进行刷新 输出给数码管,LED_Refresh 函数如下: //74HC595 驱动 //数码管刷新显示 void LED_Refresh(void) { LED_LCLK=1; delay_us(5); LED_LCLK=0; } 要正确显示数码管,需要正确的段码,接下来,我们介绍一个数码管段码查询的软件,该 软件的界面如图 17.3.1 所示: 图 17.3.1 数码管段码查询软件界面 该软件设置很简单,只要设置段码的排列顺序、数码管的极性,通过选择点击区,就可以 输出段码了。该软件也提供了一些常用的字符给我们选择。 根据我们开发板 74HC595D 驱动数码管的方式,极性选择“共阴”,排列的顺序选择“a-dp”, 如图 17.3.1 所示: 图 17.3.2 软件配置 根据软件的配置,设置了 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,.(点号),全灭,共 18 个显示字符段 码,分别是 0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e, 0x01,0x00。 smg.c 文件下的代码我们就介绍完了,接下来看看 smg.h,代码如下: #ifndef _LED_SMG_H #define _LED_SMG_H #include "sys.h" ////74HC138 操作线 #define LED_A0 PCout(10) //A0 地址线 #define LED_A1 PCout(11) //A1 地址线 #define LED_A2 PCout(12) //A2 地址线 ////74HC595 操作线 #define LED_DS PBout(3) //数据线 #define LED_LCLK PBout(4) //锁存时钟线 #define LED_SCK PBout(5) //时钟线 void LED_SMG_Init(void); void LED_Refresh(void); void LED_Write_Data(u8 duan,u8 wei); #endif 该部分比较简单,就是一些 IO 的宏定义和函数的定义。 最后说一下 main,c,该部分代码如下: //共阴数字数组 //0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, .,全灭 u8 smg_num[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe, 0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0x01,0x00}; int main(void) { HAL_Init(); //初始化 HAL 库 Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M delay_init(72); //初始化延时函数 uart_init(115200); //初始化串口 LED_Init(); //初始化 LED LED_SMG_Init(); //数码管初始化 TIM3_Init(19,7199); //2ms 定时显示 while(1) { } } u8 smg_wei=0;//数码管位选 u8 smg_duan=0;//数码管段选 u16 t=0; //回调函数,定时器中断服务函数调用 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim==(&TIM3_Handler)) { LED_Write_Data(smg_num[smg_duan],smg_wei);//数码管显示 LED_Refresh();//刷新显示 smg_wei++; if(smg_wei==8) smg_wei=0; t++; if(t==500)//数码管每秒更新 { t=0; LED0=!LED0; smg_duan++; if(smg_duan==18) smg_duan=0; } } } 代码比较简单,对数码管等其他外设初始化,控制数码管动态显示的定时器设置为 2ms 中 断,在定时器中断中每 2ms 刷新显示 1 位数码管,每 1S 时间更新显示数码管段码,字符从 0 开始不停的循环显示,同时 DS0 闪烁。然后我们编译此工程,直到编译成功为止。 代码比较简单,对数码管等其他外设初始化,控制数码管动态显示的定时器设置为 2ms 中 断,在定时器中断中每 2ms 刷新显示 1 位数码管,每 1S 时间更新显示数码管段码,字符从 0 开始不停的循环显示,同时 DS0 闪烁。至此,我们的软件设计就完成了。 17.4 下载验证 将代码下载到开发板后,可以看到 8 位数码管以 1S 时间更新显示,同时 DS0 不停的闪烁, 数码管显示如图 17.4.1 所示: 图 17.4.1 数码管显示效果 通过这一章的学习,我们学会了数码管的使用,在以后需要显示程序的编写,大家可以好 好利用。 |
|
相关推荐
|
|
STM32进行DMA数据转运,为什么只有A组最后一位数据被转运到B组去?
1229 浏览 2 评论
1561 浏览 3 评论
1185 浏览 0 评论
嵌入式开发 Win11安装ST-Link 提示 设备描述符请求失败 怎么处理?
1317 浏览 0 评论
1604 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-17 17:14 , Processed in 0.519220 second(s), Total 37, Slave 29 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191