当前位置: 首页 > java >正文

单片机-STM32部分:17、数码管

飞书文档https://x509p6c8to.feishu.cn/wiki/TOQqweKHWinugokUyqzcwb0fnTd

原理:

一个二极管等于八个LED组合在一起,想要显示什么形状,就点亮对应LED即可。

数码管根据其公共端所接的阳极和阴极的不同,分为了共阴极数码管和共阳极数码管。

共阳极接法:几个二极管的阳极接在一起,接到VCC(高电平),我们要想点亮,只要在在对应的二极管的阴极接上低电平即可。

共阴极接法:几个二极管的阴极接在一起,接到GND(低电平),我们要想点亮,只要在在对应的二极管的阳极接上高电平即可。

这节课,我们将使用共阴极数码管,这也就意味着我们要点亮数码管,要在对应的IO设置输出为高电平。

对于共阴极数码管,8个IO控制如下,就可以点亮对应的数字或字母。

16进制表示显示的数字点亮的位置二进制表示
0x3f0abcdef亮00111111
0x061bc亮00000110
0x5b2abdeg亮01011011
0x4f3abcdg亮01001111
0x664abcdg亮01100110
0x6d5acdfg亮01101101
0x7d6acdefg亮01111101
0x077abc亮00000111
0x7f8abcdefg亮01111111
0x6f9abcdfg亮01101111
0x77Aabcefg亮01110111
0x7cBcdefg亮01111100
0x39Cadef亮00111001
0x5eDbcdeg亮01011110
0x79Eadefg亮01111001
0x71Faefg亮01110001
0x00熄灭全灭00000000

但是这里我们遇到一个问题,点亮一个数码管,需要8个IO,两个数码管则需要16个IO,很多时候,单片机没有这么多IO分配到给这个模块使用,所以我们用两颗74HC595芯片来扩展驱动数码管。

74HC595芯片

该芯片是一个8位串行输入、并行输出的位移缓存器,可以简单理解为用一个IO进行数据输入,可以控制8个IO输出。

SHCP:移位寄存器时钟输入
STCP:存储寄存器时钟输入
DS:串行数据输入
OE:使能,低电平使能
MR: 复位,低电平复位

Q0~Q7:并行输出
Q7S:串行输出

  1. SHCP是上升沿的时候,写入DS的数据,上升沿时移位寄存器中的数据依次移动一位,即 Q0 中的数据移到 Q1 中,Q1 中的数据移到 Q2 中,依次类推
  2. STCP是上升沿的时候,把数据从移位寄存器转存带存储寄存器,应用时通常将 STCP置为低点平,移位结束后再在 ST_CP 端产生一个正脉冲更新显示数据。
  3. 有数据操作的过程中MR必须是高电平,OE必须是低电平,595才能工作。

由74HC595的芯片手册可以知道:74HC595芯片的发送顺序是由Q0,一直到Q7。

本设计使用了一个2位的数码管,为共阴型,为了节省单片机的IO口,使用了两片74HC595作为数码管的驱动芯片,共占用3个IO口。

第一片74HC595芯片的Q7S口,可以向下一片的74HC595芯片的串行输入口输入数据。

第一片74HC595芯片只使用了Q0、Q0两个管脚来管理数码管地址信息。
第二片74HC595芯片是用于控制数码管输出显示。

重要的一点是,先串行输入显示的数据,再串行输入地址。

与单片机相连接的三个脚分别为: DS,STCP,SHCP。

/* USER CODE BEGIN 0 */
void hc595_send_byte(unsigned char byte)
{unsigned int i;for(i = 0; i < 8; i++){//串行输入引脚,所谓串行就是使数据在一根信号线上按顺序一位一位地传输if(byte & 0x80)HAL_GPIO_WritePin(GPIOC,DS_Pin,GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOC,DS_Pin,GPIO_PIN_RESET);//SHCP发生一次上升沿的时候,74HC595才会从DS引脚上取得当前的数据HAL_GPIO_WritePin(GPIOC,SHCP_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC,SHCP_Pin,GPIO_PIN_SET);byte <<= 1;}
}void hc595_send_data(unsigned char num, unsigned char addr)
{hc595_send_byte(num); //先发需要显示的数字hc595_send_byte(1 << addr);   //再发需要点亮的数码管,这时候数字会被移位到第二个595中点亮//当移位寄存器的8位数据全部传输完毕后,制造一次锁存器时钟引脚的上升沿(先拉低电平再拉高电平)HAL_GPIO_WritePin(GPIOC, STCP_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, STCP_Pin, GPIO_PIN_SET);
}//共阳 数码管数组:0-9
//unsigned char num[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,0x80 ,0x90};
//共阴 数码管数组:0-9
unsigned char num[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};void display()
{hc595_send_data(num[1], 0);hc595_send_data(num[0], 1);
}
/* USER CODE END 0 */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */display();}/* USER CODE END 3 */

参考工程:

参考飞书文档

看完上面的原理讲解,可见数码管的显示实际上不就是每一位数码管在肉眼不可见的频率下不间断地轮流刷新,那直接放在主程序的while(1)循环里不就好了。

对于主函数有耗时任务执行的场景,也可以使用定时器来刷新数码管 。定时器刷新数码管,其一,我们可以不用过多地考虑数码管刷新的频率,因为它的刷新频率在一开始就已经设置了;其二,我们不用担心会有其他的东西干扰数码管刷新,因为我们是将数码管放在定时器中断里刷新的,只要配置的中断优先级足够高,就一定不会有其他的进程干扰数码管刷新!

http://www.xdnf.cn/news/6284.html

相关文章:

  • Dify 使用代码创建 echarts图表 (一)
  • TCP 粘包
  • Python实战案例:打造趣味猜拳小游戏
  • leetcode 56. 合并区间
  • 召回11:地理位置召回、作者召回、缓存召回
  • Maven clean 提示文件 java.io.IOException
  • 【网工】华为配置基础篇①
  • AI 时代, 需要什么样的数据底座?
  • 新型智慧园区技术架构深度解析:数字孪生与零碳科技的融合实践
  • STL?list!!!
  • 驱动-定时-秒-字符设备
  • 高频交直流电流测量技术:射频PA与MEMS测试的简单解决方案
  • kafka调优
  • 漏洞修复:tomcat 升级版本 spring-boot-starter-tomcat 的依赖项
  • 【抽丝剥茧知识讲解】引入mybtis-plus后,mapper实现方式
  • 从理论到实战:模糊逻辑算法的深度解析与应用实践
  • RabbitMQ高级篇-MQ的可靠性
  • 精益数据分析(62/126):从客户访谈评分到市场规模估算——移情阶段的实战进阶
  • 深入理解 Dijkstra 算法:原理、实现与优化
  • 【MCP教程系列】SpringBoot 搭建基于 Spring AI 的 SSE 模式 MCP 服务
  • 数字信号处理-大实验1.3
  • 为什么我不能获取到镜像,ImagePullBackoff
  • 观测云:从云时代走向AI时代
  • 二叉树(中序遍历)
  • 海信璀璨505U6真空冰箱闪耀“国家德比”
  • 从零开始完成“大模型在牙科诊所青少年拉新系统中RAG与ReACT功能实现”的路线图
  • 【Python】对象生命周期全解析
  • 【Python-Day 13】Python 元组 (Tuple) 详解:从创建、操作到高级应用场景一网打尽
  • springboot AOP 接口限流(基于IP的接口限流和黑白名单)
  • 万字解析:Java字符串