其他分享
首页 > 其他分享> > 蓝桥杯单片机第五届国赛题目-多功能事件记录器

蓝桥杯单片机第五届国赛题目-多功能事件记录器

作者:互联网

文章目录

前言

功能全部实现,实话说,这届国赛题的串口和eeprom还是很有挑战的,关于这部分需要多加练习和注意;对于常见的一些操作要多加总结,才能够在比赛的时候拿出来就用。在保存信息的时候,一定不要用保存字符串的方式!直接采用保存变量的方式(uchar)即可。我就想提几个需要注意的地方吧。

效果

说了这么多,看一下效果吧。

<iframe allowfullscreen="true" data-mediaembed="bilibili" id="jkQ87QzS-1622286668733" src="https://player.bilibili.com/player.html?aid=715811384"></iframe>

蓝桥杯单片机第五届国赛题目-多功能事件记录器演示


视频链接

代码树

在这里插入图片描述

init.c

#include "init.h"


extern uchar bf[8];


void SL(uchar _dev, uchar _data)
{
 P0 = _data; SEL(_dev);
}
 
void Timer1Init(void)		//2毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x40;		//设置定时初值
	TH1 = 0xA2;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
 ET1 = 1;
 EA = 1;
}


uchar GetKey()
{
 if(K3 == 0) return 5;
 if(K4 == 0) return 4;
 return 0;
}


void TimeRun(t_delay* time)
{
 if(time->cnt++ < time->max);
 else
 {
  time->cnt = 0;
  time->ok = 1;
 }
}

uchar FR(float _data, uchar _dig)
{
 uint i = 1;
 while(_dig--)
 {
  i = i*10;
 }
 return((uint)_data/i%10);
}

void Bf(uchar _0, uchar _1, uchar _2, uchar _3, 
        uchar _4, uchar _5, uchar _6, uchar _7)
{
 bf[0] = _0; bf[1] = _1; bf[2] = _2; bf[3] = _3;
 bf[4] = _4; bf[5] = _5; bf[6] = _6; bf[7] = _7;
}



void UartInit(void)		//1200bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR |= 0x04;		//定时器2时钟为Fosc,即1T
	T2L = 0x3C;		//设定定时初值
	T2H = 0xF6;		//设定定时初值
	AUXR |= 0x10;		//启动定时器2
 ES = 1;
}


void print(uchar* string)
{
  ES = 0; TI = 1;
  printf("%s", string);
  TI = 0; ES = 1;
}

uchar LedChange(uchar _data, uchar _dig, uchar _state)
{
  //LED的状态是反着来的
  if(!_state)
  {
   _data |= 1 << _dig;

  }
  else
  {
   _data &= ~(1 << _dig);
  }
  SL(4, _data);
  return _data;
}

main.c

#include "init.h"


enum{LED=4, EXT, SEL, CODE};
code uchar CA[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 
                   0x92, 0x82, 0xf8, 0x80, 0x90,
                   0xff, 0xc6, 0x89, 0xbf};
uchar bf[] = {1, 2, 3, 4, 5, 6, 7, 8};
uchar curDig = 0;
uchar enprint = 0;

uchar key, tmpKey, keyCnt;
enum{KS_GT, KS_AS, KS_WA};keyState=KS_GT;


t_delay delay_200 = {200, 0, 0};
t_delay tx_delay = {50, 0, 0};
t_delay cnt_65535 = {65535, 0, 0};

uchar index = 0;
uchar xdata rxBuf[20] = "0";
//发送缓冲不能小了,要避免出现其他异常情况将发送缓冲装溢出了
uchar xdata txBuf[30] = "0";
uchar revCorrect = 0;
uchar time[3];
uchar jieJin = 0;
uchar Second = 255;
//事件接近的时间
uchar timeCnt = 0;
//模式
enum{S_AUTOT, S_AUTOR}gloSta = S_AUTOT;
//显示模式
enum{DIS_WSD, DIS_TIME, DIS_ITEM}disMode = DIS_WSD;

