蓝桥杯单片机——第十二届省赛题

前言

即将开始今年的蓝桥杯省赛了,特意做一下13届模拟题(即12届真题来练一下手),写此博客来分享一下我写的蓝桥杯单片机的代码,如果有什么不对的地方欢迎大家提出来,让我们共同进步。


一、赛题

简述

这届题目考点也比较常规,数码管显示功能、LED的亮灭、DS18B20温度的读取,DAC输出、矩阵按键。其中值得我们关注的主要有两点:

1.ds18b20读取小数需要用到小数部分。

	之前的几届比赛温度读取基本上都只是整数部分,很少用到小数部分,想要取到小数部分即为取读值的后八位, 如下所示:
long ds_read()
{
	long temp,temp1;
	unsigned char low,high;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	Delay_OneWire(200);
	
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp=high&0x0f;
	temp=(high<<8)|low;
	temp1=temp*625;
	return temp1;
}
我这里将函数和temp定义为long类型是因为我的temp*625,此时的值很大,是一个6位的整数,假如是
temp*0.0625的话就不用long类型,我乘以625是因为使用习惯,当初学习的时候就是学的625,
和乘以0.0625本质上是一样的。


2.按键不能影响到数码管显示。
	
	数码管显示需要1ms的延时,在平时的使用中主要为两种方法,一是使用软件延时,另一个就是利用定时器
	定时扫描,假如用软件延时,在按下按键的时候,数码管显示会被影响的,主要表现为按按键的时候,数
	码管会熄灭,不会显示,所以这个题要用定时器来扫描。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、代码部分

1.iic.c

#include "iic.h"

#define DELAY_TIME 5

//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//I2C总线启动信号
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//I2C总线停止信号
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    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 ad_write(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

2.iic.h

代码如下(示例):

#ifndef _IIC_H
#define _IIC_H

#include "stc15f2k60s2.h"
#include "intrins.h"

sbit SDA = P2^1;
sbit SCL = P2^0;

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
void ad_write(unsigned char dat);
#endif

3.onewire.c

#include "onewire.h"

//单总线内部延时函数
void Delay_OneWire(unsigned int t)  
{
	while(t--);
}

//单总线写操作
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(50);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(50);
}

//单总线读操作
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		Delay_OneWire(1);
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(50);
	}
	return dat;
}

//DS18B20初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(120);
  	DQ = 0;
  	Delay_OneWire(800);
  	DQ = 1;
  	Delay_OneWire(100); 
    initflag = DQ;     
  	Delay_OneWire(50);
  
  	return initflag;
}
long ds_read()
{
	long temp,temp1;
	unsigned char low,high;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	Delay_OneWire(200);
	
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp=high&0x0f;
	temp=(high<<8)|low;
	temp1=temp*625;
	return temp1;
}

4.onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

#include "stc15f2k60s2.h"

sbit DQ = P1^4;  

long ds_read();
bit init_ds18b20(void);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
void Delay_OneWire(unsigned int t);

#endif

5.main.c

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


#define uchar unsigned  char

void delayms(int ms);
void us_waishe();
void Timer0Init(void);
void discan16();
void Timer1Init(void);
void smg_diplay();
void moshi();
void led();


uchar yi,er,san,si,wu,liu,qi,ba;
uchar temp[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf,0xff,0xc6,0x8c,0x88};                        //12c,13p,14
uchar d[7];
unsigned int mode=0,mushi=1,key,canshu=25,DAC,tempare_tt=0,DAC_tt=0;
long tempare;

void main()
{

	Timer0Init();
	us_waishe();
	while(1)
	{
		tempare=ds_read();
		led();
		moshi();
		smg_diplay();
		discan16();
	}
}

