历届蓝桥杯程序

本人参加了第十届蓝桥杯单片机比赛,现将整理过的自己写的第四届国赛的程序给大家参考一下。烧录国信长天的单片机即可工作。
以下有
1个main.c
1个iic.c
1个iic.h
1个ds1302.c
1个ds1302.h

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

#define somenop {nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();}
#define u8 unsigned char
u8 code smg_duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40};
u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

sbit buzzer=P0^6;
sbit relay= P0^4;

sbit RX=P1^1;
sbit TX=P1^0;

#define KEY P3
#define NO_KEY 0xff
#define KEY_STATE0 0
#define KEY_STATE1 1
#define KEY_STATE2 2

u8 xian_shi[8];
u8 mo_si=1,shi_zhong;

void send_wave()
{

	TX=1;
	somenop;somenop;somenop;somenop;somenop;
	somenop;somenop;somenop;somenop;somenop;
	TX=0;

}

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

_nop_();
_nop_();
i = 22;
j = 128;
do
{
	while (--j);
} while (--i);

}

u8 key_scan() //状态机键盘处理
{
static unsigned char key_state=KEY_STATE0;
u8 key_value=0,key_temp;
u8 key1,key2;
P30=0;P31=0;P32=0;P33=0;P34=1;P35=1;P42=1;P44=1;
if(P440) key1=0x70;
if(P42
0) key1=0xb0;
if(P350) key1=0xd0;
if(P34
0) key1=0xe0;
if((P341)&&(P351)&&(P421)&&(P441)) key1=0xf0;
P30=1;P31=1;P32=1;P33=1;P34=0;P35=0;P42=0;P44=0;
if(P300) key2=0x0e;
if(P31
0) key2=0x0d;
if(P320) key2=0x0b;
if(P33
0) key2=0x07;
if((P301)&&(P311)&&(P321)&&(P331)) key2=0x0f;
key_temp=key1|key2;
switch(key_state)
{
case KEY_STATE0:
if(key_temp!=NO_KEY)
{
key_state=KEY_STATE1;
}
break;
case KEY_STATE1:
if(key_tempNO_KEY)
{
key_state=KEY_STATE0;
}
else
{
switch(key_temp)
{
case 0x77:key_value=4 ;break;
case 0x7b:key_value=5 ;break;
case 0x7d:key_value=6 ;break;
case 0x7e:key_value=7 ;break;
case 0xb7:key_value=8 ;break;
case 0xbb:key_value=9 ;break;
case 0xbd:key_value=10;break;
case 0xbe:key_value=11;break;
case 0xd7:key_value=12;break;
case 0xdb:key_value=13;break;
case 0xdd:key_value=14;break;
case 0xde:key_value=15;break;
case 0xe7:key_value=16;break;
case 0xeb:key_value=17;break;
case 0xed:key_value=18;break;
case 0xee:key_value=19;break;
}
key_state=KEY_STATE2;
}
break;
case KEY_STATE2:
if(key_temp
NO_KEY)
{
key_state=KEY_STATE0;
}
break;
}
return key_value;

}

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

_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
	do
	{
		while (--k);
	} while (--j);
} while (--i);

}

void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}

void Time1Init() //超声波计时用
{
AUXR&=0xbf;
TMOD&=0xbf;
TL1=0x00;
TH1=0x00;
TF1=0;
TR1=0;

}

