Stm32CubeMX+Proteus仿真入门

第 五 章

本章节资料下载链接:

我用夸克网盘给你分享了「第5章 数码管显示」,点击链接或复制整段内容,打开「夸克APP」即可获取。

/f4b73M6B4U😕

链接:https://pan.quark.cn/s/9802ba84d838

1、数码管

1.1 数码管介绍

数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元,也就是多一个小数点(DP),这个小数点可以更精确的表示数码管想要显示的内容;按能显示多少个可分为 1位、 2位、 3位、 4位、6位、8位等数码管。按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管。

img

共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极 COM 接到电源正极,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。

共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极 COM 接到地线 GND 上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮

对共阴极数码来说,其 8 个发光二极管的阴极在数码管内部全部连接在一起,所以称“共阴”,而它们的阳极是独立的,通常在设计电路时一般把阴极接地。当我们给数码管的任意一个阳极加一个高电平时,对应的这个发光二极管就点亮了。如果想要显示出一个 8 字,并且把右下角的小数点也点亮的话,可以给 8个阳极全部送高电平,如果想让它显示出一个 0 字,那么我们可以除了给第“g,dp” 这两位送低电平外,其余引脚全部都送高电平,这样它就显示出 0 字了。需注意,共阴极数码管需要驱动端提供稳定电流,单片机一般提供不了,一般需要驱动电路才能稳定驱动,比如 74HC573、74HC245 等。img

编码:需要共阴极数码管显示一个2,需要ABGED两个发光二极管点亮,对应数值为1,其IGFE CDBA的二进制数值0101 1011,对应16进制为0x5B。反观共阳极显示一个2,对应的IGFE CDBA的二进制为1010 0100,对应16进制为0xA4。其他数字和部分字母显示如下所示。


共阴数码管表

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d,

0       1       2     3      4      5

0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c,

6        7      8     9      A      B

0x39, 0x5e, 0x79, 0x71, 0x00,

C        D      E     F     无显示

 

共阳数码管表

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92,

0      1        2     3      4      5

0x82, 0xF8, 0x80, 0x90, 0x88, 0x83,

6       7       8      9      A      B

0xC6, 0xA1, 0x86, 0x8E, 0xFF,

C       D       E     F     无显示

1.2 数码管动态显示

多位数码管内部的公共端是独立的,而负责显示什么数字的段线(a-dp)全部是连接在一起的,独立的公共端可以控制多位一体中的哪一位数码管点亮,而连接在一起的段线可以控制这个能点亮数码管亮什么数字,通常我们把公共端叫做“位选线”,连接在一起的段线叫做“段选线”。下图的ABCDEFG DP引脚是段选,1234是位选。

img

动态显示数码管并不是同时点亮的,而是以非常快的速度轮流点亮。比如,先点亮第一个数码管一秒的几十分之一,然后迅速切换到第二个数码管,再切换到第三个、第四个,之后又回到第一个,如此循环。这个切换速度足够快,以至于人眼无法察觉到它们是交替亮起的,看起来就像是所有数码管同时亮着一样。

1.3 74HC245 和 74HC138 芯片介绍

74HC245芯片介绍

74HC245是一种三态输出、八路信号收发器

img

真值表

img

OE和DIR引脚控制输出方向。OE低电平是输出模式,DIR为高电平时,A出入B输出。

仿真图

仿真和原理图相比取少量了VDD和GND,其他一致。选用的输出方向是A输入,B输出。

img

可以理解为,引入74HC245是增强驱动能力,A是什么电平,B就是什么电平但是驱动能力更强,LED更亮,如果取消掉74HC245直连到数码管的话,实物的数码管不够亮。

74HC138芯片简介

74HC138D是一种三通道输入、八通道输出译码器。

img

真值表:

一般固定E1 E2和E3的值为LLH。通过控制A0 A1和A2的值控制输出位置。

img

仿真图:

img

控制通过LSA LSB LSC的电平,控制输出端Y0-Y7,通过代码控制选择不同的位选,从而显示动态显示。A0、A1、A2 输入就相当于 3 位 2 进制数,A0 是低位,A1 是次高位,A2 是高位。而 Y0-Y7 具体哪一个输出有效电平,就看输入二进制对应的十进制数值。比如输入是 101(A2,A1,A0),其对应的十进制数是 5,所以 Y5 输出有效电平(低电平)。

1.4 代码工程配置

stm32cubemx:用Part01_LEDBIT复制修改命名为Part02_LEDSEG,PA0-PA7选择输出模式分别取别名为LED0-LED7,PB3-PB5输出模式,分别取别名为LSC,LSB,LSA

imgimg

重新生成初始化代码。添加两个文件smg.c和smg.h到工程文件,目录放在Public下,并添加.c和.h到工程。步骤如9.3工程配置。

smg.c的代码如下

#include "smg.h"
#include "system.h"
#include "gpio.h"

