蓝桥杯第十三届电子类单片机组程序设计

news2024/11/26 4:27:48

目录

前言

单片机资源数据包_2023

一、第十三届比赛省赛

1.比赛题目

2.赛题解读

二、部分功能实现

1.继电器的开启与关闭

2.长按切换显示状态功能的实现

3.对于温度传感器小数部分的处理

4.其他处理

1)关于数码管显示小数的处理

2)关于5s后继电器开启的处理

3)关于点亮熄灭LED灯的策略

三、完整代码演示

main.c

onewire.c

oneiwre.h

ds1302.c

ds1302.h


前言

目前能分享的处理方式前边都已经分享过了,这里还是只分享本届赛题中一些独特的处理方式。做过十四届赛题之后,感觉前边的题目都很简单,所以在省赛之前,可能会刷一些国赛题来代替省赛。关于选择题的部分,还是不再分享了,感兴趣的可以自己看看。

如果今年省赛之前,公布了新的资源数据包,或者有了新的要求,作者也会第一时间如何使用新的资源数据包完成我之前写的代码的相关修改。

这里还是以第十四届资源数据包为基础:


单片机资源数据包_2023

一、第十三届比赛省赛

1.比赛题目

2.赛题解读

本届比赛只有三个菜单,比起十四届的六个菜单,真是简单了许多。

本届比赛使用到了继电器,虽然最开始学的时候也已经介绍了继电器,但是说实话用的次数不多,而且原理与LED和数码管想通,所以后续就很少介绍了,甚至上一篇的省三模板代码也没提到继电器。本篇文章会再次重温一下继电器的使用。

其他的要就就是中规中矩了,有一个长按S17显示分秒,正常情况显示时分的功能,实现起来也比判断短按按键和判断长按按键简单的多。而且好像去年比赛也用到了这个功能。

二、部分功能实现

1.继电器的开启与关闭

开启/关闭继电器其实和点亮/熄灭一个LED灯的道理是一样的,只是操纵的锁存器不一样而已,而且中间多了一个芯片用于大电流驱动,但是这个芯片几乎不影响处理。

左边的锁存器就是我们用来控制及继电器和电机的。右边的ULN2003是一个常用的达林顿晶体管阵列,它主要用于放大输入信号,以驱动继电器或其他大电流负载。需要注意到是,ULN2003芯片输入高电平时,输出的是低电平,输入低电平时,输出的是高电平。比如现在ULN的IN5是高电平,那么对应的OUT5输出的就是低电平。

下图是蜂鸣器的原理图:

其中N RELAY就是信号输入引脚,不难看出,当N RELAYT引脚为低电平时,有电流流过继电器,继电器闭合,结合上边关于锁存器和ULN的原理图,N RELAY连接的是ULN的OUT5(N RELAY有用红色框框标注欧),OUT5对应ULN的IN5,而IN5连接的是锁存器的Q5,锁存器Q5对应的输入是D5,D5连接的是P04,也就是说,我们只需要把P04置为高电平,然后开关一下锁存器让数据保存进去,就可以完成继电器的开启,同理,将P04置为低电平,然后开关一下锁存器,就可以将锁存器熄灭。是不是跟点亮一个LED灯一样呢,只是说点亮一个LED灯需要给一个低电平,熄灭给高电平,而继电器和蜂鸣器则是高电平闭合/响,低电平不闭合/不响。

至于锁存器的开启与关闭相比大家应该都已熟知,控制用来存储ULN数据的锁存器的使能端连接的是Y5C接口(上边图片也有标注),高电平有效,我们要想开启ULN连接的锁存器,只需要将ULN连接的锁存器的使能端置为高电平,在置为低电平,即完成了一次开关。

而Y5C接口连接的是三八译码器(右边的或非门可以选择性忽视)。三八译码器的输出是P25 P26和P27,当P27 P26 P25为101时(也就是十进制的5),就可以使得Y5C为高电平,同理,如果当P27 P26 P25不为101时,Y5C输出的就是低电平,这样我们就完成了一次开关连接ULN的锁存器。

