蓝桥杯单片机第十二届国赛程序示例(reg52.h)

该代码实现了一个结合DS1302实时时钟和超声波测距功能的系统,包括时间显示、超声波数据采集与处理、参数设置以及灯光控制。程序中使用了IIC通信协议与PCA8591读取光敏电阻数据,并通过Nixie管显示结果。
摘要由CSDN通过智能技术生成

注:代码使用reg52.h头文件,采用小蜜蜂老师代码格式。

题目:

 

 

 

 

 

 

示例代码:
main.c(函数都写在main函数内,未采用模块化)

#include <REGX52.H>
#include "DS1302.h"
#include "intrins.h"
#include "IIC.h"

sfr P4=0xc0;

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

sbit L1=P3^0;
sbit L2=P3^1;
sbit L3=P3^2;
sbit L4=P3^3;

sbit R1=P4^4;
sbit R2=P4^2;
sbit R3=P3^5;
sbit R4=P3^4;

void HC573(unsigned char channel,unsigned char value);
void Delay(int x);
void Nixie(unsigned char column,unsigned char value);
void System_init();

unsigned char code Array[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};
unsigned char code Array_pot[10]={0x40,0x79,0X24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char code DS1302_Read_Address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char code DS1302_Write_Address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char Time[]={0x55,0x20,0x20,0x00,0x00,0x00,0x00};
unsigned int Distance;//超声波距离计算
unsigned char Mode_S4=0;//S4
unsigned char Mode_S5=0;//S5
unsigned char Time_P=2;//采集时间参数
unsigned char Distance_P=10;//采集距离参数
unsigned char Chao_Mode=0;//超声波采集模式
unsigned char Data_Mode=0;//数据显示模式
unsigned int Average_Data=0;//平均值
unsigned int Max_Data=0;//最大值
unsigned int Min_Data=100;//最小值
unsigned int Sum=0;//总和
unsigned int cnt=0;//记录测量数据次数
unsigned char Measur_Falg=0;//测量标志位
unsigned char Temp=0;//记录采集电压值
unsigned char Flag_Trigger=0;//触发模式下标志位
unsigned char Alarm_Flag=0;//警报标志位
unsigned char LED_Stat=0xff;//灯光设置
unsigned char LED=0xff;//用于前4个led灯光选择
//RB1光敏电阻读取
void PCF8591_Read()
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	Temp=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
}
//电压输出
void Set_DAC(unsigned char Data)
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	if(Distance<=10)
	{
		I2CSendByte(51);
	}
	else if(Distance>=78)
	{
		I2CSendByte(255);
	}
	else 
	{
		Data=3*Data+21;
		I2CSendByte(Data);
	}
	I2CSendAck(1);
	I2CStop();
}
void DS1302_Init()
{
	unsigned char i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<7;i++)
	{
		Write_Ds1302_Byte(DS1302_Write_Address[i],Time[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);
}

void DS1302_Read_Time()
{
	unsigned char i;
	for(i=0;i<7;i++)
	{
		Time[i]=Read_Ds1302_Byte(DS1302_Read_Address[i]);
	}
}
//时间显示页面
void Display_Time()
{
	Nixie(1,Array[Time[2]/16]);
	Nixie(2,Array[Time[2]%16]);
	Nixie(3,Array[16]);
	Nixie(4,Array[Time[1]/16]);
	Nixie(5,Array[Time[1]%16]);
	Nixie(6,Array[16]);
	Nixie(7,Array[Time[0]/16]);
	Nixie(8,Array[Time[0]%16]);
}

//超声波
void Delay12us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 28;
	while (--i);
}

