第十一届蓝桥杯十月省赛

本文档介绍了一个基于STM32的项目,涉及DS18B20单总线温度传感器的使用,通过I2C接口与DAC芯片交互实现温度控制。作者分享了代码实现,包括初始化、数据读取、DAC配置等,并提到项目中的关键函数如IIC和单总线驱动。通过对上一届比赛题目的反思,作者意识到之前代码的问题并进行了修正。
摘要由CSDN通过智能技术生成

【冉冰的成长日记005】
第十一届10月省赛题目

没啥感触,感觉比较简单啊这个题,
啊对,今天搞懂了DAC,看来上一届的题目我应该是写错了,虽然显示的没问题,被人带坑里了,我这就去改

看看代码吧,这篇这么简单估计也没人看

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

sbit S7=P3^0;
sbit S6=P3^1;
sbit S5=P3^2;
sbit S4=P3^3;

unsigned char code LED[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xFF, 0xC6, 0x8C};//数码管  11 c  12 p
unsigned char LEDbuff[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; //数码管缓冲区

unsigned int cnt1=0,cnt2=0,num=0;//中断计时
unsigned char T=0,TMAX=30,TMIN=20,DAC=0,max=0,min=0;		   // max和min用于存取温度上限和下限,在越界时回复初值
bit check_S7=1,check_S6=1,check_S5=1,check_S4=1;//check用来按键消抖
bit	Dis_flag=0,num_flag=0; //切换显示和设置页面显示和被选中单元闪烁
unsigned char T_flag=0;	   //切换被选中单元

void Timer0Init();	//定时器0,1ms
void Initial();		//模块初始化
void Display();		//数码管模块
void delay(unsigned int x);	  //延时函数

void main()
{
	Timer0Init();
	Initial();	 //初始化函数
	while(1)
	{
		
		if(cnt1>=500)				 //0.5s获取一次温度
		{
			DS18B20_Start();
			T = DS18B20_Get();
			cnt1=0;
		}
		if(cnt2>=300)				 //0.3s进行一次da转换
		{
			cnt2=0;
			DAC_Init(DAC);
		}
		Display();					 
	}
}

void delay(unsigned int x)			 //延时函数,ms单位
{
	int X=0,Y=0;
	for(X=0;X<x;X++)
	{
		for(Y=846;Y>0;Y--);
	}
		
}

void Initial()		//初始化函数
{
	P2 = (P2&0x1F)|0x80;
	P0 = 0xFF;		//初始化LED

	P2 = (P2&0x1F)|0xA0;
	P0 = 0x00;		//初始化继电器和蜂鸣器

	P2 = (P2&0x1F)|0xC0;
	P0 = 0xFF;
	P2 = (P2&0x1F)|0xE0;
	P0 = 0xFF;      //初始化数码管
}

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 DA()
{
	if(T>TMAX) 			{DAC=204;P2 = (P2&0x1F)|0x80;P0 = 0xFE;}
	if(T>TMIN&&T<TMAX) 	{DAC=153;P2 = (P2&0x1F)|0x80;P0 = 0xFD;}
	if(T<TMIN)			{DAC=102;P2 = (P2&0x1F)|0x80;P0 = 0xFB;}
	if(TMIN>TMAX)		{P2 = (P2&0x1F)|0x80;P0 = 0xF7;}

}

void Display_1()		 //数据显示页面
{
	LEDbuff[7] = LED[11];
	LEDbuff[6] = LED[10];
	LEDbuff[5] = LED[10];
	LEDbuff[4] = LED[10];
 	LEDbuff[3] = LED[10];
	LEDbuff[2] = LED[100];
	LEDbuff[1] = LED[T/10];
	LEDbuff[0] = LED[T%10];	
}

void Display_2()		 //参数设置页面
{
	LEDbuff[7] = LED[12];
	LEDbuff[6] = LED[10];
	LEDbuff[5] = LED[10];

	if(T_flag==2&&num_flag==1)
	{LEDbuff[4] = LED[10];
	 LEDbuff[3] = LED[10];}
	else
	 {LEDbuff[4] = LED[TMAX/10];
 	 LEDbuff[3] = LED[TMAX%10];}
	

	LEDbuff[2] = LED[100];
	
	if(T_flag==1&&num_flag==1)
	{LEDbuff[1] = LED[10];
	 LEDbuff[0] = LED[10];}
	else
	{LEDbuff[1] = LED[TMIN/10];
	 LEDbuff[0] = LED[TMIN%10];}			
}

void Display()
{
	if(Dis_flag==0)	    Display_1();
	if(Dis_flag==1)		Display_2();
}

void KEY_S7()
{
	if(S7 != check_S7)
	{
		if(check_S7==0)
		{
			if(T_flag==1) 
			{
			 if(TMIN>=100)	TMIN = 99;
			 if(TMIN<0)	TMIN = 0;
			 if(TMIN<=99&&TMIN>0)	TMIN--;
			}
			if(T_flag==2) 
			{
			 if(TMAX>100)			TMAX = 99;
			 if(TMAX<0)				TMAX = 0;
			 if(TMAX<=99&&TMAX>0)	TMAX--;
			}			
		}
		check_S7 = S7;	
	}
}

void KEY_S6()
{
	if(S6 != check_S6)
	{
		if(check_S6==0)
		{
			if(T_flag==1) 
			{
			 if(TMIN>=100)			TMIN = 99;
			 if(TMIN<0)				TMIN = 0;
			 if(TMIN<99&&TMIN>=0)	TMIN++;
			}
			if(T_flag==2) 
			{
			 if(TMAX>=100)			TMAX = 99;
			 if(TMAX<0)				TMAX = 0;
			 if(TMAX<99&&TMAX>=0)	TMAX++;
			}	
		}
		check_S6 = S6;	
	}
}

void KEY_S5()
{
	if(S5 != check_S5)
	{
		if(check_S5==0)
		{
			if(Dis_flag==1)
			{
				T_flag++;	if(T_flag==3)	T_flag=0;
			}
			if(Dis_flag==0)		T_flag=0;		
		}
		check_S5 = S5;	
	}	
}

void KEY_S4()
{
	if(S4 != check_S4)
	{
		if(check_S4==0)
		{
			Dis_flag = ~Dis_flag;	
		}
		check_S4 = S4;	
	}
}

void KEY()
{
	KEY_S4();
	KEY_S5();
	KEY_S6();
	KEY_S7();
}

void check()		 //用于判定温度下限是否超过温度上限
{
	if(Dis_flag==0&&TMAX>=TMIN)
		{max=TMAX;min=TMIN;}

	if(Dis_flag==0)
	{
		if(TMIN>TMAX)
		{
			TMAX=max;
			TMIN=min;
		}
	}
}
void InterruptTimer0() interrupt 1
{
	static unsigned char i=0;

	switch(i)
	{
		case 0:P2 = 0xC0;P0=0x80;P2=0xE0;P0=LEDbuff[0];P2=0x00;i++;break;
		case 1:P2 = 0xC0;P0=0x40;P2=0xE0;P0=LEDbuff[1];P2=0x00;i++;break;
		case 2:P2 = 0xC0;P0=0x20;P2=0xE0;P0=LEDbuff[2];P2=0x00;i++;break;
		case 3:P2 = 0xC0;P0=0x10;P2=0xE0;P0=LEDbuff[3];P2=0x00;i++;break;
		case 4:P2 = 0xC0;P0=0x08;P2=0xE0;P0=LEDbuff[4];P2=0x00;i++;break;
		case 5:P2 = 0xC0;P0=0x04;P2=0xE0;P0=LEDbuff[5];P2=0x00;i++;break;
		case 6:P2 = 0xC0;P0=0x02;P2=0xE0;P0=LEDbuff[6];P2=0x00;i++;break;
		case 7:P2 = 0xC0;P0=0x01;P2=0xE0;P0=LEDbuff[7];P2=0x00;i=0;break;
		default : break;
	}
	cnt1++; cnt2++;
	num++;	if(num==800)	{num=0;num_flag = ~num_flag;}	  //被选中单元每0.8s闪烁
	KEY();
	DA();
	check();
}

main.c 不知道是真的简单还是咋的,我才写了250行,可能是最近有些if语句折叠起来的,但是就算加上也才300多行,看来真的是因为疫情出的简单啊QAQ

在这里插入图片描述

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

#include<STC15F2K60S2.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 DAC_Init(unsigned char dat)			
{
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(0x43);
	 IIC_WaitAck();
	 IIC_SendByte(dat);
	 IIC_WaitAck();
	 IIC_Stop();
}

注意一下DAC就行,我甚至觉得比AD还简单了许多,,,

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"

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

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t=10*t;
	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;
}

void DS18B20_Start()
{
	init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
}

unsigned char DS18B20_Get()
{
   	char temp=0;
	unsigned char high=0,low=0;
	
	init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0xBE);
	
	low=Read_DS18B20();	
	high=Read_DS18B20();

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

onewire.c老生常谈,就不讲了

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

unsigned char rd_temperature(void);  //; ;
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);

void DS18B20_Start();
unsigned char DS18B20_Get();

#endif

onewire.h

#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

void DAC_Init(unsigned char dat);

#endif

iic.h

好啦,结束,我去改上一届的代码,感谢观看

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冉冰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值