bit key_flag,sonic_flag=0,shan_shuo=0;
void main()
{
unsigned int t,distance;
u8 shi,fen,miao,shi_1,fen_1,miao_1,shi_zhong=0;//分别是真的时分秒,和设置时的时分秒
u8 csb_set=30,csb_mo_si=0; //超声波初始警报值 以及是否打开超声波
u8 key_val = NO_KEY;
csb_set=Read_24C02(0x01);

P2 = 0X80;      //题目要求初始化
P0 = 0X00;

P2=0XA0;

buzzer =1;       //题目要求初始化
Delay1000ms();
P2 = 0X80;
P0=0XFF;
P2=0XA0;
buzzer =0;
P2 = 0X00;


Timer0Init();
Time1Init();
set_sfm(11,50,59);
while(1)
{	
if(key_flag == 1)
{
	 key_flag = 0;
   key_val = key_scan();	
	 switch(key_val)
	 {
		 case 4: 
			 if(mo_si==1)    //时钟设置
			 {
				if(shi_zhong==3)
				{
					if(shi_1==0)
					shi_1=24;
					shi_1--;
				}
				if(shi_zhong==2)
				{
					
					if(fen_1==0)
					fen=60;
					fen_1--;
				}
				if(shi_zhong==1)
				{
				
					if(miao_1==0)
					miao_1=60;
					miao_1--;
				}
			}
			 
			 if(mo_si==0)   //超声波设置
			{
			   csb_set--;
				Write_24C02(0x01,csb_set); 			
			}
		 break;
		 case 5:  
			 if(mo_si==1)    //时钟设置
	   {
			if(shi_zhong==3)
				{
					shi_1++;
					if(shi_1>23)
					shi_1=0;
				}
				if(shi_zhong==2)
				{
					fen_1++;
					if(fen_1>59)
					fen_1=0;
				}
				if(shi_zhong==1)
				{
					miao_1++;
					if(miao_1>59 )
					miao_1=0;
				}
			}
		 
	    if(mo_si==0)   //超声波设置
			{
			   csb_set++;
				Write_24C02(0x01,csb_set); 
								
			}
		 break;
		 case 6:   
			if(mo_si==1)
		 {
		   shi_zhong++;
			 if(shi_zhong>=4)
				 shi_zhong=0;
		 }
		 if(mo_si==0)
		 {
		    csb_mo_si++;
			 if(csb_mo_si>=2)
			 {
			    csb_mo_si=0;
			 }
			 
		 }
		 
		 break;
		 case 7:   //时钟调整或超声波调整
	    mo_si++;
			if(mo_si>=2)
				mo_si=0;
		
		
		 break;
		
	 }
	 
	 
 }
  if(shi_zhong!=0&&mo_si==1)  //显示
	{
		if(shi_zhong==1&&shan_shuo==1)   //数码管闪烁
		{
			xian_shi[0]=10;
			xian_shi[1]=10;	
		}
		else
		{
			xian_shi[0]=shi_1/10;
			xian_shi[1]=shi_1%10;
		}			
		xian_shi[2]=11;
		if(shi_zhong==2&&shan_shuo==1)   //数码管闪烁
		{
		   xian_shi[3]=10;
		   xian_shi[4]=10;	
		}
		else
		{
			xian_shi[3]=fen_1/10;
			xian_shi[4]=fen_1%10;	
		}
		xian_shi[5]=11;
		if(shi_zhong==3&&shan_shuo==1)    //数码管闪烁
		{
			xian_shi[6]=10;
			xian_shi[7]=10;	
		}
		else
		{
			xian_shi[6]=miao_1/10;
			xian_shi[7]=miao_1%10;		
		}
		 
		if(shi_zhong==3)
		set_sfm(shi_1,fen_1,miao_1);		//写入调整后时间
	}
 if(mo_si==1&&shi_zhong==0)
 {
		ET0=0;
		shi=Ds1302_Single_Byte_Read(ds1302_hr_addr);  //读ds1302数据
		fen=Ds1302_Single_Byte_Read(ds1302_min_addr);
		miao=Ds1302_Single_Byte_Read(ds1302_sec_addr);
		ET0=1;		
shi_1=shi/16*10+shi%16;    //缓存当前时间,用于调整用
		fen_1=fen/16*10+fen%16;
		miao_1=miao/16*10+miao%16;	
		
		xian_shi[0]=shi/16;   //显示时间
		xian_shi[1]=shi%16;
		xian_shi[2]=11;
		xian_shi[3]=fen/16;
		xian_shi[4]=fen%16;
		xian_shi[5]=11;
		xian_shi[6]=miao/16;
		xian_shi[7]=miao%16;
	 
 }
 if(mo_si==0&&csb_mo_si==0)    //超声波模式工作
 {  
		sonic_flag=0;
		send_wave();
		TR1=1;
		while((RX==1)&&(TF1==0));
		TR1=0;
		if(TF1==1)
		{
			TF1=0;
			distance=999;
		}
		else
		{
			t=TH1;
			t<<=8;
			t|=TL1;
			distance=(unsigned int)(t*0.017);	
		}
		TH1=0;
		TL1=0;
	
    xian_shi[0]=10;
		xian_shi[1]=10;
		xian_shi[2]=10;
		xian_shi[3]=10;
		xian_shi[4]=10;
	  xian_shi[5]=distance/100;
		xian_shi[6]=distance%100/10;
		xian_shi[7]=distance%10;
		Delay2ms()	;
		Delay2ms()	;
		Delay2ms()	;
		Delay2ms()	;
		if(distance<csb_set*1.2)   //超声波近距离警告
		{
			if(shan_shuo==1)
		  P2=0X80;P0=0X7F;P2=0X00;	   //led
		
			if(shan_shuo==0)
		  P2=0X80;P0=0XfF;P2=0X00;	
		}
		if(distance>csb_set*1.2)   //超声波远距离无警告
		{		
		  P2=0X80;P0=0XfF;P2=0X00;			
		}
		
		if(distance<=csb_set)    //超声波近距离警告
		{		
		  P2=0XA0;buzzer=1;relay=0;P2=0X00;    //继电器  蜂鸣器
		}
		if(distance>csb_set)   //超声波远距离无警告
		{		
		  P2=0XA0;buzzer=0;relay=0;P2=0X00;		 
		}
		
		
 }

  if(mo_si==0&&csb_mo_si==1)   //超声波设置值显示
	{
	  
	  xian_shi[0]=10;
		xian_shi[1]=10;
		xian_shi[2]=10;
		xian_shi[3]=10;
		xian_shi[4]=10;
	  xian_shi[5]=csb_set/100;
		xian_shi[6]=csb_set%100/10;
		xian_shi[7]=csb_set%10;
	
	
	}

}
}