void Send_Wave()
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		TX=1;
		Delay12us();
		TX=0;
		Delay12us();
	}
}
void Time_Chao()
{
	unsigned int temp;
	TMOD&=0x0F;
	TH1=0;
	TL1=0;
	Send_Wave();
	TR1=1;
	while((RX==1)&&(TF1==0));
	TR1=0;
	if(TF1==0)
	{
		temp=TH1;
		temp=(temp<<8)|TL1;
		Distance=((temp/10)*17)/100+3;
	}
	TH1=0;
	TL1=0;
}
//超声波显示
void Display_chao()
{
	Nixie(1,0xc7);
	if(Chao_Mode==0)
	{
		Nixie(2,0xc6);
	}
	else if(Chao_Mode==1)
	{
		Nixie(2,Array[15]);
	}
	Nixie(3,0xff);
	Nixie(4,0xff);
	Nixie(5,0xff);
	if((Distance/100%10)==0)Nixie(6,0xff);
	else Nixie(6,Array[Distance/100%10]);
	Nixie(7,Array[Distance/10%10]);
	Nixie(8,Array[Distance%10]);
}
//超声波增强显示
void Display_Delay(unsigned int x)
{
	while(x--)
	{
		Display_chao();
	}
}
//数据记录显示页面
void Display_Data()
{
	Nixie(1,0x89);
	if(Data_Mode==0)
	{
		Nixie(2,0xfe);
		Nixie(5,0xff);
		Nixie(6,Array[Max_Data/100%10]);
		Nixie(7,Array[Max_Data/10%10]);
		Nixie(8,Array[Max_Data%10]);
	}
	else if(Data_Mode==1)
	{
		Nixie(2,0xBF);
		Nixie(5,Array[Average_Data/1000%10]);
		Nixie(6,Array[Average_Data/100%10]);
		Nixie(7,Array_pot[Average_Data/10%10]);
		Nixie(8,Array[Average_Data%10]);
	}
	else if(Data_Mode==2)
	{
		Nixie(2,0xf7);
		Nixie(5,0xff);
		Nixie(6,Array[Min_Data/100%10]);
		Nixie(7,Array[Min_Data/10%10]);
		Nixie(8,Array[Min_Data%10]);
	}
	Nixie(3,0xff);
	Nixie(4,0xff);
}
//参数设置页面
void Display_Para()
{
	Nixie(1,0x8c);
	if(Mode_S5==0)
	{
		Nixie(2,Array[1]);
		Nixie(7,Array[Time_P/10%10]);
		Nixie(8,Array[Time_P%10]);
	}
	else if(Mode_S5==1)
	{
		Nixie(2,Array[2]);
		Nixie(7,Array[Distance_P/10%10]);
		Nixie(8,Array[Distance_P%10]);
	}
	Nixie(3,0xff);
	Nixie(4,0xff);
	Nixie(5,0xff);
	Nixie(6,0xff);
}
//显示选择
void Display_channel()
{
	if(Mode_S4==0)
	{
		if(Mode_S5==0)
		{
			Display_Time();
		}
		else if(Mode_S5==1)
		{
			Display_Delay(10);
		}
		else if(Mode_S5==2)
		{
			Display_Data();
		}
	}
	else if(Mode_S4==1)
	{
		Display_Para();
	}
}
//矩阵按键
void Key_Scan()
{
	L4=0;
	L1=L2=L3=1;
	R1=R2=R3=R4=1;
	if(R1==0)
	{
		if(Mode_S4==0){Mode_S4=1;Mode_S5=0;}
		else if(Mode_S4==1){Mode_S4=0;Mode_S5=0;}
		while(R1==0)
		{
			Display_channel();
		}
	}
	else if(R2==0)
	{
		if((Mode_S4==0)&&(Mode_S5==1))
		{
			if(Chao_Mode==0)Chao_Mode=1;
			else if(Chao_Mode==1)Chao_Mode=0;
		}
		else if((Mode_S4==0)&&(Mode_S5==2))
		{
			if(Data_Mode==0)Data_Mode=1;
			else if(Data_Mode==1)Data_Mode=2;
			else if(Data_Mode==2)Data_Mode=0;
		}
		while(R2==0)
		{
			Display_channel();
		}
	}
	L3=0;
	L1=L2=L4=1;
	R1=R2=R3=R4=1;
	if(R1==0)
	{
		if(Mode_S4==0)
		{
			if(Mode_S5==0){Mode_S5=1;}
			else if(Mode_S5==1){Mode_S5=2;Mode_S4=0;}
			else if(Mode_S5==2){Mode_S5=0;}
		}
		else if(Mode_S4==1)
		{
			if(Mode_S5==0)Mode_S5=1;
			else if(Mode_S5==1)Mode_S5=0;
		}
		while(R1==0)
		{
			Display_channel();
		}
	}
	else if(R2==0)
	{
		if((Mode_S4==1)&&(Mode_S5==0))
		{
			if(Time_P==2)Time_P=3;
			else if(Time_P==3)Time_P=5;
			else if(Time_P==5)Time_P=7;
			else if(Time_P==7)Time_P=9;
			else if(Time_P==9)Time_P=2;
		}
		else if((Mode_S4==1)&&(Mode_S5==1))
		{
			Distance_P+=10;
			if(Distance_P>80)Distance_P=10;
		}
		while(R2==0)
		{
			Display_channel();
		}
	}
}
//超声波数据记录
void Data_Deal()
{
	cnt++;
	Max_Data=Max_Data<Distance?Distance:Max_Data;
	Min_Data=Distance<Min_Data?Distance:Min_Data;
	Sum+=Distance;
	Average_Data=(Sum*10/cnt);
	if(((Distance-Distance_P)<5)||((Distance_P-Distance)<=5))//在参数测量+-5cm
	{
		Alarm_Flag++;
	}
	else 
	{
		Alarm_Flag=0;
	}
}
//超声波测量选择
void Measure_Channel()
{
	if(Chao_Mode==0)//触发模式
	{
		if(Temp>=130)//在亮状态置标志位
		{
			Flag_Trigger=1;
		}
		else if((Temp<100)&&(Flag_Trigger==1))//暗状态启动测量同时清除标志位
		{
			Time_Chao();
			Data_Deal();
			Flag_Trigger=0;//实现进行1次测量
		}
	}
	else if((Chao_Mode==1)&&((Time[0]%Time_P)==0))//定时模式
	{
		if(Measur_Falg!=Time[0])//对标志位检测,实现到时间后执行1次测量
		{
			Time_Chao();
			Data_Deal();
			Measur_Falg=Time[0];
		}
	}
}
//灯光控制
void LED_Ctrl()
{
	if(Mode_S4==0)//在数据界面选择显示前4个LED
	{
		if((Mode_S4==0)&&(Mode_S5==0))
		{
			LED_Stat=LED&0xfe;//使用LED&想要亮的灯,进行单独显示
			HC573(4,LED_Stat);
		}
		else if((Mode_S4==0)&&(Mode_S5==1))
		{
			LED_Stat=LED&0xfD;
			HC573(4,LED_Stat);
		}
		else if((Mode_S4==0)&&(Mode_S5==2))
		{
			LED_Stat=LED&0xfB;
			HC573(4,LED_Stat);
		}
	}
	else if(Mode_S4==1)//参数页面关闭前4个LED
	{
		LED_Stat=0xff;
		HC573(4,LED_Stat);
	}
	//超声波触发模式还是定时模式
	if(Chao_Mode==0)
	{
		LED_Stat=LED_Stat&0xF7;
		HC573(4,LED_Stat);
	}
	else 
	{
		LED_Stat=LED_Stat|0x08;
		HC573(4,LED_Stat);
	}
	//警报灯
	if(Alarm_Flag>=3)
	{
		LED_Stat=LED_Stat&0xef;
		HC573(4,LED_Stat);
	}
	else 
	{
		LED_Stat=LED_Stat|0x10;
		HC573(4,LED_Stat);
	}
	//光敏电阻检测灯
	if(Temp>=130)
	{
		LED_Stat=LED_Stat&0xDf;
		HC573(4,LED_Stat);
	}
	else if(Temp<100)
	{
		LED_Stat=LED_Stat|0x20;
		HC573(4,LED_Stat);
	}
}
void main()
{
	System_init();
	DS1302_Init();
	while(1)
	{
		DS1302_Read_Time();
		Display_channel();//数码管总显示选择
		Measure_Channel();//超声波测量模式选择
		PCF8591_Read();//光敏电阻读取
		Key_Scan();
		Set_DAC(Distance);//设置DAC输出
		LED_Ctrl();//灯光设置
	}
}

