【笔记】6位数码管显示定时器定时的时分秒,通过按键控制时间,自定义串口通信协议,根据单片机接收到的指令控制数码管显示

这篇具有很好参考价值的文章主要介绍了【笔记】6位数码管显示定时器定时的时分秒,通过按键控制时间,自定义串口通信协议,根据单片机接收到的指令控制数码管显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

          目的:利用PROTUES仿真软件、串口调试助手、虚拟串口,搭建单片机与PC通信仿真平台,熟悉单片机串口的配置及与PC机的通信方法;尝试制定通信协议(含开始码、指令、数据、停止码),单片机根据通信协议解析接收到的内容,并根据接收的指令执行相应的操作。

1、proteus仿真实验电路:

6个数码管显示时分秒,单片机,51单片机

6个数码管显示时分秒,单片机,51单片机

2、基本功能

程序功能:1.时分秒的动态显示。2.用三个按键实现时分秒的修改,调节的数字闪烁提示。
3.串口控制时钟的暂停、开始、清零、读取、设置时间

串口协议格式:s+指令+数据+e
s:表示开始码
指令:
  p:计时暂停(无数据位)    
  r:计时重启(无数据位)    
  c:显示清零(无数据位)    
  q:查询当前时间(无数据位)         
  t:设置时间(数据位格式为6位数字)   

6个数码管显示时分秒,单片机,51单片机

3、效果

 6个数码管显示时分秒,单片机,51单片机

6个数码管显示时分秒,单片机,51单片机文章来源地址https://www.toymoban.com/news/detail-755843.html

4、源代码 

/*******************************************************************************
程序功能:1.时分秒的动态显示。2.用三个按键实现时分秒的修改,调节的数字闪烁提示。
3.串口控制时钟的暂停、开始、清零、读取、设置时间
串口协议格式:s+指令+数据+e
s:表示开始码
指令:
	|	p:计时暂停(无数据位)	         |
	|	r:计时重启(无数据位)	         |
	|	c:显示清零(无数据位)	         |
	|	q:查询当前时间(无数据位)        
	|	t:设置时间(数据位格式为6位数字) 
*******************************************************************************/

#include <reg52.h>		 //包含需要的头文件

#define u8 unsigned char
#define u16 unsigned int	

