第十一届蓝桥杯单片机河南省赛个人源码

河南省一,客观题做得不太好,程序题实现很好
原试题链接

源码
刚开始用的是矩阵按键,后来才发现是独立按键,有部分注释没有更改

ii.c

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

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

发送应答
//void IIC_SendAck(bit ackbit)
//{
//    SCL = 0;
//    SDA = ackbit;  					// 0:应答,1:非应答
//    IIC_Delay(DELAY_TIME);
//    SCL = 1;
//    IIC_Delay(DELAY_TIME);
//    SCL = 0; 
//    SDA = 1;
//    IIC_Delay(DELAY_TIME);
//}

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

//通过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_dac(unsigned char add)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
}

onewire.c

#include "reg52.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  
{
	unsigned int i = 12;
	while(t--)
	{
		for(i=0;i<12;i++);
	}
}

//通过单总线向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;
}

unsigned char read_temperature(void)
{
    unsigned int temp;
    unsigned char low,high;
  
  	init_ds18b20();
	Delay_OneWire(1);
  	Write_DS18B20(0xCC);		
  	Write_DS18B20(0x44);		
  	
  	init_ds18b20();
	Delay_OneWire(1);
  	Write_DS18B20(0xCC);		
  	Write_DS18B20(0xBE);		

  	low = Read_DS18B20();
  	high = Read_DS18B20();
	
	temp = high;
	temp <<=4;
	temp |= (low>>4);
  	return temp;
}

main.c

#include "STC15.h"
#include "iic.h"
#include "onewire.h"

#define uchar unsigned char
#define uint unsigned int

