蓝桥杯单片机第8届模拟题

这一届的模拟题还是比较难的,用到了两个通讯协议,需要采集电压、频率、读取时间、保存参数及超压低压数据。
在写矩阵键盘模块代码时,不能对P34进行操作,否则会影响频率测量,实际上只用到前两列按键,完全可以避免P34。
频率每隔一秒刷新,即读取计数器0的中断函数里的计数值。
另外不知道为什么在定时器中断函数里对eeprom写操作会导致写入数据错误,因此只能放在主函数。

题目

在这里插入图片描述

main.c

#include<stc15f2k60s2.h>
#include <intrins.h>

#define uchar unsigned char

#define s0 0
#define s1 1
#define s2 3
#define s3 2

void init_ds1302(char t[]);
void init_ds1302_main(char t[]);
char * read_ds1302();
void write_eeprom(uchar add, char dat);
char read_eeprom(uchar add);
int read_vol( );

code uchar semg[12] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
											 0xbf, 0xff};
code uchar semg_bit[8] = {0x01, 0x2, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
uchar semg_temp[8] = {11, 11, 11, 11, 11, 11, 11, 11};

char time[3] = {13, 59, 59};
char vre[2] = {20, 10};
char event[4] = {0};
char temp_fre[5] = {0};

uchar state = s0;
int vol = 1234;
int fre = 1000;
int count = 0;

uchar c = 0;


void Delay400ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 17;
	j = 208;
	k = 27;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay4ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 44;
	j = 4;
	do
	{
		while (--j);
	} while (--i);
}


void allinit(void)		//2毫秒@11.0592MHz
{
	P2 = 0x80;	P0 = 0xff;
	P2 = 0xa0;	P0 = 0x00;
	P2 = 0xc0;	P0 = 0xff;
	P2 = 0xe0;	P0 = 0xff;
}


void TimerInit(void)		//2毫秒@11.0592MHz
{
	AUXR = 0xc0;		//定时器时钟1T模式
	TMOD = 0x06;		//设置定时器模式
	
	TL0 = TH0 = 0xff;               //fill with 0xff to c one time
	TL1 = 0x9A;		//设置定时初值
	TH1 = 0xA9;		//设置定时初值

	TF1 = 0;		//清除TF1标志
	
	TR0 = 1;		//定时器1开始计时
	TR1 = 1;		//定时器1开始计时

	ET0 = 1;
	ET1 = 1;
	
	EA = 1;
}


void disfun(uchar i, int j)
{
	if(j < 500)
	{
		P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
		P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
	}
	else
	{
		P2 = 0xe0;	P0 = 0xff;	P2 = 0x00;
		P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
	}
}


void display()
{
	static uchar i = 0;
	static int j = 0;
	P0 = 0xff;

	j++;
	if(j == 1000)
		j = 0;
	if(state == s0)
	{
		if(c == 1)
		{
			if(i == 0 || i == 1)
				disfun(i, j);
			else
			{
				P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
				P2 = 0xc0;	P0 = semg_bit[i];	 P2 = 0x00;
			}
		}
		else if(c == 2)
		{
			if(i == 3 || i == 4)
				disfun(i, j);
			else
			{
				P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
				P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
			}
		}
		else if(c == 3)
		{
			if(i == 6 || i == 7)
				disfun(i, j);
			else
			{
				P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
				P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
			}
		}
		else
		{
			P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
			P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
		}
	}
	else if(state == s1)
	{
		if(c != 0)
		{
			if( i < (c * 4) && i >= (c * 4 - 4) )
				disfun(i, j);
			else
			{
				P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
				P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
			}
		}
		else
		{
			P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
			P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
		}
	}
	else
	{
		P2 = 0xe0;	P0 = semg[semg_temp[i]];	P2 = 0x00;
		P2 = 0xc0;	P0 = semg_bit[i];	P2 = 0x00;
	}
	P0 = 0xff;
	i++;
	if(i == 8)
		i = 0;
}


void fun0()	interrupt 1
{
	count++;
}


