蓝桥杯单片机第八届国赛题目-超声波测距机的功能设计与实现

题目

在这里插入图片描述

文件树

在这里插入图片描述

代码

init.c

#include "init.h"
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;
}


void SL(uchar _dev, uchar _data)
{
  P0 = _data; SEL(_dev);
}

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)
{
  buf[0] = _0; buf[1] = _1; buf[2] = _2; buf[3] = _3;
  buf[4] = _4; buf[5] = _5; buf[6] = _6; buf[7] = _7;
}

void Run(t_delay* time)
{
 if(time->cnt++ < time->max);
 else
 {
  time->cnt = 0;
  time->ok  = 1;
 }
}
void Delay14us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 39;
	while (--i);
}

void Sonic_T()
{
 uchar i = 10;
 while(i--)
 {
  P10 = 1;
  Delay14us();
  P10 = 0;
  Delay14us();
 }
}
void Sonic_R()
{
 CH = 0; CL = 0;
 Sonic_T();CR = 1;
 while(!CF && P11);
 CR = 0;
 if(CF)
 {
  CF = 0;
  preDistance = distance;
  distance = maxDistance;
  Adc_Read(0x43, dac_value );
 }
 else
 {
  uint tmpVal;
  tmpVal = ((uint)CH << 8) | CL;
  preDistance = distance;
 if(tmpVal*0.017/12 > maxDistance)
 {
  dac_value = 0;
  Adc_Read(0x43, dac_value );
  distance = maxDistance;
 }
 else
 {
 uchar tmpVal;
  distance = tmpVal*0.017/12;
  tmpVal = (maxDistance - distance)*0.02*51;
  if(distance > 5)
  {
     dac_value  = 255;
     Adc_Read(0x43, dac_value);
  }

  else
  {
   dac_value  = tmpVal;
   Adc_Read(0x43, dac_value);
  }
  
  }
 }
}

uchar LedChange(uchar _data, uchar _dig, uchar _en)
{
 if(_en == 0)
 {
  _data |= (1 << _dig);
 }
 else if(_en == 1)
 {
  _data &= ~(1 << _dig);
 }
 else 
 {
  _data ^= (1 << _dig);
 }
 SL(4, _data);
 return(_data);
}
uchar GetKey()
{
 if(K1 == 0) return 7;
 if(K2 == 0) return 6;
 if(K3 == 0) return 5;
 if(K4 == 0) return 4; 
 return 0;
}

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

void Print(uchar *string)
{
  ES = 0;TI = 1;
  printf("%s", string);
  TI = 0; ES = 1;
}
//void Delay8ms()		//@12.000MHz
//{
//	unsigned char i, j;

//	i = 94;
//	j = 95;
//	do
//	{
//		while (--j);
//	} while (--i);
//}
uchar Check(uchar _data, uchar _dig)
{
 return(!((_data >> _dig) & 1));
}

main.c

#include "init.h"

uchar ledData = 0xff;
enum{LED=4, EXT, SEL, CODE};

//dis
uchar buf[8];
uchar code CA[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99,
                   0x92, 0x82, 0xf8, 0x80, 0x90,
                   0xff, 0x8e};
uchar curDig = 0;
                   
enum{D_DIS, D_BACK, D_SET}gloSta = D_DIS;

//key
uchar key = 0, tmpKey = 0, keyCnt = 0;
enum{KS_GT, KS_AS, KS_WA}keyState = KS_GT;                   
                   
//var
t_delay delay_200 = {200, 0, 0};
t_delay delay_300 = {300, 0, 0};
t_delay delay_100 = {100, 0, 0};
float distance;
float preDistance;
float adcVal;
uchar caoZuo = 0;
uchar maxDistance = 20;
uchar pageCnt = 0;
uchar saveData[10];
uchar index = 0;
uchar revBuf[20];
uchar sonicok = 0;
uchar soniccnt = 0;
uchar dac_value = 0;
void Timer1Handle() interrupt 3
{
 SL(CODE, 0xff); SL(SEL, 1 << curDig); SL(CODE, CA[buf[curDig]]);
 curDig = (1 + curDig)%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(key != tmpKey)
         {
          key = tmpKey;
          keyState = KS_WA;
         }
         else
          keyState = KS_GT;
       }
       else
        keyState = KS_GT;
  break;
 }
 //timerun
 Run(&delay_200);
 if(delay_300.ok == 2)
 {
  Run(&delay_300);
 }
 Run(&delay_100);
}

