第十一届蓝桥杯单片机国赛
什么?4T模拟赛和省赛做起来轻轻松松?不妨来挑战一下第十一届国赛,这一届的国赛居然没考超声波、串口通信!只要你正确地理解了题目的意思,规避出题人挖的坑,拿个国一轻轻松松。
附件:第十一届蓝桥杯单片机国赛
一、题目分析以及底层代码搭建
1.内存空间不足
看完一遍题目,感觉挺正常的,不知道哪里有坑,其实,在开头的硬件框图中,出题人已经告诉了你本题最大的坑就是存储空间不够。在备赛专栏前篇中有提到,如果你定义变量的时候没有加上存储区修饰符时,该变量的存储区修饰符默认是xdate
型的,xdata
变量存储在单片机的外部RAM中,访问速度最慢,并且默认值通常不为0。
所以如果你没有指定存储区修饰符,会导致以下结果:
- 对于需要频繁使用的变量(比如定时器、Led、Seg相关变量),访问速度一旦慢就会导致时序不精确、程序性能下降,一个程序使用很多需要频繁访问的变量时会导致程序运行到某一部分时程序崩溃,你如果做过跟串口通信有关的题目就对此深有体会了吧,串口数据缓存区会时不时的恶心你一下。
- 编译时提示错误,如
code size exceeds available memory
,烧录时失败,提示存储空间不足。
解决方法:
- 减少
xdate
的使用,多使用pdate
和idate
- 对于程序中不会更改的常量前缀加上
code
- 减少
float
型变量的使用
2.隐藏条件
其他要求的第四点指出:参数在参数设置时不生效,所以进行参数设置的时候,要再定义一个新的变量存放参数原来的值进行更改数值。
3.初始化底层代码
Init.h
#ifndef __Init_H__
#define __Init_H__void SystemInit();#endif
Init.c
#include <STC15F2K60S2.H>void SystemInit()
{P0 = 0xff;P2 = P2 & 0x1f | 0x80;P2 &= 0x1f;P0 = 0x00;P2 = P2 & 0x1f | 0xa0;P2 &= 0x1f;
}
4.Led底层代码
Led.h
#ifndef __Led_H__
#define __Led_H__void LedDisp(unsigned char *ucLed);#endif
Led.c
#include <STC15F2K60S2.H>void LedDisp(unsigned char *ucLed)
{unsigned char i, temp = 0x00;static unsigned char temp_old = 0xff;for(i = 0; i < 8; i++)temp |= (ucLed[i] << i);if(temp_old != temp){P0 = ~temp;P2 = P2 & 0x1f | 0x80;P2 &= 0x1f;temp_old = temp;}
}
5.Key底层代码
Key.h
#ifndef __Key_H__
#define __Key_H__unsigned char KeyDisp();#endif
Key.c
#include <STC15F2K60S2.H>unsigned char KeyDisp()
{unsigned char temp = 0;P44 = 0;P42 = 1;P35 = 1;P34 = 1;if(P32 == 0) temp = 5;if(P33 == 0) temp = 4;P44 = 1;P42 = 0;P35 = 1;P34 = 1;if(P32 == 0) temp = 9;if(P33 == 0) temp = 8;return temp;
}
6.Seg底层代码
Seg.h
#ifndef __Seg_H__
#define __Seg_H__void SegDisp(unsigned char wela, unsigned char dula, unsigned char point);#endif
Seg.c
#include <STC15F2K60S2.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
0xff, //空
0xbf, //-
0x8e, //F
0x89, //H
0x9a //S
};void SegDisp(unsigned char wela, unsigned char dula, unsigned char point)
{P0 = 0xff;P2 = P2 & 0x1f | 0xe0;P2 &= 0x1f;P0 = (0x01 << wela);P2 = P2 & 0x1f | 0xc0;P2 &= 0x1f;P0 = Seg_Table[dula];if(point)P0 &= 0x7f;P2 = P2 & 0x1f | 0xe0;P2 &= 0x1f;
}
7.ds1302底层代码
ds1302.h
#ifndef __ds1302_H__
#define __ds1302_H__void SetRtc(unsigned char *Rtc);
void GetRtc(unsigned char *Rtc);#endif
ds1302.c
#include <STC15F2K60S2.H>
#include <intrins.h>sbit SCK = P1^7;
sbit RST = P1^3;
sbit SDA = P2^3;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);
}code unsigned char DS1302_Arr[4] = {0x84,0x82,0x80,0x8E};void SetRtc(unsigned char *Rtc)
{unsigned char i;Write_Ds1302_Byte(DS1302_Arr[3],0x00);for(i = 0; i < 3; i++)Write_Ds1302_Byte(DS1302_Arr[i],Rtc[i]);Write_Ds1302_Byte(DS1302_Arr[3],0x80);
}void GetRtc(unsigned char *Rtc)
{unsigned char i;for(i = 0; i < 3; i++)Rtc[i] = Read_Ds1302_Byte(DS1302_Arr[i]+1);
}
8.ds18b20底层代码
ds18b20.h
#ifndef __ds18b20_H__
#define __ds18b20_H__float TemRead();#endif
ds18b20.c
#include <STC15F2K60S2.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;
}float TemRead()
{idata unsigned char TL, TH;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);TL = Read_DS18B20();TH = Read_DS18B20();return ((TH << 8) | TL) / 16.0;
}
9.iic底层代码
iic.h
#ifndef __iic_H__
#define __iic_H__unsigned char AverageFilter();#endif
iic.c
#include <STC15F2K60S2.H>
#include <intrins.h>#define DELAY_TIME 5sbit scl = P2^0;
sbit sda = P2^1;static void I2C_Delay(unsigned char n)
{do{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); }while(n--);
}void I2CStart(void)
{sda = 1;scl = 1;I2C_Delay(DELAY_TIME);sda = 0;I2C_Delay(DELAY_TIME);scl = 0;
}//
void I2CStop(void)
{sda = 0;scl = 1;I2C_Delay(DELAY_TIME);sda = 1;I2C_Delay(DELAY_TIME);
}//
void I2CSendByte(unsigned char byt)
{unsigned char i;for(i=0; i<8; i++){scl = 0;I2C_Delay(DELAY_TIME);if(byt & 0x80){sda = 1;}else{sda = 0;}I2C_Delay(DELAY_TIME);scl = 1;byt <<= 1;I2C_Delay(DELAY_TIME);}scl = 0;
}//
unsigned char I2CReceiveByte(void)
{unsigned char da;unsigned char i;for(i=0;i<8;i++){ scl = 1;I2C_Delay(DELAY_TIME);da <<= 1;if(sda) da |= 0x01;scl = 0;I2C_Delay(DELAY_TIME);}return da;
}//
unsigned char I2CWaitAck(void)
{unsigned char ackbit;scl = 1;I2C_Delay(DELAY_TIME);ackbit = sda; scl = 0;I2C_Delay(DELAY_TIME);return ackbit;
}//
void I2CSendAck(unsigned char ackbit)
{scl = 0;sda = ackbit; I2C_Delay(DELAY_TIME);scl = 1;I2C_Delay(DELAY_TIME);scl = 0; sda = 1;I2C_Delay(DELAY_TIME);
}unsigned char Ad()
{unsigned char temp;I2CStart();I2CSendByte(0x90);I2CWaitAck();I2CSendByte(0x01);I2CWaitAck();I2CStart();I2CSendByte(0x91);I2CWaitAck();temp = I2CReceiveByte();I2CSendAck(1);I2CStop();return temp;
}unsigned char AverageFilter()
{unsigned char i;unsigned int sum = 0;for (i = 0; i < 10; i++) {sum += Ad();// 多次采样}return (unsigned char)(sum / 10);
}
10.main.c
使用下面这个模板做省赛题是可以的,做国赛题就有点难受了,但是指定了存储区修饰符还是可以做的,如果你学过计算机操作系统或者嵌入式操作系统,可以试着用调度器来更改以下代码。
#include <STC15F2K60S2.H>
#include "Init.h"
#include "LED.h"
#include "Key.h"
#include "Seg.h"
#include "ds1302.h"
#include "ds18b20.h"
#include "iic.h"/* 变量声明区 */
unsigned char Key_Slow; //按键减速变量 10ms
unsigned char Key_Val, Key_Down, Key_Up, Key_Old; //按键检测四件套
unsigned int Seg_Slow; //数码管减速变量 500ms
unsigned char Seg_Buf[] = {10,10,10,10,10,10,10,10,10,10};//数码管缓存数组
unsigned char Seg_Pos;//数码管缓存数组专用索引
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};//数码管小数点使能数组
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//LED显示数据存放数组
unsigned int Time_1s, f;/* 按键处理函数 */
void Key_Proc()
{if(Key_Slow) return;Key_Slow = 1; //按键减速Key_Val = Key();Key_Down = Key_Val & ~Key_Old; Key_Up = ~Key_Val & Key_Old;Key_Old = Key_Val;}/* 信息处理函数 */
void Seg_Proc()
{if(Seg_Slow) return;Seg_Slow = 1; //数码管减速}/* 其他显示函数 */
void Led_Proc()
{}/* 定时器0只用于计数 */
void Timer0_Init(void) //1毫秒@12.000MHz
{TMOD &= 0xF0; //设置定时器模式TMOD |= 0x05;TL0 = 0; //设置定时初始值TH0 = 0; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时
}/* 定时器1用于计时 */
void Timer1_Init(void) //1毫秒@12.000MHz
{AUXR &= 0xBF; //定时器时钟12T模式TMOD &= 0x0F; //设置定时器模式TL1 = 0x18; //设置定时初始值TH1 = 0xFC; //设置定时初始值TF1 = 0; //清除TF1标志TR1 = 1; //定时器1开始计时ET1 = 1;EA = 1;
}/* 定时器1中断服务函数 */
void Timer1_Server() interrupt 3
{if(++Key_Slow == 10) Key_Slow = 0; //按键延迟if(++Seg_Slow == 100) Seg_Slow = 0; //数码管延迟if(++Seg_Pos == 8) Seg_Pos = 0; //数码管显示Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);LED_Disp(Seg_Pos,ucLed[Seg_Pos]);/* NE555 */if(++Time_1s == 1000){Time_1s = 0;f = (TH0 << 8) | TL0;TH0 = TL0 = 0;}
}void main()
{Init();Timer0_Init();Timer1_Init();while(1){Key_Proc(); Seg_Proc();Led_Proc();}
}
二、数码管模块
1.代码框架构建
可以定义bit MainMode
来控制主页面(0-数据页面 1-参数页面),在数据页面中使用unsigned char SegMode
来控制显示页面(0-时间显示 1-温度显示 2-亮暗状态),在参数页面中使用unsigned char SetMode
来控制显示页面(0-时间参数 1-温度参数 2-指示灯参数)。
可以得到以下伪代码:
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long int u32;/* 界面参数 */
idata bit MainMode; //主界面 0-数据界面 1-参数界面
idata u8 SegMode; //数据界面分界面 0-时间 1-温度 2-亮暗状态
idata u8 SetMode; //参数界面分界面 0-时间参数 1-温度参数 2-指示灯参数void SegProc()
{if(!MainMode)//数据界面{switch(SegMode){case 0://时间显示页面//...break;case 1://温度显示页面//...break;case 2://亮暗状态显示页面//...break;}}else//参数界面{switch(SetMode){case 0://时间参数//...break;case 1://温度参数//...break;case 2://指示灯参数//...break;}}
}void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;switch(KeyDown){case 4:MainMode = !MainMode;break;case 5:if(!MainMode)//数据界面{SegMode++;if(SegMode == 3)SegMode = 0;}else//参数界面{SetMode++;if(SetMode == 3)SetMode = 0;}break;}
}
2.数据页面
时间显示页面和温度显示页面都很容易实现,这边不使用float
型变量去接收实时温度读取函数的返回值,而是使用unsigned int
类型变量去接收实时温度读取函数的返回值放大10倍的值。
也可以在数码管函数内直接处理温度读取和时钟读取,但是可能数码管函数返回时有任务没做完,最好是分成多个处理函数分别处理对应的任务。
/* 温度 */
idata u16 Tem_10x; //温度读取放大10倍
/* 时间 */
pdata u8 Rtc[3] = {0x16,0x59,0x50};void DS18B20Proc()
{Tem_10x = TemRead() * 10;
}void DS1302Proc()
{GetRtc(Rtc);
}void SegProc()
{unsigned char i;if(!MainMode)//数据界面{switch(SegMode){case 0:SegPoint[2] = 0;SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){SegBuf[3*i] = Rtc[i] / 16;SegBuf[3*i+1] = Rtc[i] % 16;}break;case 1:SegBuf[0] = 12;SegBuf[1] = SegBuf[2] = SegBuf[3] = SegBuf[4] = 10;SegBuf[5] = Tem_10x / 100;SegBuf[6] = Tem_10x / 10 % 10;SegBuf[7] = Tem_10x % 10;SegPoint[6] = 1;break;}}
} void main()
{SystemInit();Timer0_Init();SetRtc(Rtc);//上电时设置当前时间while(1){//...}
}
判断电压低于多少时为遮光状态,这个数值是需要你根据板子上的情况进行判断的,先假设一个数值为遮光临界值,然后用夹逼法慢慢求出最接近遮光状态的数值,一般来说,电压低于1V为遮光状态。
同样的,为了避免使用float
型变量,下面也是使用unsigned int
型变量接受光敏电阻的电压放大100倍后的电压值。
/* AD */
idata u16 RD1_100x; //光敏电阻电压放大100倍
idata bit DarkFlag; //环境为暗检测标志位 0-亮 1-暗void ADProc()
{RD1_100x = AverageFilter() / 51.0 * 100;DarkFlag = (RD1_100x < 100) ? 1 : 0;
}void SegProc()
{unsigned char i;if(!MainMode)//数据界面{switch(SegMode){case 0://...break;case 1://...break;case 2:SegBuf[0] = 13;SegBuf[1] = 10;SegBuf[2] = RD1_100x / 100;SegBuf[3] = RD1_100x / 10 % 10;SegBuf[4] = RD1_100x % 10;SegBuf[5] = 10;SegBuf[6] = 10;SegBuf[7] = DarkFlag;SegPoint[2] = 1;SegPoint[6] = 0;break;}}
}
3.参数页面
参数界面的实现是很容易的,这边注意的是参数在退出时才生效,所以每个参数都要再定义一个新的参数接收原始值。
/* 温度 */
idata u16 Tem_10x; //温度读取放大10倍
idata u8 TemSet = 25; //温度参数,默认值25,范围00~99
idata u8 TemSetDis = 25; //温度参数在修改过程中的值
/* 时间 */
pdata u8 Rtc[3] = {0x16,0x59,0x50};
idata u8 HourSet = 17; //小时参数,默认值17,范围00~23
idata u8 HourSetDis = 17; //小时参数在修改过程中的值
/* LED */
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long int u32;/* 界面参数 */
idata bit MainMode; //主界面 0-数据界面 1-参数界面
idata u8 SegMode; //数据界面分界面 0-时间 1-温度 2-亮暗状态
idata u8 SetMode; //参数界面分界面 0-时间参数 1-温度参数 2-指示灯参数
/* AD */
idata u16 RD1_100x; //光敏电阻电压放大100倍
idata bit DarkFlag; //环境为暗检测标志位 0-亮 1-暗
/* 温度 */
idata u16 Tem_10x; //温度读取放大10倍
idata u8 TemSet = 25; //温度参数,默认值25,范围00~99
idata u8 TemSetDis = 25; //温度参数在修改过程中的值
/* 时间 */
pdata u8 Rtc[3] = {0x16,0x59,0x50};
idata u8 HourSet = 17; //小时参数,默认值17,范围00~23
idata u8 HourSetDis = 17; //小时参数在修改过程中的值
/* LED */
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
/* 数码管 */
idata u8 SegPos;
pdata u8 SegBuf[8] = {10,10,10,10,10,10,10,10};
pdata u8 SegPoint[8] = {0,0,0,0,0,0,0,0};void DS18B20Proc()
{Tem_10x = TemRead() * 10;
}void DS1302Proc()
{GetRtc(Rtc);
}void ADProc()
{RD1_100x = AverageFilter() / 51.0 * 100;DarkFlag = (RD1_100x < 100) ? 1 : 0;
}void SegProc()
{unsigned char i;if(!MainMode)//数据界面{//...}else//参数界面{switch(SetMode){case 0:SegPoint[2] = SegPoint[6] = 0;SegBuf[0] = 13;SegBuf[1] = 4;SegBuf[2] = 10;SegBuf[3] = 10;SegBuf[4] = 10;SegBuf[5] = 10;SegBuf[6] = (HourSetDis / 10) ? HourSetDis / 10 : 10;SegBuf[7] = HourSetDis % 10;break;case 1:SegBuf[0] = 13;SegBuf[1] = 5;SegBuf[6] = (TemSetDis / 10) ? TemSetDis / 10 : 10;SegBuf[7] = TemSetDis % 10;break;case 2:SegBuf[0] = 13;SegBuf[1] = 6;SegBuf[6] = 10;SegBuf[7] = LedSetDis;break;}}
}
4.数码管完整代码
void SegProc()
{unsigned char i;if(!MainMode)//数据界面{switch(SegMode){case 0:SegPoint[2] = 0;SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){SegBuf[3*i] = Rtc[i] / 16;SegBuf[3*i+1] = Rtc[i] % 16;}break;case 1:SegBuf[0] = 12;SegBuf[1] = SegBuf[2] = SegBuf[3] = SegBuf[4] = 10;SegBuf[5] = Tem_10x / 100;SegBuf[6] = Tem_10x / 10 % 10;SegBuf[7] = Tem_10x % 10;SegPoint[6] = 1;break;case 2:SegBuf[0] = 13;SegBuf[1] = 10;SegBuf[2] = RD1_100x / 100;SegBuf[3] = RD1_100x / 10 % 10;SegBuf[4] = RD1_100x % 10;SegBuf[5] = 10;SegBuf[6] = 10;SegBuf[7] = DarkFlag;SegPoint[2] = 1;SegPoint[6] = 0;break;}}else//参数界面{switch(SetMode){case 0:SegPoint[2] = SegPoint[6] = 0;SegBuf[0] = 13;SegBuf[1] = 4;SegBuf[2] = 10;SegBuf[3] = 10;SegBuf[4] = 10;SegBuf[5] = 10;SegBuf[6] = (HourSetDis / 10) ? HourSetDis / 10 : 10;SegBuf[7] = HourSetDis % 10;break;case 1:SegBuf[0] = 13;SegBuf[1] = 5;SegBuf[6] = (TemSetDis / 10) ? TemSetDis / 10 : 10;SegBuf[7] = TemSetDis % 10;break;case 2:SegBuf[0] = 13;SegBuf[1] = 6;SegBuf[6] = 10;SegBuf[7] = LedSetDis;break;}}
}
三、按键模块
S4和S5已经在数码管模块中说过了,这边需要注意的是切换主页面进入的是对应主页面的第一个页面。
S8和S9的实现也是很简单的,只需要注意每一个参数的初始值和边界值就可以了。
/* LED */
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
/* 温度 */
idata u16 Tem_10x; //温度读取放大10倍
idata u8 TemSet = 25; //温度参数,默认值25,范围00~99
idata u8 TemSetDis = 25; //温度参数在修改过程中的值
/* 时间 */
pdata u8 Rtc[3] = {0x16,0x59,0x50};
idata u8 HourSet = 17; //小时参数,默认值17,范围00~23
idata u8 HourSetDis = 17; //小时参数在修改过程中的值
/* 按键 */
idata u8 KeyVal,KeyDown,KeyUp,KeyOld;void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;switch(KeyDown){case 4:if(!MainMode){TemSetDis = TemSet;HourSetDis = HourSet;LedSetDis = LedSet;MainMode = 1;SetMode = 0;}else{TemSet = TemSetDis;HourSet = HourSetDis;LedSet = LedSetDis;MainMode = 0;SegMode = 0;}break;case 5:if(!MainMode)//数据界面{SegMode++;if(SegMode == 3)SegMode = 0;}else//参数界面{SetMode++;if(SetMode == 3)SetMode = 0;}break;case 8://减按键if(MainMode){if(SetMode == 0){if(--HourSetDis == 255)HourSetDis = 0;}else if(SetMode == 1){if(--TemSetDis == 255)TemSetDis = 0;}else{if(--LedSetDis == 3)LedSetDis = 4;}}break;case 9://加按键if(MainMode){if(SetMode == 0){if(++HourSetDis == 24)HourSetDis = 23;}else if(SetMode == 1){if(++TemSetDis == 100)TemSetDis = 99;}else{if(++LedSetDis == 9)LedSetDis = 8;}}break;}
}
四、Led模块
/* LED */
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
idata bit L1Light; //指示灯L1点亮标志位 0灭 1亮
idata bit L2Light; //指示灯L2点亮标志位 0灭 1亮
idata bit L3Light; //指示灯L3点亮标志位 0灭 1亮
idata u16 Time_3s; //暗环境计时变量
idata u16 Time_3000ms; //亮环境计时变量
- L1使能判断:若判断当前时间处于小时参数整点至下一个 8 时之间,指示灯 L1 点亮,反之熄灭。
下一个8时,简单理解就是24+8=32时,所以只需要判断当前时间是否在小时参数和32区间即可,注意的是,当前时间是以十六进制存储的,所以比较时要转换成十进制再比较。
void DS1302Proc()
{unsigned char Hour;GetRtc(Rtc);Hour = (Rtc[0] / 16) * 10 + Rtc[0] % 16;L1Light = (HourSet <= Hour && Hour < 32);
}
void LedProc()
{ucLed[0] = L1Light;
}
- L2使能判断:若判断当采集到的温度数据小于温度参数,指示灯 L2 点亮,反之熄灭。
void DS18B20Proc()
{Tem_10x = TemRead() * 10;L2Light = (Tem_10x < TemSet * 10);
}void LedProc()
{ucLed[1] = L2Light;
}
- L3使能判断:若判断环境处于“暗”状态,且持续时间超过 3 秒,指示灯 L3 点亮;环境处于“亮”状态,且持续时间超过 3 秒,指示灯 L3 熄灭
L3使能是有很多种方法的,当处于黑暗环境下时,对应的计时变量开始计时,超过3秒时让L3点亮,处于明亮环境下也一样。
什么时候清除计时变量呢?可以在黑暗环境下清除明亮环境的计时变量,在明亮环境清除黑暗环境下的计时变量。
/* LED */
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
idata bit L1Light; //指示灯L1点亮标志位 0灭 1亮
idata bit L2Light; //指示灯L2点亮标志位 0灭 1亮
idata bit L3Light; //指示灯L3点亮标志位 0灭 1亮
idata u16 Time_3s; //暗环境计时变量
idata u16 Time_3000ms; //亮环境计时变量
void ADProc()
{RD1_100x = AverageFilter() / 51.0 * 100;DarkFlag = (RD1_100x < 100) ? 1 : 0;DarkFlag ? (Time_3000ms = 0) : (Time_3s = 0);
}void LedProc()
{ucLed[2] = L3Light;
}void Timer0_Isr(void) interrupt 1
{if(++SegPos == 8)SegPos = 0;SegDisp(SegPos,SegBuf[SegPos],SegPoint[SegPos]);if(DarkFlag)//黑暗环境{if(++Time_3s >= 3001){Time_3s = 3001;L3Light = 1;}}else//光明环境{if(++Time_3000ms >= 3001){Time_3000ms = 3001;L3Light = 0;}}
}
- L4~L8使能判断:若判断环境处于“暗”状态,通过 LED 指示灯参数指定的 LED 指示灯点亮,反之熄灭, L4-L8 中未被指定的 LED 指示灯应处于熄灭状态。
由于点亮/熄灭指示灯是可以自定义的,所以需要加上互斥点亮(如果你只写ucLed[LedSet-1]=DarkFlag
,不能实现这种情况:在黑暗环境下,第四个灯亮,然后进入参数页面改成第五个灯亮,这样子第四个、第五个灯都会亮。)
/* LED */
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
idata bit L1Light; //指示灯L1点亮标志位 0灭 1亮
idata bit L2Light; //指示灯L2点亮标志位 0灭 1亮
idata bit L3Light; //指示灯L3点亮标志位 0灭 1亮
idata u16 Time_3s; //暗环境计时变量
idata u16 Time_3000ms; //亮环境计时变量
void LedProc()
{if(DarkFlag){for(i = 3; i < 8; i++)ucLed[i] = (i == LedSet-1);}elsefor(i = 3; i < 8; i++)ucLed[i] = 0;
}
五、代码整合
#include <STC15F2K60S2.H>
#include "Init.h"
#include "Seg.h"
#include "Key.h"
#include "Led.h"
#include "iic.h"
#include "ds1302.h"
#include "ds18b20.h"typedef unsigned char u8;
typedef unsigned int u16;/* 界面参数 */
idata bit MainMode; //主界面 0-数据界面 1-参数界面
idata u8 SegMode; //数据界面分界面 0-时间 1-温度 2-亮暗状态
idata u8 SetMode; //参数界面分界面 0-时间参数 1-温度参数 2-指示灯参数
/* AD */
idata u16 RD1_100x; //光敏电阻电压放大100倍
idata bit DarkFlag; //环境为暗检测标志位 0-亮 1-暗
/* 温度 */
idata u16 Tem_10x; //温度读取放大10倍
idata u8 TemSet = 25; //温度参数,默认值25,范围00~99
idata u8 TemSetDis = 25; //温度参数在修改过程中的值
/* 时间 */
pdata u8 Rtc[3] = {0x16,0x59,0x50};
idata u8 HourSet = 17; //小时参数,默认值17,范围00~23
idata u8 HourSetDis = 17; //小时参数在修改过程中的值
/* 按键 */
idata u8 KeyVal,KeyDown,KeyUp,KeyOld;
/* LED */
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};
idata u8 LedSet = 4; //指示灯参数,默认值4,范围4~8
idata u8 LedSetDis = 4; //指示灯参数修改过程中的值
idata bit L1Light; //指示灯L1点亮标志位 0灭 1亮
idata bit L2Light; //指示灯L2点亮标志位 0灭 1亮
idata bit L3Light; //指示灯L3点亮标志位 0灭 1亮
idata u16 Time_3s; //暗环境计时变量
idata u16 Time_3000ms; //亮环境计时变量
/* 数码管 */
idata u8 SegPos;
pdata u8 SegBuf[8] = {10,10,10,10,10,10,10,10};
pdata u8 SegPoint[8] = {0,0,0,0,0,0,0,0};void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyDown = ~KeyVal & KeyOld;KeyOld = KeyVal;switch(KeyDown){case 4:if(!MainMode){TemSetDis = TemSet;HourSetDis = HourSet;LedSetDis = LedSet;MainMode = 1;SetMode = 0;}else{TemSet = TemSetDis;HourSet = HourSetDis;LedSet = LedSetDis;MainMode = 0;SegMode = 0;}break;case 5:if(!MainMode)//数据界面{SegMode++;if(SegMode == 3)SegMode = 0;}else//参数界面{SetMode++;if(SetMode == 3)SetMode = 0;}break;case 8://减按键if(MainMode){if(SetMode == 0){if(--HourSetDis == 255)HourSetDis = 0;}else if(SetMode == 1){if(--TemSetDis == 255)TemSetDis = 0;}else{if(--LedSetDis == 3)LedSetDis = 4;}}break;case 9://加按键if(MainMode){if(SetMode == 0){if(++HourSetDis == 24)HourSetDis = 23;}else if(SetMode == 1){if(++TemSetDis == 100)TemSetDis = 99;}else{if(++LedSetDis == 9)LedSetDis = 8;}}break;}
}void SegProc()
{unsigned char i;if(!MainMode)//数据界面{switch(SegMode){case 0:SegPoint[2] = 0;SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){SegBuf[3*i] = Rtc[i] / 16;SegBuf[3*i+1] = Rtc[i] % 16;}break;case 1:SegBuf[0] = 12;SegBuf[1] = SegBuf[2] = SegBuf[3] = SegBuf[4] = 10;SegBuf[5] = Tem_10x / 100;SegBuf[6] = Tem_10x / 10 % 10;SegBuf[7] = Tem_10x % 10;SegPoint[6] = 1;break;case 2:SegBuf[0] = 13;SegBuf[1] = 10;SegBuf[2] = RD1_100x / 100;SegBuf[3] = RD1_100x / 10 % 10;SegBuf[4] = RD1_100x % 10;SegBuf[5] = 10;SegBuf[6] = 10;SegBuf[7] = DarkFlag;SegPoint[2] = 1;SegPoint[6] = 0;break;}}else//参数界面{switch(SetMode){case 0:SegPoint[2] = SegPoint[6] = 0;SegBuf[0] = 13;SegBuf[1] = 4;SegBuf[2] = 10;SegBuf[3] = 10;SegBuf[4] = 10;SegBuf[5] = 10;SegBuf[6] = (HourSetDis / 10) ? HourSetDis / 10 : 10;SegBuf[7] = HourSetDis % 10;break;case 1:SegBuf[0] = 13;SegBuf[1] = 5;SegBuf[6] = (TemSetDis / 10) ? TemSetDis / 10 : 10;SegBuf[7] = TemSetDis % 10;break;case 2:SegBuf[0] = 13;SegBuf[1] = 6;SegBuf[6] = 10;SegBuf[7] = LedSetDis;break;}}
}void LedProc()
{unsigned char i;ucLed[0] = L1Light;ucLed[1] = L2Light;ucLed[2] = L3Light;if(DarkFlag){for(i = 3; i < 8; i++)ucLed[i] = (i == LedSet-1);}elsefor(i = 3; i < 8; i++)ucLed[i] = 0;LedDisp(ucLed);
}void DS18B20Proc()
{Tem_10x = TemRead() * 10;L2Light = (Tem_10x < TemSet * 10);
}void DS1302Proc()
{unsigned char Hour;GetRtc(Rtc);Hour = (Rtc[0] / 16) * 10 + Rtc[0] % 16;L1Light = (HourSet <= Hour && Hour < 32);
}void ADProc()
{RD1_100x = AverageFilter() / 51.0 * 100;DarkFlag = (RD1_100x < 100) ? 1 : 0;DarkFlag ? (Time_3000ms = 0) : (Time_3s = 0);
}void Timer0_Init(void) //1毫秒@12.000MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF0; //设置定时器模式TL0 = 0x18; //设置定时初始值TH0 = 0xFC; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时ET0 = 1; //使能定时器0中断EA = 1;
}void Timer0_Isr(void) interrupt 1
{if(++SegPos == 8)SegPos = 0;SegDisp(SegPos,SegBuf[SegPos],SegPoint[SegPos]);if(DarkFlag){if(++Time_3s >= 3001){Time_3s = 3001;L3Light = 1;}}else{if(++Time_3000ms >= 3001){Time_3000ms = 3001;L3Light = 0;}}
}void main()
{SystemInit();Timer0_Init();SetRtc(Rtc);while(1){//}
}
如果程序有错误或者不理解的地方,请及时联系我。
相关文章:
第十一届蓝桥杯单片机国赛
什么?4T模拟赛和省赛做起来轻轻松松?不妨来挑战一下第十一届国赛,这一届的国赛居然没考超声波、串口通信!只要你正确地理解了题目的意思,规避出题人挖的坑,拿个国一轻轻松松。 附件:第十一届蓝桥…...
Ateme在云端构建可扩展视频流播平台
Akamai Connected Cloud帮助Ateme客户向全球观众分发最高质量视频内容。 “付费电视运营商和内容提供商现在可以在Akamai Connected Cloud上通过高质量视频吸引观众,并轻松扩展。”── Ateme首席战略官Rmi Beaudouin Ateme是全球领先的视频压缩和传输解决方案提…...
QT系列教程(20) Qt 项目视图便捷类
视频连接 https://www.bilibili.com/video/BV1XY41127t3/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 Qt项目视图便捷类 Qt项目视图提供了一些便捷类,包括QListWidget, QTableWidget, QTreeWidget等。我们分别介绍这几个便捷类。 我们先创建一个Qt …...
【最后203篇系列】014 AI机器人-1
说明 终于开张了,我觉得AI机器人是一件真正正确,具有商业价值的事。 把AI机器人当成一笔生意,我如何做好这笔生意?一端是业务价值,另一端是技术支撑。如何构造高质量的内容和服务,如何确保技术的广度和深度…...
cfi网络安全 网络安全hcip
目录 RIP (路由信息协议) 算法 开销 版本 开销值的计算方式 RIPV1和RIPV2的区别 RIP的数据包 Request(请求)包 Reponse(应答)包 RIP的特征 周期更新 RIP的计时器 1,周期更新计时器 2,失效计时器 3,垃圾回收计时器 RIP的核心思…...
HTML 基础
一、HTML 基本结构 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>页面标题</title> </head> <body><!-- 可见内容区域 --> </body> </html><!DOCTYPE html>:声明…...
数据结构与算法:归并排序
目录 归并排序的基本思想 归并排序的特性总结 代码 归并排序的非递归版 归并排序的基本思想 归并排序是建立在归并操作上的一种有效的排序算法。改算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列…...
Tweak Power:全方位电脑系统优化的高效工具
在日常使用电脑时,系统性能的下降、垃圾文件的堆积以及硬盘的老化等问题常常困扰着用户。为了提升电脑性能、优化系统运行,许多人会选择系统优化工具。然而,国内一些系统优化软件常常因为广告过多或功能冗杂而让人望而却步。此时,…...
stm32中分析UART中IDLE,RXNE,TC,TXE这些标志位的作用
下面将基于 STM32 标准库,结合之前提到的不同应用场景,给出使用 TXE、TC、IDLE 和 RXNE 标志位的代码示例及分析。 1. 连续数据发送(使用 TXE) 应用场景 向外部设备连续发送大量数据,如向显示屏发送显示数据、向传感…...
代码随想录算法训练营第十天,150.逆波兰表达式求值,239.滑动窗口最大值,347.前K个高频元素
今日内容:150.逆波兰表达式求值,239.滑动窗口最大值,347.前K个高频元素,栈与队列总结 心得:昨天休息了一天,栈与队列的题都比较典型,之前也是恶补过堆栈的知识,所以做起来相对kmp好一…...
【python】Flask web框架
文章目录 一、Flask 简介二、核心组件解析2.1 路由系统2. 模板引擎 (Jinja2)2.3 表单处理与请求上下文 三、现代开发实践3.1 应用工厂模式3.2 异步处理支持 四、安全最佳实践五、性能优化策略六、扩展生态精选七、部署方案对比 一、Flask 简介 Flask 是基于 Python 的微型 Web…...
Node.js:快速启动你的第一个Web服务器
Node.js 全面入门指南 文章目录 Node.js 全面入门指南一 安装Node.js1. Windows2. MacOS/Linux 二 配置开发环境1. VSCode集成 三 第一个Node.js程序1. 创建你的第一个Node.js程序 四 使用Express框架1. 快速搭建服务器 一 安装Node.js 1. Windows 以下是Windows环境下Node.j…...
3-003:在 MySQL 中建索引时需要注意哪些事项?
在 MySQL 中创建索引时,需要注意以下事项,以确保索引高效且合理: 1. 选择合适的索引类型 主键索引(PRIMARY KEY):每个表只能有一个,默认是聚簇索引。唯一索引(UNIQUE)&…...
基于WPF的雷达上位机系统开发实践
一、雷达上位机系统概述 1.1 系统功能需求 现代雷达上位机系统通常需要实现以下核心功能模块: 数据采集与解析 支持多种通信协议(TCP/IP、UDP、RS422等) 实时解析雷达原始数据(目标距离、方位、速度、RCS等) 典型数…...
版本号标识
Visual Studio 16 2019 是 Microsoft Visual Studio 2019 的版本号标识。具体来说: Visual Studio 是微软提供的一款集成开发环境(IDE),用于开发各种应用程序,如桌面软件、Web 应用、移动应用等,支持多种编…...
计算机考研C语言
C语言程序设计从入门到精通【2025完整版】考研复试 嵌入式 计算机二级 软考 专升本也适用_哔哩哔哩_bilibili 1、第一个C程序 helloC #include <stdio.h>int main(){printf("hehe");return 0;}每个C语言程序不管有多少行代码,都是从main函数开始执…...
STM32 内置的通讯协议
数据是以帧为单位发的 USART和UART的区别就是有没有同步功能 同步是两端设备有时钟连接,异步是没时钟连接,靠约定号的频率(波特率)接收发送数据 RTS和CTS是用来给外界发送已“可接收”或“可发送”信号的,一般用不到…...
QT:串口上位机
创建工程 布局UI界面 设置名称 设置数据 设置波特率 波特率默认9600 设置数据位 数据位默认8 设置停止位 设置校验位 调整串口设置、接收设置、发送设置为Group Box 修改配置 QT core gui serialport 代码详解 mianwindow.h 首先在mianwindow.h当中定义一个串口指…...
f QT测试
# 添加 Qt Test 模块,用于支持单元测试功能 QT testlib# 添加 Qt 的核心模块和 GUI 模块,这是构建 Qt 应用程序的基础模块 QT core gui# 如果 Qt 的主版本号大于 4,则添加 widgets 模块。 # 这是因为 Qt Widgets 模块是从 Qt 5 开始引…...
vue3在ts中动态添加DOM(1、使用render函数,2、使用tsx)
1、使用render函数和h函数 h函数创建虚拟节点(VNode),render函数实现虚拟节点生成真实DOM元素 实现添加一个el-button按钮 <script setup lang"ts"> import { ElButton } from "element-plus"; //需要在页面中引…...
C++基础(VScode环境安装)
MinGW Distro - nuwen.net 安装完成之后我们打开刚刚的安装路径,找到并打开MinGW -> bin,进入bin文件夹之后点一下这里,右键复制路径 之后我们进入设置,搜索“环境变量”,选择“编辑系统环境变量” 按WinR,输入cmd࿰…...
MySQL:SQL优化实际案例解析(持续更新)
文章目录 一、MySQL:SQL优化1、时间格式化问题(字符串)2、in/inner join的问题 一、MySQL:SQL优化 1、时间格式化问题(字符串) -- 优化前 SELECT * FROM test_table WHERE date_format( begin_time, %Y-%…...
代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus适用场景和工作方式
在 Swift 开发中,在 Swift 开发中,代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus 主要用于 组件之间的通信,但它们的适用场景和工作方式有…...
力扣第585题
with t as (select *, count(tiv_2015) over(partition by tiv_2015) cnt1 , count(*) over(partition by lat,lon) cnt2 from insurance) select round(sum(tiv_2016),2) tiv_2016 from t where cnt1>1 and cnt21; 以上代码的思路: ①明确查询需求:…...
C++学习——顺序表(四)
文章目录 前言一、最大连续1的个数二、差的绝对值为K的数对数目三、数组中两元素的最大乘积四、数组元素和与数字和的绝对值的差五、K个元素的最大和六、等差三元组的数目七、移除元素 前言 本文为《C学习》的第14篇文章,今天通过Leetcode的几道题来熟悉顺序表的大…...
java虚拟机(JVM)以及各种参数详解
Java 虚拟机(JVM)提供了许多参数来调整其行为和性能,以便更好地适应不同的应用场景。理解和使用这些参数对于优化 Java 应用程序的性能非常重要。以下是一些常用的 JVM 参数及其详细说明: 1. 内存管理参数 -Xms<size>&…...
Android电量与流量优化
Android电量与流量优化 一、电量优化基础 1.1 电量消耗原理 Android设备的电量消耗主要来源于以下几个方面: 屏幕显示:屏幕是耗电量最大的硬件之一,尤其是高亮度和高刷新率的屏幕。CPU处理:CPU执行计算任务时会消耗大量电量,尤其是高负载运算。网络通信:移动数据、Wi-…...
机器人运动学与动力学
在当今科技飞速发展的时代,机器人已逐渐渗透到我们生活的方方面面,从工业生产线上的高效作业,到医疗领域的精准辅助,再到家庭服务的贴心陪伴,机器人技术的广泛应用正深刻改变着我们的生活和工作方式。而在机器人技术的…...
【web前端开发】HTML排版标签、HTML语义化标签、常用的文本标签
1、HTML排版标签 标签名 标签含义 单/双标签 h1~h6 …...
Linux的TTY子系统(TTY框架)的重要结构体termios的`c_iflag`字段的BRKINT选项和IGNBRK选项的含义【详解串口的BREAK信号】
引言 要搞清楚结构体termios的c_iflag字段的BRKINT选项和IGNBRK选项的含义,首先要搞清楚BREAK信号的含义。其实当你搞清楚BREAK信号后,结构体termios的c_iflag字段的BRKINT选项和IGNBRK选项的含义你也就自然知道了。 1. 什么是 BREAK 信号?…...
YashanDB认证,YCA证书认证教程,免费证书,内含真题考试题库及答案——五分钟速成
目录 一.账号及平台注册登录流程 二.登录进行设备调试核验 三.考试(考完获取分数) 四.获取证书 五.题库及答案 一.账号及平台注册登录流程 1-点击这里进行账号注册(首次学习必须先注册,有账号之后可以直接在2号链接登录&#…...
网络爬虫-1:发送请求+维持会话+代理设置/超时设置
1.基于get发送请求 2.基于post发送请求 3.维持会话 4.代理设置/超时设置 一.基于get发送请求 1.获取网页源码1 使用json库中的json.loads(),将json格式的字符串变为Python的字典形式 以下通过http://httpbin.org/get网址进行基本练习操作 import requests import json urlh…...
VSCode 配置优化指南:打造极致高效的前端开发环境
VSCode 配置优化指南:打造极致高效的前端开发环境 一、基础环境配置:让开发更流畅 1. 性能优化设置 // settings.json {"files.autoSave": "afterDelay", // 自动保存(延迟1秒)"files.exclud…...
【实战-解决方案】Webpack 打包后很多js方法报错:not defined
问题分析 在不打包的情况下,方法(如 checkLoginStatus、filterSites、initProgressBar 等)可以正常运行,而经过 Webpack 打包后报 is not defined 错误,通常有以下几个可能的原因: 全局变量丢失 在 Webpac…...
第16届计算智能与软件工程国际研讨会(CISE 2026)
第16届计算智能与软件工程国际研讨会(CISE 2026) The 16th Intl Conference on Computational Intelligence and Software Engineering(CISE 2026) 时间:2026年1月9-11日 地点:中国 三亚 邮箱投稿:editor1academicx.org 检索࿱…...
laravel中 添加公共/通用 方法/函数
一,现在app 下面创建Common目录,然后在创建Common.php 文件 二,修改composer.json文件 添加这个到autoload 中 "files": ["app/Common/Common.php"]"autoload": {"psr-4": {"App\\": &quo…...
Android 自定义View之底部导航栏
文章目录 Android 自定义View之底部导航栏概述代码定义TabIndex定义Tab定义TabView定义NavigationBarFragmentSwitchHelper管理类使用 源码下载 Android 自定义View之底部导航栏 概述 封装一个通用的底部导航栏控件。 代码 定义TabIndex Retention(AnnotationRetention.SOU…...
[Kubernetes] 7控制平面组件
1. 调度 kube- scheduler what 负责分配调度pod到集群节点监听kube-apiserver,查询未分配node的pod根据调度策略分配这些pod(更新pod的nodename)需要考虑的因素: 公平调度,资源有效利用,QoS,affinity, an…...
定时器Tim输出比较(output compare)
输出比较OC(Output Compare) 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形 每个高级定时器和通用定时器都拥有4个输出比较通道,高级定时器的前3个通道额外拥有死区生…...
Linux Shell 脚本编程极简入门指南
一、学习前提准备 ✅ 环境要求: Linux系统(Ubuntu/CentOS等)或 WSL (Windows用户) 任意文本编辑器(推荐VSCode/Vim) 基础命令行操作能力 🔍 验证环境: # 查看系统默认Shell echo $SHELL #…...
C++:二分习题
1. 借教室 503. 借教室 - AcWing题库 在大学期间,经常需要租借教室。 大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。 教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。 面对海…...
【AIGC】计算机视觉-YOLO系列家族
YOLO系列家族 (1)YOLO发展史(2) YOLOX(3) YOLOv6(4) YOLOv7(5) YOLOv8(6) YOLOv9(7)YOLOv10(8&…...
浅谈SSE爬虫
什么是SSE SSE(Server-Sent Events,服务器推送事件)是一种用于在Web应用程序中实现单向实时数据传输的技术。它允许服务器通过HTTP连接向客户端(通常是浏览器)推送更新的数据,而无需客户端主动请求。 目前主流的大模型 就是采用的 SSE,想deepseek、chatgpt、通以千问。…...
Goland如何玩依赖注入——基于gone@v2创建一个service
经过多天的工作,终于把gone2的beta版本发布出去了。在v2版本中,做了很多更新,最大的改进是将一些不必要的概念给隐藏起来了,提供了Provider机制…… 文章目录 1. 安装**gonectr**2.创建项目2.1 项目结构 2.2 简单说明3. 启动项目…...
rpmlib(SetVersions) is needed by can-uilts-v2019.00.0-alt1.aarch64
在我在Linux中安装离线CAN工具时,出现了一个问题, rootwanghuo:~# rpm -ivh can-uilts-v2019.00.0-alt1.aarch64.rpm error: Failed dependencies:rpmlib(SetVersions) is needed by can-uilts-v2019.00.0-alt1.aarch64 意思是尝试安装 can-uilts-v20…...
处理Java中的异常
处理Java中的异常 在 Java 中,异常处理是通过 try-catch-finally 语句来实现的。Java 提供了一种强大的机制,用于捕捉和处理程序运行中的各种错误和异常。通过这种方式,你可以有效地捕捉到可能导致程序崩溃的错误,并做出相应的处…...
mac 苍穹外卖 前端环境配置
博主的 mac 是 m2。 结合以下两篇,成功配置前端环境。 macOS 配置苍穹外卖前端环境_macbook怎么nginx下载外卖-CSDN博客 苍穹外卖-Mac配置前端开发环境_sudo 启动 nginx 有什么区别-CSDN博客 一、安装nginx 我使用的是 homebrew,homebrew 的安装请自…...
前端系统测试(单元、集成、数据|性能|回归)
有关前端测试的面试题 系统测试 首先,功能测试部分。根据资料,单元测试是验证最小可测试单元的正确性,比如函数或组件。都提到了单元测试的重要性,强调其在开发早期发现问题,并通过自动化提高效率。需要整合我搜索到的资料中的观点,比如单元测试的方法(接口测试、路径覆…...
Python:函数式编程
函数式编程(Functional Programming, FP)是一种编程范式,强调通过纯函数、不可变数据和声明式风格来构建程序。Python 虽然不是纯函数式语言,但提供了丰富的函数式编程工具。(简单来说是,函数约等于模块功能࿰…...
Spring Boot中@Valid 与 @Validated 注解的详解
Spring Boot中Valid 与 Validated 注解的详解 引言 在Spring Boot应用中,参数校验是确保数据完整性和一致性的重要手段。Valid和Validated注解是Spring Boot中用于参数校验的两个核心注解。本文将详细介绍这两个注解的用法、区别以及代码样例。 Valid注解 功能介…...