void fun1() interrupt 3
{
	static int c_fre = 0, j = 0;
	static uchar state_vre = s0;
	uchar k;
	int div = 1000;
	char *temp;
	
	display();
	
	/***存时间、电压参数,取频率各位数值***/
	if(state == s0)
	{
		if(c != 0)
			init_ds1302(&time);
	}
	else if(state == s2)
	{
		/***读频率***/
		c_fre++;
		if(c_fre >= 500)
		{
			TR0 = 0;
			if(c == 1)
			{
				if(count != 0)
					fre = 1000000 / count;
				else
					fre = 0;
			}
			else
				fre = count;
			div = 10000;
			for(k = 0; k < 5; k++)
			{
				temp_fre[k] = fre / div;
				fre = fre - temp_fre[k] * div;
				div = div / 10;
			}
			c_fre = 0;
			count = 0;
			TR0 = 1;
		}	
	}
	
	/***每隔0.2秒读取电压及时间***/	
	j++;
	if(j >= 100)
	{
		j = 0;
		
		vol = read_vol();
		
		temp = read_ds1302();
		time[0] = temp[0];
		time[1] = temp[1];
		time[2] = temp[2];

		/***状态机判断电压情况 并保事件及其发生时间***/
		switch(state_vre)
		{
			case s0:
			{
				if(vol > vre[0] * 100)
				{
					event[0] = 1;
					event[1] = time[0];
					event[2] = time[1];
					event[3] = time[2];
					state_vre = s1;
				}
				else	if(vol < vre[1] * 100)
				{
					event[0] = 0;
					event[1] = time[0];
					event[2] = time[1];
					event[3] = time[2];
					state_vre = s1;
				}
				else
					state_vre = s0;
			}	break;
			
			case s1:
			{
				if(vol >= vre[1] * 100 && vol <= vre[0] * 100)
					state_vre = s0;
			}	break;
			
			default: state_vre = s0;	break;
		}
			
		if(c == 0 && state == s1)
		{
			div = 1000;
			for(k = 0; k < 3; k++)
			{
				temp_fre[k] = vol / div;
				vol = (vol - temp_fre[k] * div);
				div = div / 10;
			}
		}
	}
}


char keyscan()
{
	char keyvalue;
	static uchar keystate = s0;
	uchar keyrow, keycloumn, keycode, i, j;
	
	P3 = P3 | 0x0f; P44 = 0; P42 = 0;
	keyrow = P3 & 0x0f;
	P3 = P3 & 0xf0;	P44 = 1; P42 = 1;
	if(P44 == 0)			keycloumn = 0x70;
	else if(P42 == 0)	keycloumn = 0xb0;	
	else							keycloumn = 0xf0;
	keycode = ~(keyrow | keycloumn);
	
	switch(keystate)
	{
		case s0:
			if(keycode)
				keystate = s1;
			else
				keyvalue = -1;
			break;

		case s1:
		{
			if(keycode)
			{
				for(i =0; i< 4; i++)
					for(j =0; j< 4; j++)
						if(keycode == (0x80 >> i | 0x08 >> j))
						{
							keyvalue = (i + 1) * 4 + j ;
							break;
						}
				keystate = s2;
			}
			else
				keystate = s0;
		}	break;

		case s2:
		{
			keyvalue = -1;
			if(!keycode)
				keystate = s0;
		}	break;
		
		default:	keystate = s0;	break;
	}

	return keyvalue;
}


void menu(char keyvalue)
{
	uchar i = 0;
	
	if(keyvalue == 4)
		c++;
	semg_temp[0] = c;

	switch(state)
	{
		case s0:
		{
			semg_temp[0] = time[0] / 10;
			semg_temp[1] = time[0] % 10;
			semg_temp[2] = 10;
			semg_temp[3] = time[1] / 10;
			semg_temp[4] = time[1] % 10;
			semg_temp[5] = 10;
			semg_temp[6] = time[2] / 10;
			semg_temp[7] = time[2] % 10;
			if(c != 0)
			{
				if(keyvalue == 11)
				{
					time[c - 1] = time[c - 1] + 1;
					if(c == 1)
					{
						if(time[c - 1] > 23)
							time[c - 1] = 0;
					}
					else
					{
						if(time[c - 1] > 59)
							time[c - 1] = 0;
					}
				}
				else if(keyvalue == 10)
				{
					time[c - 1] = time[c - 1] - 1;
					if(c == 1)
					{
						if(time[c - 1] < 0)
							time[c - 1] = 23;
					}
					else
					{
						if(time[c - 1] < 0)
							time[c - 1] = 59;
					}
				}	
			}
			else	;
			
			if(keyvalue == 6)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s1;
			}
			else if(keyvalue == 5)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s2;
			}
			else if(keyvalue == 9)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s3;
			}
			else	;
			
			if(c == 4)
				c = 0;
		}	break;

		case s1:
		{
			if(c != 0)
			{
				semg_temp[0] = vre[0] / 10;
				semg_temp[1] = vre[0] % 10;
				semg_temp[2] = 0;
				semg_temp[3] = 0;
				semg_temp[4] = vre[1] / 10;
				semg_temp[5] = vre[1] % 10;
				semg_temp[6] = 0;
				semg_temp[7] = 0;
				if(keyvalue == 11)
				{
					vre[c - 1] = vre[c - 1] + 5;
					if(vre[c - 1] > 50)
						vre[c - 1] = 0;
				}
				else if(keyvalue == 10)
				{
					vre[c - 1] = vre[c - 1] - 5;
					if(vre[c - 1] < 0)
						vre[c - 1] = 50;
				}
				write_eeprom(4, vre[0]);
				write_eeprom(5, vre[1]);
			}
			else
			{
				semg_temp[0] = 10;
				semg_temp[1] = 1;
				semg_temp[2] = 10;
				semg_temp[3] = 11;
				for(i = 4; i < 8; i++)
					semg_temp[i] = temp_fre[i - 4];
			}
			
			if(keyvalue == 7)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s0;
			}
			else if(keyvalue == 5)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s2;
			}
			else if(keyvalue == 9)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s3;
			}
			else	;
			
			if(c == 3)
				c = 0;
		}	break;

		case s2:
		{
			semg_temp[0] = 10;
			semg_temp[1] = 2;
			semg_temp[2] = 10;
			for(i = 3; i < 8; i++)
				semg_temp[i] = temp_fre[i - 3];
			
			if(keyvalue == 7)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s0;
			}
			else if(keyvalue == 6)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s1;
			}
			else if(keyvalue == 9)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s3;
			}
			else	;
			
			if(c == 2)
				c = 0;			
		}	break;
		
		case s3:
		{
			if(c != 0)
			{
				semg_temp[0] = event[1] / 10;
				semg_temp[1] = event[1] % 10;
				semg_temp[2] = 10;
				semg_temp[3] = event[2] / 10;
				semg_temp[4] = event[2] % 10;
				semg_temp[5] = 10;
				semg_temp[6] = event[3] / 10;
				semg_temp[7] = event[3] % 10;				
			}
			else
			{
				semg_temp[6] = 0;
				semg_temp[7] = event[0];
				for(i = 0; i < 6; i++)
				{
					semg_temp[i] = 11;
				}
			}
			
			if(keyvalue == 7)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s0;
			}
			else if(keyvalue == 6)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s1;
			}
			else if(keyvalue == 5)
			{
				c = 0;
				for(i = 0; i < 8; i++)
					semg_temp[i] = 11;
				state = s2;
			}
			else	;
			
			if(c == 2)
				c = 0;	
		}	break;
		
		default:	state = s0;	break;
	}

}