void SensorProcess()
{
 if(delay_200.ok == 1)
 {
  delay_200.ok = 0;
  adcVal = Adc_Read(0x43, 250);
//  BF(F_C, F_C, F_C, F_C,
//     FR(distance, 3), FR(distance, 2),FR(distance, 1),FR(distance, 0));
  BF(F_C, F_C, F_C, F_C,
     FR(adcVal, 3), FR(adcVal, 2),FR(adcVal, 1),FR(adcVal, 0));
 }
}

void DisProcess()
{
 switch(gloSta)
 {
  case D_DIS:
  if(caoZuo == 1)
  {
   BF(1, F_C, F_C, FR(preDistance, 1),FR(preDistance, 0),
      FR(distance, 2),FR(distance, 1),FR(distance, 0));
  }
  else
  {
   float sum;
   sum = preDistance + distance;
   BF(1, F_C, F_C, FR(sum, 1),FR(sum, 0),
      FR(distance, 2),FR(distance, 1),FR(distance, 0));
  }
  break;
  
  case D_BACK:
   BF(FR(pageCnt+1, 1), FR(pageCnt+1, 0), F_C,F_C,F_C,
      FR(saveData[pageCnt], 2),FR(saveData[pageCnt], 1),FR(saveData[pageCnt], 0));
  break;
  
  case D_SET:
   BF(F_F, F_C, F_C,F_C,F_C,
      F_C,FR(maxDistance, 1),FR(maxDistance, 0));
  break;
 }
}
void KD_dis()
{
 if(key == 7)
 {
  caoZuo = (caoZuo + 1)%2;
 }
}
void KD_back()
{
 if(key == 7)
 {
  pageCnt = (pageCnt + 1)%10;
 }
}
void KD_SET()
{
 if(key == 7)
 {
  if(maxDistance < 90)
  {
   maxDistance = maxDistance + 10;
  }
  else
   maxDistance = 0;
 } 
}
void keyProcess()
{
 if(key == 4)
 {
  Sonic_R();
  sonicok = 1;soniccnt  = 0;
  Rotate_Save((uchar)distance);
  Code_Write(0, saveData, 8);
  Code_Write(1, &saveData[8], 2);
  Code_Write(0, saveData, 8);
  Code_Write(1, &saveData[8], 2);
 }
 if(key == 5)
 {
  gloSta = (gloSta != D_BACK)? D_BACK:D_DIS;
  if(gloSta == D_BACK)
  {
    pageCnt = 0;
  }
 }
 if(key == 6)
 {
  gloSta = (gloSta != D_SET)? D_SET:D_DIS;
 }
 switch(gloSta)
 {
  case D_DIS:
       KD_dis();
  break;
  case D_BACK:
       KD_back();
  break;
  case D_SET:
       KD_SET();
  break;
 }
}
void Rotate_Save(uchar _dat)
{
 uchar i;
 for(i = 0; i < 9; i++)
 {
  saveData[i] = saveData[i+1];
 }  
 saveData[i] = _dat; 
}

