答案仅供参考,有错误欢迎指正,非常感谢!!!
文件较多,代码较长,感谢查看!!!
目录
题目分析
这必须要吐槽这届的国赛题目,感觉很不严谨,都不知道出题者是怎么想的。如果要参考这届国赛的题目,参考意义不大。
按键部分
先看一下按键部分。
- 我就问一下,这电压阈值设置是干哈用的呀?摆设用的吗?嗯?
- 你那个快速增加功能是个啥呀?何为快速增加呀?你快速的标准呢?
- 如果按这样说的话,在电压阈值参数设置界面下:在快速增加功能关闭的状态下,按下S6的时间如果在800ms内,阈值+0.1,如果大于800ms,快速增加功能则开启;在快速增加功能开启的状态下,按下S6的时间如果在800ms内,阈值不断地增加,如果按下S6的时间大于800ms,快速增加功能则关闭。
LED灯部分
这讲的是啥啊,难道上电后不是每时每刻都在测量的吗?你不测量,我一上电就按下S5呢?我存个寂寞?
我的理解是,在数据显示状态下。
还有,连上电初始状态也没有,这届国赛题,我真的是服了。
main.h
#ifndef __MAIN_H_
#define __MAIN_H_
#define uchar unsigned char
#define uint unsigned int
#include <STC15F2K60S2.H>
#include "Init.h"
#include "SMG.h"
#include "DSQ.h"
#include "YanShi.h"
#include "DLKey.h"
#include "iic.h"
#include "onewire.h"
#include "LN555.h"
void SMG_XianShi();
void LED_XianShi();
#endif
main.c
#include "main.h"
uchar KuaiSu_GongNeng_flag=0;//快速功能开启标志位
uchar yu_zhi=1;//阈值
uchar jie_mian=0;//界面
uchar xian_shi=0;//显示
uchar ShuJu_XianShi=0;//数据显示
uchar ShuJu_HuiXian=0;//数据回显
int wen_du=0;//温度
uint Hz=0;//频率
uchar flag1=0;//定时器1标志位
uint LN555_time=0;//555定时器的时间
uchar key_num=0;//键值
uchar dian_ya=0;//电压
uint S6_KeyTime=0;//S6按键按下的时间
int EEPROM_wen_du=0;//EEPROM存储的温度
uchar EEPROM_dian_ya=0;//EEPROM存储的电压
uint EEPROM_Hz=0;//EEPROM存储的频率
uchar EEPROM_yu_zhi;//EEPROM存储的阈值
uchar ADC_date=0;//ADC采集到电压数据
uchar ADC_flag=2;//ADC采集标志位
void main(){
uchar key_num_old;//上一个键值
uint wen_du_temp;//临时的温度
uint EEPROM_di;//EEPROM的低8位
uint EEPROM_gao;//EEPROM的高8位
Init_BZ();
SMG_Init();
DSQ_1_Init();
DLKey_Init();
LN555_Init();
if(IIC_EEPROM_GetDate(0x50)==1){//如果地址0x51做了标志,则读取EEPROM数据
//读取EEPROM的温度数据
EEPROM_gao=IIC_EEPROM_GetDate(0x10);
Delay10ms();
EEPROM_di=IIC_EEPROM_GetDate(0x11);
Delay10ms();
if(EEPROM_gao>=0x80){//上一次存储的温度为负
EEPROM_gao=EEPROM_gao&0x7f;//清除最高标志位
EEPROM_wen_du=-((EEPROM_gao<<8)|EEPROM_di);
}
else{
EEPROM_wen_du=((EEPROM_gao<<8)|EEPROM_di);
}
//读取EEPROM的电压数据
EEPROM_dian_ya=IIC_EEPROM_GetDate(0x20);
Delay10ms();
//读取EEPROM的频率数据
EEPROM_gao=IIC_EEPROM_GetDate(0x30);
Delay10ms();
EEPROM_di=IIC_EEPROM_GetDate(0x31);
Delay10ms();
EEPROM_Hz=(EEPROM_gao<<8)|EEPROM_di;
//读取EEPROM阈值数据
EEPROM_yu_zhi=IIC_EEPROM_GetDate(0x40);
Delay10ms();
}
while(1){
//获取键值
key_num_old=key_num;
key_num=DLKey_GetKeynum();
if(key_num!=key_num_old||(key_num==6&&jie_mian==2)){//不在参数界面下,或者前后键值不同才能进入
if(key_num==4){//“切换”按键
if(jie_mian==0){//在数据显示界面
ShuJu_XianShi++;
ShuJu_XianShi=ShuJu_XianShi%3;
}
else if(jie_mian==1){//在数据回显界面
ShuJu_HuiXian++;
ShuJu_HuiXian=ShuJu_HuiXian%3;
}
}
else if(key_num==5){//“存储”按键
EEPROM_wen_du=wen_du;
EEPROM_dian_ya=dian_ya;
EEPROM_Hz=Hz;
EEPROM_yu_zhi=yu_zhi;
//第一次上电,按下存储数据,做下标志位
if(IIC_EEPROM_GetDate(0x50)!=1){
IIC_EEPROM_XieDate(0x50,1);
Delay10ms();
}
//存储温度
if(wen_du<0){//温度在0下的
wen_du_temp=-wen_du;
IIC_EEPROM_XieDate(0x10,((wen_du_temp>>8)|0x80));//最高位置1,作0下温度的标志位 1xxx xxxx 最高15000 -> 0011 1010 1001 1000
Delay10ms();
IIC_EEPROM_XieDate(0x11,(wen_du_temp&0x00ff));
Delay10ms();
}
else{//0度以上
IIC_EEPROM_XieDate(0x10,(wen_du>>8));
Delay10ms();
IIC_EEPROM_XieDate(0x11,(wen_du&0x00ff));
Delay10ms();
}
//存储电压
IIC_EEPROM_XieDate(0x20,dian_ya);
Delay10ms();
//存储频率
IIC_EEPROM_XieDate(0x30,(Hz>>8));
Delay10ms();
IIC_EEPROM_XieDate(0x31,(Hz&0x00ff));
Delay10ms();
//存储阈值
IIC_EEPROM_XieDate(0x40,yu_zhi);
Delay10ms();
}
else if(key_num==6){//“回显”按键
if(jie_mian!=2){//不在参数设置界面
jie_mian++;
jie_mian=jie_mian%2;
}
else{//在参数设置界面
if(KuaiSu_GongNeng_flag){//快速功能开启
if(S6_KeyTime==100||S6_KeyTime==200||S6_KeyTime==300||S6_KeyTime==400||S6_KeyTime==500||S6_KeyTime==600||S6_KeyTime==700){//100ms加一次
yu_zhi++;
if(yu_zhi>50){
yu_zhi=1;
}
}
}
else if(key_num!=key_num_old&&KuaiSu_GongNeng_flag==0){//快速功能关闭,避免连续触发
yu_zhi++;
if(yu_zhi>50){
yu_zhi=1;
}
}
}
}
else if(key_num==7){//参数“设置”按键
jie_mian++;
jie_mian=jie_mian%3;
if(jie_mian==1){//跳过回显界面
jie_mian++;
jie_mian=jie_mian%3;
}
}
}
//获取温度
wen_du=DS18B20_GetWenDu()*100;
//获取电压
if(ADC_flag>=1){
ADC_date=IIC_ADC_GetDate(3);
ADC_flag=0;
}
}
}
void DSQ_1_ZD() interrupt 3{
flag1++;
LN555_time++;
ADC_flag++;
//555定时器计算频率
if(LN555_time>=1000){
Hz=((unsigned int)TH0<<8)|(unsigned int)TL0;
TH0=0;
TL0=0;
LN555_time=0;
}
//快速功能开启与关闭
if(jie_mian==2&&key_num==6){//在参数界面设置界面下
S6_KeyTime++;
}
else{
S6_KeyTime=0;
}
if(S6_KeyTime>=800){//S6按下时间达到0.8s
KuaiSu_GongNeng_flag++;
KuaiSu_GongNeng_flag=KuaiSu_GongNeng_flag%2;
S6_KeyTime=0;
}
if(flag1>=2){
flag1=0;
SMG_XianShi();
LED_XianShi();
}
}
void SMG_XianShi(){//数码管显示
switch(jie_mian){
case 0:{//数据显示界面
switch(ShuJu_XianShi){
case 0:{//温度显示界面
if(wen_du>=10000){
SMG_Show(12,16,16,wen_du/10000,(wen_du/1000)%10,((wen_du/100)%10)+32,(wen_du/10)%10,wen_du%10);
}
else if(wen_du>=1000){
SMG_Show(12,16,16,16,wen_du/1000,((wen_du/100)%10)+32,(wen_du/10)%10,wen_du%10);
}
else if(wen_du>=0){
SMG_Show(12,16,16,16,16,(wen_du/100)+32,(wen_du/10)%10,wen_du%10);
}
else if(wen_du>-1000){
SMG_Show(12,16,16,16,17,((-wen_du)/100)+32,((-wen_du)/10)%10,(-wen_du)%10);
}
else if(wen_du>-10000){
SMG_Show(12,16,16,17,(-wen_du)/1000,(((-wen_du)/100)%10)+32,((-wen_du)/10)%10,(-wen_du)%10);
}
break;
}
case 1:{//电压显示界面
dian_ya=((ADC_date*1.0)/51.0)*10;
SMG_Show(25,16,16,16,16,16,(dian_ya/10)+32,dian_ya%10);
break;
}
case 2:{//频率显示界面
if(Hz>=10000){
SMG_Show(15,16,16,Hz/10000,(Hz/1000)%10,(Hz/100)%10,(Hz/10)%10,Hz%10);
}
else if(Hz>=1000){
SMG_Show(15,16,16,16,Hz/1000,(Hz/100)%10,(Hz/10)%10,Hz%10);
}
else if(Hz>=100){
SMG_Show(15,16,16,16,16,Hz/100,(Hz/10)%10,Hz%10);
}
else if(Hz>=10){
SMG_Show(15,16,16,16,16,16,Hz/10,Hz%10);
}
else if(Hz>=0){
SMG_Show(15,16,16,16,16,16,16,Hz);
}
break;
}
}
break;
}
case 1:{//数据回显显示界面
switch(ShuJu_HuiXian){
case 0:{//温度数据回显界面
if(EEPROM_wen_du>=10000){
SMG_Show(18,12,16,EEPROM_wen_du/10000,(EEPROM_wen_du/1000)%10,((EEPROM_wen_du/100)%10)+32,(EEPROM_wen_du/10)%10,EEPROM_wen_du%10);
}
else if(EEPROM_wen_du>=1000){
SMG_Show(18,12,16,16,EEPROM_wen_du/1000,((EEPROM_wen_du/100)%10)+32,(EEPROM_wen_du/10)%10,EEPROM_wen_du%10);
}
else if(EEPROM_wen_du>=0){
SMG_Show(18,12,16,16,16,(EEPROM_wen_du/100)+32,(EEPROM_wen_du/10)%10,EEPROM_wen_du%10);
}
else if(EEPROM_wen_du>-1000){
SMG_Show(18,12,16,16,17,((-EEPROM_wen_du)/100)+32,((-EEPROM_wen_du)/10)%10,(-EEPROM_wen_du)%10);
}
else if(EEPROM_wen_du>-10000){
SMG_Show(18,12,16,17,(-EEPROM_wen_du)/1000,(((-EEPROM_wen_du)/100)%10)+32,((-EEPROM_wen_du)/10)%10,(-EEPROM_wen_du)%10);
}
break;
}
case 1:{//电压数据回显界面
SMG_Show(18,25,16,16,16,16,(EEPROM_dian_ya/10)+32,EEPROM_dian_ya%10);
break;
}
case 2:{//频率数据回显界面
if(EEPROM_Hz>=10000){
SMG_Show(18,15,16,EEPROM_Hz/10000,(EEPROM_Hz/1000)%10,(EEPROM_Hz/100)%10,(EEPROM_Hz/10)%10,EEPROM_Hz%10);
}
else if(EEPROM_Hz>=1000){
SMG_Show(18,15,16,16,EEPROM_Hz/1000,(EEPROM_Hz/100)%10,(EEPROM_Hz/10)%10,EEPROM_Hz%10);
}
else if(EEPROM_Hz>=100){
SMG_Show(18,15,16,16,16,EEPROM_Hz/100,(EEPROM_Hz/10)%10,EEPROM_Hz%10);
}
else if(EEPROM_Hz>=10){
SMG_Show(18,15,16,16,16,16,EEPROM_Hz/10,EEPROM_Hz%10);
}
else if(EEPROM_Hz>=0){
SMG_Show(18,15,16,16,16,16,16,EEPROM_Hz);
}
break;
}
}
break;
}
case 2:{//电压阈值设置界面
SMG_Show(24,16,16,16,16,16,(yu_zhi/10)+32,yu_zhi%10);
break;
}
}
}
void LED_XianShi(){//LED灯显示
uchar L1_2_3=0xff;
if(jie_mian==0){
switch(ShuJu_XianShi){
case 0:{
L1_2_3=0xfe;
break;
}
case 1:{
L1_2_3=0xfd;
break;
}
case 2:{
L1_2_3=0xfb;
break;
}
}
}
else{
L1_2_3=0xff;
}
P0=L1_2_3;
P2=(P2&0x1f)|0x80;
P2=(P2&0x1f)|0x00;
}
Init.h
#ifndef __INIT_H_
#define __INIT_H_
#include <STC15F2K60S2.H>
void Init_BZ();
#endif
Init.c
#include "Init.h"
void Init_BZ(){
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2=(P2&0x1f)|0x80;
P0=0xff;
}
SMG.h
#ifndef __SMG_H_
#define __SMG_H_
#include <STC15F2K60S2.H>
void SMG_Init();
void SMG_Show(unsigned char n1,n2,n3,n4,n5,n6,n7,n8);
#endif
SMG.c
#include "SMG.h"
unsigned char code SMG_ZK[]={ //????
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
void SMG_Init(){
P2=(P2&0x1f)|0xc0;
P0=0xff;
P2=(P2&0x1f)|0xe0;
P0=0xff;
}
void SMG_Show(unsigned char n1,n2,n3,n4,n5,n6,n7,n8){
static unsigned char i=0;
i++;
i=i%8;
P2=(P2&0x1f)|0xc0;
switch(i){
case 1:{
P0=0x01;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n1];
break;
}
case 2:{
P0=0x02;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n2];
break;
}
case 3:{
P0=0x04;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n3];
break;
}
case 4:{
P0=0x08;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n4];
break;
}
case 5:{
P0=0x10;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n5];
break;
}
case 6:{
P0=0x20;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n6];
break;
}
case 7:{
P0=0x40;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n7];
break;
}
case 0:{
P0=0x80;
P2=(P2&0x1f)|0xe0;
P0=~SMG_ZK[n8];
break;
}
}
P2=(P2&0x1f)|0x00;
}
DSQ.h
#ifndef __DSQ_H_
#define __DSQ_H_
#include <STC15F2K60S2.H>
void DSQ_1_Init();
#endif
DSQ.c
#include "DSQ.h"
void DSQ_1_Init(){
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初值
TH1 = 0xD1; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;
ET1=1;
}
YanShi.h
#ifndef __YANSHI_H_
#define __YANSHI_H_
#include <STC15F2K60S2.H>
#include "intrins.h"
void Delay10ms();
#endif
YanShi.c
#include "YanShi.h"
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
DLKey.h
#ifndef __DLKEY_H_
#define __DLKEY_H_
#include "YanShi.h"
void DLKey_Init();
unsigned char DLKey_GetKeynum();
#endif
DLKey.c
#include "DLKey.h"
void DLKey_Init(){
P30=1;
P31=1;
P32=1;
P33=1;
}
unsigned char DLKey_GetKeynum(){
unsigned char key_num=0;
if(P30==0){
Delay10ms();
if(P30==0){
key_num=7;
}
}
else if(P31==0){
Delay10ms();
if(P31==0){
key_num=6;
}
}
else if(P32==0){
Delay10ms();
if(P32==0){
key_num=5;
}
}
else if(P33==0){
Delay10ms();
if(P33==0){
key_num=4;
}
}
DLKey_Init();
return key_num;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit SDA = P2^1;
sbit SCL = P2^0;
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);
unsigned char IIC_ADC_GetDate(unsigned char di_zhi);
void IIC_DAC_XieDate(unsigned char date);
void IIC_EEPROM_XieDate(unsigned char di_zhi,unsigned char date);
unsigned char IIC_EEPROM_GetDate(unsigned char di_zhi);
#endif
iic.c
#include "iic.h"
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
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;
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;
}
unsigned char IIC_ADC_GetDate(unsigned char di_zhi){
unsigned char date;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(di_zhi);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
date=IIC_RecByte();
IIC_SendAck(1);
IIC_WaitAck();
IIC_Stop();
return date;
}
void IIC_DAC_XieDate(unsigned char date){
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
void IIC_EEPROM_XieDate(unsigned char di_zhi,unsigned char date){
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(di_zhi);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
}
unsigned char IIC_EEPROM_GetDate(unsigned char di_zhi){
unsigned char date;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(di_zhi);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
date=IIC_RecByte();
IIC_SendAck(1);
IIC_WaitAck();
IIC_Stop();
return date;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include <STC15F2K60S2.H>
sbit DQ = P1^4;
unsigned char rd_temperature(void);
float DS18B20_GetWenDu();
#endif
onewire.c
#include "onewire.h"
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//单总线写操作
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);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
float DS18B20_GetWenDu(){
unsigned char di,gao;
float wen_du,zheng_shu,xiao_shu;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
EA=0;
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
EA=1;
EA=0;
di=Read_DS18B20();
gao=Read_DS18B20();
EA=1;
if(gao>=248){
di=~di;
gao=~gao;
if(di==0xff){
di=0;
gao++;
}
else{
di++;
}
zheng_shu=((gao<<4)|(di>>4))*1.0;
xiao_shu=(di&0x0f)*0.0625;
wen_du=-(zheng_shu+xiao_shu);
}
else{
zheng_shu=((gao<<4)|(di>>4))*1.0;
xiao_shu=(di&0x0f)*0.0625;
wen_du=(zheng_shu+xiao_shu);
}
return wen_du;
}
LN555.h
#ifndef __LN555_H_
#define __LN555_H_
#include <STC15F2K60S2.H>
void LN555_Init();
#endif
LN555.c
#include "LN555.h"
void LN555_Init(){
TMOD=(TMOD&0xf0)|0x05;
TH0=0;
TL0=0;
TR0=1;
ET0=0;
}