十五届蓝桥杯单片机-四川前五代码

本文详细描述了一个使用STC15F2K60S2单片机开发的系统,包括定时器用于频率测量、DS1302实时时钟读取、数码管显示频率及时间、超限参数设置、IIC通信进行电压输出,并处理按键输入进行界面切换和参数调整。
摘要由CSDN通过智能技术生成
#include <STC15F2K60S2.H>
#include "ds1302.h"
#include "iic.h"
float f_jz=0;//校准参数
unsigned int f_cx=2000;//超限参数
unsigned char state=0,state_cs=0,state_huixian=0;//数码管界面切换标志位
float f=0;//频率
float voltage_out;//输出电压
bit led_sign=0;//频率界面下的led闪烁标志位
unsigned int f_max=0;
unsigned char hour,minute,second;//时间
unsigned char hour_last,minute_last,second_last;//最大频率发生时间
unsigned char smg_clk=0,key_clk=0,vol_clk=0;
unsigned char smg[8] = {16,16,16,16,16,16,16,16};
unsigned char dot[8] = {0,0,0,0,0,0,0,0};
unsigned char led[8] = {0,0,0,0,0,0,0,0};
unsigned char position=0;
code unsigned char duanma[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xff,  //空白  16
0xc7,   //L  17
0x8c,   //P  18
0xbf,    //横杠  19
0x89   //H
};
//锁存器选择函数
void suocunqi(unsigned char channel,unsigned char dat)
{
	P2 = (P2 & 0x1f) | 0x00;
	P0 = dat;
	switch(channel)
	{
		case 4:P2 = (P2 & 0x1f) | 0x80;break;
		case 5:P2 = (P2 & 0x1f) | 0xa0;break;
		case 6:P2 = (P2 & 0x1f) | 0xc0;break;
		case 7:P2 = (P2 & 0x1f) | 0xe0;break;
	}
	P2 = (P2 & 0x1f) | 0x00;
}
//系统初始化函数
void system_init()
{
	suocunqi(4,0xff);
	suocunqi(5,0x00);
	suocunqi(7,0xff);
}
//数码管位选函数
void smg_bit(unsigned char *smg,unsigned char *dot)
{
	suocunqi(7,0xff);
	suocunqi(6,0x01<<position);
	if(dot[position])
		suocunqi(7,duanma[smg[position]]&0x7f);
	else
		suocunqi(7,duanma[smg[position]]);
}
//led位选函数
void led_bit(unsigned char *led)
{
	static unsigned char temp_led = 0xff;
	if(led[position])
		temp_led &= ~(0x01<<position);
	else
		temp_led |= 0x01<<position;
	suocunqi(4,temp_led);
}
//定时器扫描函数
void timer_init()
{
	AUXR &= 0xBF;		//定时器1时钟12T模式
	AUXR &= 0x7F;		//定时器0时钟12T模式
	TMOD = 0x04;
	TH0 = 0xff;
	TL0 = 0xff;
	TH1 = (65536 - 1000)/256;
	TL1 = (65536 - 1000)%256;
	TF0=TF1=0;	
	EA=1;
	ET1=ET0=1;
	TR0=TR1=1;
}