void led()
{
	if(mushi==1)
	{
		if(mode==0)
		{
			P2=0X80;P0=0XFc;
		}
		else if(mode==1)
		{
			P2=0X80;P0=0XFA;
		}
		else if(mode==2)
		{
			P2=0X80;P0=0XF6;
		}
	}
	else if(mushi==2)
	{
		if(mode==0)
		{
			P2=0X80;P0=0XFD;
		}
		else if(mode==1)
		{
			P2=0X80;P0=0XFB;
		}
		else if(mode==2)
		{
			P2=0X80;P0=0XF7;
		}
	}	
}
void moshi()
{
	if(mushi==1)
	{
		if(tempare/100<(canshu*100))
		{
			DAC=0;ad_write((DAC/100)*51);
		}
		else if(tempare/100>(canshu*100))
		{
			DAC=500;ad_write((DAC/100)*51);
		}
	}
	else if(mushi==2)
	{
		if(tempare/100<=2000)
		{
			DAC=100;ad_write((DAC/100)*51);
		}
		else if((tempare/100>2000)&&(tempare<4000))
		{
			DAC=(0.15*(tempare/100)-200);ad_write((DAC/100)*51);
		}
		else if(tempare/100>=4000)
		{
			DAC=400;ad_write((DAC/100)*51);
		}
	}
}
void smg_diplay()
{
	if(mode==0)                                                          //温度显示界面
	{
		d[0]=12;d[1]=11;d[2]=11;d[3]=11;d[4]=tempare/100000;d[5]=tempare%100000 / 10000; d[6] = tempare % 10000 / 1000; d[7]=tempare%1000/100;  
	}
	else if(mode==1)                                                     //参数
	{
		d[0]=13;d[1]=11;d[2]=11;d[3]=11;d[4]=11;d[5]=11; d[6] = canshu /10; d[7]=canshu%10;
	}
	else if(mode==2)                                                     //DAC
	{
		d[0]=14;d[1]=11;d[2]=11;d[3]=11;d[4]=11;d[5]=DAC/100; d[6] = DAC %100/10; d[7]=DAC%10;
	}
}
void discan16()
{
	unsigned char temd;
	P44=0;P42=1;P3=0X7F;
	temd=P3;
	temd=temd&0x0f;
	if(temd!=0x0f)
	{
		delayms(5);
		temd=P3;
		temd=temd&0x0f;
		if(temd!=0x0f)
		{
			temd=P3;
			switch(temd)
			{ 
				case 0x77:key=4 ;                                    //S4
					if(mode==0)mode=1;                             //mode=0温度显示界面,mode=1参数设置界面,mode=2DAC输出界面
					else if(mode==1)mode=2;
					else if(mode==2)mode=0;break;
				case 0x7B: key=5;                    				//S5
						if(mushi==1)mushi=2;
						else if(mushi==2)mushi=1;break;
					
				
			}
			while(temd!=0x0f)
			{
				temd=P3;
				temd=temd&0x0f;
			}
		}
	}
	P44=1;P42=0;P3=0XBF;
	temd=P3;
	temd=temd&0x0f;
	if(temd!=0x0f)
	{
		delayms(5);
		temd=P3;
		temd=temd&0x0f;
		if(temd!=0x0f)
		{
			temd=P3;
			switch(temd)
			{
				case 0xb7:key=8;if(mode==1)canshu=canshu-1; break;                                     //参数界面S8
				case 0xbb:key=9;if(mode==1)canshu=canshu+1; break;                          //S9		
			}
			while(temd!=0x0f)
			{
				temd=P3;
				temd=temd&0x0f;
			}
		}
	}
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}


void Timer0() interrupt 1
{
	uchar pos;
	P2=(P2&0X1F)|0XC0;
	P0=0X01<<pos;
	P2=(P2&0X1F)|0XE0;
	if(pos==5)
	{
		if((mode==0)||(mode==2))
		{
			P0=temp[d[pos]]&0x7f;
		}
		else if(mode==1)
		{
			P0=temp[d[pos]];
		}	
	}
	else 
	{
		P0=temp[d[pos]];
	}
	pos++;
	if(pos>=8)pos=0;
}
void us_waishe()
{
	P2=0X80;P0=0XFF;
	P2=0XA0;P0=0X00;
	P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void delayms(int ms)
{
	unsigned int i,j;
	for(i=ms;i>0;i--)
		for(j=845;j>0;j--);
}

总结

enmm,大致检查了一下代码,应该没得啥问题吧,不过我也不确定,假如发现了有错误欢迎提出来让我改正,最后祝福大家都能进国赛

  • 27
    点赞
  • 160
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值