//共阴极数码管显示0~F的段码数据
uint8_t gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//数码管端口8位数据同时操作,不影响高位
//写入数据到8位端口,数据低位对应端口低引脚
//GPIO_Pin:8位端口低位引脚
//data:写入数据
void SMG_Write_Data(u8 data)
{
#if 1
		uint16_t Set_Pins = 0, Rst_Pins = 0;
	//DataDir('O');
	if(data & 0x01) Set_Pins |= LED0_Pin;
	else Rst_Pins |= LED0_Pin;
	if(data & 0x02) Set_Pins |= LED1_Pin;
	else Rst_Pins |=  LED1_Pin;
	if(data & 0x04) Set_Pins |=  LED2_Pin;
	else Rst_Pins |=  LED2_Pin;
	if(data & 0x08) Set_Pins |=  LED3_Pin;
	else Rst_Pins |=  LED3_Pin;
	if(data & 0x10) Set_Pins |=  LED4_Pin;
	else Rst_Pins |=  LED4_Pin;
	if(data & 0x20) Set_Pins |=  LED5_Pin;
	else Rst_Pins |=  LED5_Pin;
	if(data & 0x40) Set_Pins |=  LED6_Pin;
	else Rst_Pins |=  LED6_Pin;
	if(data & 0x80) Set_Pins |=  LED7_Pin;
	else Rst_Pins |=  LED7_Pin;
	
	HAL_GPIO_WritePin(GPIOA, Set_Pins, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOA, Rst_Pins, GPIO_PIN_RESET);
#else
	 GPIOA->ODR = gsmg_code[data];  
#endif
}

//数码管显示
void SMG_Display(uint8_t dat[],uint8_t pos)
{
	u8 i=0;
	u8 pos_temp=pos-1;//从0开始

	for(i=pos_temp;i<8;i++)
	{
	   	switch(i)//位选
		{
			case 0: LSC=1;LSB=1;LSA=1;break;
			case 1: LSC=1;LSB=1;LSA=0;break;
			case 2: LSC=1;LSB=0;LSA=1;break;
			case 3: LSC=1;LSB=0;LSA=0;break;
			case 4: LSC=0;LSB=1;LSA=1;break;
			case 5: LSC=0;LSB=1;LSA=0;break;
			case 6: LSC=0;LSB=0;LSA=1;break;
			case 7: LSC=0;LSB=0;LSA=0;break;
		}
		SMG_Write_Data(dat[i]);
		//传送段选数据
		HAL_Delay(2);//延时一段时间,等待显示稳定
		SMG_Write_Data(0x00);//消隐
	}
}


smg.h代码如下

#ifndef _smg_H
#define _smg_H
#include "system.h"
//位带定义
#define LSA 	PBout(5)
#define LSB 	PBout(4)
#define LSC 	PBout(3)

#define HCA0	PAout(0)
#define HCA1	PAout(1)
#define HCA2	PAout(2)
#define HCA3	PAout(3)
#define HCA4	PAout(4)
#define HCA5	PAout(5)
#define HCA6	PAout(6)
#define HCA7	PAout(7)

extern uint8_t gsmg_code[17];
//函数声明
void SMG_Display(uint8_t dat[],uint8_t pos);
void SMG_Write_Data(u8 data);
#endif


main.c添加头文件说明

img

/ USER CODE BEGIN Includes /

#include "smg.h"

#include "system.h"

#include "stm32f1xx_hal_gpio.h"

#include "string.h"

/ USER CODE END Includes /

添加变量声明

img

/ USER CODE BEGIN 1 /

 u8 smgbuf[8];

 u32 num = 87654321;

 u8 qwan,bwan,swan,wan,qian,bai,shi,ge=0;

 / USER CODE END 1 /

main函数添加代码段

 / USER CODE BEGIN WHILE /

  qwan=num/10000000%10;

  bwan=num%10000000/1000000;

  swan=num%1000000/100000;

  wan=num%100000/10000;

  qian=num%10000/1000;

  bai=num%1000/100;

  shi=num%100/10;   /num先求余得到十位个位 再求整得到十位  数码管显示十位/

  ge=num%10;     /num求余  数码管显示个位/

 while (1)

 {

  / USER CODE END WHILE /

 / USER CODE BEGIN 3 /  

  memset(smgbuf, 0, sizeof(smgbuf));

  smgbuf[0]=gsmg_code[qwan];

  smgbuf[1]=gsmg_code[bwan];

  smgbuf[2]=gsmg_code[swan];

  smgbuf[3]=gsmg_code[wan];

  smgbuf[4]=gsmg_code[qian];

  smgbuf[5]=gsmg_code[bai];

  smgbuf[6]=gsmg_code[shi];

  smgbuf[7]=gsmg_code[ge];

  SMG_Display(smgbuf,1);

 }

 / USER CODE END 3 /

img

实验现象:

数码管显示87654321

img

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