当前位置: 首页 > news >正文

第十六届蓝桥杯单片机组4T模拟赛二

难点:
PCF8591同时测量两条通道数据
避免重复触发
采集触发时的时间数据存放
未采集的数据显示
清空数据

如果你系统的学习过C语言和数据结构与算法,解决本题还是很轻松的。

附件:第十六届蓝桥杯单片机组4T模拟赛二

在这里插入图片描述

一、基础知识

  • PCF8591:如果你在读取通道 1 后立即读取通道 3,会导致以下问题:
    1.电压参数未稳定:PCF8591 在切换通道后,需要一定的时间来稳定电压参数。
    如果立即读取下一个通道,可能会导致读取的值不准确。
    2.通道切换延迟:PCF8591 的通道切换需要时间,具体取决于芯片的采样速率和硬件设计。如果没有足够的延迟,读取的值可能仍然是上一个通道的值。
    解决方法已经在另一篇文章给出了:PCF8591一次读取多条通道导致测量值不准确的原因及解决方法
  • 通过PCF8591采集的电压数据不稳定:可以使用以下方法:
    1.均值滤波:对多次采样结果取平均值
    2.中值滤波:对多次采样结果取中值
    3.滑动平均滤波:维护一个滑动窗口,计算窗口内数据的平均值
    4.卡尔曼滤波:适用于动态系统的高级滤波算法
    本篇文章使用的是均值滤波,其他几种在单片机中有点大炮打蚊子的感觉,在以后的嵌入式系列再作介绍。
  • string.h中的两个常用函数
    1.memset
    memset 用于将一段内存区域的内容设置为指定的值
    (1)函数原型:void* memset(void* ptr, int value, size_t num);
    (2)参数:
    ptr:指向要设置的内存区域的指针
    value:要设置的值(以 int 形式传递,但实际按unsigned char处理
    num:要设置的字节数
    (3)功能:
    ptr指向的内存区域的前num个字节设置为value
    2.memcpy
    memcpy 用于将一段内存区域的内容复制到另一段内存区域。
    (1)函数原型:void* memcpy(void* dest, const void* src, size_t num);
    (2)参数:
    dest:指向目标内存区域的指针
    src:指向源内存区域的指针
    num:要复制的字节数
    (3)功能:
    src指向的内存区域的前 num个字节复制到dest指向的内存区域

二、板子现象演示

1.时间界面

上电显示时间界面,从23时59分50秒开始计时,同时LED1点亮,其余指示灯熄灭。
在这里插入图片描述

2.数据界面

按下S4切换成数据页面,数码管显示RB2和RD1的值,指示灯L2点亮。
在这里插入图片描述

3.历史查询界面

按下S4切换历史查询界面,未触发数据采集时显示-,指示灯L3点亮,该页面按下S5切换历史查询子界面。
在这里插入图片描述

4.触发采集

任意界面光敏电阻电压<RB2电压时触发采集(持续处于该状态时不触发),由于手机拍照遮光触发三次。

触发采集时亮的灯是L8,下面这张图是错误的,后面的Led模块已经修改好了。
在这里插入图片描述

5.触发三次采集后的历史查询页面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.清空记录时间

在这里插入图片描述

三、数码管模块

1.添加P R C -的段码

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, //-
0x8c, //P
0xc1, //U
0x88, //A
0xc6, //C
};
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;
}

2.时间页面

在这里插入图片描述

  • 添加DS1302底层代码
#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 *ucRtc)
{
	unsigned char i;
	Write_Ds1302_Byte(DS1302_Arr[3],0x00);
	
	for(i = 0; i < 3; i++)
		Write_Ds1302_Byte(DS1302_Arr[i],ucRtc[i]);
	
	Write_Ds1302_Byte(DS1302_Arr[3],0x80);
}

void GetRtc(unsigned char *ucRtc)
{
	unsigned char i;
	
	for(i = 0; i < 3; i++)
		ucRtc[i] = Read_Ds1302_Byte(DS1302_Arr[i]+1);
}
  • main.c函数中的DS1302数据处理函数
pdata u8 ucRtc[3] = {0x23,0x59,0x50};

void DS1302Proc()
{
	GetRtc(ucRtc);
}

void main()
{
	SystemInit();
	Timer0_Init();
	SetRtc(ucRtc);//设定时间
	while(1)
	{
		DS1302Proc();
	}
}
  • 数码管显示
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long int u32;

idata u8 SegPos;//数码管扫描位
idata u8 SegMode;//数码管显示页面

