文章目录
- 硬件电路
- 连接方式
- 函数实现
- 文章福利
硬件电路
通过上述原理图,可知拓展板上的数码管是一个共阴数码管,也就是说某段数码管接上高电平时,就会点亮。
上述原理图还给出一个提示,即:三个数码管分别与三个74HC595移位缓存器并联,而三个移位寄存器串联。
74LS595芯片实际上是一个8位串行输入、并行输出的位移缓存器。也就是说数据是一个一个进入,但是一起输出的。
当SCK处于上升沿时,串行数据由SDL输入到内部的8位位移缓存器,并由Q7’输出;而并行输出则是在LCK处于上升沿时,将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低使能时,并行输出端的输出值等于并行输出缓存器所存储的值。
点亮三个数码管需要3*8=24个数据,而一个74LS595移位寄存器只能够存储8位数据,其存储值远小于输入值。
根据上述的原理,可知:上图中seg3数码管的数据是经seg2数码管位移过来的,而seg2数码管数据是经seg1数码管位移过来。也就是说数码管刷新的顺序为seg3->seg2->seg1。
共阴数码管显示说明
首先来看看一个数码管的段码分布吧!🤤🤤🤤
也就是说一个数码管是由八段组成,a段为最低位,dp为最高位。
由于拓展板的数码管是一个共阴数码管(1有效)。那么显示数值的段码由来示例分析为:
显示值 | dp | g | f | e | d | c | b | a | 十六进制表示 |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0x3f |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0x06 |
0. | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0xbf |
1. | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0x86 |
连接方式
经过查找原理图,不难发现74LS595芯片的三个输入端(SER、PCLK、SCK)实际上分别与PA1、PA2、PA3引脚相连接。
因此,其连接方式如下图:
函数实现
cubeMx配置
函数示例
声明定义:
// 声明GPIO分组及引脚
#define RCLK_PIN GPIO_PIN_2
#define RCLK_PORT GPIOA
#define SER_PIN GPIO_PIN_1
#define SER_PORT GPIOA
#define SCK_PIN GPIO_PIN_3
#define SCK_PORT GPIOA
// 声明函数别名
#define RCLK_H HAL_GPIO_WritePin(RCLK_PORT, RCLK_PIN, GPIO_PIN_SET)
#define RCLK_L HAL_GPIO_WritePin(RCLK_PORT, RCLK_PIN, GPIO_PIN_RESET)
#define SER_H HAL_GPIO_WritePin(SER_PORT, SER_PIN, GPIO_PIN_SET)
#define SER_L HAL_GPIO_WritePin(SER_PORT, SER_PIN, GPIO_PIN_RESET)
#define SCK_H HAL_GPIO_WritePin(SCK_PORT, SCK_PIN, GPIO_PIN_SET)
#define SCK_L HAL_GPIO_WritePin(SCK_PORT, SCK_PIN, GPIO_PIN_RESET)
函数实现:
/************ 共阴数码管段码 *****************/
// 0 1 2 3 4 5 6 7 8 9 - 熄灭
u8 segTab[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x40, 0x00,
// 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. - 熄灭
0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef, 0x40, 0x00,
// A B C D E F 熄灭
0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00 };
// 储存数码管需要显示的值
u8 segBuff[3] = {10,10,10};
/* -------------------------------- begin -------------------------------- */
/**
* @Name segDisplay
* @brief 数码管显示函数
* @param None
* @retval None
* @author 黑心萝卜三条杠
* @Data 2023-03-02
**/
/* -------------------------------- end -------------------------------- */
void segDisplay(void)
{
u8 code_tmp = 0,j = 0;
static u8 i = 3;
code_tmp = segTab[segBuff[i-1]];
// 拉低复位端口 低电平有效 表示需要写入数据
RCLK_L;
for(j = 0; j < 8; ++j)
{
// 拉低控制信号
SCK_L;
// 判断最高位是否为1
if(code_tmp & 0x80)
// 写入1
SER_H;
else
// 写入0
SER_L;
code_tmp = code_tmp << 1;
// 拉低控制信号
SCK_L;
// 拉高控制信号
SCK_H;
}
// 拉高复位端口 一般默认接VCC 表示写入数据完成
RCLK_H;
// 移动下一次显示数码管的位置
if(--i > 0 ) i = 3;
}
使用说明:使用时直接将要显示的数据放入数组segBuff[]
,再调用刷新函数segDisplay()
code>即可。
例如
void sysWork(void)
{
static int i = 0;
segDisplay();
segBuff[0] = i;
segBuff[1] = i+1;
segBuff[2] = i+2;
i = (i+1)%24;
}
注意使用上述的segDisplay()
函数还需要调整刷新频率,否则会出现闪烁的情况。
若认为老实调节频率过于麻烦,可以使用下面这个版本的>segDisplay()
:
/* -------------------------------- begin -------------------------------- */
/**
* @Name segDisplay
* @brief 数码管显示函数
* @param None
* @retval None
* @author 黑心萝卜三条杠
* @Data 2023-03-02
**/
/* -------------------------------- end -------------------------------- */
void segDisplay(void)
{
u8 code_tmp = 0,j = 0,i = 3;
for(i=3;i>0;--i)
{
code_tmp = segTab[segBuff[i-1]];
// 拉低复位端口 低电平有效 表示需要写入数据
RCLK_L;
for(j = 0; j < 8; ++j)
{
// 拉低控制信号
SCK_L;
// 判断最高位是否为1
if(code_tmp & 0x80)
// 写入1
SER_H;
else
// 写入0
SER_L;
code_tmp = code_tmp << 1;
// 拉低控制信号
SCK_L;
// 拉高控制信号
SCK_H;
}
// 拉高复位端口 一般默认接VCC 表示写入数据完成
RCLK_H;
}
}
至于函数调用本质上是一样的,只不过可以不用细调数码管的刷新频率了。🤣🤣🤣
文章福利
下边是小编个人整理出来免费的蓝桥杯嵌入式福利,有需要的童鞋可以自取哟!🤤🤤🤤
- 【蓝桥杯嵌入式】第十一届蓝桥杯嵌入式省赛(第二场)程序设计试题及其题解
- 【蓝桥杯嵌入式】第十二届蓝桥杯嵌入式省赛程序设计试题以及详细题解
- 【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式省赛程序设计试题及其详细题解
- 【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式省赛(第二场)程序设计试题及其题解
- 【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式国赛程序设计试题以及详细题解
- 【蓝桥杯】一文解决蓝桥杯嵌入式开发板(STM32G431RBT6)LCD与LED显示冲突问题,并讲述LCD翻转显示
也欢迎大家留言或私信交流,共同进步哟!😉😉😉