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

目录

前言

单片机资源数据包_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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3+ts+elementplus写一个登录页面教程

文章目录 前言1. 安装 Vue CLI 和 TypeScript 支持2. 创建登录组件 文章重点内容 前言 前期准备步骤&#xff1a; 创建一个使用 Vue 3 和 TypeScript 的登录页面涉及到多个步骤。以下是一个基本的教程&#xff0c;帮助你从头开始构建这样一个页面&#xff1a; 1. 安装 Vue CL…

Ollama部署在线ai聊天

概述&#xff1a;虽然ollama在Windows方面还有很多bug&#xff0c;但不妨碍它在ai领域上面的成就 第一步&#xff1a;安装Ollama 官网&#xff1a;Download Ollama on Windows 下载安装即可。说明一下ollama的安装位置只能是c盘&#xff0c;好像改不了&#xff0c;但是数据模…

算法学习——LeetCode力扣动态规划篇8

算法学习——LeetCode力扣动态规划篇8 300. 最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删…

FA模型切换Stage模型之module的切换

从FA模型切换到Stage模型时&#xff0c;开发者需要将config.json文件module标签下的配置迁移到module.json5配置文件module标签下&#xff0c;具体差异见下列表格。 表1 FA模型module标签与Stage模型module标签差异对比 表2 FA模型metaData和Stage中metadata对比 表3 FA模型me…

【UI框架】——保姆式使用教程

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

深度学习500问——Chapter05: 卷积神经网络(CNN)(2)

文章目录 5.6 有哪些池化方法 5.7 1x1卷积作用 5.8 卷积层和池化层有什么区别 5.9 卷积核是否一定越大越好 5.10 每层卷积是否只能用一种尺寸的卷积核 5.11 怎样才能减少卷积层参数量 5.12 在进行卷积操作时&#xff0c;必须同时考虑通道和区域吗 5.13 采用宽卷积的好处有什么 …

多线程JUC 第2季 synchornized和Lock锁(重入,公平)

一 锁 1.1 锁的介绍 synchronized&#xff0c;和lock锁都是一种悲观锁。悲观锁适用于写多场景&#xff0c;乐观锁适用于读多场景&#xff0c;实现策略有&#xff1a;版本号和cas自旋算法。 1.2 类锁和对象锁的使用场景 1.3 任何对象都有一把锁 之所以任何一个对象都有把锁…

html第二次作业

骨架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, initi…

PyTorch深度学习快速入门(小土堆)

文章目录 16. 神经网络的基本骨架17.卷积操作18.卷积层 16. 神经网络的基本骨架 forward: import torch from torch import nnclass Tudui(nn.Module):def __init__(self):super().__init__()def forward(self,input):outputinput1return output#创建Tudui的实例对象 tuduiTu…

Django详细教程(二) - 部门用户管理案例

文章目录 前言一、新建项目二、新建app三、设计表结构四、新建数据库五、新建静态文件六、部门管理1.部门展示2.部门添加3.部门删除4.部门编辑 七、模板继承八、用户管理1.辨析三种方法方法一&#xff1a;原始方法方法二&#xff1a;Form组件(简便)方法三&#xff1a;ModelForm…

ARM-按键中断实验

代码 #include "stm32mp1xx_gic.h" #include "stm32mp1xx_exti.h" extern void printf(const char *fmt, ...); unsigned int i 0; void do_irq(void) {//获取要处理的中断的中断号unsigned int irqnoGICC->IAR&0x3ff;switch (irqno){case 99:pr…

前端工程师————HTML5学习

HTML5基础 开发工具很多&#xff0c;其中Hbulider较好用&#xff0c;下载网址如下&#xff1a; DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 html表示整个页面 head表示搜素框 body表示内容 ti…

【蓝桥杯】矩阵快速幂

一.快速幂概述 1.引例 1&#xff09;题目描述&#xff1a; 求A^B的最后三位数表示的整数&#xff0c;A^B表示&#xff1a;A的B次方。 2&#xff09;思路&#xff1a; 一般的思路是&#xff1a;求出A的B次幂&#xff0c;再取结果的最后三位数。但是由于计算机能够表示的数字…

Gromacs模拟一:配体-双链蛋白质复合物体系准备

1、蛋白质的准备&#xff1a; 在RCSB网站下载想要的蛋白晶体&#xff08;教程里是3htb&#xff09;&#xff0c;用notepad等编辑器或是分子可视化软件除去里面的非蛋白分子或离子。 这里采用的是一个经过分子对接后的蛋白质pdb和配体小分子的pdb。 教程里提到的配体是2-丙基…

java算法day39 | 动态规划part02 ● 62.不同路径 ● 63. 不同路径 II

62.不同路径 思路&#xff1a; 本题非常巧妙。 第一步&#xff1a;定义一个dp数组存储到达每个位置的路径数。 第二步&#xff1a;每个位置的路径数它左面位置的路径数上面位置的路径数。 第三步&#xff1a;不好想的是如何初始化数组。 既然只能向下或向右走&#xff0c;可推出…

网络七层模型之会话层:理解网络通信的架构(五)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

浅谈AI未来发展趋势与挑战

对于AI大模型未来发展趋势与挑战的个人看法&#xff1a; 1、未来的发展趋势&#xff1a; AI大模型未来发展趋势可以从以下几个关键方面来讨论&#xff1a; 1. 能源与计算效率 绿色计算与节能技术&#xff1a;随着硬件技术的发展&#xff0c;预计未来的AI大模型将进一步降低能…

python电商结合双轨制

最近又重新整合翻看以前的数据&#xff0c;图片&#xff0c;绘画&#xff0c;还有各种编程代码&#xff0c;python,leetcode,还有关于商业方面的一些见解,想起了大学时候和同学们并肩作战&#xff0c;熬夜编码的时光。还有大数据&#xff0c;八爪鱼爬虫。 下面是我的手稿电商打…

Arduino通过Wire库读取AS5600编码器数据

Arduino通过Wire库读取AS5600编码器数据 ✨在实际测试中&#xff0c;测试AS5600除了使用径向磁铁之外&#xff0c;球型的或者正四方体的强磁铁&#xff0c;也是可以准确的测量角度。测试高度的话&#xff0c;从板子&#xff08;芯片引脚底部&#xff09;到磁铁底部15毫米内&…

算法打卡day21(开始回溯)

今日任务&#xff1a; 1&#xff09;77.组合 77.组合 题目链接&#xff1a;77. 组合 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;带你学透回溯算法-组合问题&#xff08;对应力扣题目&#xff1a;77…