uchar ledData = 0xfe;
float adcVal, adc1Val;
uchar storeData[5][7] = {0}; 
//调试使用
//uchar storeData1[5][6] = {{1,2,3, 4  ,5 ,25},
//                          {1,2,3, 4  ,5 ,25},
//                          {1,2,3, 4  ,5 ,25},
//                          {1,2,3, 4  ,5 ,25},
//                          {1,2,3, 4  ,5 ,25}};
void Timer1Hanle() interrupt 3
{
 SL(CODE, 0xff);SL(SEL, 1 << curDig); SL(CODE, CA[bf[curDig]]);
 curDig = (curDig + 1)%8;
 switch(keyState)
 {
  case KS_GT:
   keyCnt = 0; tmpKey =GetKey(); keyState = KS_AS;
  break;
  
  case KS_AS:
   if(keyCnt++ < 10);
   else if(tmpKey == GetKey())
   {
    if(tmpKey != key)
    {
     key = tmpKey;keyState = KS_WA;
    }
    else
    {
     keyState = KS_GT;
    }
   }
   else
   {
    keyState = KS_GT;
   }
  break;
 }
 TimeRun(&delay_200);
 if(tx_delay.ok == 2)
  TimeRun(&tx_delay);
 //如果允许计算时间
 if(cnt_65535.ok == 2)
  TimeRun(&cnt_65535); 
}

void Sensor()
{
 if(delay_200.ok == 1)
 {
  delay_200.ok = 0;
  Temp_Read();
  adcVal = ADC_Read(0x43, 0);
  adc1Val = ADC_Read(0x41, 0);
  if(adc1Val < 50)
  {
   jieJin = 1;
   ledData = LedChange(ledData, 2, 1);
   //如果计时没有开始,那么让计时开始
   if(cnt_65535.cnt == 0)
    cnt_65535.ok = 2;
  } 
  else
  {
   jieJin = 0;
   ledData = LedChange(ledData, 2, 0);
   //如果已经开始计时,那么停止
   if(cnt_65535.cnt != 0)
   {
    uchar tmpString[7];
    cnt_65535.ok = 0;
    timeCnt = cnt_65535.cnt*2/1000;
    tmpString[0] = (uint)tempVal/100;
    tmpString[1] = (uint)adcVal;
    tmpString[2] = time[2];
    tmpString[3] = time[1];
    tmpString[4] = time[0];
    tmpString[5] = timeCnt; 
    stack(tmpString);
    cnt_65535.cnt = 0;
   }  
  }
  DS1302_Read();
 }
}
void UartHandle() interrupt 4
{
 if(TI) TI = 0;
 if(RI)
 {
  RI = 0;
  //如果进来的时候是第一次,因此开启计时
  if(tx_delay.ok == 0)
  tx_delay.ok = 2;
  //进来是因为串口接收中断
  if(index < 20)
  {
   rxBuf[index++] = SBUF;
  }
 }
}
void UartProcess()
{
 //如果接收超时,触发检查事件
  //如果进来的时候是因为计时结束
  if(tx_delay.ok == 1)
  {
   //结束标志清零
   tx_delay.ok = 0; 
   //如果接收的数据是6位
   if(index == 6)
   {
   	//如果口令正确
    if(strncmp(rxBuf, "AAASSS", 6) == 0)
    {
     enprint = 1;
    }
   }
   //如果口令不是正确的,那么就是错误的
   else
   {
    enprint = 2;
   }
   //不管哪种情况,都需要将index清空
   index = 0;
  }
 //如果口令正确
 if(enprint == 1)
 {
  uchar i;
  enprint = 0;
  //根据状态来选择串口的输出
  switch(gloSta)
  {
   case S_AUTOT:
    //开启串口输出
    revCorrect = 1;
   break;
   
   case S_AUTOR:
    for(i = 0; i < 5; i++)
    {
     uchar temp[25] = {0};
     sprintf(temp, "{%bu-%bu%%}-{%bu-%bu-%bu}{%bu}\r\n",
                storeData[i][0], storeData[i][1], storeData[i][2], storeData[i][3], storeData[i][4], storeData[i][5]);
     print(temp);
     //很重要,不然会联结
     Delay8ms();
    }
   break;
  }
  //如果口令不正确关闭输出      
 }
 else if(enprint == 2)
 {
  enprint = 0;
  revCorrect = 0;
 }
}

