学习笔记|小数点控制原理|数码管动态显示|段码跟位码|STC32G单片机视频开发教程(冲哥)|第十集:数码管动态显示

文章目录

  • 1.数码管动态刷新的原理
  • 2.动态刷新原理
  • 3.8位数码管同时点亮
    • 新建一个数组选择每个位需要显示的内容
    • 实战小练:简易10秒免单计数器
    • 将刷新动作写成函数
  • 课后练习:

1.数码管动态刷新的原理

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
上述图片引用自:51单片机初学2-数码管动态扫描
用一排端口来控制段码,需要显示哪几个就点亮哪几个段,和看电影一样,一个一个的打开,关闭,一个个的画面,组成动画。
在这里插入图片描述

2.动态刷新原理

具体的控制的流程如图所示,N表示有几个数码管!
在这里插入图片描述

其中需要注意每个延时不能太短,我们这边程序就以1ms为准,且需要保证总共一个循环结束的时间不能大于20ms,因为人眼的视觉不容易分辨出50HZ以上的动态刷新。
给他延时一定时间以后再切到第二位,再打开位码,顺次循环,8个管同时点亮。

3.8位数码管同时点亮

1.在上一课的基础上,新增一个位码选择的数组
以上一节的工程5.seg为模板,建立6.seg-active:
屏蔽原来的静态显示代码,增加4位数码管的显示代码:

		//第1位的数码管显示0P7 = COM_Tab[0];P6 = SEG_Tab[0];	//这个数码管输出段码delay_ms(1);//第2位的数码管显示1P7 = COM_Tab[1];P6 = SEG_Tab[1];	//这个数码管输出段码delay_ms(1);//第3位的数码管显示2P7 = COM_Tab[2];P6 = SEG_Tab[2];	//这个数码管输出段码delay_ms(1);//第4位的数码管显示3P7 = COM_Tab[3];P6 = SEG_Tab[3];	//这个数码管输出段码delay_ms(1);

编译,下载,主频24MHZ,每次下载前发送自定义命令,数码管显示0123。
改为延迟为200ms,在文件头部宏定义最大时间延迟:

#define SEG_DELAY 200	//延时ms
//while主循环中使用宏定义,可实现批量修改延迟时间
delay_ms(SEG_DELAY);

可以看到明显的闪烁。
如果只需要数码管从1 开始显示到8,观察代码中的段码和位码参数变量,值相同,可以使用num变量。num最大值为7,只有8位数码管。
需要加个判断来限定:

		P7 = COM_Tab[num];P6 = SEG_Tab[num+1];	//这个数码管输出段码,从1 开始显示到8delay_ms(SEG_DELAY);num++;if(num>7){num = 0;}

新建一个数组选择每个位需要显示的内容

如果待显示数据无规律,则需要新建一个数组选择每个位需要显示的内容!
新建数组:u8 Show_Tab[8] = {1,5,0,3,5,7,3,3};
修改显示函数的相关内容:

		P7 = COM_Tab[num];		//位码选择P6 = SEG_Tab[Show_Tab[num]];   //需要显示的数组内容,如果 num =0 ->Show_Tab[num] = 1->P6 =0xf9delay_ms(SEG_DELAY);num++;if(num>7){num = 0;}

实战小练:简易10秒免单计数器

在这里插入图片描述

1.在前四位数码管上显示目标时间,即“ 10. 00 ”表示定时时间10秒钟
2.后四位显示当前的计时00.00,最小单位为10ms,
3.按下开始按钮后,每10ms最末尾的数字+1;知道按下结束按钮后停止计数。
首先,小数点怎么去点亮?默认数组中小数点不点亮,添加小数点位。
复制原有的段码,然后将复制部分减0x80:

u8 SEG_Tab[20] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //0-9段码选择,添加0-9带小数点的段码//定义基础显示代码Show_Tab[0] = 1;	 //选择1Show_Tab[1] = 10;    //选择“0.”Show_Tab[2] = 0;    //选择0Show_Tab[3] = 0;    //选择0

看效果,前4位是10.00,后面还是5733(之前的代码未修改),可以修改原显示代码,全都显示0.

u8 Show_Tab[8] = {0,0,0,0,0,0,0,0};