u8 WeiMa[6]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};
u8 DuanMa[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

//函数声明
void Delay_ms(u16 xms);
void ShuMaGuan(u8 wei,u8 duan);
void Display_Timer(u8 hour,u8 min,u8 sec);
u8 Key_Scan();
void PutChar(u8 n);
void UartInit();
void PutString(u8 *p);
void Key_Timer_Set();
void Uart_Timer_Set();
void Pintf_Uart();


//引脚定义
sbit SW1=P3^2;
sbit SW2=P3^3;
sbit SW3=P3^4;

u8 Hour=0,Min=0,Sec=0;//全局变量,时分秒
u8 mode=0;//全局变量:状态切换,0:时钟显示,1:调节时;2:调节分;3:调节秒
bit flash_tip=1;//数码管闪烁标志,为0时数码管熄灭,为一时数码管显示

#define Data_SIZE 15 //数据长度
u8 USART_RX_BUF[Data_SIZE]; //接收缓冲,最大Data_SIZE个字节.末字节为换行符 
u8 Start_Receiving=0; //开始接收标志位
u8 Receive_OK=0;   //接收完毕接收位 1为接收完毕

//函数功能:定时器初始化
void Time0init()
{
	TMOD|=0x01;				//设置定时器模式
	TF0=0;					//清除TF0标志
	TH0=(65536-50000)/256;  //设置定时初值
	TL0=(65536-50000)%256;	//设置定时初值
	TR0=1;					//定时器0允许计时
	ET0=1;					//中断允许
	EA=1;					//CPU中断允许位打开
}

//串口初始化
void UartInit()  //9600bps@11.0592MHz
{
 
	 PCON &= 0x8F;  //波特率倍速
	 SCON = 0x50;  //8位数据,可变波特率
	 TMOD &= 0x0F;  //清除定时器1模式位
	 TMOD |= 0x20;  //设定定时器1为8位自动重装方式
	 TL1 = 0xFD;   //设定定时初值
	 TH1 = 0xFD;  //设定定时器重装值
	 TR1 = 1;  //启动定时器1
	 EA=1;
	 ES=1;  //打开接收中断
}

/*******************************************************************************
* 函 数 名: void main()
* 函数功能: 主函数
*******************************************************************************/
void main()
{
	
	
	Time0init();//定时器
	UartInit(); //串口
	Pintf_Uart();//输入提示
	while(1)
	{
		Key_Timer_Set();//按键控制时钟
		Uart_Timer_Set();//按键调节时钟
		Display_Timer(Hour,Min,Sec);//数码管显示
		
	}
}

/*******************************************************************************
* 函 数 名: void Pintf_Uart()
* 函数功能: 串口助手输入指示
*******************************************************************************/
void Pintf_Uart()
{
	/***************输入指示*******************/
	PutString("Please input:s+command(data)+e\r\n");
	PutString("Stop_Time:spe\r\n");
	PutString("Start_Time:sre\r\n");
	PutString("Zero_Time:sce\r\n");
	PutString("Read_Time:sqe\r\n");
	PutString("Set_Time:st******e\r\n");
	/*******************************************/
}

/*******************************************************************************
* 函 数 名: void Key_Timer_Set()
* 函数功能: //按键调节时钟
*******************************************************************************/
void Key_Timer_Set()
{
	u8 keynum;
	keynum=Key_Scan();//按键返回值
	if(keynum)   //非0表示有按键按下
	{
		switch(keynum)  //判断是哪个按键按下,按键一调节模式,按键2自加,按键3自减
		{
			case 1:if(++mode>=4) mode=0;break;  //++mode为先自增再判断是否大于4
			case 2:
				if(mode==1) if(++Hour>=24) Hour=0;//++mode为先自增再判断是否大于4
				if(mode==2) if(++Min>=60) Min=0;//++Min先自增再判断是否大于60
				if(mode==3) if(++Sec>=60) Sec=0;//++Sec先自增再判断是否大于60
				break;										
			case 3:
				if(mode==1)	if(--Hour==255) Hour=23;//--Hour先自增再判断是否溢出
				if(mode==2) if(--Min==255) Min=59;//--Min先自增再判断是否大溢出
				if(mode==3) if(--Sec==255) Sec=59;//--Sec先自增再判断是否大溢出
				break;
			default:break;
		}
	}	
}
/*******************************************************************************
* 函 数 名: void Key_Timer_Set()
* 函数功能: 串口调节时钟
串口协议格式:s+指令+数据+e
s:表示开始码
指令:
	|	p:计时暂停(无数据位)	|
	|	r:计时重启(无数据位)	|
	|	c:显示清零(无数据位)	|
	|	q:查询当前时间(无数据位)         
	|	t:设置时间(数据位格式为6位数字)  
*******************************************************************************/
void Uart_Timer_Set()
{
	static u8 Hour_1,Min_1,Sec_1;//时间暂存 
	if(Receive_OK) //如果串口接收到数据
	{
		Receive_OK=0;
		switch(USART_RX_BUF[0])//存入数组的数据没有开始码,所以第一个数据是指令
		{
			case 'p':   //时钟暂停
				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
					PutString("Error!\r\n");
				else
				{
					TR0=0;
					PutString("Stop OK!\r\n");
				}
				
				break;
			case 'r':   //开始计时
				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
					PutString("Error!\r\n");
				else
				{
					TR0=1;
					PutString("Start OK!\r\n");
				}
				break;
			case 'c':   //清零
				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
					PutString("Error!\r\n");
				else
				{
					Hour=0;
					Min=0;
					Sec=0;
					PutString("Zero OK!\r\n");
				}
				
				break;
			case 'q':   //查询当前时间
				if(USART_RX_BUF[1]!='e')//说明第2位数组的数据不是停止码
					PutString("Error!\r\n");
				else
				{
					PutString("The time is:");
					PutChar(Hour/10+48);  //转化ASCII码字符,0为48,1为48+1=49.....
					PutChar(Hour%10+48);
					PutChar(':');
					PutChar(Min/10+48);
					PutChar(Min%10+48);
					PutChar(':');
					PutChar(Sec/10+48);
					PutChar(Sec%10+48);
					PutString("\r\n");
				}
				
				break;
			case 't':   //设置时间
				if(USART_RX_BUF[7]!='e')//如果接收到的数据不是6位数字,说明第7位数组的数据不是停止码
					PutString("Error!\r\n");
				else
				{
					Hour_1=(USART_RX_BUF[1]-48)*10+(USART_RX_BUF[2]-48); //转化成十进制
					Min_1=(USART_RX_BUF[3]-48)*10+(USART_RX_BUF[4]-48); //转化成十进制
					Sec_1=(USART_RX_BUF[5]-48)*10+(USART_RX_BUF[6]-48); //转化成十进制
					if(Hour_1>23 || Min_1>59 || Sec_1>59)  //超出时间阈值
						PutString("Error!\r\n");	
					else  
					{
						Hour=Hour_1;  
						Min=Min_1;
						Sec=Sec_1;
						PutString("Set OK!\r\n");
					}
				}
				break;
			default:PutString("Error!\r\n");break;
		}
		ES=1;  //开启接收
	}
}

/*******************************************************************************
* 函 数 名: void Delay_ms(u16 xms)
* 函数功能: 软件延时函数,xms为延时多少毫秒
*******************************************************************************/
void Delay_ms(u16 xms)
{
	
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 135;
		do
		{
			while (--j);
		} while (--i);
	}
}