pdata u8 SegBuf[8] = {10,10,10,10,10,10,10,10};//数码管数据缓存区
pdata u8 SegPoint[8] = {0,0,0,0,0,0,0,0};//数码管小数点使能位
pdata u8 ucRtc[3] = {0x23,0x59,0x50};//时钟

void SegProc()
{
	unsigned char i;
	switch(SegMode)
	{
		case 0:
			SegBuf[2] = SegBuf[5] = 11;//-
			for(i = 0; i < 3; i++)
			{
				SegBuf[3*i] = ucRtc[i] / 16;
				SegBuf[3*i+1] = ucRtc[i] % 16;
			}
		break;
	}
}		

3.数据页面

在这里插入图片描述

  • iic底层
    对AD处理时使用的方法是连续读取两次,丢弃第一次的值,并且使用均值滤波(不使用滤波也行)。
#include <STC15F2K60S2.H>
#include <intrins.h>

#define DELAY_TIME	5

sbit 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 add)
{
	unsigned char temp;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(add);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(add);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return temp;
}

unsigned char AverageFilter(unsigned char add) 
{
	unsigned char i;
 	unsigned int sum = 0;
	for (i = 0; i < 10; i++) 
	{
		sum += Ad(add);// 多次采样
 	}
    return (unsigned char)(sum / 10);  
}
  • main.c中的AD数据处理函数ADProc()
idata u16 RD1_100x, RB2_100x;//RD1、RB2放大100倍

void ADProc()
{
	RD1_100x = AverageFilter(0x01) / 51.0 * 100;
	RB2_100x = AverageFilter(0x03) / 51.0 * 100;
}
  • 数码管显示
void SegProc()
{
	unsigned char i;
	if(!record)
	{
		switch(SegMode)
		{
			case 0:
				//...
			break;
				
			case 1:
				SegBuf[0] = 12;//P
				SegBuf[1] = RD1_100x / 100;
				SegBuf[2] = RD1_100x / 10 % 10;
				SegBuf[3] = RD1_100x % 10;
				SegBuf[4] = 13;//U
				SegBuf[5] = RB2_100x / 100;
				SegBuf[6] = RB2_100x / 10 % 10;
				SegBuf[7] = RB2_100x % 10;
				SegPoint[1] = SegPoint[5] = 1;
			break;
		}
	}
}		

4.历史查询界面

在这里插入图片描述
由于历史查询界面中记录的是最近三次的触发时间,这边为了方便
使用二维数组pdata u8 rtc_record[3][3];来记录三组时间
定义idata u8 rtc_record_x;为二维数组的行索引
由于时钟的小时不可能为24,所以二维数组的初值赋值为0x24,在数码管就可以通过判断二维数组的rtc_record[rtc_record_x][0]是否为0x24进行判断是否为空。

idata u8 rtc_record_x;
pdata u8 rtc_record[3][3] = {0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24};