void Timer0() interrupt 1 using 1
{
static unsigned int key_count = 0,sing_count = 0,i = 0,shan_count=0;
key_count++;
sing_count++;

if(key_count == 10)   //中断进入键盘程序
{
	key_count = 0;
	key_flag = 1;
}

 
if(sing_count == 3)
{
	sing_count = 0;
	P2 = 0xc0; P0 = 0X00; P2=0X00;
	
  P2 = 0xE0; P0 =~smg_duan[xian_shi[i]]; P2=0X00;   //中断进入显示数码管
	
	P2 = 0xc0; P0 = smg_wei[i]; P2=0X00;

	i++;
	if(i == 8)
		i = 0;
}

	shan_count++;   //中断进入闪烁程序
	if(shan_count>1000)
	{
		  shan_count=0;
	  	shan_shuo=~shan_shuo;
	}

}

此处是iic的c文件


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

#include “iic.h”

//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}

//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}

//应答位控制
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}

//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
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++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;

for(i=0;i<8;i++)
{   
	SCL = 1;
	somenop;
	da <<= 1;
	if(SDA) 
	da |= 0x01;
	SCL = 0;
	somenop;
}
return da;

}

unsigned char Read_24C02(unsigned char addr)
{
unsigned char tmp;

IIC_Start();					
IIC_SendByte(0xa0); 		
IIC_WaitAck();					
IIC_SendByte(addr); 		
IIC_WaitAck(); 					

IIC_Start();						
IIC_SendByte(0xa1); 		
IIC_WaitAck();				
tmp = IIC_RecByte();		
IIC_Ack(0); 						
IIC_Stop();							
return tmp;

}