/*******************************************************************************
* 函 数 名: void ShuMaGuan(u8 wei,u8 duan)
* 函数功能: 静态显示一位,参数:wei控制位选duan控制段选,表示要显示的一个数字
*******************************************************************************/
void ShuMaGuan(u8 wei,u8 duan)
{
	P1=WeiMa[wei];    //位选
	P2=DuanMa[duan];  //段选
	Delay_ms(1); //间隔一段时间扫描
	P1=0xFF;    
	P2=0xFF;	   //消隐
}

/*******************************************************************************
* 函 数 名: void Display_Timer(u8 hour,u8 min,u8 sec)
* 函数功能:数码管动态显示
  flash_tip为数码管闪烁标志,为0时数码管熄灭,为一时数码管显示
  flash_tip每4.5秒进行取反
*******************************************************************************/
void Display_Timer(u8 hour,u8 min,u8 sec)
{
	if(mode!=1 || flash_tip==1) //mode=1时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示
	{
		ShuMaGuan(5,hour/10);
		ShuMaGuan(4,hour%10);
	}
	else P1=0xFF;
	
	
	if(mode!=2 || flash_tip==1)//mode=2时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示
	{
		ShuMaGuan(3,min/10);
		ShuMaGuan(2,min%10);
	}
	else P1=0xFF; 
	
	
	if(mode!=3 || flash_tip==1)//mode=3时,左边的条件一直为假,当flash_tip=1时,或运算为真,进入if,数码管显示
	{
		ShuMaGuan(1,sec/10);
		ShuMaGuan(0,sec%10);
	}
	else P1=0xFF;  
}

/*******************************************************************************
* 函 数 名: u8 Key_Scan()
* 函数功能: 独立按键检测,按键按下分别返回1.2.3
*******************************************************************************/
u8 Key_Scan()
{
	static u8 key_up=1; //按键按松开标志
	if(key_up && (SW1==0 || SW2==0 || SW3==0))
	{
		Delay_ms(10); //去抖动
		key_up=0; //松手标志为0,那么下次再检测,if结果为0,则不会进入这里的语句
		if(SW1==0) return 1;
		if(SW2==0) return 2;
		if(SW3==0) return 3;
	}
	else if(SW1 == 1 && SW2 == 1 && SW3 == 1) key_up=1; //松手标志
	return 0; // 无按键按下
}

/*******************************************************************************
* 函 数 名: void PutChar(u8 n)
* 函数功能: 发送一个字符
*******************************************************************************/
void PutChar(u8 n)
{
	 SBUF=n;
	 while(!TI);
	 TI=0;
}

/*******************************************************************************
* 函 数 名: void PutString(u8 *p)
* 函数功能: 发送字符串
*******************************************************************************/
void PutString(u8 *p)
{
	while(*p!='\0')
	{
		PutChar(*p);
		p++;
	}
}
/*******************************************************************************
* 函 数 名: void uart() interrupt 4
* 函数功能: 串口中断服务函数,单片机接收数据并存入USART_RX_BUF[]数组中
开始码s不存入数组
*******************************************************************************/
void uart() interrupt 4
{
	static u8 Data_count=0;
	u8 Data;
	if(RI==1)
	{
		RI=0;
		Data=SBUF;
		if(Data=='s')
		{
			Start_Receiving=1;  //开始接收数据
		}
		else if(Start_Receiving)
		{
			USART_RX_BUF[Data_count++]=Data;//数据还没结束发送,就存到USART_RX_BUF[]数组中
			if(Data=='e')
			{
				Start_Receiving=0;
				Data_count=0;
				Receive_OK=1;
				ES=0;
			}
			
		}
		
	}
}

/*******************************************************************************
* 函 数 名: void Time0() interrupt 1
* 函数功能: 定时器0中断服务函数,时钟效果
*******************************************************************************/
void Time0() interrupt 1
{
	static unsigned char flag_1,flag_2; 
	TH0=(65536-50000)/256;  
	TL0=(65536-50000)%256;//重新赋初值
	
	if(mode==0)flag_1++;  //mode为0时,数码管正常显示
	else flag_2++;   
	
	if(flag_1==20 && mode==0)  //每秒执行一次
	{
		flag_1=0;
		if(++Sec>=60) //++Sec先自增再判断是否大于60  
		{
			Sec=0;
			if(++Min>=60)//++Min先自增再判断是否大于60
			{
				Min=0;
				if(++Hour>=24)//++Hour先自增再判断是否大于60
				{
					Hour=0;
				}
			}
		}
	}
	if(flag_2==9)
	{
		flash_tip=~flash_tip;//每4.5秒进行取反
		flag_2=0;
	}

}