void SegProc()
{
	unsigned char i;
	if(!record)
	{
		switch(SegMode)
		{
			case 0:
				//...
			break;
				
			case 1:
				//...
			break;
			
			case 2:
				SegBuf[0] = 14;
				SegBuf[1] = rtc_record_x + 1;
				SegPoint[1] = SegPoint[5] = 0;
				//如果该组数据未采集,则除了前两位其余显示-
				if(rtc_record[rtc_record_x][0] == 0x24)
				{
					SegBuf[2] = 11;
					SegBuf[3] = 11;
					SegBuf[4] = 11;
					SegBuf[5] = 11;
					SegBuf[6] = 11;
					SegBuf[7] = 11;
				}
				//该组数据已采集,正常显示
				else
					for(i = 0; i < 3; i++)
					{
						SegBuf[2*i+2] = rtc_record[rtc_record_x][i] / 16;
						SegBuf[2*i+3] = rtc_record[rtc_record_x][i] % 16;
					}
			break;
		}
	}

5.触发采集

/*变量定义*/
idata u8 rtc_record_x;//二维数组行索引
pdata u8 rtc_record[3][3] = {0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24};//二维数组存放记录的时间

idata bit record;//触发标志位
idata bit has_record;//重复触发检测位

在这里插入图片描述
在实现该功能,应采取从大到小的方法来实现

  • 当采集到光敏电压值 < RB2 电压值时,触发 1 次
void ADProc()
{
	RD1_100x = AverageFilter(0x01) / 51.0 * 100;
	RB2_100x = AverageFilter(0x03) / 51.0 * 100;
	//光敏电压:RD1                                                                                                                                                                                                                                                                                                       
	if(RD1_100x < RB2_100x && !record)
	{
		record = 1;
		GetRtc(rtc_record[0]);//采集第一组时间
	}
}
  • 触发后,立即切换到“触发界面”,显示本次触发时间, 3s 内不可重复触发。 3 秒后返回“原状态”
idata u16 Time_3s;

void ADProc()
{
	RD1_100x = AverageFilter(0x01) / 51.0 * 100;
	RB2_100x = AverageFilter(0x03) / 51.0 * 100;
	//光敏电压:RD1                                                                                                                                                                                                                                                                                                       
	if(RD1_100x < RB2_100x && !record)
	{
		record = 1;
		GetRtc(rtc_record[0]);//采集第一组时间
	}
	if(RD1_100x >= RB2_100x)
		has_record = 0;
}

void Timer0_Isr(void) interrupt 1
{
	//systick++;
	if(++SegPos == 8) SegPos = 0;
	SegDisp(SegPos,SegBuf[SegPos],SegPoint[SegPos]);
	if(record)
		if(++Time_3s == 3000)
		{
			Time_3s = 0;
			record = 0;
		}
}
  • 接下来考虑不重复触发
    idata bit has_record;//重复触发检测位
void ADProc()
{
	RD1_100x = AverageFilter(0x01) / 51.0 * 100;
	RB2_100x = AverageFilter(0x03) / 51.0 * 100;
	//光敏电压:RD1                                                                                                                                                                                                                                                                                                       
	if((RD1_100x < RB2_100x) && !record && !has_record)
	{
		has_record = 1;
		record = 1;
		GetRtc(rtc_record[0]);//采集第一组时间
	}
	if(RD1_100x >= RB2_100x)
		has_record = 0;
}
  • 接下来写一个函数,实现以下功能

触发后, “历史查询界面”,记录本次触发时间。越早记录的数据,索引值越大,最近一次触发时间索引值
为 1。历史查询界面可记录最近 3 次的触发时间。

(1)数据移动

for (i = 2; i > 0; i--)
    memcpy(rtc_record[i], rtc_record[i - 1], 3);

将rtc_record[1] 的数据复制到 rtc_record[2]
将rtc_record[0] 的数据复制到 rtc_record[1]
每次移动的数据长度为 3 个字节(时、分、秒)

(2)获取新数据
GetRtc(rtc_record[0]);
调用 GetRtc() 函数,将新数据存储到 rtc_record[0] 中。
(3)代码

void UpdateRtcRecord()
{
	unsigned char i;
	for(i = 2; i > 0; i--)
		memcpy(rtc_record[i],rtc_record[i-1],3);
	
	GetRtc(rtc_record[0]);
}
  • 调用UpdateRtcRecord()
void UpdateRtcRecord()
{
	unsigned char i;
	for(i = 2; i > 0; i--)
		memcpy(rtc_record[i],rtc_record[i-1],3);
	
	GetRtc(rtc_record[0]);
}

void ADProc()
{
	RD1_100x = AverageFilter(0x01) / 51.0 * 100;
	RB2_100x = AverageFilter(0x03) / 51.0 * 100;
	//光敏电压:RD1                                                                                                                                                                                                                                                                                                       
	if((RD1_100x < RB2_100x) && !record && !has_record)
	{
		has_record = 1;
		record = 1;
		UpdateRtcRecord();
	}
	if(RD1_100x >= RB2_100x)
		has_record = 0;
}

6.数码管完整代码

void SegProc()
{
	unsigned char i;
	if(!record)//没有处于记录页面
	{
		switch(SegMode)
		{
			case 0:
				SegBuf[2] = SegBuf[5] = 11;
				for(i = 0; i < 3; i++)
				{
					SegBuf[3*i] = ucRtc[i] / 16;
					SegBuf[3*i+1] = ucRtc[i] % 16;
				}
			break;
				
			case 1:
				SegBuf[0] = 12;
				SegBuf[1] = RD1_100x / 100;
				SegBuf[2] = RD1_100x / 10 % 10;
				SegBuf[3] = RD1_100x % 10;
				SegBuf[4] = 13;
				SegBuf[5] = RB2_100x / 100;
				SegBuf[6] = RB2_100x / 10 % 10;
				SegBuf[7] = RB2_100x % 10;
				SegPoint[1] = SegPoint[5] = 1;
			break;
			
			case 2:
				SegBuf[0] = 14;
				SegBuf[1] = rtc_record_x + 1;
				SegPoint[1] = SegPoint[5] = 0;
				if(rtc_record[rtc_record_x][0] == 0x24)
				{
					SegBuf[2] = 11;
					SegBuf[3] = 11;
					SegBuf[4] = 11;
					SegBuf[5] = 11;
					SegBuf[6] = 11;
					SegBuf[7] = 11;
				}
				else
					for(i = 0; i < 3; i++)
					{
						SegBuf[2*i+2] = rtc_record[rtc_record_x][i] / 16;
						SegBuf[2*i+3] = rtc_record[rtc_record_x][i] % 16;
					}
			break;
		}
	}
	else//处于记录页面
	{
		SegBuf[0] = 13;
		SegBuf[1] = 13;
		SegPoint[1] = SegPoint[5] = 0;
		for(i = 0; i < 3; i++)
		{
			SegBuf[2*i+2] = rtc_record[0][i] / 16;
			SegBuf[2*i+3] = rtc_record[0][i] % 16;
		}
	}
}

四、按键模块

1.底层代码

#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(P33 == 0)temp = 8;
	return temp;
}