void System_init()
{
	HC573(4,0xff);
	HC573(5,0x00);
}

void HC573(unsigned char channel,unsigned char value)
{
	P2=(0x1f&P2)|0x00;
	P0=value;
	switch(channel)
	{
		case 4:P2=(0x1f&P2)|0x80;break;
		case 5:P2=(0x1f&P2)|0xa0;break;
		case 6:P2=(0x1f&P2)|0xc0;break;
		case 7:P2=(0x1f&P2)|0xe0;break;
		case 0:P2=(0x1f&P2)|0x00;break;
	}
	P2=(0x1f&P2)|0x00;
}

void Delay(int x)		//@12.000MHz
{
	unsigned char i, j;
	while(x--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}

void Nixie(unsigned char column,unsigned char value)
{
	HC573(6,0x01<<(column-1));
	HC573(7,value);
	Delay(1);
	HC573(6,0x01<<(column-1));
	HC573(7,0xff);
}

ds1302.c

#include <REGX52.H>
#include "intrins.h"

sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;

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

ds1302.h

#ifndef __DS1302_H_
#define __DS1302_H_

void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte ( unsigned char address );

#endif

iic.c

#include <REGX52.H>
#include "intrins.h"

sbit sda=P2^1;
sbit scl=P2^0;

#define DELAY_TIME	5

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

iic.h

#ifndef __IIC_H_
#define __IIC_H_

void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
void I2CSendAck(unsigned char ackbit);
unsigned char I2CWaitAck(void);

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

brepot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值