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

阴阳脚数码管

1.小故事

最近,我接到了一个既“清肺”又“烧脑”的新任务,设计一个低功耗蓝牙肺活量计。在这个项目中我们借鉴了一款蓝牙跳绳的硬件设计方案,特别是它的显示方案——数码管。

在电子工程领域,初学者往往从操作LED开始,随后进阶到控制数码管,由此可见,数码是非常基础,使用非常广泛的一个电子元件。

在这里插入图片描述
然而,刚拿到这个4位数码管时,我注意到了一个不寻常的特点:这个4位数码管仅有7个引脚,而传统4位数码管至少需要12个引脚,最初,我误以为该数码管内部集成了某种芯片,所以才导致引脚简化。

但是,当供应商提供资料时,我才发现它内部并没有芯片,它就是通过普通IO脚控制的数码管,但是这种数码管并不是我们常见的数码管,供应商给的名字是:阴阳脚数码管(单排数码管)!
在这里插入图片描述
顿时,我被这霸气名字所吸引,决定探究一番,经过查阅资料、搭建电路、编写程序,不出意外地,我成功点亮了这个阴阳脚数码管。

这个阴阳脚数码管十分有趣,于是我记录下这段简短开发经历,既是对自己学习的总结,也是希望将这个过程分享朋友们。

2.常见的数码管电路

众所周知,常见的数码管分为两大类:共阴数码、共阳数码。如下图所示:在这里插入图片描述
数码管内部由二极管组成,当给二极管加正向电压时,二极管点亮,下图是4位数码管的内部电路图(这个数码管有个12引脚)。
在这里插入图片描述

3.阴阳脚数码管电路

阴阳脚数码管的电路图很奇怪,4位数码管电路图如下:在这里插入图片描述
根据电路图,不难发现 1脚和2脚之间接了一个二极管,2脚和1脚之间又接了一个二极管。正是这种神奇的操作,一个引脚即接了一个发光二极管的阳极(正极),同时还接了其他发光二极管的阴极(负极),因此这种数码管就被称为阴阳脚数码管。在这里插入图片描述

4.工作原理

阴阳脚数码管工作原理是什么?
阴阳脚数码管使用了二极管的单向导通性,前文说到数码管的 1脚和2脚之间接了一个二极管1,2脚和1脚之间又接了一个二极管2,工作原理如下图:在这里插入图片描述
为什么会有阴阳脚数码管?它的优势是什么?在这里插入图片描述
阴阳脚数码管的优势是:控制引脚少,功耗低。
控制引脚少

对于阴阳脚数码管,两个引脚可以控制2个LED ,3个引脚可以控制6个LED,7个引脚可以控制48个LED!

引脚和控制LED数量的关系是一种组合关系!这就意味着,控制同样数量的LED,阴阳脚数码的控制引脚更少。在这里插入图片描述
低功耗

由于阴阳脚数码管的同一个引脚接了多个LED,例如7个引脚的阴阳脚数码管,其中1个脚最多可以接12个LED!通常情况下阴阳脚数码管同一时刻只会有1个发光二极管被点亮,而普通二极管最多会有8个发光二极管被点亮,因此阴阳脚数码管功耗低(亮度低)。在这里插入图片描述

5.程序设计

代码设计思路是:

1、设置一组大小为36的IO控制数组,这个数组中存放这控制36组LED的IO引脚。

2、设置一个大小为36的显示缓存,每个数据对应一个LED的状态。

3、设计一个循环显示36个LED状态的函数。

4、设计一个0~9这10个数值转换为7段数码管的映射函数。

5、将4位数转换映射到36个显示缓存。
在这里插入图片描述
注意事项:需要亮的LED通过两个引脚的高低电平点亮,其它的IO口一定要设为悬浮输入模式。

代码如下