当然,开关锁存器之前我们要先给P0置为。我们可以向控制LED灯一样控制继电器,定义一个变量用来记录ULN的状态。然后通过宏函数开改变ULN中对应的值,并且开关一次锁存器。代码如下:

unsigned char ULN=0x00;//ULN芯片状态(控制继电器和蜂鸣器)

#define RELAY_ON()    ULN|=0x01<<4;            P0=ULN;P2|=0xA0;P2&=0xBF;P2&=0x1F;
#define RELAY_OFF()    ULN&=~(0x01<<4);    P0=ULN;P2|=0xA0;P2&=0xBF;P2&=0x1F;

2.长按切换显示状态功能的实现

先看题目要求

简单点说就是按下S17之后,显示分秒,其他状态下显示时分。

不需要判断长短按,反正就是按下去之后切换一下显示,我们直接在按下按键的while循环中加上我们需要显示的数据即可(由于就这一个长按,所以长按时显示的数据就没写在菜单显示函数里了),同时不再调用菜单显示函数即可(避免发生冲突)。注意这个长按功能仅在时间显示菜单有效。

P34=0;
if(P32==0)
{
    Delay5ms();
    while(P32==0)//如果长按了17,由于只在长按时有效果,所以就把菜单直接显示在这里了
    {//一旦跳出这个循环,show_menu函数就会开始运行,这个临时菜单就会被清除
        if(mod==1)
        {
            Nixie_num[0]=21;//U
            Nixie_num[1]=2;//2
            Nixie_num[2]=20;
            Nixie_num[3]=Time[1]/10%10;//分钟
            Nixie_num[4]=Time[1]/1%10;
            Nixie_num[5]=22;
            Nixie_num[6]=Time[0]/10%10;//秒
            Nixie_num[7]=Time[0]/1%10;
        }
    }
    Delay5ms();
    key_value=17;
}
 

3.温度传感器小数部分的读取

温度传感器的指令就不在说了,忘记的可以看下边这篇文章:

蓝桥杯电子类单片机学习二——DS18B20温度传感器(onewire驱动)_蓝桥别ds18b20驱动文件是要自己写吗-CSDN博客

这里只回忆一下用于存储寄存器。温度数据的存储使用了两个8为寄存器,分别即为高八位(high)和低八位(low)。

高八位的高四位是符号位,为0时说明是正温度;高八位的低四位和低八位的高四位合起来也刚好是八位,是温度的整数部分;低八位的低四位是小数部分,精度可以达到1/16=0.0625.

之前我处理温度传感器时,都是只取高八位的低四位和低八位的高四位作为返回值,也就是返回的是温度的整数部分:

temp=high;
temp&=0x0F;
temp<<=8;
temp|=low;
temp>>=4;
 

return temp;

现在我们需要连同返回温度的小数部分,题目是只要求精确到小数点后一位,所以我们只需要将温度数据扩大十倍,并且将温度的小数部分最高位给加上去即可,这样就做到了保留小数点后一位。小数部分是低八位的低四位,只需要取出低八位的低四位,让它x10*/16即可。*10是为了扩大十倍,/16十位是因为最开始的精度是1/16度。

最开始学的时候,老师都是教的温度扩大16倍,读取温度之后,再把温度值乘以个1/16,我感觉很正式但是确实十分繁琐,尤其是我写的代码只为了应对这场比赛时,这样做就显得没太多必要。

temp=high;
temp&=0x0F;
temp<<=8;
temp|=low;
temp>>=4;

xiaoshu=low;
xiaoshu&=0x0F;//提取温度的小数部分

temp=temp*10+xiaoshu*10/16;

return temp;

4.其他处理

关于这些特殊处理肯定有许多,也肯定有一些是大家比较好奇的,但是之前已经分享过许多了,这里就只在提一下,需要的可以去查看对应的文章。

1)数码管显示小数的处理

我是把断码表0-9显示数字0到9,10-19显示带小数点的0到9,也就也是0. 1.等等。这样如果我需要显示小数点,比如需要显示num的十位,并且加上小数点,只需要

NIxie_num[0]=num/10%10+10;

即可。

