蓝桥杯单片机第14届国赛满分代码
·

回头看看,从找出被撑爆的内存,再到最后完美搞定 DAC 的“幻灯片”平滑输出,这 100 分全是我一步步啃下硬骨头、坚持不懈调试换来的!
main.c
#include <STC15F2K60S2.H>
#include <seg.h>
#include <chao.h>
#include <ds18b20.h>
#include <key.h>
#include <led.h>
#include <pcf8591.h>
#include <seg.h>
#include <init.h>
unsigned char seg_pos;
idata unsigned char seg_buf[8]={10,10,10,10,10,10,10,10};
idata unsigned char seg_point[8]={0,0,0,0,0,0,0,0};
idata unsigned char ucled[8]={0,0,0,0,0,0,0,0};
unsigned char seg_slow_down;//100
unsigned char key_slow_down;//10
unsigned char ad_slow_down;//70
unsigned char led_slow_down;//50
unsigned char segmode;
unsigned char key_val;//当前状态
unsigned char key_old;//以前的状态
unsigned char key_down;
unsigned char key_up;
unsigned char m,can,she;
float tem;
unsigned int dis;
unsigned char jvcan=40;
unsigned char wcan=30;
char j=0;
unsigned char j_fu;
unsigned int su=340;
idata float xia=1.0;
bit f2s;//s8,s9是否同时按下的标志位
unsigned int t2000ms;//s8,s9按键均处于按下状态,状态持续时间是否超过2s
bit jilu;//jilu==1时,所有按键操作无效
unsigned int t6000ms;
bit start_adc;
unsigned char adc_index;
float v_shu;
unsigned char t100ms;
unsigned char t100ms_ji;
bit f100ms;
xdata unsigned int dis_ji[70];
// ========== 新增这一行 ==========
extern unsigned int time_quan;
// ================================//它告诉编译器“不要重新分配内存了,这个变量在别的 .c 文件里已经定义过了,你直接拿来用就行”。
unsigned char j_index;
unsigned char shu_index;
void seg_proc()
{
if(seg_slow_down<100)return;
seg_slow_down=0;
tem=rd_temperature();
distance(); // 仅调用一次超声波函数,目的是让底层更新全局变量 time_quan
switch(segmode)
{
case 0://测距界面
seg_point[1]=1;
//温度数据
if(tem>=10)
{
seg_buf[0]=(unsigned char )tem/10%10;
seg_buf[1]=(unsigned char )tem%10;
seg_buf[2]=((unsigned int )(tem*10+0.5))%10;
}
else
{
seg_buf[0]=10;
seg_buf[1]=(unsigned char )tem%10;
seg_buf[2]=((unsigned int )(tem*10+0.5))%10;
}
seg_buf[3]=11;
//测距数据
if(m==0)//cm
{
seg_buf[4]=10;
seg_buf[5]=10;
seg_buf[6]=(dis>=10)?dis/10 %10:10;
seg_buf[7]=(dis>=1)?dis %10:10;
seg_point[5]=0;
seg_point[6]=0;
}
else//m
{
seg_buf[4]=10;
seg_buf[5]=0;
seg_buf[6]=(dis>=10)?dis/10 %10:10;
seg_buf[7]=(dis>=1)?dis %10:10;
seg_point[5]=1;
seg_point[6]=0;
}
break;
case 1://参数界面
seg_point[1]=0;
seg_point[5]=0;
seg_point[6]=0;
seg_buf[0]=12;
seg_buf[1]=can+1;
seg_buf[2]=10;
seg_buf[3]=10;
seg_buf[4]=10;
seg_buf[5]=10;
if(can==0)//距离参数
{
seg_buf[6]=jvcan/10;
seg_buf[7]=jvcan%10;
}
else//温度参数
{
seg_buf[6]=(wcan>=10)?wcan/10:10;
seg_buf[7]=wcan%10;
}
break;
case 2://工厂模式
seg_point[1]=0;
seg_point[5]=0;
seg_buf[0]=13;
seg_buf[1]=she+1;
//校准值数据
switch(she)
{
case 0://标准值设置界面
seg_buf[2]=10;
seg_buf[3]=10;
seg_buf[4]=10;
if(j>=0)
{
seg_buf[5]=10;
seg_buf[6]=(j>=10)?j/10 %10:10;
seg_buf[7]=(j>=0)?j %10:10;
}
else
{
j_fu=j*(-1);
if(j_fu>=10)
{
seg_buf[5]=11;
seg_buf[6]=j_fu/10 %10;
seg_buf[7]=j_fu %10;
}
else
{
seg_buf[5]=10;
seg_buf[6]=11;
seg_buf[7]=j_fu %10;
}
}
seg_point[6]=0;
break;
case 1://介质设置界面
seg_buf[2]=10;
seg_buf[3]=10;
//传输速度
seg_buf[4]=(su>=1000)?su/1000 %10:10;
seg_buf[5]=(su>=100)?su/100 %10:10;
seg_buf[6]=(su>=10)?su/10 %10:10;
seg_buf[7]=(su>=1)?su %10:10;
seg_point[6]=0;
break;
case 2://dac输出设置
seg_buf[2]=10;
seg_buf[3]=10;
seg_buf[4]=10;
seg_buf[5]=10;
//dac输出下限值
if(xia<1)//0.1
{
seg_buf[6]=0;
seg_buf[7]=(unsigned char)(xia*10+0.2);
seg_point[6]=1;
}
else//2.0
{
seg_buf[6]=(unsigned char)(xia*10+0.2)/10;
seg_buf[7]=(unsigned char)(xia*10+0.2)%10;
seg_point[6]=1;
}
break;
}
break;
}
}
void key_proc()
{
if(key_slow_down<10)return ;
key_slow_down=0;
key_val=rd_key();
key_down=key_val &(key_old^key_val);
key_up=~key_val & (key_old^key_val);
if(jilu==0)//不在记录状态
{
if(key_val==89)//s8,s9均处于按下状态
{
f2s=1;
}
else
{
f2s=0;//t2000ms不再开始计时
if(t2000ms>2000)//s8,s9处于按下状态,且状态持续时间超过2s
{
m=0;
jvcan=40;
wcan=30;
j=0;
su=340;
xia=1.0;
segmode=0;
t2000ms=0;
}
}
key_old=key_val;
switch(key_down)
{
case 4://界面按键
if(++segmode==3)segmode=0;
if(segmode==0)//每次重新进入测距界面
{
m=0;
}
if(segmode==1)//每次从测距界面切换到参数界面
{
can=0;
}
if(segmode==2)
{
she=0;
}
break;
case 5:
switch(segmode)
{
case 0://在测距界面下
m^=1;//切换距离显示单位
break;
case 1://在参数界面下
can^=1;
break;
case 2://在工厂模式下
if(++she==3)she=0;
break;
}
break;
case 8://加
if(segmode==1&&can==0)//在距离参数界面下
{
jvcan+=10;
if(jvcan>92)jvcan=10;
}
if(segmode==1&&can==1)//在温度参数界面下
{
if(++wcan==81)wcan=0;
}
if(segmode==2&&she==0)
{
j+=5;
if(j>91)j=-90;
}
if(segmode==2&&she==1)
{
su+=10;
if(su>9991)su=10;
}
if(segmode==2&&she==2)
{
xia+=0.1;
if(xia>2.05)xia=0.1;
}
if(segmode==0)//在测距界面下,定义为距离“记录”按键
{
jilu=1;//开始记录接下来6秒内距离数据的连续变化
t6000ms=0;//开始计时
j_index=0;//开始从0开始记录电压
}
break;
case 9://减
if(segmode==1&&can==0)//在距离参数界面下
{
jvcan-=10;
if(jvcan<8)jvcan=90;
}
if(segmode==1&&can==1)//在温度参数界面下
{
if(--wcan>200)wcan=80;
}
if(segmode==2&&she==0)
{
j-=5;
if(j<-91)j=90;
}
if(segmode==2&&she==1)
{
su-=10;
if(su<9)su=9990;
}
if(segmode==2&&she==2)
{
xia-=0.1;
if(xia<0.09)xia=2.0;
}
if(segmode==0)//在测距界面下,定义为“输出”按键
{
if(jilu==0)//设备已完成数据记录
{
start_adc=1;//开始让dac把dis_ji[]里的数据像放幻灯片一样一张张播出来
adc_index=0;
}
}
break;
}
}
}
void led_proc()
{
unsigned char i;
if(led_slow_down<50)return ;
led_slow_down=0;
//校准测距结果
dis=(unsigned int)((su*100)*((time_quan/1000000.0)/2.0)+j);//(没按S8前):只测距,不输出DAC
//led指示灯
if(segmode==0)//测距界面
{
if(dis>=255)
{
for(i=0;i<8;i++)
{
ucled[i]=1;
}
}
else
{
for(i=0;i<8;i++)
{
if((dis&(0x01<<i))!=0)
ucled[i]=1;
else ucled[i]=0;
}
}
}
if(segmode==1)//参数界面
{
ucled[7]=1;
ucled[0]=ucled[1]=ucled[2]=ucled[3]=ucled[4]=ucled[5]=ucled[6]=0;
}
if(segmode==2)//工厂界面
{
ucled[0]=(f100ms==1)?1:0;
ucled[7]=ucled[1]=ucled[2]=ucled[3]=ucled[4]=ucled[5]=ucled[6]=0;
}
//继电器控制
if((dis>=jvcan-5)&&(dis<=jvcan+5)&&(tem<=wcan))relay(1);
else relay(0);
}
void ad_proc()
{
unsigned int dis_val;//用于输出dis_ji[]里的数据
if(ad_slow_down<70)return ;
ad_slow_down=0;
if(start_adc==1)//开始输出adc
{
if(adc_index<60)//电压没有输完
{
dis_val=dis_ji[adc_index];//一个一个数据接着来
//DAC输出功能
if(dis_val<10)
{
v_shu=xia;
}
else if(dis_val>=10&&dis_val<=90)
{
v_shu=((5.0-xia)/80.0)*(dis_val-90.0)+5.0;
}
else
{
v_shu=5.0;
}
da_zhuanhuan(v_shu*51.0);
adc_index++;//切换到下一个数据
}
else//说明已经全部输出完了
{
adc_index=0;//从0开始输出电压
start_adc=0;//停止输出adc
}
}
}
void servicet1() interrupt 3
{
seg_slow_down++;
ad_slow_down++;
key_slow_down++;
led_slow_down++;
if(++seg_pos==8)seg_pos=0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(ucled);
//判断s8,s9同时按下有没有超过2s
if(f2s==1)
{
if(t2000ms<3000)
{
t2000ms++;
}
}
if(jilu==1)//开始记录接下来6s内距离数据的连续变化
{
if(++t6000ms==6000)
{
t6000ms=0;
jilu=0;//数据记录完成
}
if(++t100ms_ji==100)//把6000ms分成60分
{
t100ms_ji=0;
dis_ji[j_index]=dis;//把数据存进了 dis_ji 数组里
j_index++;
}
}
if(++t100ms==100)
{
t100ms=0;
f100ms^=1;
}
}
void main()
{
Delay750ms();
rd_temperature();
sys_init();
Timer1_Init();
while(1)
{
seg_proc();
key_proc();
led_proc();
ad_proc();
}
}
seg.c
#include <seg.h>
unsigned char code seg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char code seg_duan[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,
0xbf,0x8c,0x8e};
//11---,12--P,13--F
void seg_disp(unsigned char wei,duan,point)
{
P0=0XFF;
P2=P2&0X1F|0XE0;
P2&=0X1F;
P0=seg_wei[wei];
P2=P2&0X1F|0Xc0;
P2&=0X1F;
P0=seg_duan[duan];
if(point==1)P0&=0x7f;
P2=P2&0X1F|0XE0;
P2&=0X1F;
}
init.c
#include <init.h>
void sys_init(void)
{
P0=0xff;
P2=P2&0X1F|0X80;
P2&=0X1F;
P0=0x00;
P2=P2&0X1F|0Xa0;
P2&=0X1F;
}
void Delay750ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
}
led.c
#include <led.h>
static unsigned char temp_l=0x00;
static unsigned char temp_old_l=0xff;
void led_disp(unsigned char *ucled)
{
temp_l=0x00;
temp_l=(ucled[0]<<0)|(ucled[1]<<1)|
(ucled[2]<<2)|(ucled[3]<<3)|
(ucled[4]<<4)|(ucled[5]<<5)|
(ucled[6]<<6)|(ucled[7]<<7);
if(temp_l!=temp_old_l)
{
P0=~temp_l;
P2=P2&0X1F|0X80;
P2&=0X1F;
temp_old_l=temp_l;
}
}
static unsigned char temp_3=0x00;
static unsigned char temp_old_3=0xff;
void relay(bit enable)
{
if(enable==1)
{
temp_3|=0x10;
}
else temp_3 &=~0x10;
if(temp_3!=temp_old_3)
{ EA=0;
P0=temp_3;
P2=P2&0X1F|0Xa0;
P2&=0X1F;
temp_old_3=temp_3;
EA=1;
}
}
pcf8591.c
#include <pcf8591.h>
/* # I2C浠g爜鐗囨璇存槑
1. 鏈枃浠跺す涓彁渚涚殑椹卞姩浠g爜渚涘弬璧涢€夋墜瀹屾垚绋嬪簭璁捐鍙傝€冦€?
2. 鍙傝禌閫夋墜鍙互鑷缂栧啓鐩稿叧浠g爜鎴栦互璇ヤ唬鐮佷负鍩虹锛屾牴鎹墍閫夊崟鐗囨満绫诲瀷銆佽繍琛岄€熷害鍜岃瘯棰?
涓鍗曠墖鏈烘椂閽熼鐜囩殑瑕佹眰锛岃繘琛屼唬鐮佽皟璇曞拰淇敼銆?
*/
sbit scl=P2^0;
sbit sda=P2^1;
#define DELAY_TIME 1
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
////
//unsigned char I2CReceiveByte(void)
//{
// unsigned char da;
// unsigned char i;
// for(i=0;i<8;i++){
// scl = 1;
// I2C_Delay(DELAY_TIME);
// da <<= 1;
// if(sda)
// da |= 0x01;
// scl = 0;
// I2C_Delay(DELAY_TIME);
// }
// return da;
//}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
////
//void I2CSendAck(unsigned char ackbit)
//{
// scl = 0;
// sda = ackbit;
// I2C_Delay(DELAY_TIME);
// scl = 1;
// I2C_Delay(DELAY_TIME);
// scl = 0;
// sda = 1;
// I2C_Delay(DELAY_TIME);
//}
//unsigned char ad_zhuanhuan(unsigned char addr)//读
//{
// unsigned char temp;
// EA=0;
// //start
// I2CStart();
//
// //写芯片地址
// I2CSendByte(0x90);
// I2CWaitAck();
// //写选择通道
// I2CSendByte(addr);
// I2CWaitAck();
//
//
// //start
// I2CStart();
// //写芯片地址
// I2CSendByte(0x91);
// I2CWaitAck();
//
//
// //保存数据
// temp=I2CReceiveByte();
// //发送ack(1)
// I2CSendAck(1);
// //stop
// I2CStop();
//
// EA=1;
// return temp;
//
//}
void da_zhuanhuan(unsigned char dat)//写
{
EA=0;
//start
I2CStart();
//写芯片地址
I2CSendByte(0x90);
I2CWaitAck();
//写选择通道
I2CSendByte(0x41);
I2CWaitAck();
//写数据
I2CSendByte(dat);
I2CWaitAck();
//stop
I2CStop();
EA=1;
}
//void ee_write(unsigned char *str,unsigned char addr,unsigned char num)
//{
// EA=0;
// //start
// I2CStart();
//
//
// //写芯片地址
// I2CSendByte(0xa0);
// I2CWaitAck();
// //写选择通道
// I2CSendByte(addr);
// I2CWaitAck();
//
// //写数据
// while(num--)
// {
// I2CSendByte(*str++);
// I2CWaitAck();
// I2C_Delay(200);
// }
//
// //stop
// I2CStop();
// EA=1;
//
// I2C_Delay(255);
// I2C_Delay(255);
// I2C_Delay(255);
// I2C_Delay(255);
//}
//void ee_read(unsigned char *str,unsigned char addr,unsigned char num)
//{
// EA=0;
// //start
// I2CStart();
//
//
// //写芯片地址
// I2CSendByte(0xa0);
// I2CWaitAck();
// //写选择通道
// I2CSendByte(addr);
// I2CWaitAck();
//
//
// //start
// I2CStart();
// //写芯片地址
// I2CSendByte(0xa1);
// I2CWaitAck();
//
//
// //保存数据
// while(num--)
// {
// *str++=I2CReceiveByte();
// if(num)I2CSendAck(0);
// else I2CSendAck(1);
// }
//
// //stop
// I2CStop();
// EA=1;
//}
key.c
#include <key.h>
unsigned char rd_key(void)
{
unsigned char temp=0;
AUXR&=~0X10;
P44=0;P42=1;P35=1;P34=1;
if(P30==0)temp=7;
if(P31==0)temp=6;
if(P32==0)temp=5;
if(P33==0)temp=4;
P44=1;P42=0;P35=1;P34=1;
if(P30==0)temp=11;
if(P31==0)temp=10;
if(P32==0)temp=9;
if(P33==0)temp=8;
if(P33==0&&P32==0)temp=89;
P44=1;P42=1;P35=0;P34=1;
if(P30==0)temp=15;
if(P31==0)temp=14;
if(P32==0)temp=13;
if(P33==0)temp=12;
AUXR |=0X10;
return temp;
}
chao.c
#include <chao.h>
sbit TX=P1^0;
sbit RX=P1^1;
// 在文件头部定义一个全局变量
unsigned int time_quan;
void Delay12us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 38;
while (--i);
}
void wave_init(void)
{
unsigned char i;
EA=0;
for(i=0;i<8;i++)
{
TX=1;
Delay12us();
TX=0;
Delay12us();
}
EA=1;
}
unsigned int distance(void)
{
unsigned int time;
CH=CL=0;
CMOD=0X00;
wave_init();
CR=1;
while((RX==1)&&(CF==0));
CR=0;
if(CF==0)
{
time=(CH<<8)|CL;
time_quan=time;
return (time*0.017);
}
else//超时没收到
{
CF=0;
time_quan=0;
return 0;
}
}
ds18b20.c
#include <ds18b20.h>
sbit DQ=P1^4;
/* # 鍗曟€荤嚎浠g爜鐗囨璇存槑
1. 鏈枃浠跺す涓彁渚涚殑椹卞姩浠g爜渚涘弬璧涢€夋墜瀹屾垚绋嬪簭璁捐鍙傝€冦€?
2. 鍙傝禌閫夋墜鍙互鑷缂栧啓鐩稿叧浠g爜鎴栦互璇ヤ唬鐮佷负鍩虹锛屾牴鎹墍閫夊崟鐗囨満绫诲瀷銆佽繍琛岄€熷害鍜岃瘯棰?
涓鍗曠墖鏈烘椂閽熼鐜囩殑瑕佹眰锛岃繘琛屼唬鐮佽皟璇曞拰淇敼銆?
*/
//
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;
}
//
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 rd_temperature(void)
{
unsigned char low,high;
EA=0;init_ds18b20();EA=1;
EA=0;Write_DS18B20(0xcc);EA=1;
EA=0;Write_DS18B20(0xbe);EA=1;
EA=0;low=Read_DS18B20();EA=1;
EA=0;high=Read_DS18B20();EA=1;
EA=0;init_ds18b20();EA=1;
EA=0;Write_DS18B20(0xcc);EA=1;
EA=0;Write_DS18B20(0x44);EA=1;
return ((float)(high<<8|low))*0.0625;
}
更多推荐
所有评论(0)