【蓝桥杯-单片机】基于定时器的倒计时程序设计

news2024/11/28 22:51:45

基于定时器的倒计时程序

题目如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现过程中遇到的一些问题

01 如何改变Seg_Buf数组的值数码管总是一致地显示0 1 2 3 4 5

首先这个问题不是在main.c中关于数码管显示部分的逻辑错误,就是发生在数码管的底层错误。
检查了逻辑部分,没有发现问题
转而查找底层上面的错误。
底层的Seg.c是这样写的:

#include <Seg.h>

unsigned char code Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f ,0x00};
unsigned char code Seg_Wela[] = {0xfe ,0xfd ,0xfb,0xf7,0xef,0xdf};

void Seg_Disp(unsigned char wela,dala)
{
	//消影
	P0 = 0x00;
	P2_6 = 1;
	P2_6 = 0;
	
	P0 = Seg_Wela[wela];
	P2_7 = 1;
	P2_7 = 0;
	
	P0 = Seg_Dula[wela];//问题出现在这里!
	P2_6 = 1;
	P2_6 = 0;
}

果然被我发现了,段选数组的索引写错了,写成了wela,这样无论如何,数码管的每一位都会按照传入的wela来显示(wela在main函数中即Seg_Pos,这个变量在0-5范围内循环)

	if(++Seg_Pos == 6) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);

02 按下设置按键KEY4设置好倒计时参数后,该参数应该在什么时机传输给Time_Count倒计时变量用于倒计时呢?

(1)设置完就对Time_Count赋值

//按键处理函数Key_Proc()
void Key_Proc()
{
	if(Key_Slow_Down)return;
	Key_Slow_Down = 1;//按键减速程序
	
	//这三行要背下来
	Key_Val = Key_Read();//读取按下的键码值
	Key_Down = Key_Val &(Key_Val ^ Key_Old);//捕获下降沿
	Key_Old = Key_Val;//辅助扫描
	
	switch(Key_Down)
	{
		//框架先搭好,内容先不写
		case 1:
			if(Seg_Mode == 0) System_Flag = 1;
		break;
		
		case 3:
			Seg_Mode ^= 1;
		break;
		
		case 4:
			if(Seg_Mode == 1)
			{
				if(++Set_Dat_Index == 3) Set_Dat_Index = 0;
				Time_Count = Set_Dat[Set_Dat_Index];//设置完就对Time_Count赋值!!!!!!
			}
		break;
			
		case 2:
			if(Seg_Mode == 0) Time_Count = Set_Dat[Set_Dat_Index];
		break;
	}
}

如果这样的话,会导致切换回显示模式后已经倒计时了一段时间了,不是从设置的值开始倒计时的。想要切换回显示模式从设置的值开始倒计时,需要在切换回显示模式后,再对Time_Count赋值。

(2)在切换成显示模式后对Time_Count赋值

//按键处理函数Key_Proc()
void Key_Proc()
{
	if(Key_Slow_Down)return;
	Key_Slow_Down = 1;//按键减速程序
	
	//这三行要背下来
	Key_Val = Key_Read();//读取按下的键码值
	Key_Down = Key_Val &(Key_Val ^ Key_Old);//捕获下降沿
	Key_Old = Key_Val;//辅助扫描
	
	switch(Key_Down)
	{
		//框架先搭好,内容先不写
		case 1:
			if(Seg_Mode == 0) System_Flag = 1;
		break;
		
		case 3:
			Seg_Mode ^= 1;
			if(Seg_Mode == 0)
				Time_Count = Set_Dat[Set_Dat_Index]  ;//切换到显示界面再对Time_Count赋值!!!!!!
		break;
		
		case 4:
			if(Seg_Mode == 1)
			{
				if(++Set_Dat_Index == 3) Set_Dat_Index = 0;
				//Time_Count = Set_Dat[Set_Dat_Index];
			}
		break;
			
		case 2:
			if(Seg_Mode == 0) Time_Count = Set_Dat[Set_Dat_Index];
		break;
	}
}