新建计时变量,大小选择为u32,u32 TimCount = 0; //计数单位为ms 每加1,表示过去了1ms
4-7位的显示代码为:

		if(RUN_state == 1){TimCount++; //每执行完1次,加1Show_Tab[4] = TimCount/10000%10;    //取万位,Show_Tab[5] = TimCount/1000%10; //取千位,Show_Tab[6] = TimCount/100%10;  //取百位,Show_Tab[7] = TimCount/10%10; //取10位,除以10即舍去最低位,103%10 = 3,1030/10%10=3}

编译烧录,数据在跳动,但显示还是不正常:
1、且按暂停后没有重新从0启动,刚开始的时候没有把数据清0,修改代码:

if( RUN_State == 0 )TimCount = 0;

2、百位数上的一个小数点没有显示,改为:Show_Tab[5] = TimCount/1000%10+10; //取千位并显示小数点
重新编译,下载。显示10.000000,没有显示00.00,修改:在Show_Tab[8]的对应位置原数据+10:

u8 Show_Tab[8] = {0,0,0,0,0,10,0,0};  //数码管均重置为0,10代表第10位(0x40),带小数点。显示0.00。//即要想显示数字+小数点,只要在数字前面加1,变成10几,就可以了

在这里插入图片描述

编译烧录,显示:10.0000.00,效果正常,按key1从0开始计数,数字跳动,再按一下,停止,重新按键,又从0开始计数。
而按下key1的情况下,只显示1位,需要调整代码:
看一下key1按下执行到哪里?“while(KEY1 == 0);”,等待按键松开,所以显示在这里不动了。
所以解决问题的关键在于:等待按键松开的过程中,还要保持这个数码管不断的显示。
则需要把数码管的显示代码挪过来,在等待过程中再显示一遍,循环的时候数据还要自加:

				while(KEY1 == 0)   //增加重复显示代码,防止等待KEY1按下的过程中只显示1位0{P7 = COM_Tab[num];		//位码选择P6 = SEG_Tab[Show_Tab[num]];   //需要显示的数组内容,如果 num =0 ->Show_Tab[num] = 1->P6 =0xf9delay_ms(SEG_DELAY);num++;if(num>7){num = 0;}}

编译后运行,按下key1时,参数也一直在动。

将刷新动作写成函数

重复的刷新工作可以用一个函数去代替
先声明:void SEG_Fre(void); //专门用于数码管刷新
再实现:

void SEG_Fre(void) //专门用于数码管刷新
{//---------------------------数码管刷新---------------------------------u8 num = 0;P7 = COM_Tab[num];		//位码选择P6 = SEG_Tab[Show_Tab[num]];   //需要显示的数组内容,如果 num =0 ->Show_Tab[num] = 1->P6 =0xf9delay_ms(SEG_DELAY);num++;if(num>7){num = 0;}
}

代码中使用,完整代码为:

#include "COMM/stc.h"		//调用头文件
#include "COMM/usb.h"#define KEY1 P32		//定义一个按键 引脚选择P32
#define KEY2 P33		//定义一个按键 引脚选择P33#define BEEP P54		//定义一个按键 引脚选择P54#define SEG_Delay  1	//延时多少ms#define MAIN_Fosc 24000000UL	//定义主时钟char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";u8 SEG_Tab[20] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};	//0-9段码,0-9带小数点
u8 COM_Tab[8] = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };	//0-7的位码数组
u8 Show_Tab[8] = {3,0,0,0,0,10,0,0};u32 TimCount = 0;		//计数单位1ms
bit RUN_State = 0;		//开始运行/结束运行
u8 num = 0;void sys_init();	//函数声明
void delay_ms(u16 ms);	//unsigned intvoid SEG_Fre( void ); //专门用于数码管刷新void main()					//程序开始运行的入口
{sys_init();				//USB功能+IO口初始化usb_init();				//usb库初始化EA = 1;					//CPU开放中断,打开总中断。while(1)		//死循环{if( DeviceState != DEVSTATE_CONFIGURED ) 	//continue;if( bUsbOutReady ){usb_OUT_done();}//------------------------------------------------数码管刷新-------------------------------------------------Show_Tab[0]  = 1;		//选择 1Show_Tab[1]  = 10;		//选择 0.Show_Tab[2]  = 0;		//选择 0Show_Tab[3]  = 0;		//选择 0if( RUN_State==1 ){TimCount++;Show_Tab[4] = TimCount/10000%10;Show_Tab[5] = TimCount/1000%10+10;Show_Tab[6] = TimCount/100%10;Show_Tab[7] = TimCount/10%10;		//取10位}SEG_Fre();if( KEY1 ==0 ){delay_ms(10);if( KEY1 ==0 ){BEEP = 0;delay_ms(10);BEEP = 1;while( KEY1 ==0 ){SEG_Fre();}if( RUN_State==0 )TimCount = 0;RUN_State = !RUN_State;}}}
}
/*11111110 0XFE11111101 0XFD11111011 0XFB11110111 0XF711101111 0XEF11011111 0XDF10111111 0XBF01111111 0X7F
*/void sys_init()		//函数定义
{WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快EAXFR = 1; //扩展寄存器(XFR)访问使能CKCON = 0; //提高访问XRAM速度P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口P3M0 = 0x00;P3M1 = 0x00;P3M0 &= ~0x03;P3M1 |= 0x03;//设置USB使用的时钟源IRC48MCR = 0x80;    //使能内部48M高速IRCwhile (!(IRC48MCR & 0x01));  //等待时钟稳定USBCLK = 0x00;	//使用CDC功能需要使用这两行,HID功能禁用这两行。USBCON = 0x90;
}void delay_ms(u16 ms)	//unsigned int
{u16 i;do{i = MAIN_Fosc/6000;while(--i);}while(--ms);
}void SEG_Fre( void )
{//位码选择第一位,段码选择0u8 num = 0; //也可以放在main函数前,作为全局变量P7 = COM_Tab[num];			//位码的选择P6 = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码 赋给 P6   NUM =0 -> Show_Tab[num]] = 1 -> p6 = oxF9delay_ms(SEG_Delay);num++;if( num >7 )num = 0;
}