对应的Seg_Table为

code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
//0.到9.
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
};

2)5s后继电器开启的处理

这里的处理主要是指5s,我们定义一个标志位is_5s,如果is_5s被置为0之后,5s后,定时器会把is_5s置为1.我们在需要开始计时的地方加上is_5s=0;然后开始检查is_5s,当is_5s变为1之后,说明已经过去5s了,具体在定时器1里的实现如下:

unsigned int count_5s=1;
void Timer0_Isr(void) interrupt 1
{
    P0=0x01<<location;NIXIE_CHECK();
    P0=Seg_Table[Nixie_num[location]];NIXIE_ON();
    
    if(++location==8)
        location=0;
    
    if(is_5s==0)//如果标志位被置为0,
    {
        if(++count_5s==5000)//5s后将标志位置为1
        {
            is_5s=1;
            count_5s=0;
        }
    }
}

这个的处理思路可以应用到包括长按短按按键,各种几秒后怎么怎么样等。当然关于这个的处理不唯一,虽然我这样写的可能会比较繁琐,但我敢保证我的处理方式绝对不会出问题,我也一直在用这种处理方式。

3)点亮熄灭LED灯的策略

我对于点亮/熄灭LED的处理都是定义一个标志位,用于记录某个LED灯处理点亮还是熄灭状态,如果满足点亮某个LED灯的条件,并且这个LED灯处于熄灭状态,则点亮这个LED灯,并且修改标志位;如果满足熄灭某个LED的条件,并且这个LED灯处于点亮状态,则熄灭这个LED灯,并且修改标志位。

这样子处理可以避免重复熄灭或点亮时,造成LED灯异常闪烁或者出现残影,也可以保证当LED灯停止闪烁之后,LED灯总是处在熄灭状态。

我们假设点亮LED的条件为tiaojian,tiaojian为1时说明需要点亮LED灯1,否则需要熄灭LED1,则根据上述可以写出以下代码:

bit L1_is_on=0;//LED灯状态标志位,为0说明未点亮,为1说明点亮了

void Led_run(void)
{
    if(L1_is_on==0&&tiaojian==0)//如果点亮满足条件,并且LED并未点亮
    {//则点亮LED灯
        LED_ON(0);
        L1_is_on=1;
    }
    else if(L1_is_on==1&&tiaojian==1)//如果满足熄灭条件,并且LED灯未熄灭
    {//则熄灭
        LED_OFF(0);
        L1_is_on=0;
    }
}

三、完整代码演示

main.c

#include <stc15.h>
#include <intrins.h>
#include "onewire.h"
#include "ds1302.h"

code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
//0.到9.
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
0xFF,//20 熄灭
0xC1,//21 U
0xBF//22 -
};

unsigned char Led_Num=0xFF;//LED灯状态
unsigned char ULN=0x00;//ULN芯片状态(控制继电器和蜂鸣器)

#define LED_ON(x)				Led_Num&=~(0x01<<x);P0=Led_Num;P2|=0x80;P2&=0x9F;P2&=0x1F;
#define LED_OFF(x)			Led_Num|=0x01<<x;		P0=Led_Num;P2|=0x80;P2&=0x9F;P2&=0x1F;
#define LED_OFF_ALL()		Led_Num=0xFF;				P0=Led_Num;P2|=0x80;P2&=0x9F;P2&=0x1F;

#define RELAY_ON()	ULN|=0x01<<4;			P0=ULN;P2|=0xA0;P2&=0xBF;P2&=0x1F;
#define RELAY_OFF()	ULN&=~(0x01<<4);	P0=ULN;P2|=0xA0;P2&=0xBF;P2&=0x1F;

#define NIXIE_CHECK()	P2|=0xC0;P2&=0xDF;P2&=0x1F;
#define NIXIE_ON()		P2|=0xE0;P2&=0xFF;P2&=0x1F;

void Timer0_Init(void);		//1毫秒@12.000MHz
void Delay100ms(void);	//@12.000MHz
void get_key(void);//读取按键
void show_menu(void);//显示菜单
void run(void);
void Led_run(void);//LED控制