03 倒计时到0之后为什么数码管又变成55再倒计时呢?

这是因为Time_Count–,没有对其作任何限制的情况下,Time_Count减为0之后会再从255开始减递减(Time_Count是一个unsigned char类型的变量,该变量8bit,变量可以表示的范围为0-255)。而我们只让数码管显示到十位数,因此我们看到的就是数码管从55开始倒计时。

对中断服务函数代码作如下修改:

void Timer0Server() interrupt 1
{
	//定时器的初值一定要记得从上面复制过来
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
	if(++Seg_Pos == 6) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
	
	//模板以外的东西
	if(System_Flag == 1)
		//倒计时开始
	{
		if(++Timer_1000ms == 1000)
		{
			Timer_1000ms = 0;
			Time_Count--;//相当于1s中减少一次(倒计时一次)
			if(Time_Count==255) Time_Count=0;//修改代码!!!!!!!!!!!!!!!!!!
		}
	}
}

修改代码之后数码管会停在00的位置。

在这里插入图片描述

至此,所有代码如下所示(不包含设置参数以1s为周期闪烁):

//头文件声明
#include <REGX52.H>
#include <Key.h>
#include <Seg.h>//动态数码管会用到数码管的底层?

//变量声明
unsigned char Key_Slow_Down;//按键减速专用变量 10ms
unsigned char Key_Val,Key_Down,Key_Old;//按键扫描专用变量

unsigned int Seg_Slow_Down;//数码管减速专用变量 500mschar:0-255.char不够用

//动态数码管
unsigned char Seg_Pos;//数码管扫描变量
unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据存放数组

unsigned char Seg_Mode;//数码管显示页面 0-显示 1-设置,默认为0
unsigned int Timer_1000ms;//1000ms标志位
unsigned char Time_Count = 30;//倒计时变量

//按键
bit System_Flag;//0-暂停 1-开始倒计时

unsigned char Set_Dat[3] = {15,30,60};//设置参数储存数组
unsigned char Set_Dat_Index = 1;

//LED点亮标志位
bit Timer0Flag;//0-倒计时没有到0;1-倒计时到0


//按键处理函数Key_Proc()
void Key_Proc()
{
	if(Key_Slow_Down)return;
	Key_Slow_Down = 1;//按键减速程序
	
	//这三行要背下来
	Key_Val = Key_Read();//读取按下的键码值
	Key_Down = Key_Val &(Key_Val ^ Key_Old);//捕获下降沿
	Key_Old = Key_Val;//辅助扫描
	
	switch(Key_Down)
	{
		//框架先搭好,内容先不写
		case 1:
			if(Seg_Mode == 0) System_Flag = 1;
		break;
		
		case 3:
			Seg_Mode ^= 1;
			//if(Seg_Mode == 0)
				//Time_Count = Set_Dat[Set_Dat_Index];
		break;
		
		case 4:
			if(Seg_Mode == 1)
			{
				if(++Set_Dat_Index == 3) Set_Dat_Index = 0;
				Time_Count = Set_Dat[Set_Dat_Index];
			}
		break;
			
		case 2:
			if(Seg_Mode == 0) Time_Count = Set_Dat[Set_Dat_Index];
		break;
	}
}

//信息显示函数Seg_Proc()
void Seg_Proc()
{
	if(Seg_Slow_Down)return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	//现在没有要显示的信息,这里先空着。(模板以外的东西)
	Seg_Buf[0] = Seg_Mode + 1;
	if(Seg_Mode == 0)//显示模式
	{
		Seg_Buf[4] = Time_Count/10%10;//可以写成Time_Count/10嘛
		Seg_Buf[5] = Time_Count%10;
	}
	else//处于设置模式
	{
		Seg_Buf[4] = Set_Dat[Set_Dat_Index]/10%10;
		Seg_Buf[5] = Set_Dat[Set_Dat_Index]%10;
		
	}


}