课后练习:

一、做一个简易时钟,功能如下
1.初始状态显示00 - 00 - 00,分别作为时,分,秒;
2.每隔一秒钟,秒+1,一分钟,分+1,以此类推;
3.时间到达00 - 00 - 30的时候,蜂鸣响3秒钟表示闹钟。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/126771.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 大表如何ddl

大家好,我是蓝胖子,mysql对大表(千万级数据)的ddl语句,在生产上执行时一定要千万小心,一不小心就有可能造成业务阻塞,数据库io和cpu飙高的情况。今天我们就来看看如何针对大表执行ddl语句。 通过这篇文章,…

推荐一款程序员截图神器!

快来看一下程序员必备的一款截图工具 今天就来和大家说一下作为程序员必备截图神器,几乎每一个程序员都会设置开机自启,因为这个截图功能太太太好用了!!!只要你在键盘上按下F1就可以轻松截取整个屏幕,然后…

OpenHarmony:如何使用HDF驱动控制LED灯

一、程序简介 该程序是基于OpenHarmony标准系统编写的基础外设类:RGB LED。 目前已在凌蒙派-RK3568开发板跑通。详细资料请参考官网:https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk3568-openharmony/tree/master/samples/b02_hdf_rgb_led。 …

【【STM32--28--IO引脚的复用功能】】

STM32–28–IO引脚的复用功能 STM32的IO复用功能 何为复用? 我们先了解一下何为通用 IO端口的输入或输出是由GPIO外设控制,我们称之为通用 复用: IO端口的输入或者是输出是由其他非GPIO外设控制就像经常说的USART 由 DR寄存器进行输出 STM32的IO复用功…

docker 笔记11: Docker容器监控之CAdvisor+InfluxDB+Granfana

1.原生命令 docker stats命令的结果 是什么 2.是什么 容器监控3剑客 CAdvisor监控收集InfluxDB存储数据Granfana展示图表 3.CAdvisor 4.InfluxDB 5.Granfana 6.总结 7.compose容器编排,一套带走 新建目录 7.1新建3件套组合的 docker-compose.yml version: 3.1vo…

通过 Jetbrains GateWay实现Remote Development

本次环境准备 环境准备:win10、一台安装有树莓派系统的树莓派(也可以是其他的服务器) 第一步:通过官网下载JetBrains Gateway 官网地址:https://www.jetbrains.com/remote-development/gateway/ 第二步:安装…

Shell 运算符及语法结构

目录 一、Shell运算符 1.1 表达式expr 1.2 运算操作 1.3 操作实例 二、Shell条件判断 2.1 基本语法 2.2 值、权限、类型、多条件判断 三、Shell流程控制 3.1 if 流程语法 3.2 case 流程语法 3.3 for 流程语法 3.4 内部运算符 3.5 while循环流程语法 四、Shell读…

ElasticSearch的安装部署-----图文介绍