2.功能处理

在这里插入图片描述

idata u8 rtc_record_x;//二维数组行索引
pdata u8 rtc_record[3][3] = {0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24};//二维数组存放记录的时间

void KeyProc()
{
	KeyVal = KeyDisp();
	KeyDown = KeyVal & ~KeyOld;
	KeyUp = ~KeyVal & KeyOld;
	KeyOld = KeyVal;
	switch(KeyDown)
	{
		case 4://页面流转
			if(++SegMode == 3) SegMode = 0;
			//每次进入历史查询页面时,索引值默认为1
			if(!SegMode) rtc_record_x = 0;
		break;
		
		case 5://历史查询页面子页面控制
			if(SegMode == 2)
				if(++rtc_record_x == 3)
					rtc_record_x = 0;
		break;
		
		case 8://清空记录的数据
			if(SegMode == 2)
			{
				rtc_record_x = 0;
				//memset:将`rtc_record`指向的内存区域的前`9`个字节设置为`0x24`
				//在数码管中判断数据为空时比较数据是0x24
				memset(rtc_record,0x24,9);
			}
		break;
	}
}

五、Led模块

在这里插入图片描述
看到这种指定页面指定指示灯亮的依旧使用互斥点亮

pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};

void LedProc()
{
	unsigned char i;
	for(i = 0; i < 3; i++)
		ucLed[i] = (SegMode == i);
	ucLed[7] = record;
	LedDisp(ucLed);
}

六、完整代码(各模块退出处理请自行添加)

#include <STC15F2K60S2.H>
#include <string.h>
#include "Init.h"
#include "Key.h"
#include "Seg.h"
#include "Led.h"
#include "iic.h"
#include "ds1302.h"

typedef unsigned char u8;
typedef unsigned int u16;

idata u8 SegPos;
idata u8 SegMode;
idata u8 KeyVal, KeyDown, KeyUp, KeyOld;
idata u8 rtc_record_x;

idata u16 RD1_100x, RB2_100x;
idata u16 Time_3s;

pdata u8 SegBuf[8] = {10,10,10,10,10,10,10,10};
pdata u8 SegPoint[8] = {0,0,0,0,0,0,0,0};
pdata u8 ucRtc[3] = {0x23,0x59,0x50};
pdata u8 rtc_record[3][3] = {0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24};
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};

idata bit record;//触发标志位
idata bit has_record;//重复触发检测位

void UpdateRtcRecord()
{
	unsigned char i;
	for(i = 2; i > 0; i--)
		memcpy(rtc_record[i],rtc_record[i-1],3);
	
	GetRtc(rtc_record[0]);
}

void KeyProc()
{
	KeyVal = KeyDisp();
	KeyDown = KeyVal & ~KeyOld;
	KeyUp = ~KeyVal & KeyOld;
	KeyOld = KeyVal;
	switch(KeyDown)
	{
		case 4:
			if(++SegMode == 3) SegMode = 0;
			if(!SegMode) rtc_record_x = 0;
		break;
		
		case 5:
			if(SegMode == 2)
				if(++rtc_record_x == 3)
					rtc_record_x = 0;
		break;
		
		case 8:
			if(SegMode == 2)
			{
				rtc_record_x = 0;
				memset(rtc_record,0x24,9);
			}
		break;
	}
	
}