void EventProcess()
{
 if(revCorrect)
 {
  //如果一秒到了
  if(Second != time[0])
  {
   //发送相应命令
   Second =  time[0];
   sprintf(txBuf, "{%.0f-%.0f%%}-{%bu-%bu-%bu}{%bu}\r\n",
                tempVal/100.0, adcVal, time[2], time[1], time[0], jieJin);
   print(txBuf);
  }
 }
}

//按键处理
void keyProcess()
{
 switch(key)
  {
   case 4:
    gloSta = (gloSta == S_AUTOT)?S_AUTOR:S_AUTOT;
    //互锁的先关闭所有,再根据条件开启响应的led
    ledData = LedChange(ledData, 1, 0);
    ledData = LedChange(ledData, 0, 0);
    if(gloSta == S_AUTOR)
    {
     revCorrect = 0;
     ledData = LedChange(ledData, 1, 1);
    }
    else
    {
     ledData = LedChange(ledData, 0, 1);
    }
   break;
   case 5:
    if(disMode == DIS_WSD)
     disMode = DIS_TIME;
    else if(disMode == DIS_TIME)
     disMode = DIS_ITEM;
    else
     disMode = DIS_WSD;
   break;
  }
}


void DisProcess()
{
 switch(disMode)
 {
  case DIS_WSD:
   Bf(FR(tempVal, 3), FR(tempVal, 2), F_CC, F_C, F_C, FR(adcVal, 1), FR(adcVal, 0), F_H);   
  break;
  
  case DIS_TIME:
   Bf(FR(time[2], 1), FR(time[2], 0), F_SEP, 
      FR(time[1], 1), FR(time[1], 0), F_SEP, 
      FR(time[0], 1), FR(time[0], 0));   
  break;
  
  case DIS_ITEM:
   Bf(F_C, F_C, F_C, 
      F_SEP, FR(timeCnt, 3), FR(timeCnt, 2), 
      FR(timeCnt, 1), FR(timeCnt, 0));
  break;
 }
}
//非常重要
void Delay8ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 94;
	j = 95;
	do
	{
		while (--j);
	} while (--i);
}

void stack(uchar* string)
{
 uchar i = 0;
 for(; i < 4; i++)
 {
  memcpy(storeData[i], storeData[i+1], 6);
 }
 memcpy(storeData[i], string, 6); 
 for(i = 0; i < 5; i++)
 {
  EEPROM_Write(i*8, storeData[i], 6);
  EEPROM_Write(i*8, storeData[i], 6);
  EEPROM_Write(i*8, storeData[i], 6);
 }
}
void StoreInit()
{
  uchar i = 0;
//调试使用
// for(i = 0; i < 5; i++)
// {
//  EEPROM_Write(i*8, storeData1[i], 7);
//  EEPROM_Write(i*8, storeData1[i], 7);
//  EEPROM_Write(i*8, storeData1[i], 7);
// }
 for(i = 0; i < 5; i++)
 {
  uchar tmpData[6];
  EEPROM_Read(i*8, 6, storeData[i]);
  EEPROM_Read(i*8, 6, tmpData);
  while(strncmp(tmpData,storeData[i],6) != 0)
  {
   EEPROM_Read(i*8, 6, storeData[i]);
   EEPROM_Read(i*8, 6, tmpData);
  } 
 }
//调试使用
// for(i = 0; i < 5; i++)
// {
//  uchar temp[20] = {0};
//  sprintf(temp, "%bu%bu%bu%bu%bu%bu\r\n", storeData[i][0],storeData[i][1],storeData[i][2],storeData[i][3],storeData[i][4],storeData[i][5]);
//  print(temp);
//  //很重要,不然会联结
//  Delay8ms();
// }
}
void main()
{
 //初始化
 BPOFF;RLOFF;
 SL(LED, ledData);
 //清屏
 memset(bf, F_C, 8);
 Timer1Init();
 UartInit();
 DS1302_init(23, 59, 55);
 StoreInit();
 while(1)
 {
  Sensor();
  UartProcess();
  EventProcess();
  DisProcess();
  if(keyState == KS_WA)
  {
   keyProcess();
   keyState = KS_GT;
  }
 }
}

onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"
#include "type.h"
sbit DQ = P1^4;  //单总线接口
float tempVal;
//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
 t = t * 10;
	while(t--);
}

//通过单总线向DS18B20写一个字节
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);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
  Delay_OneWire(1);
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(1);
	}
	return dat;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(8); 
   initflag = DQ;     
  	Delay_OneWire(5);
  	return initflag;
}


void Temp_Read()
{
 uint tmpVal;
 init_ds18b20();
 Write_DS18B20(0xcc);
 Write_DS18B20(0x44);
 while(!DQ);
 init_ds18b20();
 Write_DS18B20(0xcc);
 Write_DS18B20(0xbe);
 tmpVal = Read_DS18B20();
 tmpVal = ((uint)Read_DS18B20() << 8) | tmpVal;
 //防止乱跳
 if(tmpVal*6.25 < 5000)
 tempVal = tmpVal*6.25;
}

iic.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "reg52.h"
#include "intrins.h"
#include "type.h"
#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					// 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
     IIC_Delay(DELAY_TIME);
     da <<= 1;
     if(SDA) da |= 1;
     SCL = 0;
     IIC_Delay(DELAY_TIME);
    }
    return da;    
}

float ADC_Read(uchar _addr, uchar _data)
{
  uchar tmpVal;
  IIC_Start();
  IIC_SendByte(0x90);
  IIC_WaitAck();
  IIC_SendByte(_addr);
  IIC_WaitAck();
  IIC_SendByte(_data);
  IIC_WaitAck();
  IIC_Stop();
  IIC_Start();
  IIC_SendByte(0x91);
  IIC_WaitAck();
  tmpVal = IIC_RecByte();//每次一开始读的是128
  IIC_SendAck(0);
  return(IIC_RecByte()*99.0/255);
 //光敏是阳光越大,电压越大,电阻越小
}

void EEPROM_Write(uchar _addr, uchar* _data, uchar _dig)
{
  EA = 0;
  IIC_Start();
  IIC_SendByte(0xa0);
  IIC_WaitAck();
  IIC_SendByte(_addr);
  IIC_WaitAck();
  while(_dig--)
  {
   IIC_SendByte(*_data++);
   IIC_WaitAck();
  }
  IIC_Stop();
  EA = 1;
}
void EEPROM_Read(uchar _addr, uchar _dig, uchar* _des)
{
  EA = 0;
  IIC_Start();
  IIC_SendByte(0xa0);
  IIC_WaitAck();
  IIC_SendByte(_addr);
  IIC_WaitAck();
  IIC_Start();
  IIC_SendByte(0xa1);
  IIC_WaitAck();
   _dig--;
  while(_dig--)
  {
   *_des++ = IIC_RecByte();
   IIC_SendAck(0);
  }
  *_des++ = IIC_RecByte();
  IIC_Stop();
   EA = 1;
}

ds1302.c