void main()
{
	char keyvalue;
	uchar i;

	init_ds1302_main(&time);
	vol = read_vol();
	for(i = 0; i < 4; i++)
		event[i] = read_eeprom(i);
	for(i = 4; i < 6; i++)
	{
		vre[i - 4] = read_eeprom(i);
		if((vre[i - 4] % 5 != 0) || (vre[i - 4] > 50))
		{
			vre[0] = 20;
			vre[1] = 10;
		}
	}
	
	allinit();
  TimerInit( );
	Delay400ms();
	while(1)
	{
		keyvalue = keyscan();
		menu(keyvalue);
		for(i = 0; i < 4; i++)
			write_eeprom(i, event[i]);
		Delay4ms();
	}
	
}

iic.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "reg52.h"
#include "intrins.h"

#define uchar unsigned char

#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);
}


//等待应答
bit IIC_WaitAck(void)
{
    SDA  = 1;
    IIC_Delay(DELAY_TIME);
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
		
		if(SDA)
		{
			SCL = 0;
			IIC_Stop( );
			return 0;
		}
		else
		{
			SCL = 0;
			return 1;
		}
}

//通过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;    
}


void write_eeprom(uchar add, char dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

char read_eeprom(uchar add)
{
  char dat;
	
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_Stop();
	
	return dat;
}


int read_vol( )
{
  uchar dat;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_Stop();
	
	return (dat * 19.6078);
}

ds1302.c

/*
  程序说明: DS1302驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char											

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												

void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return temp;			
}

void init_ds1302_main(char *time)
{
	uchar addr, i;
	
	addr = 0x84;
	
	Write_Ds1302_Byte(0x8e, 0x00);
	for(i = 0; i < 3; i++)
	{
		Write_Ds1302_Byte(addr, ( (time[i]/10) << 4 | time[i] % 10) );
		addr -= 2;
	}
	Write_Ds1302_Byte(0x8e, 0x80);
}

void init_ds1302(char *time)
{
	uchar addr, i;
	
	addr = 0x84;
	
	Write_Ds1302_Byte(0x8e, 0x00);
	for(i = 0; i < 3; i++)
	{
		Write_Ds1302_Byte(addr, ( (time[i]/10) << 4 | time[i] % 10) );
		addr -= 2;
	}
	Write_Ds1302_Byte(0x8e, 0x80);
}

char * read_ds1302()
{
	uchar addr, i;
	char time[3];
	
	addr = 0x85;
	
	Write_Ds1302_Byte(0x8e, 0x00);
	for(i = 0; i < 3; i++)
	{
		time[i] = Read_Ds1302_Byte(addr);
		time[i] = (time[i] / 16) * 10 + time[i] % 16;
		addr -= 2;
	}
	Write_Ds1302_Byte(0x8e, 0x80);
	
	return time;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值