蓝桥杯单片机12届省赛主观题解题
Posted WILLPOWER-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯单片机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)
{
《蓝桥杯真题》:2.第十二届省赛