距离比赛还有15天,昨天发愤图强,想做一个练练手,又想到了第十二届的第二批没有写,然后在同专业大佬的帮助下,在一天做完了一届,速度最快的一次了,废话不多说,先看原题
设计思路
第一眼看真是没什么特别难的感觉,就是一个长按键还没有想到解决方法,先从四个按键入手,S4按键切换三个模式,一开始我用的是递归,在四个while循环,直接把整个程序写死在一个函数里面了,也是迫不得已,当时也没想出什么好方法,S5是电压模式切换,这个就是两个模式切换,简单,S6是读取电压值,一看到保存数据,我直接写了个eeprom,后来一想,没必要那么麻烦,直接保存在一个中间变量进行比较就好,S7也是一样的思路。
到了LED的部分,这个一开始我把所有的LED都写到数码管显示的函数里面了,但是注意了,长按S7是可以关闭LED的,但是关闭LED不影响数码管,这就看出来我的代码有很大问题了,所以要记住,LED一定不要和数码管显示放在一个函数里面。
关于长按怎么做,我这里是大佬教我的,用的定时器2,计时1ms,使变量count_led++,如果count_led=1000后,计时1s,把count_led置为0,然后另一个变量,设一个新变量count_S7每1s自加1,这样的话,定时器中断就设置完毕了,接下来就是S7的长按功能,当S7被按下后,使count_led和count_S7都置0,接下来就进行判断,如果count_S7>=1,判断灯的状态,我们设变量aaa灯亮aaa为0,灯灭aaa为1,如果aaa<1则aaa++,把灯灭掉,else aaa=0,让灯亮,这就实现了长按,看文字描述还是不是很懂,要看代码才行。
源代码
IIC.C
#include "reg52.h"
#include "intrins.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;
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;
}
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;
}
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;
}
MAIN.C
#include<reg51.h>
#include<iic.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sfr AUXR = 0x8e;
sfr T2H = 0xD6;
sfr T2L = 0xD7;
sfr IE2 = 0xAF;
sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;
unsigned char code shuzi[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0xbf,0xff};
unsigned char code zimu[]={0x88,0x83,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0x8c,0xc1,0xc8};
unsigned char code num[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
unsigned char code weizhi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char ledweizhi[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff};
unsigned int count_f = 0;
unsigned char count_t = 0;
unsigned int dat_f = 0;//频率数值
unsigned int dat_term = 0;//周期数值
unsigned char S5_mode=4;
uchar mode;
uint count_led=0;
uint count_S7=0;
uint voltage_temp;//存电压的中间变量
uint fre_temp;//存频率的中间变量
uchar i=0;
uchar j=0;
int voltage_rd1;//rd1的电压值
int dat_rd1;//rd1的数值
int voltage_rb2;//rb2的电压值
int dat_rb2;//rb2的数值
uchar aaa=0;//灯的状态
void led_0();
void Scan_S7();
void led_fun();
void Scan_S4();
void Scan_S5();
void Scan_S6();
void delay_ms(int ms)
{
int q,w;
for(q = 0;q<ms;q++){
for(w=845;w>0;w--);
}
}
void shumaguan_shuzi(uchar a,uchar b)
{
delay_ms(1);
P2=(P2&0X1f)|0xC0;P0=weizhi[a];
P2=(P2&0X1f)|0xE0;P0=shuzi[b];
delay_ms(1);
}
void shumaguan_zimu(uchar a,uchar b)
{
delay_ms(1);
P2=(P2&0X1f)|0xC0;P0=weizhi[a];
P2=(P2&0X1f)|0xE0;P0=zimu[b];
delay_ms(1);
}
void ledlight(uchar x)
{
P2=(P2&0X1f)|0x80;
P0=ledweizhi[x];
}
void Init()
{
R1=R2=R3=R4=1;
}
void Init_Timer()
{
TH0 = 0xff;
TL0 = 0xff;
TH1 = (65536 - 50000) / 256;
TL1 = (65536 - 50000) % 256;
TMOD = 0x16;
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
}
void Timer2(void)
{
T2H = (65535-1000)/256;
T2L = (65535-1000)%256;
EA = 1;
IE2 |=0x04;
AUXR|=0x10;
}
void Service_T12() interrupt 12
{
T2H = (65535-1000)/256;
T2L = (65535-1000)%256;
if(count_led==1000)
{
count_led=0;
count_S7++;
}
else count_led++;
}
void Service_T0() interrupt 1
{
count_f++;
}
void Service_T1() interrupt 3
{
TH1 = (65536 - 50000) / 256;
TL1 = (65536 - 50000) % 256;
count_t++;
if(count_t == 20)
{
dat_f = count_f;
count_f = 0;
count_t = 0;
}
}
void display_f()
{
mode=0;
shumaguan_zimu(0,5);
if(dat_f>9999)
shumaguan_shuzi(3,dat_f/10000);
if(dat_f>999)
shumaguan_shuzi(4,dat_f/1000%10);
if(dat_f>99)
shumaguan_shuzi(5,dat_f/100%10);
if(dat_f>9)
shumaguan_shuzi(6,dat_f/10%10);
shumaguan_shuzi(7,dat_f%10);
}
void display_term()
{
mode=1;
shumaguan_zimu(0,10);
dat_term=1000000/dat_f;
if(dat_f>9999)
shumaguan_shuzi(3,dat_term/1000);
if(dat_f>999)
shumaguan_shuzi(4,dat_term/1000%10);
if(dat_f>99)
shumaguan_shuzi(5,dat_term/100%10);
if(dat_f>9)
shumaguan_shuzi(6,dat_term/10%10);
shumaguan_shuzi(7,dat_term%10);
}
void display_RD1()
{
mode=2;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x01);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat_rd1 = IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
voltage_rd1=dat_rd1*100/51;
shumaguan_zimu(0,9);
shumaguan_shuzi(1,10);
shumaguan_shuzi(2,1);
shumaguan_shuzi(6,voltage_rd1%100/10);
shumaguan_shuzi(7,voltage_rd1%10);
P2=(P2&0X1f)|0xC0;P0=weizhi[5];
P2=(P2&0X1f)|0xFF;P0=shuzi[voltage_rd1/100]+0x80;
}
void display_Rb2()
{
mode=3;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat_rb2 = IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
voltage_rb2=dat_rb2*100/51;
shumaguan_zimu(0,9);
shumaguan_shuzi(1,10);
shumaguan_shuzi(2,3);
shumaguan_shuzi(6,voltage_rb2%100/10);
shumaguan_shuzi(7,voltage_rb2%10);
P2=(P2&0X1f)|0xC0;P0=weizhi[5];
P2=(P2&0X1f)|0xFF;P0=shuzi[voltage_rb2/100]+0x80;
}
void Scan_S4()
{
if(R4==0)
{
while(R4==0){display_term();}
while(1)
{
led_fun();
Scan_S7();
display_term();
if(R4==0)
{
if(R4==0)
{
while(R4==0){display_RD1();}
while(1)
{
led_fun();
Scan_S7();
display_RD1();
Scan_S5();
if(R4==0)
{
delay_ms(60);
if(R4==0)
{
while(R4==0){display_f();}
while(1)
{
led_fun();
Scan_S7();
display_f();
if(R4==0)
{
if(R4==0)
{
while(R4==0){Scan_S4();}
while(1)
{
Scan_S4();
}
}
}
while(R4==0);
}
while(R4==0);
}
}
while(R4==0);
}
while(R4==0);
}
}
while(R4==0);
}
while(R4==0);
}
}
void Scan_S5()
{
if(R3==0)
{
delay_ms(10);
if(R3==0)
{
S5_mode++;
while(R3==0);
}
}
if(S5_mode%2==0)
{
display_RD1();
}
if(S5_mode%2==1)
{
while(1)
{
led_fun();
Scan_S7();
Scan_S6();
display_Rb2();
if(R3==0)
{
delay_ms(10);
if(R3==0)
{
break;
while(R3==0);
}
}
}
}
}
void Scan_S6()
{
if(R2==0)
{
delay_ms(50);
if(R2==0)
{
voltage_temp=voltage_rb2;
while(R2==0);
}
}
}
void Scan_S7()
{
if(R1==0)
{
count_S7=0;
count_led=0;
while(R1==0);
if(count_S7>=1) {if(aaa<1) aaa++;else aaa=0;}
else
{
fre_temp=dat_f;
}
}
}
void led_fun()
{
if(aaa==0)
{
if(mode==0)
{
if(dat_f>fre_temp)
{
P2=(P2&0X1f)|0x80;
P0=0xf9;
}
else ledlight(2);
}
if(mode==1)
{
ledlight(3);
}
if(mode==2)
{
ledlight(4);
}
if(mode==3)
{
if(voltage_rb2>voltage_temp)
{
P2=(P2&0X1f)|0x80;
P0=0xee;
}
else ledlight(4);
}
}
if(aaa==1)
{
P2=0x80;P0=0xff;
}
}
void main()
{
Init_Timer();
Timer2();
Init();
while(1)
{
led_fun();
Scan_S7();
Scan_S6();
Scan_S4();
display_f();
}
}
总体来说,就是长按键那里有点让人懵,剩下的部分还是很简单的。