蓝桥杯单片机第十二届省赛(比较简洁版)

 

 

 

 思路:本次赛题比较简单,将界面与数据分开处理,这样代码会比较明了

两个底层就不细说了

#include <STC15F2K60S2.H>
#include <iic.h>
#include <onewire.h>

#define Px(adr,dat) {P2=(P2&0x1f)|(adr<<5);P0=dat;}
对于38译码器的处理我使用了一个宏定义
思路:P2&0x1f是将P2的高三位置0,adr<<5是将片选移到高三位,最后的或处理就能将38译码器配置好段选,最后的P0=dat就是直接输出了

/* 头文件 */

void Timer0Init();
void Smg_Show();
void Key_Ser();
void Key_Scan();
void LED_Display();
void Smg_Display();
void DAC_OUT();

/* 函数声明 */


unsigned char KeyDelay,Key,keynum,bloose;
/* 按键变量 */

unsigned char point,Smg_Dat[8],Smg_Arr[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc1,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf,0xa1,0x86,0xc6,0x7f,0x88,0x8c};
这些都是一些段码就不细说了
/* 数码管变量 */

float tempreature;
unsigned int Tcount,Tp_Cmp=25;
/* 温度变量 */
	
unsigned char page,mode;
/* 界面变量 */

unsigned char Dcount;
float DA_Dat;
/* DA变量 */

unsigned char LED;
/* LED变量 */
	
void main()
{
	Timer0Init();
	init_18b20();//初始化18b20,避免上电显示85的情况
	Px(4,0xff);
	Px(5,0x00);//关闭无关设备
	while(1)
	{
		if (Tcount>=750)//温度读取 750ms读取一次
		{
			Tcount=0;
			tempreature=TP_RD();
		}
		if (Dcount>=200)//DAC输出 200ms输出一次
		{
			Dcount=0;
			DAC_OUT();
		}
		Smg_Display();
		LED_Display();
		if (keynum) Key_Ser();//按键处理函数 必须加上前面的判断 否则检测不到
	}
}

void T0Int() interrupt 1
{
	Tcount++;
	Dcount++;
	
	Smg_Show();//显示数码管
	Key_Scan();//按键扫描
	Px(4,~LED);//LED显示 这里将LED变量取反以便后续操作
}

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

void Smg_Show()//数码管显示函数
{
	Px(6,0x01<<point);Px(7,Smg_Arr[Smg_Dat[point++]]);point%=8;
}
思路:用point变量作为指针,可同时对数码管的位选及其段选进行移位操作,将该函数直接在中断里调用
优点:对数码管段选数据的操作只需要改变Smg_Dat数组的各个位数
缺点:小数点不能进行或操作显示
unsigned char Key_Get()//扫描矩阵键盘
{
	unsigned char keynum=0;
	keynum=0;
	P34=1;P35=1;P42=0;P44=1;
	if (P30==0) keynum=11;
	else if (P31==0) keynum=10;
	else if (P32==0) keynum=9;
	else if (P33==0) keynum=8;
	P34=1;P35=1;P42=1;P44=0;
	if (P30==0) keynum=7;
	else if (P31==0) keynum=6;
	else if (P32==0) keynum=5;
	else if (P33==0) keynum=4;
	
	return keynum;
}

void Key_Scan()//按键扫面函数 在中断里调用
{
	if (KeyDelay==0)
	{
		Key=Key_Get();//获取第一次按下的键值
		if (Key!=0) KeyDelay=15;//15ms消抖处理
		else bloose=0;//松键判断标志 0为松键
	}
	else 
	{
		if (--KeyDelay==0)//15ms延时结束
		{
			keynum=Key_Get();//再次获取键值
			if (keynum!=Key) keynum=0;//前后键值不一样就会置0 防止按键按下进行错误操作
		} 
	}
}