文章目录 背景什么是ElasticSearch使用场景 ElasticSearch的在linux环境下的安装部署前期准备分配权限(正式实操)启动ElasticSearch创建用户组创建用户,并设置密码用户添加到elasticsearch用户组指定用户操作目录的一个操作权限切换用户 解压elasticsearch修改es的配…

计算机脚本的概念,如何编写、使用脚本 (Script)?

一、脚本的概念和使用场景 在计算机领域的脚本,指的是使用一种特定的描述性语言,依据一定的格式编写的可执行文件脚本语言又被称为扩建的语言或者动态语言, 是一种编程语言, 用来控制软件应用程序, 脚本通常是以文本 (ASCⅡ) 保存, 只是在被调用时进行解…

【Docker】Docker的使用案例以及未来发展、Docker Hub 服务、环境安全的详细讲解

Docker的工具实践及root概念和Docker容器安全性设置 1. 使用案例2. Docker解决的问题3. Docker未来发展4. Docker Hub 服务5. 技术局限6. Docker环境安全7. 容器部署安全 1. 使用案例 Docker是一个命令行工具,它提供了中央“docker”执行过程中所需的所有工具。这使…

奇舞周刊第 505 期:实践指南-前端性能提升 270%!

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 实践指南-前端性能提升 270% 当我们疲于开发一个接一个的需求时,很容易忘记去关注网站的性能,到了某一个节点,猛地发现,随着越来越多…

存储空间压缩6倍 ,多点DMALL零售SaaS场景降本实践

🧑‍💼 作者简介 冯光普:多点 DMALL 数据库团队负责人,负责数据库稳定性建设与 DB PaaS 平台建设,在多活数据库架构、数据同步方案等方面拥有丰富经验。 杨家鑫:多点高级 DBA,擅长故障分析与性能…

GPT引领前沿热点、AI绘图

GPT对于每个科研人员已经成为不可或缺的辅助工具,不同的研究领域和项目具有不同的需求。如在科研编程、绘图领域: 1、编程建议和示例代码: 无论你使用的编程语言是Python、R、MATLAB还是其他语言,都可以为你提供相关的代码示例。 2、数据可…

深度入门 Android 车机核心 CarService 的构成和链路

作者:TechMerger 本文将结合 Android 系统整体,对 CarService 的构成和链路对其做一个全面的分析和理解。 构成 1. CarServiceHelperService 系统服务 SystemServer 中专门为了 Automotive OS 设立的系统服务,用来管理车机的核心服务 CarS…

【Nginx24】Nginx学习:压缩模块Gzip

Nginx学习:压缩模块Gzip 又是一个非常常见的模块,Gzip 现在也是事实上的 Web 应用压缩标准了。随便打开一个网站,在请求的响应头中都会看到 Content-Encoding: gzip 这样的内容,这就表明当前这个请求的页面或资源使用了 Gzip 压缩…

Java基础——反射

1 概述 Java反射提供了一种动态获取类信息及动态修改运行规则的机制。 反射指运行时获取一个类中的信息,并控制其行为。运行时可以获取构造器对象Constructor,可以获取成员变量对象Field,可以获取方法对象Method 2 获取类对象的方式 获取C…

看完这篇 教你玩转渗透测试靶机Vulnhub——Momentum:2

Vulnhub靶机Momentum:2渗透测试详解 Vulnhub靶机介绍:Vulnhub靶机下载:Vulnhub靶机安装:Vulnhub靶机漏洞详解:①:信息收集:②:漏洞发现:③:文件上传漏洞利用:…

Mysql--事务

事务 开始之前,让我们先想一个场景,有的时候,为了完成某个工作,需要完成多种sql操作 比如转账 再比如下单 第一步 我的账户余额减少 第二步 商品的库存要减少 第三步 订单表中要新增一项 事务的本质,就是为了把多个操…

jmeter While控制器

一种常见的循环控制语句,用于重复执行一段代码块,直到指定的条件不再满足。 参数: 空LASTJMeter变量、函数、属性或任意其他可用表达式 (jmeter提供的方法)。判断变量值count_num小于等于20,推荐简单的几…

Django+Nginx+uWSGI+Supervisor实战

大家好,真的是许久没有更新文章了,甚是想念,最近这段时间事情很多,家里的事情、工作的事情,真没有太多时间去码文章,其实已经搁置了些许文章,没有整理,趁着这段时间风平浪静&#xf…