/* 其他显示函数 */
//Led_Proc()
void Led_Proc()
{
	if(Time_Count == 0)
	{
		P1 = 0x00;//LED全亮
		P2_3 = 0;//蜂鸣器使能
	}
	else
	{
		P1 = 0xff;//LED全灭
		P2_3 = 1;//蜂鸣器关闭
	}
}

//Timer0Init()定时器0的中断初始化函数
void Timer0Init(void)		//1毫秒@12.000MHz
{
	//AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	//复制过来之后不要忘记加上两句话
	ET0 = 1;
	EA = 1;
}


//Server定时器0的中断服务函数
//a++是先进行取值,后进行自增。++a是先进行自增,后进行取值
void Timer0Server() interrupt 1
{
	//定时器的初值一定要记得从上面复制过来
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
	if(++Seg_Pos == 6) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
	
	//模板以外的东西
	if(System_Flag == 1)
		//倒计时开始
	{
		if(++Timer_1000ms == 1000)
		{
			Timer_1000ms = 0;
			Time_Count--;//相当于1s中减少一次(倒计时一次)
			if(Time_Count==255) Time_Count=0;
		}
	}
}
//主函数
void main()
{
	Timer0Init();//上电时立即调用定时器初始化函数
	while(1)
	{
		//三大处理单元:按键、数码管、LED
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}

04 如何实现设置参数以1s为周期闪烁?

(1)在变量声明区新增两个变量:
注:以1s为周期闪烁,即500ms亮,500ms灭。

unsigned int Timer_500ms;//500ms标志位
bit Seg_Flag;//数码管标志位,即控制数码管的亮灭

(2)在中断服务函数中

	if(++Timer_500ms == 500)
	{
		Timer_500ms = 0;
		Seg_Flag ^= 1;
		//因为默认值为0,只需要对其取反即可,不需要赋值,可以用^=1来对一个变量取反
	}

(3)在数码管显示函数中

//信息显示函数Seg_Proc()
void Seg_Proc()
{
	if(Seg_Slow_Down)return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	//现在没有要显示的信息,这里先空着。(模板以外的东西)
	Seg_Buf[0] = Seg_Mode + 1;
	if(Seg_Mode == 0)//显示模式
	{
		Seg_Buf[4] = Time_Count/10%10;//可以写成Time_Count/10嘛
		Seg_Buf[5] = Time_Count%10;
	}
	else//处于设置模式
	{
//		Seg_Buf[4] = Set_Dat[Set_Dat_Index]/10%10;
//		Seg_Buf[5] = Set_Dat[Set_Dat_Index]%10;
//修改如下:
		if(Seg_Flag == 1)
		{
			Seg_Buf[4] = 10;
			Seg_Buf[5] = 10;
		}
		else
		{
			Seg_Buf[4] = Set_Dat[Set_Dat_Index]/10%10;
			Seg_Buf[5] = Set_Dat[Set_Dat_Index]%10;
		}
	}
}

05 最终版代码

//头文件声明
#include <REGX52.H>
#include <Key.h>
#include <Seg.h>//动态数码管会用到数码管的底层?

//变量声明
unsigned char Key_Slow_Down;//按键减速专用变量 10ms
unsigned char Key_Val,Key_Down,Key_Old;//按键扫描专用变量

unsigned int Seg_Slow_Down;//数码管减速专用变量 500mschar:0-255.char不够用

//动态数码管
unsigned char Seg_Pos;//数码管扫描变量
unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据存放数组

unsigned char Seg_Mode;//数码管显示页面 0-显示 1-设置,默认为0
unsigned int Timer_1000ms;//1000ms标志位
unsigned char Time_Count = 30;//倒计时变量

//按键
bit System_Flag;//0-暂停 1-开始倒计时

unsigned char Set_Dat[3] = {15,30,60};//设置参数储存数组
unsigned char Set_Dat_Index = 1;

//设置参数闪烁
unsigned int Timer_500ms;//500ms标志位
bit Seg_Flag;//数码管标志位

//LED点亮标志位
bit Timer0Flag;//0-倒计时没有到0;1-倒计时到0


//按键处理函数Key_Proc()
void Key_Proc()
{
	if(Key_Slow_Down)return;
	Key_Slow_Down = 1;//按键减速程序
	
	//这三行要背下来
	Key_Val = Key_Read();//读取按下的键码值
	Key_Down = Key_Val &(Key_Val ^ Key_Old);//捕获下降沿
	Key_Old = Key_Val;//辅助扫描
	
	switch(Key_Down)
	{
		//框架先搭好,内容先不写
		case 1:
			if(Seg_Mode == 0) System_Flag = 1;
		break;
		
		case 3:
			Seg_Mode ^= 1;
			//if(Seg_Mode == 0)
				//Time_Count = Set_Dat[Set_Dat_Index];
		break;
		
		case 4:
			if(Seg_Mode == 1)
			{
				if(++Set_Dat_Index == 3) Set_Dat_Index = 0;
				Time_Count = Set_Dat[Set_Dat_Index];
			}
		break;
			
		case 2:
			if(Seg_Mode == 0) Time_Count = Set_Dat[Set_Dat_Index];
		break;
	}
}

//信息显示函数Seg_Proc()
void Seg_Proc()
{
	if(Seg_Slow_Down)return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	//现在没有要显示的信息,这里先空着。(模板以外的东西)
	Seg_Buf[0] = Seg_Mode + 1;
	if(Seg_Mode == 0)//显示模式
	{
		Seg_Buf[4] = Time_Count/10%10;//可以写成Time_Count/10嘛
		Seg_Buf[5] = Time_Count%10;
	}
	else//处于设置模式
	{
//		Seg_Buf[4] = Set_Dat[Set_Dat_Index]/10%10;
//		Seg_Buf[5] = Set_Dat[Set_Dat_Index]%10;
		if(Seg_Flag == 1)
		{
			Seg_Buf[4] = 10;
			Seg_Buf[5] = 10;
		}
		else
		{
			Seg_Buf[4] = Set_Dat[Set_Dat_Index]/10%10;
			Seg_Buf[5] = Set_Dat[Set_Dat_Index]%10;
		}
	}
}

/* 其他显示函数 */
//Led_Proc()
void Led_Proc()
{
	if(Time_Count == 0)
	{
		P1 = 0x00;//LED全亮
		P2_3 = 0;//蜂鸣器使能
	}
	else
	{
		P1 = 0xff;//LED全灭
		P2_3 = 1;//蜂鸣器关闭
	}
}

//Timer0Init()定时器0的中断初始化函数
void Timer0Init(void)		//1毫秒@12.000MHz
{
	//AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	//复制过来之后不要忘记加上两句话
	ET0 = 1;
	EA = 1;
}


//Server定时器0的中断服务函数
//a++是先进行取值,后进行自增。++a是先进行自增,后进行取值
void Timer0Server() interrupt 1
{
	//定时器的初值一定要记得从上面复制过来
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
	if(++Seg_Pos == 6) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
	
	//模板以外的东西
	if(System_Flag == 1)
		//倒计时开始
	{
		if(++Timer_1000ms == 1000)
		{
			Timer_1000ms = 0;
			Time_Count--;//相当于1s中减少一次(倒计时一次)
			if(Time_Count==255) Time_Count=0;
		}
	}
	
	if(++Timer_500ms == 500)
	{
		Timer_500ms = 0;
		Seg_Flag ^= 1;
		//因为默认值为0,只需要对其取反即可,不需要赋值,可以用^=1来对一个变量取反
	}
}
//主函数
void main()
{
	Timer0Init();//上电时立即调用定时器初始化函数
	while(1)
	{
		//三大处理单元:按键、数码管、LED
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}

参考视频:https://www.bilibili.com/video/BV1TR4y1k7iz?p=6&vd_source=5af7b905774c79f1754cd4ab83975115

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

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

相关文章

[Labtools 27-1429] XML parser encountered a problem in file

平台&#xff1a;Vivado2108.3 最近在使用vivado的debug过程中发现&#xff0c;编译好工程后打开open hardware manager出现如下错误。 [Labtools 27-1429] XML parser encountered a problem in file E:/githome/xxxx/hw_1/hw.xml at line 1 : XML character encoding not su…

C语言结构体类型,结构体变量的创建和初始化,结构中存在的内存对齐

1.语言结构体类型 结构是⼀些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 声明 struct tag {member-list; }variable-list; 例如声明一本书&#xff1a; struct Book {char name[20]; //书名char author[20]; //作者int price; //定价…

快速入门uniapp-day03

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;给自己一个梦想&#xff0c;给世界一个惊喜。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章目录 什么是标签栏…

第7篇:全加器的Signal Tap调试

Q&#xff1a;上一篇里我们对全加器进行了功能仿真&#xff0c;这次我们用Quartus软件里的Signal Tap Logic Analyzer工具对全加器进行调试。 A&#xff1a;Signal Tap Logic Analyzer是Quartus Prime设计软件中自带的系统级调试工具&#xff0c;它可以在FPGA设计中采集和显示…

halcon颜色提取

在Halcon中&#xff0c;颜色提取通常用于从图像中提取特定颇具的区域或对象。 将输入的 RGB 颜色空间转换为 HSV * 根据颜色提取想要的目标 for Index:1 to 2 by 1read_image (Image, cableIndex)* 获取一个三通道图像中每个通道的图像* 红色通道&#xff08;R&#xff09;、绿…

Linux:Gitlab:16.9.2 创建用户及项目仓库基础操作(2)

我在上一章介绍了基本的搭建以及邮箱配置 Linux&#xff1a;Gitlab:16.9.2 (rpm包) 部署及基础操作&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136821311?spm1001.2014.3001.5501 本章介绍一下用户的创建&#xff0c;组内设置用户&…

STP环路避免实验(华为)

思科设备参考&#xff1a;STP环路避免实验&#xff08;思科&#xff09; 一&#xff0c;技术简介 Spanning Tree Protocol&#xff08;STP&#xff09;&#xff0c;即生成树协议&#xff0c;是一种数据链路层协议。主要作用是防止二层环路&#xff0c;并自适应网络变化和故障…

Linux-Arm环境下配置编译qt-everywhere及交叉编译环境

前言 最近在搞交叉编译的事&#xff0c;手上拿了个同事的香橙派玩交叉编译&#xff0c;现在来到了第一步&#xff0c;就是先在arm上配置qt的开发环境。当然了Qt没有直接提供qt on arm&#xff0c;而是需要自行在arm环境下编译一个qt环境出来&#xff0c;所以这里需要使用到qt提…

Ubuntu---之命令学习

方便于作者自用的命令手册&#xff0c;不喜勿喷 ls ls是查看指定路径下的文件信息&#xff0c;可以是相对路径也可以是绝对路径 使用参数&#xff1a; -a&#xff1a;列出全部文件&#xff08;包含隐藏文件&#xff0c;如.bashrc&#xff09;-l&#xff1a;列出文件的全部信…

【智能家居】东胜物联提供软硬一体化智能家居解决方案,助企业提高市场占有率

背景 随着智能家居市场的不断壮大&#xff0c;越来越多的消费者开始享受到它带来的便捷和效益。现在&#xff0c;他们可以通过远程或语音控制设备进行个性化设置&#xff0c;比如调节照明和温度&#xff0c;让生活变得更加舒适和智能化。 根据SPER市场研究&#xff0c;预计秘…

K8s的Pod出现Init:ImagePullBackOff问题的解决,(以calico网络插件为例)

问题描述&#xff1a; 对于这类问题的解决思路应该都差不多&#xff0c;本文以calico插件安装为例&#xff0c;发现有个Pod的镜像没有pull成功 第一步&#xff1a;查看这个pod的描述信息 kubectl describe pod calico-node-t9rql -n kube-system从上图发现是docker拉取"…

【Linux】Linux开发工具-vim / 编译器-gcc/g++ / 调试器-gdb / git操作 / 项目自动化构建工具-make/Makefile

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.在Linux写自己的第一个程序 1.1 nano指令 1.2 nano指令的使用 1.2.1 介绍 1.2.2 演示 1.2.2.1 创建.c文件 1.2.2.2 nano cod…

windows下的IDEA运用Scala 编写的 Apache Spark 应用程序

目录 一.环境要求 虚拟机环境 1.linux操作系统 2.jdk 3.Hadoop环境 4.spark 5.scala Windows环境 1.jdk 2.Hadoop&#xff08;同上&#xff09; 3.Scala 4. 安装winutils 二.IDEA的安装 idea下载 1、网站 2、下载 3、 安装 idea的配置 1.汉化 2.下载scala…

Windows电脑上如何进行硬盘分区操作!

在Windows操作系统环境下,对电脑硬盘进行分区是一种常见的硬盘管理手段,它可以帮助用户更好地组织和管理存储空间,确保操作系统、应用程序和用户数据各有所属。本文将详细介绍在Windows PC上进行硬盘分区的步骤,适用于Windows 7到Windows 11等不同版本的操作系统。 步骤一:…

C# visual studio 2022 学习2

类成员&#xff1a; 1.字段成员 字段只是类中声明的一个变量&#xff0c;用来在对象中存储信息。 &#xff08;1&#xff09;.静态字段 使用static关键字修饰的就是静态字段&#xff0c;静态字段属于类而不属于某个类实例&#xff0c;对它的访问使用“类名.静态字段名” &…

el-tree 设置默认展开指定层级

el-tree默认关闭所有选项&#xff0c;但是有添加或者编辑删除的情况下&#xff0c;需要刷新接口&#xff0c;此时会又要关闭所有选项&#xff1b; 需求&#xff1a;在编辑时、添加、删除 需要将该内容默认展开 <el-tree :default-expanded-keys"expandedkeys":da…

JS+CSS3点击粒子烟花动画js特效

JSCSS3点击粒子烟花动画js特效 JSCSS3点击粒子烟花动画js特效

大数据技术学习笔记(十三)—— HBase

目录 1 Hbase 概述1.1 Hbase 定义1.2 HBase 数据模型1.2.1 HBase 逻辑结构1.2.2 HBase 物理存储结构1.2.3 数据模型 1.3 HBase 基本架构 2 HBase Shell 操作2.1 基本操作2.2 namespace 操作2.3 表操作 3 HBase 原理深入3.1 RegionServer 架构3.2 HBase 写流程3.3 MemStore Flus…

【技术栈】Redis 企业级解决方案

​ SueWakeup 个人主页&#xff1a;SueWakeup ​​​​​​​ 系列专栏&#xff1a;学习技术栈 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 个性签名&…

C# 使用OpenCvSharp4将Bitmap合成为MP4视频的环境

环境安装步骤&#xff1a; 在VS中选中项目或者解决方案&#xff0c;鼠标右键&#xff0c;选择“管理Nuget包”&#xff0c;在浏览窗口中搜索OpenCVSharp4 1.搜索OpenCvSharp4,选择4.8.0版本&#xff0c;点击安装 2.搜索OpenCvSharp4.runtime.win,选择4.8.0版本&#xff0c;点…