void SegProc()
{
	unsigned char i;
	if(!record)
	{
		switch(SegMode)
		{
			case 0:
				SegBuf[2] = SegBuf[5] = 11;
				for(i = 0; i < 3; i++)
				{
					SegBuf[3*i] = ucRtc[i] / 16;
					SegBuf[3*i+1] = ucRtc[i] % 16;
				}
			break;
				
			case 1:
				SegBuf[0] = 12;
				SegBuf[1] = RD1_100x / 100;
				SegBuf[2] = RD1_100x / 10 % 10;
				SegBuf[3] = RD1_100x % 10;
				SegBuf[4] = 13;
				SegBuf[5] = RB2_100x / 100;
				SegBuf[6] = RB2_100x / 10 % 10;
				SegBuf[7] = RB2_100x % 10;
				SegPoint[1] = SegPoint[5] = 1;
			break;
			
			case 2:
				SegBuf[0] = 14;
				SegBuf[1] = rtc_record_x + 1;
				SegPoint[1] = SegPoint[5] = 0;
				if(rtc_record[rtc_record_x][0] == 0x24)
				{
					SegBuf[2] = 11;
					SegBuf[3] = 11;
					SegBuf[4] = 11;
					SegBuf[5] = 11;
					SegBuf[6] = 11;
					SegBuf[7] = 11;
				}
				else
					for(i = 0; i < 3; i++)
					{
						SegBuf[2*i+2] = rtc_record[rtc_record_x][i] / 16;
						SegBuf[2*i+3] = rtc_record[rtc_record_x][i] % 16;
					}
			break;
		}
	}
	else
	{
		SegBuf[0] = 13;
		SegBuf[1] = 13;
		SegPoint[1] = SegPoint[5] = 0;
		for(i = 0; i < 3; i++)
		{
			SegBuf[2*i+2] = rtc_record[0][i] / 16;
			SegBuf[2*i+3] = rtc_record[0][i] % 16;
		}
	}
}

void LedProc()
{
	unsigned char i;
	for(i = 0; i < 3; i++)
		ucLed[i] = (SegMode == i);
	ucLed[7] = record;
	LedDisp(ucLed);
}

void DS1302Proc()
{
	GetRtc(ucRtc);
}

void ADProc()
{
	RD1_100x = AverageFilter(0x01) / 51.0 * 100;
	RB2_100x = AverageFilter(0x03) / 51.0 * 100;
	//光敏电压:RD1                                                                                                                                                                                                                                                                                                       
	if((RD1_100x < RB2_100x) && !record && !has_record)
	{
		has_record = 1;
		record = 1;
		UpdateRtcRecord();
	}
	if(RD1_100x >= RB2_100x)
		has_record = 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(record)
		if(++Time_3s == 3000)
		{
			Time_3s = 0;
			record = 0;
		}
}

void main()
{
	SystemInit();
	Timer0_Init();
	SetRtc(ucRtc);
	while(1)
	{
		
	}
}

相关文章:

  • JVM常用概念之String.intern()
  • Linux(Centos 7.6)命令详解:zip
  • 递归专题刷题
  • linux下ollama离线安装
  • Unity游戏开发中的网格简化与LOD技术(Mesh Simplification LOD)
  • Linux基础--文件权限+软件包管理+管道符
  • mysql中in和exists的区别?
  • 深入解析ECDSA与RSA公钥算法:原理、对比及AWS最佳实践
  • 【AD】5-14 多跟走线设置
  • 16位-32768的补码和原码是什么【补码和原码的转换】
  • spring IOC(实现原理)
  • 如何让一个类作为可调用对象被thread调用?
  • WSL with NVIDIA Container Toolkit
  • 基于单片机的风速报警装置设计
  • 深度学习模型组件之优化器--自适应学习率优化方法(Adadelta、Adam、AdamW)
  • 【Ant Design X Vue】Vue 首个 AI 组件库发布!
  • 前端题目类型
  • 记录小白使用 Cursor 开发第一个微信小程序(一):注册账号及下载工具(250308)
  • manus本地部署方法研究测试
  • 后序线索化二叉树,并找到指定结点前驱,非递归逆序输出
  • wordpress小说站/市场营销计划书模板
  • 网站备案是域名备案还是服务器备案/知乎小说推广对接平台
  • 哪个公司做网站专业/查询域名注册信息
  • 那个网站可以做logo/竞价推广账户托管服务
  • 广州建站模板平台/怎样创建一个网站
  • 东莞网站建设seo/临沂seo推广