void UartHandle() interrupt 4
{
 if(TI) TI = 0;
 if(RI)
 {
  RI = 0;
  if(delay_300.ok == 0)
   delay_300.ok = 2;
  if(index < 20)
  {
   revBuf[index++] = SBUF;
  }
 }
}
void UartProcess()
{
 if(delay_300.ok == 1)
 {
  delay_300.ok = 0;
  if(index == 3)
  {
   SL(LED, 0x0);
   if(strncmp(revBuf, "hel", 3) == 0)
   {
    uchar tmpVal[50];
    sprintf(tmpVal, "%bd-%bd-%bd-%bd-%bd-%bd-%bd-%bd-%bd-%bd",
            saveData[0],saveData[1],saveData[2],saveData[3],saveData[4],saveData[5],saveData[6],saveData[7],saveData[8],saveData[9]);
    Print(tmpVal);
   }
  }
  index = 0;
 }
}
void LedProcess()
{
 if(sonicok == 1)
 {
   if(delay_100.ok == 1)
   {
    delay_100.ok = 0;
    if(soniccnt++ < 10)
    {
     ledData = LedChange(ledData, 0, 2);
    }
    else
    {
     ledData = LedChange(ledData, 0, 0);
     sonicok = 0; 
    }
   }
 }
 switch(gloSta)
 {
  case D_SET:
   if(!Check(ledData, 6))
   {
    ledData = LedChange(ledData, 7, 0);
    ledData = LedChange(ledData, 6, 1);   
   }
  break;
  case D_BACK:
   if(!Check(ledData, 7))
   {
    ledData = LedChange(ledData, 6, 0);
    ledData = LedChange(ledData, 7, 1);
   }
  break;
 }
}
void main()
{
  BPOFF; RLOFF;
  SL(LED, ledData);
  Timer1Init();
  memset(buf, F_C, 8);
  //UartInit();
  //超声波初始化
  CMOD |= 0x08;
  Code_Read(0, saveData, 8);
  Code_Read(1, &saveData[8], 2);
  while(1)
  {
   DisProcess();
   SensorProcess(); 
   UartProcess();
   LedProcess();
   if(keyState == KS_WA)
   {
    keyProcess();
    keyState = KS_GT;
   }
  }
}

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;    
}

void Code_Write(uchar _addr, uchar* _data, uchar _dig)
{
 IIC_Start();
 IIC_SendByte(0xa0);
 IIC_WaitAck();
 IIC_SendByte(_addr*8);
 IIC_WaitAck();
 while(_dig--)
 {
  IIC_SendByte(*_data++);
  IIC_WaitAck();
 }
 IIC_Stop();
}
void Code_Read(uchar _addr, uchar* _data, uchar _dig)
{
 IIC_Start();
 IIC_SendByte(0xa0);
 IIC_WaitAck();
 IIC_SendByte(_addr*8);
 IIC_WaitAck();
 IIC_Start();
 IIC_SendByte(0xa1);
 IIC_WaitAck();
 _dig--;
 while(_dig--)
 {
  *_data++ = IIC_RecByte();
  IIC_SendAck(0);
 }
 *_data++ = IIC_RecByte();
 IIC_Stop();
}
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();
 IIC_SendAck(0);
 return(IIC_RecByte());
}

init.h

#ifndef _INIT_H
#define _INIT_H
#include "stc15f2k60s2.h"
#include "intrins.h"
#include "string.h"
#include "stdio.h"
#include "type.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_F 11
sbit K1 = P3^0; sbit K2 = P3^1; sbit K3 = P3^2; sbit K4 = P3^3; 
extern uchar buf[8];
extern float distance;
extern float adcVal;
extern float preDistance;
extern uchar maxDistance;
extern uchar dac_value;
typedef struct delay
{
  uint max;
  uint cnt;
  uchar ok;
}t_delay;  


//函数
void SL(uchar _dev, uchar _data);
void BF(uchar _0, uchar _1, uchar _2, uchar _3,
         uchar _4, uchar _5, uchar _6, uchar _7);
uchar FR(float _data, uchar _dig);
void Timer1Init(void);
void Run(t_delay* time);
void Sonic_R();
uchar LedChange(uchar _data, uchar _dig, uchar _en);
void Code_Read(uchar _addr, uchar* _data, uchar _dig);
void Code_Write(uchar _addr, uchar* _data, uchar _dig);
float Adc_Read(uchar _addr, uchar _data);
uchar GetKey();
void Rotate_Save(uchar _dat);
void Print(uchar *string);
void UartInit(void);
void Delay8ms()	;
uchar Check(uchar _data, uchar _dig);
#endif

type.h

#ifndef _TYPE_H
#define _TYPE_H
#define uchar unsigned char
#define uint unsigned int




#endif

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一WILLPOWER一

你的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值