资讯详情

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

文章目录

  • 前言
  • 效果
  • 代码树
    • init.c
    • main.c
    • onewire.c
    • iic.c
    • ds1302.c
    • init.h
    • onewire.h
    • iic.h
    • ds1302.h
    • type.h
  • 交流群

前言

所有功能都实现了。说实话,这个国家赛题的串口和eeprom它仍然很具挑战性。这部分需要更多的练习和注意;对于一些常见的操作,我们应该多总结一下,以便在比赛中使用。保存信息时,不要保存字符串!直接保存变量(uchar)可以。我只想提一些需要注意的地方。

  • 一是要注意strcpy和memcpy区别在于字符串的复制和内存的复制。字符串的复制不能用于数组的复制,因为一旦数组中出现0,就会识别出空字符!
  • 注意数组的大小是否可以安装格式化字符串!
  • 第二个是eeprom的处理,eeprom分为32页,一页8页Byte,因此,它可以通过页面写作来保存。例如,您的起始地址为0,即第一页,起始位置为8,为第二页。我发现在使用页面写作后,写作和阅读仍然有一些问题,所以我使用了一种特殊的方法来处理它。这部分可以通过程序来理解
  • 不要写字符串数据的接收和判断。例如,我发送的数据不一定是6位数据。如果数据宽度不同,写字的程序必然会导致错误。这也可以从我的字符串处理部分来理解。
  • 我不发标题,网上都有。

效果

说了这么多,看看效果。

注意声音有点大,不好意思录进去

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

视频链接

代码树

在这里插入图片描述

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 

标签: 系列电阻rl0805fr

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台