void Key_Ser()//按键处理函数
{
	if (bloose==0)//松键进入
	{
		if (keynum==4)page++;//界面切换
		else if (keynum==5&&page==2)mode=!mode;//DAC模式切换
		else if (keynum==8&&page==1&&Tp_Cmp!=0)Tp_Cmp--;//温度参数处理
		else if (keynum==9&&page==1&&Tp_Cmp!=99)Tp_Cmp++;
		page%=3;
		bloose=1;//将松键标志置1
	}
	keynum=0;
}
注:按键处理这里有两种思路,一是以界面划分,二是以键值划分,这里按键的功能和界面比较简单,所以采用按键划分

void Smg_Display()//数码管段选的数据处理
{
	if (page==0)//初始默认界面
	{
		Smg_Dat[0]=25;
		Smg_Dat[1]=11;
		Smg_Dat[2]=11;
		Smg_Dat[3]=11;
		Smg_Dat[4]=(int)tempreature/10%10;
		Smg_Dat[5]=(int)tempreature%10+12;
		Smg_Dat[6]=(int)(tempreature*10)%10;
		Smg_Dat[7]=(int)(tempreature*100)%10;
	}
	else if (page==1)//参数设置界面
	{
		Smg_Dat[0]=28;
		Smg_Dat[1]=11;
		Smg_Dat[2]=11;
		Smg_Dat[3]=11;
		Smg_Dat[4]=11;
		Smg_Dat[5]=11;
		Smg_Dat[6]=Tp_Cmp/10;
		Smg_Dat[7]=Tp_Cmp%10;
	}
	else if (page==2)//DAC输出界面 DA_Dat在下面的DAC_OUT中处理的
	{
		Smg_Dat[0]=27;
		Smg_Dat[1]=11;
		Smg_Dat[2]=11;
		Smg_Dat[3]=11;
		Smg_Dat[4]=11;
		Smg_Dat[5]=(int)DA_Dat+12;
		Smg_Dat[6]=(int)(DA_Dat*10)%10;
		Smg_Dat[7]=(int)(DA_Dat*100)%10;
	}
}

void LED_Display()//LED数据处理界面 这里比较简单就不细说了
{
	if (mode==0)LED|=0x01;
	else LED&=0xfe;
	if (page==0)LED|=0x02;
	else LED&=0xfd;
	if (page==1)LED|=0x04;
	else LED&=0xfb;
	if (page==2)LED|=0x08;
	else LED&=0xf7;
}
void DAC_OUT()//DAC输出函数
{
	if (mode==0)//模式1的输出方式
	{
		if (tempreature<Tp_Cmp){DAC(0);DA_Dat=0;}
		else {DAC(255);DA_Dat=5;}
	}
	else //模式二的输出方式
	{
		if (tempreature<=20){DAC(51);DA_Dat=1;}
		else {DAC((char)((tempreature*0.15-2)*51));DA_Dat=tempreature*0.15-2;}
	}
}
18b 代码,这些原理不细说了
#include <STC15F2K60S2.H>
#include <intrins.h>
void Delay750ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 35;
	j = 51;
	k = 182;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

sbit DQ = P1^4;  //ե؜Пޓࠚ

//ե؜Пғʱگ˽
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t*=12;
	while(t--);
}

//ͨڽե؜ПвDS18B20дһٶؖޚ
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//ՓDS18B20ׁȡһٶؖޚ
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//DS18B20ʨѸԵʼۯ
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

float TP_RD()
{
	unsigned char low,high;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low=Read_DS18B20();
	high=Read_DS18B20();
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	return ((high<<8)|low)/16.0;
}
void init_18b20()
{
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay750ms();
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
}






 

iic代码

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

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}    


#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//؜Пӽޅ֨ӥ
sbit SDA = P2^1;  /* ˽ߝП */
sbit SCL = P2^0;  /* ʱדП */


//؜ПǴ֯͵ݾ
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(bit 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 AD_RD(unsigned char adr)
{
	unsigned char dat;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	IIC_SendByte(0x40|adr);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	
	dat=IIC_RecByte();
	IIC_Ack(0);
	IIC_Stop();
	
	return dat;
}

void DAC(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	IIC_SendByte(0x40);
	IIC_WaitAck();
	
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值