/*
*********************************************************************************************************
Includes 
*********************************************************************************************************
*/
#include "FreeRTOS.h"
#include "impedance_bsp.h"
#include "stm32f10x.h"
#include "task.h"
/*
********************************************************************************************************
Define
*********************************************************************************************************
*/
//数码管中的LED总数
#define LED_NUM (36)
//数码管的IO总数
#define IO_NUM (7)
//数码管中的一位显示8中的段码数量
#define SEG_NUM (7)
/*
*********************************************************************************************************
Variables
*********************************************************************************************************
*/
//定义单片机IO引脚,归一化操作
uint16_t led_pin_buff[IO_NUM] =
{GPIO_Pin_4,GPIO_Pin_5,GPIO_Pin_7,GPIO_Pin_0,GPIO_Pin_1,GPIO_Pin_2,GPIO_Pin_12    };
//定义单片机IO口,归一化操作
GPIO_TypeDef *led_port_buff[IO_NUM]=
{GPIOA,GPIOA,GPIOA,GPIOB,GPIOB,GPIOB,GPIOB    
};
//通常情况下控制外设IO不会是同花顺(同一个IO口的依次相连的引脚,
//因此我们定义一个数组,将数码管的物理引脚按照顺序填入数组。//大小为36的LED正极控制IO数组,1个数值对应1个LED , 1代表脚1 ,7代表脚7
uint8_t positive_io_buff[LED_NUM]=
{
1,1,4,5,1,2,3,
2,2,5,2,2,3,4,
5,3,4,6,6,4,5,
7,6,5,6,4,6,5,
3,7,6,1,3,1,3,
7
};
//大小为36的LED负极控制IO数组,1个数值对应1个LED, 1代表脚1 ,7代表脚7
uint8_t negative_io_buff[LED_NUM]=
{
2,3,1,1,4,1,1,
3,4,2,6,5,2,2,
4,5,5,1,3,3,3,
6,7,6,4,6,5,7,
6,3,2,5,4,6,7,
2
};//大小为36显示缓存,1个缓存对应1个LED
uint8_t display_cache[LED_NUM]=
{
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0    
};//数码管 0~ 9 的段码映射值  10 为空显示
uint8_t led_table[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
// 0x3f = 0x0011 1111
//数组中的每个数值,对应4位数码管中的一个数码管显示内容,
uint8_t display_data[4] ={0,0,0,0};/*
*********************************************************************************************************
Function 
*********************************************************************************************************
*/
/*
*********************************************************************************************************
Function 
*********************************************************************************************************
*/
/***********************************************************************************************************
* @描述    :  初始化led_gpio_init的IO口
***********************************************************************************************************/
void led_bsp_init(void)
{    GPIO_InitTypeDef GPIO_InitStructure;    /* 使能SPI引脚相关的时钟 */RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE );/* 普通IO即可 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);/* 普通IO即可 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);        
}
/***********************************************************************************************************
* @描述    :  IO全部设置为悬浮模式
***********************************************************************************************************/
void led_gpio_clear(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/***********************************************************************************************************
* @描述    :  设置IO口
***********************************************************************************************************/
void led_gpio_set( GPIO_TypeDef * port ,uint16_t pin)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(port, &GPIO_InitStructure);    
}
/***********************************************************************************************************
* @描述    :  设置一个LED状态
***********************************************************************************************************/
void set_one_led_state(uint8_t num , uint8_t state)
{//IO全部设置为悬浮模式led_gpio_clear();//将本次对应LED的IO口设置为输出led_gpio_set(led_port_buff[ positive_io_buff[num] - 1 ] , led_pin_buff[ positive_io_buff[num] - 1] );led_gpio_set(led_port_buff[ negative_io_buff[num] - 1 ] , led_pin_buff[ negative_io_buff[num] - 1] );// 显示缓存为1 则点亮LEDif( state == 1){GPIO_SetBits( led_port_buff[ positive_io_buff[num] - 1 ]    , led_pin_buff[ positive_io_buff[num] - 1]  );}else{GPIO_ResetBits( led_port_buff[ positive_io_buff[num] - 1 ] , led_pin_buff[ positive_io_buff[num] - 1]  );}//无论LED亮或者灭 负极IO都为低0GPIO_ResetBits( led_port_buff[ negative_io_buff[num] - 1 ] , led_pin_buff [ negative_io_buff[num] - 1] );
}/***********************************************************************************************************
硬件层
***********************************************************************************************************//***********************************************************************************************************
* @描述    :  根据缓存数据刷新LED亮灭状态
***********************************************************************************************************/
void refresh_led(void)
{uint8_t i;//设置LED_NUM个LED状态for(i = 0 ; i < LED_NUM ; i++){        set_one_led_state(i,display_cache[i]);vTaskDelay(1);        }
}
/***********************************************************************************************************
* @描述    :  段码值映射
***********************************************************************************************************/
void led_8bit_mapping(uint8_t *buff ,uint8_t value)
{uint8_t i;for(i = 0 ; i < SEG_NUM ; i++)buff[i] = 0;for(i = 0 ; i < SEG_NUM ; i++){if((led_table[value] & (0x01<<i)) != 0)buff[i]     = 1;    }    
}
/***********************************************************************************************************
* @描述    :  4位数据转换成段码
***********************************************************************************************************/
void data_mapping_cache(uint8_t *buff)
{uint8_t i;for(i = 0 ; i < 4 ; i++){    led_8bit_mapping(&display_cache[i*SEG_NUM] , buff[i]);    }
}
/***********************************************************************************************************
* @描述    : LED显示数据
***********************************************************************************************************/
void led_show_data(uint8_t *buff)
{//数据映射到LED显示缓存data_mapping_cache(buff);//LED更新显示内容refresh_led();
}
/***********************************************************************************************************
数据显示
***********************************************************************************************************//***********************************************************************************************************
* @描述    :  led测试
***********************************************************************************************************/
void led_test(void)
{static  uint32_t clk_num = 0;uint8_t i;//用于测试 数据变化if((clk_num++%70)==0){for(i = 0 ; i < 4 ; i++){        display_data[i]++;if(display_data[i] > 10)display_data[i] = 0;        }}//显示数据led_show_data(display_data);//延时vTaskDelay(1);
}
/***********************************************END*********************************************************/

6.总结

1、介绍了阴阳脚数码管。
2、学习了阴阳脚数码管工作原理。
3、学习了阴阳脚数码管驱动代码。

7.打油诗

在这里插入图片描述
希望获取源码和数据表的朋友可以在评论区留言!!!

希望获取源码和数据表的朋友可以在评论区留言!!!

希望获取源码和数据表的朋友可以在评论区留言!!!

创作不易希望朋友们点赞,转发,评论,关注!
大家的点赞,转发,评论,关注将是我持续更新的动力!
在这里插入图片描述

相关文章:

阴阳脚数码管

1.小故事 最近&#xff0c;我接到了一个既“清肺”又“烧脑”的新任务&#xff0c;设计一个低功耗蓝牙肺活量计。在这个项目中我们借鉴了一款蓝牙跳绳的硬件设计方案&#xff0c;特别是它的显示方案——数码管。 在电子工程领域&#xff0c;初学者往往从操作LED开始&#xff…...

【Vue3-Typescript】<script setup lang=“ts“> 使用 ref标签 怎么获取 refs子组件呢

注意&#xff1a;请确保子组件已经正确挂载&#xff0c;并且通过 defineExpose 暴露了您想要在父组件中访问的属性或方法 parent.vue <template><child ref"childRef"></child><button click"fun">点击父组件</button> &l…...

npm 超详细使用教程

文章目录 一、简介二、npm安装三、npm 的使用3.1 npm初始化项目3.2 安装包3.3 安装不同版本包3.4 避免系统权限3.5 更新包3.6 卸载包3.7 执行脚本3.8 pre- 和 post- 脚本3.9 npm link3.10 发布和卸载发布的包3.11 使用npm版本控制3.22 npm资源 四、总结 一、简介 npm&#xff…...

TypeScript函数

函数 函数:复用代码块 函数可以不写返回值 调用函数-----函数名() function a(){console.log(无参函数); } a();需要再函数后&#xff0c;写上返回值类型 没有返回值 使用void function e():string{return 可乐 } console.log(我得到了e()); function d():void{console.l…...

中海油某海上平台轨道巡检机器人解决方案

配电房作为能源传输和分配的核心枢纽&#xff0c;其安全运行直接影响到企业的生产稳定性和安全性。对于中海油这样的大型能源企业&#xff0c;配电房的运行状况至关重要。然而&#xff0c;传统的人工巡检方式存在效率低、作业风险高、巡检误差大等问题。为提升巡检效率、降低安…...

【NXP-MCXA153】SPI驱动移植

介绍 SPI总线由摩托罗拉公司开发&#xff0c;是一种全双工同步串行总线&#xff0c;由四个IO口组成&#xff1a;CS、SCLK、MISO、MOSI&#xff1b;通常用于CPU和外设之间进行通信&#xff0c;常见的SPI总线设备有&#xff1a;TFT LCD、QSPI FLASH、时钟模块、IMU等&#xff1b…...

Python if 编程题|Python一对一辅导教学

你好&#xff0c;我是悦创。 以下为 if 编程练习题&#xff1a; 1. 奇数乘积问题 题目描述: 编写一个程序&#xff0c;判断给定的两个整数是否都是奇数&#xff0c;如果是&#xff0c;返回它们的乘积&#xff1b;如果不是&#xff0c;返回它们的和。输入: num1, num2输出: n…...

机器学习——第十一章 特征选择与稀疏学习

11.1 子集搜索与评价 对一个学习任务来说&#xff0c;给定属性集&#xff0c;其中有些属性可能很关键、很有用&#xff0c;另一些属性则可能没什么用.我们将属性称为"特征" (feature) &#xff0c;对当前学习任务有用的属性称为"相关特征" (relevant featu…...

花式表演无人机技术详解

花式表演无人机作为现代科技与艺术融合的典范&#xff0c;以其独特的飞行姿态、绚烂的灯光效果及精准的控制能力&#xff0c;在各类庆典、体育赛事、音乐会等合中展现出非凡的魅力。本文将从以下几个方面对花式表演无人机技术进行详细解析。 1. 三维建模与编程 在花式表演无人…...

服务器那点事--防火墙

Linux服务器那点事--防火墙 Ⅰ、开启关闭Ⅱ、放开端口 Ⅰ、开启关闭 禁止防火墙开机自启systemctl disable firewalld 关闭防火墙systemctl stop firewalld 查看防火墙状态systemctl status firewalldⅡ、放开端口 例如&#xff1a;放开3306端口 设置放开3306端口 [rootbpm2…...

C:每日一题:单身狗

​​​​ 一、题目&#xff1a; 在一个整型数组中&#xff0c;只有一个数字出现一次&#xff0c;其他数组都是成对出现的&#xff0c;请找出那个只出现一次的数字。 整型数组 int arr[ ] {1,1,2,2,3,4,4} 二、思路分析&#xff1a; 1.&#xff0c;明确目标&#xff0c;选择…...

SQL之使用存储过程循环插入数据

1、已经创建了任务日志表 CREATE TABLE t_task_log (id bigint NOT NULL AUTO_INCREMENT,task_id bigint NOT NULL COMMENT 任务ID,read_time bigint NOT NULL COMMENT 单位秒&#xff0c;读取耗时,write_time bigint NOT NULL COMMENT 单位秒&#xff0c;写入耗时,read_size …...

智慧楼宇公厕系统小程序,提高卫生间管理使用效率

在当今的智慧楼宇中&#xff0c;公厕系统的管理和使用效率成为了衡量楼宇品质的重要指标之一。智慧楼宇公厕系统小程序的出现&#xff0c;为解决这一问题带来了全新的思路和方法。 一、检查公厕环境数据 智慧公厕系统不仅关注如厕的基本需求&#xff0c;还注重提升如厕环境的质…...

深度剖析:云数据库与传统数据库的显著差异

【若您对以下内容感兴趣&#xff0c;欢迎关注或联系我们】 在当今数字化时代&#xff0c;数据库技术不断演进&#xff0c;云数据库和传统数据库作为两种主要的数据库类型&#xff0c;在多个方面存在明显区别。下面我们将深入探讨这些差异。 一、部署方式 云数据库&#xff1…...

# 利刃出鞘_Tomcat 核心原理解析(六)

利刃出鞘_Tomcat 核心原理解析&#xff08;六&#xff09; 一、Tomcat专题 - 内容 1、Web 应用配置 2、Tomcat 管理配置 3、JVM 配置 4、Tomcat 集群 5、Tomcat 安全 6、Tomcat 性能调优 7、Tomcat 附加功能。 二、Tomcat专题 - Web应用配置介绍 1、Web.xml 配置文件…...

双亲委派模型

优质博文&#xff1a;IT-BLOG-CN 虚拟机设计团队把类加载阶段中的 “通过一个类的全限定名来获取描述此类的二进制字节流” 这个动作放到 Java虚拟机外部去实现&#xff0c;以便应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。 从Java虚拟机…...

Linux下ETCD安装、配置、命令

目录 1. ETCD简介 2. ETCD的安装 2.1 准备环境 2.2 下载ETCD 2.3 解压和移动文件 2.4 验证安装 3. ETCD的配置 3.1 基本配置 3.2 配置文件 3.3 集群配置 4. ETCD的常用命令 4.1 插入键值对 4.2 读取键值对 4.3 删除键值对 4.4 监视键的变化 4.5 列出所有键值 …...

【QT】静态库与动态库

文章目录 开始之前一、静态库(static Library)定义使用场景特点程序示例 二、动态库(dynamic Library)定义使用场景特点。程序示例第二种调用 开始之前 测试环境&#xff1a;Qt 5.15.2 Based on Qt 6.4.3(MSVC 2019, x86_64) 操作系统&#xff1a;Windows11 专业版 编程语言&am…...

R的行和列命名和类型的转换

下面内容摘录自&#xff1a; 4章8节&#xff1a;用R做数据重塑&#xff0c;行列命名和数据类型转换-CSDN博客 欢迎订阅我们专栏 一、行和列命名 在数据科学和统计分析中&#xff0c;命名是组织和管理数据的一个重要部分。尤其是在处理复杂的多维数据集时&#xff0c;为行和列命…...

某通用系统0day审计过程

前言 代码审计篇章都是自己跟几个师傅们一起审计的1day或者0day(当然都是小公司较为简单)&#xff0c;禁止未经允许进行转载&#xff0c;发布到博客的用意主要是想跟师傅们能够交流下审计的思路&#xff0c;毕竟审计的思路也是有说法的&#xff0c;或者是相互源码共享也OK&…...

windows C++-高级并发和异步(一)

并发和异步的由来已经很久了&#xff0c;对于从xp开始编程的人来说&#xff0c;这个概念并不陌生&#xff0c;但问题在于&#xff0c;在早期&#xff0c;这两个技术被认为是操作系统提供的服务&#xff0c;而非编程语言的概念。 事情发生变化的原因&#xff0c;和C标准不断变迁…...

Java FX 学习

声明&#xff1a;参考视频 一. Stage与Scene 舞台与场景&#xff1a;JavaFX应用程序将Ul容器定义为舞台&#xff08;Stage&#xff09;与场景&#xff08;Scene&#xff09;Stage类是顶级容器&#xff0c;它对应于窗体&#xff0c;其内容由Scene决定。Scene类是所有可视化内容…...

【走迷宫】

题目 DFS代码 #include<bits/stdc.h> using namespace std; const int N 110; int matrix[N][N]; int n, m; int dx[4] {-1, 0, 1, 0}, dy[4] {0, 1, 0, -1}; int dis[N][N]; void dfs(int x, int y, int cnt) {if(cnt > dis[n-1][m-1]) return;if(x n-1 &&a…...

linux(debian)迁移var数据到已分配逻辑卷的物理盘

文章目录 0 背景1 查看当前情况1.1 查看磁盘空间1.2 列出所有可用块设备的信息&#xff0c;而且还能显示他们之间的依赖关系1.3 查看可用磁盘1.4 查看卷组 2 卷组中创建逻辑卷3 创建文件系统4 创建临时文件夹并挂载&#xff0c;然后备份源文件5 修改开机挂载配置5.1 查看原配置…...

【产品那些事】什么是应用程序安全态势管理(ASPM)?

文章目录 前言当前应用安全(AppSec)推进遇到的问题关于ASPM的定义 为什么需要ASPM&#xff1a;B端客户核心需求ASPM产品关键策略理想状态下的ASPMASPM与CSPM的区别国内外产品参考 前言 随着现代软件开发实践的快速演变&#xff0c;特别是在敏捷开发和 DevOps 的推动下&#xf…...

cocosUI多分辨率适配

需求&#xff1a;由于各个设备的分辨率和尺寸并不一样&#xff0c;所以需要一套适配系统去很好的针对不同的设备分辨率或尺寸进行适配&#xff0c;以给玩家一个很好的游戏体验。 目前的主流适配方案 目前&#xff0c;针对不同设备的适配&#xff0c;主流的方案通常包括以下几种…...

无法加载到主类

说明&#xff1a;记录一次项目启动错误&#xff0c;如下&#xff1a; 错误信息&#xff1a;错误: 找不到或无法加载主类 com.hezy.App 原因: java.lang.ClassNotFoundException: com.hezy.App 解决&#xff1a;首先&#xff0c;在项目中勾选这个&#xff0c;显示target文件夹 …...

深入理解Kafka核心设计与实践原理_03

深入理解Kafka核心设计与实践原理_03 03_消费者3.1消费者与消费者组3.2客户端开发3.2.1 必要的参数配置3.2.2 订阅主题与分区 草稿 03_消费者 与生产者对应的是消费者&#xff0c;应用程序可以通过KafkaConsumer来订阅主题&#xff0c;并从订阅的主题中拉取消息。不过在使用Ka…...

MySQL- 覆盖索引

覆盖索引&#xff08;Covering Index&#xff09;是 MySQL 中的一种优化技术&#xff0c;它能够显著提高查询性能。在使用覆盖索引的情况下&#xff0c;查询操作只需要访问索引即可获取所需的数据&#xff0c;而不必再访问表的实际数据行&#xff08;即不需要回表&#xff09;。…...

JSON与EXL文件互转

功能&#xff1a;实现json到excel文件的相互转换(支持json多选版) 目的&#xff1a;编码与语言对应&#xff0c;方便大家使用 页面设计&#xff1a; 介绍&#xff1a; 1.选择文件栏目选择想要转换的文件 2.生成路径是转换后文件所在目录 3.小方框勾选与不勾选分别代表exl到…...