到了这里,关于【笔记】6位数码管显示定时器定时的时分秒,通过按键控制时间,自定义串口通信协议,根据单片机接收到的指令控制数码管显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32+HAL+Proteus】系列学习教程---数码管显示定时

    1、STM32 基于HAL库定时器的使用; 2、加强数码管的学习。 3、具体目标:利用定时器3实现一个60秒的定时,定时时间在数码管上显示,定时时间到,蜂鸣器响一声作为提示功能。         自动生成的代码中,中断回调函数都有一个__weak ,加上了__weak 修饰符的函数,

    2024年04月09日
    浏览(78)
  • 51单片机---编程实现流水灯----键盘控制数码管显示--利用74LS164扩展并行输出口---定时中断方式驱动一个数码管

    目录 基于51单片机,用c语言编程实现流水灯 代码: 使用C语言编写的基于51单片机的键盘控制数码管显示 代码: 基于51单片机,用c语言编程实现利用74LS164扩展并行输出口 代码: 基于51单片机,用c语言编程实现定时中断方式驱动一个数码管  代码:  1- 2- 上述代码中,使用

    2024年02月16日
    浏览(51)
  • 单片机学习笔记---静态数码管显示

    目录 数码管是什么? 一位数码管的引脚定义 四位一体的数码管引脚定义 数码管的原理图解析 数码管怎么显示数据?(总结+代码显示) 今天开始学习数码管,它比LED和独立按键复杂一点 LED数码管是一种简单、廉价的 显示器 ,是由多个发光二极管封装在一起组成“8”字型

    2024年02月20日
    浏览(43)
  • 学习笔记|认识数码管|控制原理|数码管实现0-9的显示|段码跟位码|STC32G单片机视频开发教程(冲哥)|第九集:数码管静态显示

    数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元,也就是多一个小数点(DP)这个小数点可以更的表示数码管想要显示的内容;按能显示多少个(8)可分为1位、2位、3位、4位、5位、6位、7位等数码管。 按发光二极管单元连接方

    2024年02月10日
    浏览(52)
  • verilog学习笔记- 15)动态数码管显示实验

    目录 简介: 实验任务: 硬件设计: 程序设计: 下载验证: 由于一般的静态驱动操作虽然方便,但占用的 I/0 口较多,例如要驱动6 位 8 段数码管,以静态驱动方式让数码管各个位显示不同的数值,如“123456”,需要占用6 × 8 = 48个I/O 口,虽然对于 FPGA 这种 I/O 口较多的芯片

    2024年02月07日
    浏览(47)
  • 学习笔记|小数点控制原理|数码管动态显示|段码跟位码|STC32G单片机视频开发教程(冲哥)|第十集:数码管动态显示

    上述图片引用自:51单片机初学2-数码管动态扫描 用一排端口来控制段码,需要显示哪几个就点亮哪几个段,和看电影一样,一个一个的打开,关闭,一个个的画面,组成动画。 具体的控制的流程如图所示,N表示有几个数码管! 其中需要注意每个延时不能太短,我们这边程

    2024年02月07日
    浏览(43)
  • 学习C51单片机——矩阵按键控制数码管显示数字(学习笔记Keil5)

    单片机检测矩阵按键是否被按下的依据是检测与该按键对应的 I/O 口是否为低电平

    2024年04月17日
    浏览(48)
  • STC15F2K60S2学习笔记2——数码管动态显示

    目录 1.STC15F2K60S2数码管简介 2.STC15F2K60S2数码管点亮原理 3.STC15F2K60S2数码管的原理图 ①位选 ②段选 ③74HC138译码器 74HC02或非门 4.点亮一个数码管显示1 5.动态数码管显示01234567 6.动态数码管消除残影 STC15F2K60S2所用数码管属于共阳数码管,所谓共阳数码管是指将所有发光二极管的

    2024年02月04日
    浏览(54)
  • 【单片机】【数码管】数码管显示

      1. 数码管的显示器及其接口 单片机系统中 常用的显示器有: 发光二极管LED显示器、液晶LCD显示器、TFT液晶显示器。本文主要是关于LED显示器的说明。 LED显示器有两种显示结构:段显示(7段、米字型等)和点阵显示(5x8、8x8点阵等)。 LED数码管根据接法可以分为共阴和共

    2024年02月08日
    浏览(53)
  • 51单片机(四)静态数码管和动态数码管显示

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月09日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包