uchar code SMG_Duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x39,0x73};//11C 12P
uint code SMG_Com[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管位选

uchar temp_table[8]={10,10,10,10,10,10,10,10};//初始化温度显示数组,默认不显示
uchar set_table[8]={10,10,10,10,10,10,10,10};//初始化参数设置数组,默认不显示

static	uint temp = 0;	//默认温度为0
static	char temp_max = 30;//默认上限温度为30℃
static	char temp_min = 20;//默认下限温度为20℃
static uchar menu = 0;	 //默认界面为数据显示界面

static	char temp_max_prev = 30;//默认合理的上限温度为30℃
static	char temp_min_prev = 20;//默认合理的下限温度为20℃

bit temp_set_flag = 0;	//定义参数切换按键标志
bit key_flag = 0;		//定义10ms扫描按键标志
bit led_flag = 1;		//定义温度合理时LED可亮标志

#define KEY P3 
uchar trg = 0;
uchar cont = 0;

//按键扫描函数
void KeyScan(void)	
{
	uchar KeyData = KEY ^ 0xff;
	trg =  KeyData & (KeyData ^ cont);
	cont = 	KeyData;
}

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

//控制DAC输出函数
void dac_ctrl(void)
{
	if((temp!=85) && led_flag)
	{
		if(temp > temp_max)   //温度大于上限温度,输出4V
		{
			write_dac((4+0.04)*255/5);
			P2 = 0x80;P0 = 0xfe;P2 = 0x00;
		}
		if((temp >= temp_min) && (temp <= temp_max))//温度介于上限温度和下限温度,输出3V
		{
			write_dac((3+0.04)*255/5);
			P2 = 0x80;P0 = 0xfd;P2 = 0x00;
		}
		if(temp < temp_min)	   //温度小于下限温度,输出2V
		{
			write_dac((2+0.04)*255/5);
			P2 = 0x80;P0 = 0xfb;P2 = 0x00;
		}			
	}
	
}
//控制数组显示函数
void table_ctrl(void)
{
   if(temp!=85)	//当温度显示为非85℃时,显示数组,否则显示默认值
   {
	  temp_table[0] = 11;
	  temp_table[1] = 10;
	  temp_table[2] = 10;
	  temp_table[3] = 10;
	  temp_table[4] = 10;
	  temp_table[5] = 10;
   	  temp_table[6] = temp/10;
   	  temp_table[7] = temp%10;
   }
   
   //参数设置数组 
   set_table[0] = 12;
   set_table[1] = 10;
   set_table[2] = 10;
   set_table[3] = temp_max/10;
   set_table[4] = temp_max%10;
   set_table[5] = 10;
   set_table[6] = temp_min/10;
   set_table[7] = temp_min%10;
}

//控制显示界面函数
void menu_ctrl(void)
{
	if(key_flag)//10ms进行按键扫描、温度读取、显示界面切换
	{
		key_flag = 0; //清除标志
		KeyScan();	 //按键扫描
		temp = read_temperature();//读取温度值

		if(trg & 0x08)  //S4进行界面切换
		{
			menu++;
			temp_set_flag = 0;//清除参数设置标志
			if(menu == 1) //判断显示参数界面时,上限温度和下限温度是否合理
			{
				if(temp_max < temp_min)//不合理时,将上限温度和下限温度恢复为上一次的合理值
				{
				   temp_max = temp_max_prev;
				   temp_min = temp_min_prev;
				   menu = 0;	        //显示温度数据界面
				}
			}
			if(menu == 2) //界面切换
			  menu = 0;
		}
		if(menu == 1) //处于参数设置界面事S5、S6、S7按键有效
		{
			if(trg & 0x04) //S5控制上限温度和下限温度参数切换
			{
				temp_set_flag = !temp_set_flag;
			}
			if(trg & 0x02)  //S6控制上限温度或下限温度的增加
			{
			    if(temp_set_flag)
				{
				   	temp_max ++;
					if(temp_max == 100)	//设置参数范围
					   temp_max = 99;
				}
				else
				{
				   	temp_min ++;
					if(temp_min == 100)	 //设置参数范围
					   temp_min = 99;
				}
			}
			if(trg & 0x01)	 //S7控制上限温度或下限温度的减少
			{
			    if(temp_set_flag)
				{
				   	temp_max --;
					if(temp_max == -1)	//设置参数范围
					   temp_max = 0;
				}
				else
				{
				   	temp_min --;
					if(temp_min == -1)	//设置参数范围
					   temp_min = 0;
				}
			}	
		}
		
		if(temp_max >= temp_min) //当上限温度和下限温度合理时,将其值保存到合理的上限、下限温度
		{
			 temp_max_prev = temp_max;
			 temp_min_prev = temp_min;
			 led_flag = 1;	 			 //温度参数合理时LED可亮标志
		}
		else
		{
			P2 = 0x80;P0 = 0xf7;P2 = 0x00; //温度不合理时,L4亮
			led_flag = 0;				   //温度参数合理LED可亮标志清0
		}	
	}
}

void main(void)
{
	Timer0Init();  //定时器初始化
	P2 = 0xa0;P0 = 0x00;P2 = 0x00; //默认蜂鸣器、继电器关闭
	P2 = 0x80;P0 = 0xff;P2 = 0x00; //默认LED关闭
	temp = read_temperature(); //读取DS18B20第一次温度(85℃)
	while(1)
	{
		menu_ctrl();
		table_ctrl();
		dac_ctrl();
	}
}

void Timer0()interrupt 1
{
	static int smg_count = 0,key_count =0,i = 0;
	if(smg_count++ == 1)
	{
		smg_count = 0;
		P2 = 0xc0;P0 = 0x00;P2 = 0x00;//消影
		if(menu == 0)
		{
		   P2 = 0xe0;P0 = ~SMG_Duan[temp_table[i]];P2 = 0x00; //显示温度数据
		}
		if(menu == 1)
		{
		   P2 = 0xe0;P0 = ~SMG_Duan[set_table[i]];P2 = 0x00;  //显示参数设置
		}
		P2 = 0xc0;P0 = SMG_Com[i];P2 = 0x00;
		i++;
		if(i == 8)
			i = 0;
	}
	if(key_count++ ==10)  //定时10ms
	{
		key_count = 0;
		key_flag = 1;
	}
}

错误不妥之处,欢迎批评指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值