unsigned char Nixie_num[]={20,20,20,20,20,20,20,20};
unsigned char location=0;//当前扫描到数码管的位置,中间变量
unsigned char key_value=0;//读取到的键值
unsigned char mod=0;//菜单模式
unsigned char temp_canshu=23;//温度参数
unsigned int temp=0;//读取到的温度,已扩大十倍
bit work=0;//工作状态 0温度控制 1时间控制
void main()
{
	LED_OFF_ALL();//熄灭所有LED灯
	ds_init();//初始化ds1302
	read_temp();//上电读取一次温度传感器
	RELAY_OFF();//关闭继电器
	Delay100ms();

	Timer0_Init();//定时器0初始化
	EA=1;
	while(1)
	{
		run();
		get_key();
		show_menu();
		
	}
}
bit relay_is_on=0;
bit is_5s=0;

void run()
{
	temp=read_temp();//读取温度
	ds_read();//读取时间
	Led_run();//控制LED灯
	if(Time[1]==0&&Time[0]==0)//如果到了整点
	{//由于下边有两处都需要判断整点,所以把整点的判断放在了work上边
		is_5s=0;//将5s标志位置为0,5s后标志位会被置为1
	}
	if(work==0)//如果处在时间控制模式下
	{
		//如果继电器处于关闭状态,并且当前读到的温度高于温度参数(注意读取到的温度为方便处理,以扩大十倍)
		if(relay_is_on==0&&temp/10>temp_canshu)
		{//则打开继电器
			RELAY_ON();
			relay_is_on=1;
		}
		//如果当前继电器处于开启状态,并且读取到的温度低于温度参数
		else if(relay_is_on==1&&temp/10<temp_canshu)
		{//则熄灭继电器
			RELAY_OFF();
			relay_is_on=0;
		}
	}
	
	else if(work==1)//如果处在时间控制模式下
	{
		if(is_5s==0&&relay_is_on==0)
		{
			RELAY_ON();//开启继电器
			relay_is_on=1;
		}
		else if(relay_is_on==1&&is_5s==1)//如果已经到了5s并且继电器还没关闭
		{//则关闭继电器
			RELAY_OFF();
			relay_is_on=0;
		}
	}
	Delay100ms();
}
unsigned int count_5s=1;
void Timer0_Isr(void) interrupt 1
{
	P0=0x01<<location;NIXIE_CHECK();
	P0=Seg_Table[Nixie_num[location]];NIXIE_ON();
	
	if(++location==8)
		location=0;
	
	if(is_5s==0)//如果标志位被置为0,
	{
		if(++count_5s==5000)//5s后将标志位置为1
		{
			is_5s=1;
			count_5s=0;
		}
	}
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x20;				//设置定时初始值
	TH0 = 0xD1;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;				//使能定时器0中断
}