void Write_24C02(unsigned char addr, unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}

unsigned char read_adc(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return temp;
}

void write_adc(unsigned char add)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}


此处是iic的h文件

#ifndef _IIC_H
#define _IIC_H

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

#define somenop {nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1; /* 数据线 /
sbit SCL = P2^0; /
时钟线 */

//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(unsigned char ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char Read_24C02(unsigned char addr);
void Write_24C02(unsigned char addr, unsigned char dat);
unsigned char read_adc(unsigned char add);
void write_adc(unsigned char add);

bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);

#endif


此处是ds1302的c文件

#include “ds1302.h”

/单字节写入一字节数据/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) 1)
{
SDA_SET; //#define SDA_SET SDA=1 /电平置高/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /电平置低/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/********************************************************************/
/单字节读出一字节数据/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R
1) #define SDA_R SDA /电平读取/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}

/********************************************************************/
/向DS1302 单字节写入一字节数据/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{

RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

RST_SET;			/*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;	 
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
Write_Ds1302_Byte(dat);	 /*写入数据:dat*/
RST_CLR;				 /*停止DS1302总线*/

}

/********************************************************************/
/从DS1302单字节读出一字节数据/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST_CLR; /RST脚置低,实现DS1302的初始化/
SCK_CLR; /SCK脚置低,实现DS1302的初始化/

RST_SET;	/*启动DS1302总线,RST=1电平置高 */	
addr = addr | 0x01;	 
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
RST_CLR;		   /*停止DS1302总线*/
SDA_CLR; 		//xiu gai   fei chang zhong yao

return temp;

}

void set_sfm(char shi,char fen,char miao)
{
Ds1302_Single_Byte_Write(0x8e,0); //关闭写保护
Ds1302_Single_Byte_Write(0x80,(miao/10)*16+miao%10); //以BCD码写入秒数据
Ds1302_Single_Byte_Write(0x82,(fen/10)*16+fen%10); //以BCD码写入分数据
Ds1302_Single_Byte_Write(0x84,(shi/10)*16+shi%10); //以BCD码写入时数据
Ds1302_Single_Byte_Write(0x8e,0x80); //打开写保护
}


此处是ds1302的h文件

#ifndef DS1302_H
#define DS1302_H

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

sbit SCK=P1^7;
sbit SD=P2^3;
sbit RST=P1^3;
//
/复位脚/
#define RST_CLR RST=0 /电平置低/
#define RST_SET RST=1 /电平置高/
/双向数据/
#define SDA_CLR SD=0 /电平置低/
#define SDA_SET SD=1 /电平置高/
#define SDA_R SD /电平读取/
/时钟信号/
#define SCK_CLR SCK=0 /时钟信号/
#define SCK_SET SCK=1 /电平置高/
/
/
#define ds1302_sec_addr 0x80 //秒数据地址
#define ds1302_min_addr 0x82 //分数据地址
#define ds1302_hr_addr 0x84 //时数据地址
#define ds1302_date_addr 0x86 //日数据地址
#define ds1302_month_addr 0x88 //月数据地址
#define ds1302_day_addr 0x8A //星期数据地址
#define ds1302_year_addr 0x8C //年数据地址

#define ds1302_control_addr 0x8Ee //写保护命令字单元地址
#define ds1302_charger_addr 0x90 //涓电流充电命令字地址
#define ds1302_clkburst_addr 0xBE //日历、时钟突发模式命令字地址
/********************************************************************/

//
/单字节写入一字节数据/
extern void Write_Ds1302_Byte(unsigned char dat);
/
/
/单字节读出一字节数据/
extern unsigned char Read_Ds1302_Byte(void);

//
/
/
/向DS1302单字节写入一字节数据/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/
/从DS1302单字节读出一字节数据/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
extern void set_sfm(char shi,char fen,char miao);

#endif
//
//       END FILE
/
/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值