学习笔记|小数点控制原理|数码管动态显示|段码跟位码|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.mzph.cn/news/77116.shtml

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

相关文章

UG\NX CAM二次开发 设置2D工序部件边界 UF_CAMBND_append_bnd_from_curve

文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 设置2D工序部件边界 UF_CAMBND_append_bnd_from_curve 效果: 代码: static int init_proc(UF_UI_selection_p_t select, void* user_data) { int errorCode = 0; int num_triples = 1; …

【echarts】legend长度过长,内容过多导致换行怎么办?

通过设置翻页即可解决该问题 关键代码: type: scroll,// pageFormatter: , // 隐藏翻页的数字pageButtonItemGap: 2, // 翻页按钮的两个之间的间距pageIconColor: #6495ed, // 翻页下一页的三角按钮颜色pageIconInactiveColor: #aaa, // 翻页(即翻页到…

vue三个点…运算符时报错 Syntax Error: Unexpected token

出现以下问题报错: 解决: 在项目根目录新建一个名为.babelrc的文件 {"presets": ["stage-2"] }

docker 部署 node.js(express) 服务

1、在 express 项目根目录下新增 Dockerfile 文件,内容如下: 创建服务容器的方法,可以根据自己的情况选择: 1、以下示例为宿主机没有安装 node 环境的写法; 2、先在本地构建包含 node 和 express 的基础镜像&#xff0…

视频监控/安防监控/AI视频分析/边缘计算/TSINGSEE青犀AI算法智慧仓储解决方案

随着全球经济与科学技术的双重推动,我国的仓储管理已经进入了高速发展时期,物流仓储也由简单的储藏仓库向智能化仓储转变。TSINGSEE青犀AI智慧仓储解决方案是利用先进的信息技术和物联网技术来提高仓储管理效率、降低成本的一种仓储管理模式。 方案功能 …

【Linux学习笔记】基础命令2

1. rmdir指令 && rm指令1.1. 基础概念1.2. 命令用法1.2.1. rmdir命令1.2.2. rm命令1.2.3. rm命令的注意事项 2. man命令3. cp指令3.1. cp指令基础概念3.2. cp命令的用法 4. mv命令5. cat命令6. more命令 && less命令6.1. more命令6.2. less命令 7. head命令和t…

基于springboot+vue的大学社团管理系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

【算法】反悔贪心

文章目录 反悔贪心力扣题目列表630. 课程表 III871. 最低加油次数LCP 30. 魔塔游戏2813. 子序列最大优雅度 洛谷题目列表P2949 [USACO09OPEN] Work Scheduling GP1209 [USACO1.3] 修理牛棚 Barn RepairP2123 皇后游戏(🚹省选/NOI− TODO) 相关…

哪里可以了解轻量的工作流引擎?

如果想要实现高效率的办公,可以使用轻量的工作流引擎低代码技术平台。随着工作量日益繁重起来,传统的办公制作方式已经无法满足现实需要的,采用轻量级的表格制作工具,就能在无形中缓解办公压力,创造更高效、灵活、优质…

【Java】线程池八股文一

日常工作中有用到线程池吗?什么是线程池?为什么要使用线程池? 作为 JUC 包下的门面担当,线程池是名副其实的 JUC 一哥,不了解线程池,那说明你对 JUC 包其他工具也了解的不咋样吧,对 JUC 没深入…

成绩定级脚本(Python)

成绩评定脚本 写一个成绩评定的python脚本,实现用户输入成绩,由脚本来为成绩评级: #成绩评定脚本.pyscoreinput("please input your score:") if int(score)> 90:print("A") elif int(score)> 80:print("B&…

error:03000086:digital envelope routines::initialization error

项目背景 前端vue项目启动突然报错error:03000086:digital envelope routines::initialization error 我用的开发工具是vscode,node版本是v18.17.0 前端项目版本如下↓ 具体报错如下↓ 报错原因 node版本过高 解决方法 1输入命令 $env:NODE_OPTIONS"--op…

【Redis】Lua脚本在Redis中的基本使用及其原子性保证原理

文章目录 背景一、Eval二、EvalSHA三、Redis 对 Lua 脚本的管理3.1 script flush3.2 script exists3.3 script load3.4 script kill 四、Lua在Redis中原子性执行的原理 背景 Lua 本身是一种轻量小巧的脚本语言,在Redis2.6版本开始引入了对Lua脚本的支持。通过在服务…

社群团购对接,【概率思维】可以增加你做项目的成功率!

社群团购对接,【概率思维】可以增加你做项目的成功率! 今天来聊一个关于概率的问题,我们不管去做社群团购项目、做流量,还是做销售,我们都要有概率思维,有了这个思维以后,就可以增加你的成功率…

QT 完成登陆界面跳转到聊天室+完成学生管理系统的查找和删除功能

一、完成登陆界面跳转到聊天室 1> 项目结构 2> 源码 ① .pro ②main #include "mywnd.h" #include"chatCli.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MyWnd w;w.show();Form f;QObject::co…

Spring-MVC的文件上传下载,及插件的使用(让项目开发更节省时间)

目录 一、概述 ( 1 ) 介绍 ( 2 ) 讲述 二、上传 三、下载 四、jrebel的使用 五、多文件上传 给我们带来什么收获 一、概述 ( 1 ) 介绍 Spring MVC的文件上传下载是指在Spring MVC框架中实现文件的上传和下载功能。文件上传是指将本地计算机上的文件上传到服务器端…

vue+antd——实现table表格的打印——分页换行,每页都有表头——基础积累

这里写目录标题 场景效果图功能实现1&#xff1a;html代码功能实现2&#xff1a;css样式功能实现3&#xff1a;js代码补充内容page-break-inside 属性page-break-after属性page-break-before 属性 场景 最近在写后台管理系统时&#xff0c;遇到一个需求&#xff0c;就是要实现…

电池电动汽车的健康状态 SOH 和充电状态 SOC 估计

微❤关注“电气仔推送”获得资料 主要内容&#xff1a; 健康状态 SOH采用平均加权最小二乘法&#xff08;AWTLS&#xff09;进行估计&#xff0c;并对比了加权最小二乘 &#xff08;WLS&#xff09;、总最小二乘法&#xff08;TLS&#xff09;以及加权总最小二乘法&#xff0…

Python基于Flask的高校舆情分析,舆情监控可视化系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 运行效果图 基于Python的微博大数据舆情分析&#xff0c;舆论情感分析可视化系统 系统介绍 微博舆情分析系…

小白备战大厂算法笔试(五)——树

文章目录 二叉树常用术语初始化插入与删除常见类型满二叉树完全二叉树完满二叉树平衡二叉树 二叉树退化二叉树遍历层序遍历前序、中序、后序遍历 数组表示二叉树表示完美二叉树表示任意二叉树 二叉搜索树查找节点插入节点删除节点遍历有序搜索效率常见应用 AVL树常见术语节点高…