蓝桥杯单片机12届省赛主观题解题

题目

在这里插入图片描述

文件树

在这里插入图片描述

程序

main.c

#include "init.h"

enum{LED = 4, EXT, SEL, CODE};
uchar curDig = 0;
uchar code CA[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99,
					0x92, 0x82, 0xf8, 0x80, 0x90,
					0xff, 0xc6, 0x8c, 0x88, 
					0xc0&0x7f, 0xf9&0x7f, 0xa4&0x7f, 0xb0&0x7f, 0x99&0x7f,
					0x92&0x7f, 0x82&0x7f, 0xf8&0x7f, 0x80&0x7f, 0x90&0x7f};
uchar buf[] = {F_C, F_CC, F_CC, F_CC, F_CC, F_CC, F_CC, F_CC};
uchar key, tmpKey, keyCnt;
uint serCnt;
enum{K_GT, K_AS, K_WA}keyState = K_GT;

code uint serMax = 300;
t_delay delay300 = {200, 0, 0};

uchar state = 0;
uchar canShu = 25;
uchar scanShu = 25;
uchar moShi = 0;
uchar vVal = 0;
uchar ledData = 0xff;
void Timer1Handle() interrupt 3
{
	SL(CODE ,0xff); SL(SEL, 1 << curDig); SL(CODE, CA[buf[curDig]]);
	curDig = (1 + curDig) %8;
	switch(keyState)
	{
		case K_GT:
				tmpKey = GetKey();
				keyState = K_AS;
				keyCnt = 0;
				serCnt = 0;
		break;

		case K_AS:
				if(keyCnt++ < 10);
				else if(tmpKey == GetKey())
				{
					if(tmpKey != key)
					{
						key = tmpKey;
						keyState = K_WA;
					}
					else if(serCnt++ < serMax);
					else
					keyState = K_WA;
				}
				else 
					keyState = K_GT;
		break;
	}
	TimeRun(&delay300);
}
void DisPlay()
{
	switch(state)
	{
		case 0:
			Buf(F_C, F_CC, F_CC, F_CC, 
			FR(tempVal, 3),FR(tempVal, 2)+XS,FR(tempVal, 1),FR(tempVal, 0));		 
		break;

		case 2:
			{
			float tmpVal = vVal*100/51.0;
			Buf(F_A, F_CC, F_CC, F_CC, F_CC,
			FR(tmpVal, 2)+XS,FR(tmpVal, 1),FR(tmpVal, 0));
			}
		break;
	}
}


void led()
{
	uchar i = 0;
	if(moShi == 0 && checkbit(ledData, 0) == 1)
	{
		ledData = changebit(ledData, 0, 0);
		SL(LED, ledData);
	}
	else if(moShi == 1 && checkbit(ledData, 0) == 0)
	{
		ledData = changebit(ledData, 0, 1);
		SL(LED, ledData);
	}
	for(i = 0; i < 3; i++)
	{
		if(state == i)
		{
			if(checkbit(ledData, i+1) == 1)
			{
				//将三个灯先都关闭,因为他们互斥,因此只有一个灯会亮.
				ledData |= 0x0e; 
				ledData = changebit(ledData, i+1, 0);
				SL(LED, ledData);
			}
		}
	}

}
void Detect()
{
	if(delay300.ok)
	{
		delay300.ok = 0;
		TempRead();
		vVal = CalcDac( tempVal, moShi);
		DacInit(0x43, vVal);
		DisPlay();
		led();
	}
}

void main()
{
	BPOFF;RLOFF;
	SL(LED, 0xff);
	Timer1Init();
	EA = 1;
	while(1)
	{
		Detect();
		if(keyState == K_WA)
		{
			if(key == 1)
			moShi = (moShi + 1)%2;
			else if(key == 3)
			{
				state = (state + 1)%3;
				if(state == 1)
				{
					Buf(F_P, F_CC, F_CC, F_CC, 
						F_CC,F_CC,FR(scanShu, 1),FR(scanShu, 0));		 
				}
				else //当退出参数设置模式,才确定参数
				{
					scanShu = canShu;
				}
			}
			else if(1 == state)
			{
				if(key == 2)
				{
					if(canShu < 99)
					canShu++;
				}			
				else if(key == 4)
				{
					if(canShu > 0)
					canShu--;
				}
				Buf(F_P, F_CC, F_CC, F_CC, 
					F_CC,F_CC,FR(canShu, 1),FR(canShu, 0));
			}
			keyState = K_GT;
		}
	}

}


init.c

#include "init.h"