/*
  程序说明: DS1302驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include <reg52.h>
#include <intrins.h>
#include "type.h"
sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												
extern uchar time[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);			
//}
uchar Read(){
	 unsigned char i,temp=0x00;
 	for (i=0;i<8;i++){		
			SCK=0;
			temp>>=1;	
			if(SDA)
				temp|=0x80;	
				SCK=1;
	}
	return (temp);		
}
void DS1302_init(uchar _h, uchar _m, uchar _s){
	uchar i;
	_h = (_h/10%10 << 4) | _h%10;
	_m = (_m/10%10 << 4) | _m%10;
	_s = (_s/10%10 << 4) | _s%10;
	Write_Ds1302_Byte(0x8e, 0);
	RST=0;	_nop_();
	SCK=0;	_nop_();
	RST=1; 	_nop_();
	Write_Ds1302(0xbe);
	Write_Ds1302(_s);	
	Write_Ds1302(_m);	
	Write_Ds1302(_h);	
	for(i = 0; i < 5; i++){
		Write_Ds1302(0);	
	}
	RST=0;
	Write_Ds1302_Byte(0x8e, 0x80);
}
void DS1302_Read(){
		Write_Ds1302_Byte(0x8e, 0);
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(0xbf);
  time[0] = Read();
		time[1] = Read();
		time[2] = Read();
		time[0] = (time[0] >> 4)*10 + (time[0] & 0x0f);
		time[1] = (time[1] >> 4)*10 + (time[1] & 0x0f);
		time[2] = (time[2] >> 4)*10 + (time[2] & 0x0f);
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
		SCK=1;	_nop_();
		SDA=0;	_nop_();
		SDA=1;	_nop_();
		Write_Ds1302_Byte(0x8e, 0x80);
}

init.h

#ifndef _INIT_H
#define _INIT_H
#include "stc15f2k60s2.h"
#include "stdio.h"
#include "intrins.h"
#include "type.h"
#include "onewire.h"
#include "iic.h"
#include "string.h"
#include "ds1302.h"

#define SEL(x) P2=P2&0x1f|x<<5;P2=P2&0x1f
sbit BP = P0^6; sbit RL = P0^4;
#define BPON BP = 1; SEL(5)
#define BPOFF BP = 0; SEL(5)
#define RLON RL = 1; SEL(5)
#define RLOFF RL = 0; SEL(5)
#define F_C 10
#define F_CC 11
#define F_H 12
#define F_SEP 13
sbit K1 = P3^0; sbit K2 = P3^1; sbit K3 = P3^2; sbit K4 = P3^3;

typedef struct delay
{
 uint max;
 uint cnt;
 uchar ok;
}t_delay;


void SL(uchar _dev, uchar _data);
void Timer1Init(void);
uchar GetKey();
void TimeRun(t_delay* time);
uchar FR(float _data, uchar _dig);
void Bf(uchar _0, uchar _1, uchar _2, uchar _3, 
        uchar _4, uchar _5, uchar _6, uchar _7);
void UartInit(void);
void print(uchar* string);
uchar LedChange(uchar _data, uchar _dig, uchar _state);
void stack(uchar* string);
void Delay8ms();		//@12.000MHz
#endif	

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H
extern float tempVal;
void Temp_Read();
#endif

iic.h

#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
float ADC_Read(uchar _addr, uchar _data);
void EEPROM_Write(uchar _addr, uchar* _data, uchar _dig);
void EEPROM_Read(uchar _addr, uchar _dig, uchar* _des);
#endif

ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
void DS1302_Read();
void DS1302_init(uchar _h, uchar _m, uchar _s);
#endif

type.h

#ifndef _TYPE_H
#define _TYPE_H

#define uchar unsigned char
#define uint unsigned int
#endif

交流群

在这里插入图片描述

标签:char,uchar,void,unsigned,国赛,蓝桥,单片机,IIC,time
来源: https://blog.csdn.net/qq_37429313/article/details/117387021