void Delay100ms(void)	//@12.000MHz
{
	unsigned char data i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 144;
	k = 71;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay5ms(void)	//@12.000MHz
{
	unsigned char data i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}
void get_key(void)
{
	unsigned char key_P3=P3;
	unsigned char key_P4=P4;
	
	P3=0xFF;
	P4=0xFF;
	
	//按键读取的while(P32==0)中运行了run()函数,使得按下按键时不会影响其他设备的运行
	P35=0;
	if(P32==0){Delay5ms();while(P32==0){run();}Delay5ms();key_value=13;}
	else if(P33==0){Delay5ms();while(P33==0){run();}Delay5ms();key_value=12;}
	P35=1;
	
	P34=0;
	if(P32==0)
	{
		Delay5ms();
		while(P32==0)//如果长按了17,由于只在长按时有效果,所以就把菜单直接显示在这里了
		{//一旦跳出这个循环,show_menu函数就会开始运行,这个临时菜单就会被清除
			if(mod==1)
			{
				run();
				Nixie_num[0]=21;//U
				Nixie_num[1]=2;//2
				Nixie_num[2]=20;
				Nixie_num[3]=Time[1]/10%10;//分钟
				Nixie_num[4]=Time[1]/1%10;
				Nixie_num[5]=22;
				Nixie_num[6]=Time[0]/10%10;//秒
				Nixie_num[7]=Time[0]/1%10;
			}
		}
		Delay5ms();
		key_value=17;
	}
	else if(P33==0){Delay5ms();while(P33==0){run();}Delay5ms();key_value=16;}
	P34=1;
	
	//S12 菜单切换
	if(key_value==12)
	{
		if(mod==0)
			mod=1;
		else if(mod==1)
			mod=2;
		else if(mod==2)
			mod=0;
	}
	//S13 工作状态切换
	else if(key_value==13)
	{
		work=~work;
	}
	//S16 加
	else if(key_value==16)
	{
		if(mod==2)
			temp_canshu=temp_canshu<99 ? temp_canshu+1:99;
	}
	//S17 减 长按的功能在上边
	else if(key_value==17)
	{
		if(mod==2)
			temp_canshu=temp_canshu>10 ? temp_canshu-1:10;
	}
	key_value=0;
	P3=key_P3;
	P4=key_P4;
}
void show_menu(void)
{
	Nixie_num[0]=21;//显示U
	Nixie_num[1]=mod+1;//显示菜单数
	if(mod==0)
	{
		Nixie_num[2]=20;//熄灭
		Nixie_num[3]=20;//熄灭
		Nixie_num[4]=20;//熄灭
		Nixie_num[5]=temp/100%10;//显示2
		Nixie_num[6]=temp/10%10+10;//显示3.
		Nixie_num[7]=temp/1%10;//显示5
	}
	else if(mod==1)
	{
		Nixie_num[2]=20;
		Nixie_num[3]=Time[2]/10%10;
		Nixie_num[4]=Time[2]/1%10;
		Nixie_num[5]=22;
		Nixie_num[6]=Time[1]/10%10;
		Nixie_num[7]=Time[1]/1%10;
	}
	else if(mod==2)
	{
		Nixie_num[2]=20;
		Nixie_num[3]=20;
		Nixie_num[4]=20;
		Nixie_num[5]=20;
		Nixie_num[6]=temp_canshu/10%10;
		Nixie_num[7]=temp_canshu/1%10;
	}
}
bit L1_is_on=0;
bit L2_is_on=0;
bit L3_is_on=0;
void Led_run(void)
{
	if(L1_is_on==0&&is_5s==0)//如果处在整点之后的5s内
	{
		LED_ON(0);
		L1_is_on=1;
	}
	else if(L1_is_on==1&&is_5s==1)
	{
		LED_OFF(0);
		L1_is_on=0;
	}
	
	if(L2_is_on==0&&work==1)//如果处在时间控制模式,则L2点亮
	{
		LED_ON(1);
		L2_is_on=1;
	}
	else if(L2_is_on==1&&work==0)
	{
		LED_OFF(1);
		L2_is_on=0;
	}
	
	if(relay_is_on==1)//如果继电器闭合,则L3闪烁
	{
		if(L3_is_on==0)
		{
			LED_ON(2);
			L3_is_on=1;
		}
		else if(L3_is_on==1)
		{
			LED_OFF(2);
			L3_is_on=0;
		}
	}
	else if(relay_is_on==0&&L3_is_on==1)//如果继电器没有闭合,并且L3被点亮了,则熄灭L3
	{
		LED_OFF(2);
		L3_is_on=0;
	}
}

onewire.c

/*	# 	单总线代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <stc15.h>
#include <intrins.h>
#include "onewire.h"
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

//
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

unsigned int read_temp(void)
{
	unsigned char low,high;
	unsigned int temp=0;
	unsigned char xiaoshu=0;
	init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
	init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0xBE);
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp=high;
	temp&=0x0F;
	temp<<=8;
	temp|=low;
	temp>>=4;
	
	xiaoshu=low;
	xiaoshu&=0x0F;//提取温度的小数部分

	temp=temp*10+xiaoshu*10/16;
	
	return temp;
}

oneiwre.h

#ifndef _ONE_WIRE_H_
#define _ONE_WIRE_H_

unsigned int read_temp(void);

#endif

ds1302.c

/*	# 	DS1302代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/								
#include <stc15.h>
#include <intrins.h>
#include "ds1302.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
unsigned char Time[3]={20,53,23};
//
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		SDA = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}
void ds_init(void)
{
	unsigned char add=0x80;
	unsigned char i=0;
	Write_Ds1302_Byte(0x8E,0x00);
	for(;i<3;i++)
	{
		Write_Ds1302_Byte(add,(Time[i]/10<<4)|(Time[i]%10));
		add+=2;
	}
	Write_Ds1302_Byte(0x8E,0x80);
}
void ds_read(void)
{
	unsigned char add=0x81;
	unsigned char i=0,dat=0;
	for(;i<3;i++)
	{
		dat=Read_Ds1302_Byte(add);
		Time[i]=dat/16*10+dat%16;
		add+=2;
	}
}

ds1302.h

#ifndef _DS_1302_H_
#define _DS_1302_H_

extern unsigned char Time[3];
void ds_read(void);
void ds_init(void);

#endif

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

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

相关文章

(完结)Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(三)项目优化

本文参考自 Springboot3微服务实战12306高性能售票系统 - 慕课网 (imooc.com) 本文是仿12306项目实战第&#xff08;三&#xff09;章——项目优化&#xff0c;本篇将讲解该项目最后的优化部分以及一些压测知识点 本章目录 一、压力测试-高并发优化前后的性能对比1.压力测试相关…

系统需求分析报告(原件获取)

第1章 序言 第2章 引言 2.1 项目概述 2.2 编写目的 2.3 文档约定 2.4 预期读者及阅读建议 第3章 技术要求 3.1 软件开发要求 第4章 项目建设内容 第5章 系统安全需求 5.1 物理设计安全 5.2 系统安全设计 5.3 网络安全设计 5.4 应用安全设计 5.5 对用户安全管理 …

Android 自定义EditText

文章目录 Android 自定义EditText概述源码可清空内容的EditText可显示密码的EditText 使用源码下载 Android 自定义EditText 概述 定义一款可清空内容的 ClearEditText 和可显示密码的 PasswordEditText&#xff0c;支持修改提示图标和大小、背景图片等。 源码 基类&#xf…

相机标定学习记录

相机标定是计算机视觉和机器视觉领域中的一项基本技术&#xff0c;它的主要目的是通过获取相机的内部参数&#xff08;内参&#xff09;和外部参数&#xff08;外参&#xff09;&#xff0c;以及镜头畸变参数&#xff0c;建立起现实世界中的点与相机成像平面上对应像素点之间准…

枚举--enum和动态内存管理(malloc和free)

枚举---enum&#xff1a;它的本意就是列举事物&#xff0c;比如&#xff0c;颜色和性别&#xff0c;则代码为&#xff1a; #include<stdio.h> //枚举的示例&#xff1a;性别&#xff0c;颜色 enum sex//性别 {MALE,FEMALE,SECRTY }; enum clore//颜色 {ROW,BLUS,GREEN …

查找某数据在单链表中出现的次数

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct LinkNode {ElemType data;LinkNode* next; }LinkNode, * LinkList; //尾插法建立单链表 void creatLinkList(LinkList& L) {L (LinkNode*)mallo…

Vue系列——数据对象

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>el:挂载点</title> </head> <body&g…

本地项目上传到GitHub

本文档因使用实际项目提交做为案例&#xff0c;故使用xxx等字符进行脱敏&#xff0c;同时隐藏了部分输出&#xff0c;已实际项目和命令行输出为准 0、 Git 安装与GitHub注册 1&#xff09; 在下述地址下载Git&#xff0c;安装一路默认下一步即可。安装完成后&#xff0c;随便…

【面试经典150 | 动态规划】零钱兑换

文章目录 Tag题目来源解题思路方法一&#xff1a;动态规划 写在最后 Tag 【动态规划】【数组】 题目来源 322. 零钱兑换 解题思路 方法一&#xff1a;动态规划 定义状态 dp[i] 表示凑成总金额的最少硬币个数。 状态转移 从小到大枚举要凑成的金额 i&#xff0c;如果当前…

电动车“锂”改“铅”屡被查?新国标或疏于考虑用户真实需求

最近几个月&#xff0c;电动自行车又走到了舆论中心。 “315期间”&#xff0c;不少媒体集中报道了超标电动自行车改装上牌事件。3月18日至20日&#xff0c;新华社推出电动自行车安全隐患系列调查&#xff0c;聚焦点之一就是改装超标问题。而在近段时间&#xff0c;综合媒体报…

MarTech调研总结整理

整体介绍 概念解释&#xff1a; Martech是一种智慧营销的概念&#xff0c;将割裂的营销&#xff08;Marketing&#xff09;、技术&#xff08;Technology&#xff09;与管理&#xff08;Management&#xff09;联系在一起&#xff0c;Martech将技术溶于全营销流程中&#xff0…

基于Java实验室预约管理系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

《操作系统导论》第14章读书笔记:插叙:内存操作API

《操作系统导论》第14章读书笔记&#xff1a;插叙&#xff1a;内存操作API —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第14章读书笔记&#xff1a;插叙&#xff1a;内存操作API1.内存类型1.1.栈内存&#xff1a;它的申请和释放操作是编译器来隐式管理的&#xff0c;所…

FebHost:意大利.IT域名一张意大利网络名片

.IT域名是意大利的国家顶级域名&#xff0c;对于意大利企业和个人而言,拥有一个属于自己的”.IT”域名无疑是件令人自豪的事。这个被誉为意大利互联网标志性代表的域名,不仅隐含着浓厚的意大利文化特色,还为使用者在当地市场的推广铺平了道路。 对于那些希望在意大利市场建立强…

2核4G服务器可以承载多少用户?卡不卡?

腾讯云轻量应用服务器2核4G5M配置性能测评&#xff0c;腾讯云轻量2核4G5M带宽服务器支持多少人在线访问&#xff1f;并发数10&#xff0c;支持每天5000IP人数访问&#xff0c;腾讯云百科txybk.com整理2核4G服务器支持多少人同时在线&#xff1f;并发数测试、CPU性能、内存性能、…

手把手在K210上部署自己在线训练的YOLO模型

小白花了两天时间学习了一下K210&#xff0c;将在线训练的模型部署在K210&#xff08;代码后面给出&#xff09;上&#xff0c;能够识别卡皮巴拉水杯&#xff08;没错&#xff0c;卡皮巴拉&#xff0c;情绪稳定&#xff0c;真的可爱&#xff01;&#xff09;。数据集是用K210拍…

C语言例1-11:语句 while(!a); 中的表达式 !a 可以替换为

A. a!1 B. a!0 C. a0 D. a1 答案&#xff1a;C while()成真才执行&#xff0c;所以!a1 &#xff0c;也就是 a0 原代码如下&#xff1a; #include<stdio.h> int main(void) {int a0;while(!a){a;printf("a\n");} return 0; } 结果如…

数字化转型导师坚鹏:新质生产力发展解读、方法与案例

新质生产力发展解读、方法与案例 课程背景&#xff1a; 很多学员存在以下问题&#xff1a; 不知道如何理解新质生产力&#xff1f; 不清楚如何发展新质生产力&#xff1f; 不知道新质生产力发展案例&#xff1f; 课程特色&#xff1a; 有实战案例 有原创观点 有…

Linux课程____selinux模式

一、是什么 它叫做“安全增强型 Linux&#xff08;Security-Enhanced Linux&#xff09;”&#xff0c;简称 SELinux&#xff0c;它是 Linux 的一个安全子系统 二、有啥用 就是最大限度地减小系统中服务进程可访问的资源&#xff08;根据的是最小权限原则&#xff09;。避免…

leetcode:392. 判断子序列

题目&#xff1a; class Solution { public:bool isSubsequence(string s, string t) {} }; 题解&#xff1a; 很巧妙的题解&#xff1a;循环遍历两个字符串&#xff0c;两个字符串都没遍完就继续遍历&#xff0c;字符串s先遍历完结果为true&#xff0c;字符串t先遍历完结果为…