unsigned int count_f=0,count_1=0,count_2;
void timer0() interrupt 1
{
	count_f++;
}
void timer1() interrupt 3
{
	if(++count_1==1000)
	{
		count_1=0;
		f = count_f + f_jz;
		if(f>f_max) 
		{
			f_max = f;
			hour_last = hour;
			minute_last = minute;
			second_last = second;
		}
		count_f=0;
	}

}
void Timer5Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0x18;		//设置定时初值
	T2H = 0xFC;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	IE2 |= 0x04;
	EA = 1;
}
void timer2() interrupt 12
{
	smg_clk++;//注意不超过100
	key_clk++;
	vol_clk++;
	smg_bit(smg,dot);
	if(position<=1) led_bit(led);
	if(++position==8) position=0;	
	if(++count_2==200)
	{
		count_2=0;
		led_sign^=1;
	}
}
//电压输出函数
void wt_voltage()
{	unsigned char temp_vol;
	if(vol_clk<6) return;
	vol_clk=0;
	if(f>=0)//频率数据正常
	{
		if(f>=f_cx) voltage_out=5.0;
		else if(f>=500) voltage_out= (f-500)/(f_cx-500)*4+1;
		else voltage_out = 1.0;
	}
	else voltage_out=0;
	temp_vol = voltage_out*(255/5.0);
	
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x40);
	I2CWaitAck();
	I2CSendByte(temp_vol);
	I2CWaitAck();
	I2CStop();
}
//时间读取与初始化函数
void ds1302_init()
{
	Write_Ds1302_Byte(0x8e,0x00);
	Write_Ds1302_Byte(0x84,0x13);
	Write_Ds1302_Byte(0x82,0x03);
	Write_Ds1302_Byte(0x80,0x05);
	Write_Ds1302_Byte(0x8e,0x80);
}
void rd_time()
{
	hour = Read_Ds1302_Byte (0x85);
	minute = Read_Ds1302_Byte (0x83);
	second = Read_Ds1302_Byte (0x81);
}
//数码管显示函数
unsigned int temp_1;
void smg_display()
{
	if(smg_clk<60) return;
	smg_clk=0;
	rd_time();//时间刷新
	switch(state)
	{
		case 0://频率界面
			temp_1 = f;
			smg[0] = 15;
			smg[1] = 16;
			smg[2] = 16;
			smg[3] = f>=0?temp_1>=10000?temp_1/10000%10:16:16;
			smg[4] = f>=0?temp_1>=1000?temp_1/1000%10:16:16;
			smg[5] = f>=0?temp_1>=100?temp_1/100%10:16:16;
			smg[6] = f>=0?temp_1>=10?temp_1/10%10:16:17;
			smg[7] = f>=0?temp_1%10:17;			
		break;
		case 1://参数界面
			switch(state_cs)
			{
				case 0://超限参数界面
					temp_1 = f_cx;
					smg[0] = 18;
					smg[1] = 1;
					smg[2] = 16;
					smg[3] = 16;
					smg[4] = temp_1>=1000?temp_1/1000%10:16;
					smg[5] = temp_1>=100?temp_1/100%10:16;
					smg[6] = temp_1>=10?temp_1/10%10:16;
					smg[7] = temp_1%10;		
				break;
				case 1://校准值参数界面
					temp_1 = f_jz>=0?f_jz:-f_jz;
					smg[0] = 18;
					smg[1] = 2;
					smg[2] = 16;
					smg[3] = 16;
					smg[4] = temp_1>=1000?(temp_1/1000%10):(f_jz<=-100?19:16);
					smg[5] = temp_1>=100?temp_1/100%10:16;
					smg[6] = temp_1>=10?temp_1/10%10:16;
					smg[7] = temp_1%10;						
				break;
			}	
		break;
		case 2://时间界面
			smg[0] = hour/16;
			smg[1] = hour%16;
			smg[2] = 19;
			smg[3] = minute/16;
			smg[4] = minute%16;
			smg[5] = 19;
			smg[6] = second/16;
			smg[7] = second%16;
		break;
		case 3://回显界面
			switch(state_huixian)
			{
				case 0://回显频率
					temp_1 = f_max;
					smg[0] = 20;
					smg[1] = 15;
					smg[2] = 16;
					smg[3] = temp_1>=10000?temp_1/10000:16;
					smg[4] = temp_1>=1000?temp_1/1000%10:16;
					smg[5] = temp_1>=100?temp_1/100%10:16;
					smg[6] = temp_1>=10?temp_1/10%10:16;
					smg[7] = temp_1%10;							
				break;
				case 1://回显时间
					smg[0] = 20;
					smg[1] = 10;				
					smg[2] = hour_last/16;
					smg[3] = hour_last%16;
					smg[4] = minute_last/16;
					smg[5] = minute_last%16;
					smg[6] = second_last/16;
					smg[7] = second_last%16;
				break;
			}
		break;
	}
}
//按键扫描函数
unsigned char rd_key()
{
	unsigned char key=0;
	P32=0;P33=1;P44=P42=1;
	if(P44==0) key=5;
	if(P42==0) key=9;
	P32=1;P33=0;P44=P42=1;
	if(P44==0) key=4;
	if(P42==0) key=8;
	return key;
}
unsigned char key_new,key_old,key_down;
void key_proc()
{
	if(key_clk<10) return;
	key_clk=0;
	
	key_new = rd_key();
	key_down = key_new & (key_new ^ key_old);
	key_old = key_new;
	
	switch(key_down)
	{
		case 4:
			if(++state==4) state=0;
			if(state==1) state_cs=0;
			if(state==3) state_huixian=0;
		break;
		case 5:
			switch(state)
			{
				case 1:state_cs^=1;break;
				case 3:state_huixian^=1;break;
			}
		break;
		case 8:
			if(state==1)//参数界面下有效
			{
				switch(state_cs)
				{
					case 0:if(f_cx<9000) f_cx+=1000;break;
					case 1:if(f_jz<900) f_jz+=100;break;
				}				
			}
		break;
		case 9:
			if(state==1)//参数界面下有效
			{
				switch(state_cs)
				{
					case 0:if(f_cx>1000) f_cx-=1000;break;
					case 1:if(f_jz>-900) f_jz-=100;break;
				}				
			}
		break;
	}
}
//led控制函数
void led_control()
{
	led[0] = (state==0&&led_sign==1)?1:0;
	led[1] = ((f>f_cx&&led_sign==1) || f<0)?1:0;
}
void main()
{
	system_init();
	Timer5Init();
	timer_init();
	ds1302_init();
	while(1)
	{
	smg_display();
	wt_voltage();
	key_proc();
	led_control();
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值