extern uchar scanShu;
extern uchar buf[8];
code uchar table[][2] = {0,1,1,0};
void SL(uchar _dev, uchar _data)
{
	EA = 0;
	P0 = _data;
	SELE(_dev);
	EA = 1;
}

void TimeRun(t_delay* time)
{
	if(time->cnt++ < time->max);
	else
	{
		time->cnt = 0;
		time->ok = 1;
	}
}
void Buf(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 Timer1Init(void)		//2毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x40;		//设置定时初值
	TH1 = 0xA2;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1 = 1;
}

uchar GetKey()
{
	uchar i;
	C1 = 1; C2 = 1;
	for(i = 0; i < 2; i++)
	{
		R1 = table[i][0]; R2 = table[i][1];
		if(0 == C1) return 2*i+1;
		else if(0 == C2) return 2*i+2;
	}
	return 0;
}

uchar FR(float tmpVal, uchar dig)
{
	switch(dig)
	{
		case 0: return((uint)tmpVal%10);
		case 1: return((uint)tmpVal/10%10);
		case 2: return((uint)tmpVal/100%10);
		case 3: return((uint)tmpVal/1000%10);
		case 4: return((uint)tmpVal/10000%10);
	}
	return 0;	
}
uchar CalcDac( float tmpVal, uchar mode)
{
	if(mode == 0)
	{
		if(tmpVal/100 < scanShu)
		return 0;
		else
		return 255;
	}
	else
	{
		if(tmpVal/100 <= 20)
		return 51;
		else if(tmpVal/100 >=40)
		return 204;
		else
		//函数为3/20*X-2   X:为温度 Y:为电压
		//因此温度和对应DAC的值函数为:51*(3/20*X-2)
		return(51.0*(3/20.0*(tmpVal/100)-2));
		//以为基准电压不可能为准5.0,因此数据有偏差,其实可以用偏移解决的,这个可以自己调。
	}
}

uchar checkbit(uchar _data, uchar _dig)
{
	_data = ((_data >> _dig) & 0x01);
	return(_data);
}
uchar changebit(uchar _data, uchar _dig, uchar val)
{
	if(val)
	return(_data | (1 << _dig));
	else
	return(_data & ~(1 << _dig));
} 


onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"
#include "type.h"
sbit DQ = P1^4;  //单总线接口
extern tempVal = 0;
//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t = t * 8;
	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++)
	{
	 EA = 0;
		DQ = 0;
		Delay_OneWire(1);///
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		EA = 1;
		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 TempRead()
{
	uint tmpVal = 0;
	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;
	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;    
//}


void DacInit(uchar _addr, uchar _data)
{
	IIC_Start();	
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(_addr);
	IIC_WaitAck();
	IIC_SendByte(_data);
	IIC_WaitAck();
	IIC_Stop();
}

type.h

#ifndef _TYPE_H
#define _TYPE_H


#define uchar unsigned char
#define uint unsigned int

#endif

init.h

#ifndef _INIT_H
#define _INIT_H
#include "stc15f2k60s2.h"
#include "intrins.h"
#include "stdio.h"
#include "type.h"
sbit BP = P0^6; sbit RL = P0^4;
sbit SONT = P1^0; sbit SONR = P1^1;
#define SELE(x) P2=P2&0x1f|x<<5; P2=P2&0x1f
#define BPON	BP = 1;P2=P2&0x1f|5<<5; P2=P2&0x1f
#define BPOFF	BP = 0;P2=P2&0x1f|5<<5; P2=P2&0x1f
#define RLON	RL = 1;P2=P2&0x1f|5<<5; P2=P2&0x1f
#define RLOFF	RL = 0;P2=P2&0x1f|5<<5; P2=P2&0x1f

#define F_CC 10
#define F_C		11
#define	F_P		12
#define F_A		13
#define XS 14
sbit C1 = P4^4; sbit C2 = P4^2; sbit R1 = P3^2; sbit R2 = P3^3;


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

void TimeRun(t_delay* time);
void SL(uchar _dev, uchar _data);
void Timer1Init(void);
void Buf(uchar _0, uchar _1, uchar _2, uchar _3, 
		 uchar _4, uchar _5, uchar _6, uchar _7);
uchar GetKey();
void TempRead();
void DacInit(uchar _addr, uchar _data);
uchar FR(float tmpVal, uchar dig);
uchar CalcDac( float tmpVal, uchar mode);
uchar checkbit(uchar _data, uchar _dig);
uchar changebit(uchar _data, uchar _dig, uchar val);
extern tempVal;
#endif
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一WILLPOWER一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值