蓝桥杯单片机第十二届省赛题详细讲解

看之前强烈建议先自己做一遍!!!

演示视频

题目讲解

首先根据系统程序框图来提前调试好各模块部分的功能。比如按键,数码管,PCF8591电压输出,温度读取。
在这里插入图片描述
然后看数码管显示界面
在这里插入图片描述

uchar SMG_mode=0;//控制数码管模式
uchar temp_var=25;//温度参数定义
int outV=325;//输出电压参数定义
signed long temp=0; //温度获取参数
bit output_mode=0;//输出电压模式
void main(void)
{
    
    
	init(); //初始化开发板
	while(1)
	{
    
    
		temp=rd_temperature();//获取温度
		if(SMG_mode==0) //模式一温度显示
		{
    
    
			SMG[0]=23;SMG[1]=SMG[2]=SMG[3]=20;
			SMG[4]=temp/100000;//20 0000
			SMG[5]=temp%100000/10000+10;
			SMG[6]=temp%10000/1000;
			SMG[7]=temp%1000/100;
		}
		else if(SMG_mode==1)//模式二温度参数显示
		{
    
    
			SMG[0]=22;SMG[1]=SMG[2]=SMG[3]=SMG[4]=SMG[5]=20;
			SMG[6]=temp_var/10;SMG[7]=temp_var%10;	
		}
		else if(SMG_mode==2)//模式三输出电压参数显示
		{
    
    
			SMG[0]=24;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
			SMG[5]=outV/100+10;SMG[6]=outV%100/10;SMG[7]=outV%10;			
		}
		SMG_output();
		Jkey_scan();
	}
}

写完记得烧录调试一下。
做完这些接着看按键扫描程序。
在这里插入图片描述

void Jkey_scan(void)
{
    
    
	unsigned char i,key;
	for(i=0x80;i>8;i >>=1)
	{
    
    
		if(i==0x80){
    
    P44=0;P42=1;P3=~i;}
		else if(i==0x40){
    
    P44=1;P42=0;P3=~i;}
		else {
    
    P44=1;P42=1;P3=~i;}
		if(i==0x80){
    
    key=P3;key&=0x7f;}
		else if(i==0x40){
    
    key=P3;key&=0xbf;}
		else {
    
    key=P3;}
		if((key&0x0f)!=0x0f)
		{
    
    
			Delay5ms();
			if((key&0x0f)!=0x0f)
			{
    
    
				switch(key)
				{
    
    
					case 0x7b: //s5
						if(output_mode==0)output_mode=1;
					else output_mode=0;
						break; //s5
					case 0x77: //s4
						if(SMG_mode==0)SMG_mode=1;
					else if(SMG_mode==1)SMG_mode=2;
					else SMG_mode=0;
						break; 
					case 0xbb: //s9
						if(SMG_mode==1){
    
    
						temp_var+=1;}
						break;
					case 0xb7:	//s8
						if(SMG_mode==1){
    
    
						temp_var-=1;}
						break;
				}
			}
			while((key&0x0f)!=0x0f)
			{
    
    
				key=P3;SMG_output(); //按下按键不影响数码管显示
			}
		}
	}
}

电压输出功能。

if(output_mode==0)//电压输出模式一
{
    
    
	if(temp_var>(temp/10000))
	{
    
    
		outV=0;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
		IIC_write(PCF8591_address,Output_address,0);//输出0v
	}
	else {
    
    IIC_write(PCF8591_address,Output_address,255);outV=500;}//输出5v
}
else//电压输出模式二
{
    
    
	//先把直线表示出来
	//(255/5*4-255/5)/20 x -z== y z=102
	//7.65x-102=y
	IIC_write(PCF8591_address,Output_address,((7.65*(temp/10000))-102));
	outV=(((7.65*(temp/10000))-102)*5/255)*100;
}

然后接着看题目。
在这里插入图片描述
在这里插入图片描述
LED指示灯。

if(output_mode==0){
    
    led&=0xfe;}//l1点亮
else led|=0x01;
if(SMG_mode==0){
    
    led&=0xfd;led|=0x04;led|=0x08;}//l2点亮
else if(SMG_mode==1){
    
    led&=0xfb;led|=0x02;led|=0x08;}//l3点亮
else if(SMG_mode==2){
    
    led&=0xf7;led|=0x04;led|=0x02;}//l4点亮
P2=0X80;P0=led;

完整程序

main.c

#include<stc15f2k60s2.h>
#include"intrins.h"
#include "iic.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int

#define PCF8591_address 0x90
#define Move_address 0x03
#define Output_address 0x40

void SMG_output(void);
void init(void);
void Delay1ms(void);
void Jkey_scan(void);
void Delay5ms(void);
uchar tab[]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf,0x8c,0xc6,0x88};//p c a
uchar SMG[8]={
    
    20,20,20,20,20,20,20,20};//初始显示20,全息数码管
uchar SMG_mode=0;//控制数码管模式
uchar temp_var=25;//温度参数定义
int outV=325;//输出电压参数定义
signed long temp=0; //温度获取参数
bit output_mode=0;//输出电压模式 0为DAC 输出电压与温度相关。1为DAC 按照图 7 给出的关系输出电压。
uchar led=0xff;//led定义
void main(void)
{
    
    
	init(); //初始化开发板
	while(1)
	{
    
    
		temp=rd_temperature();//获取温度
		if(SMG_mode==0) //模式一温度显示
		{
    
    
			SMG[0]=23;SMG[1]=SMG[2]=SMG[3]=20;
			SMG[4]=temp/100000;//20 0000
			SMG[5]=temp%100000/10000+10;
			SMG[6]=temp%10000/1000;
			SMG[7]=temp%1000/100;
		}
		else if(SMG_mode==1)//模式二温度参数显示
		{
    
    
			SMG[0]=22;SMG[1]=SMG[2]=SMG[3]=SMG[4]=SMG[5]=20;
			SMG[6]=temp_var/10;SMG[7]=temp_var%10;	
		}
		else if(SMG_mode==2)//模式三输出电压参数显示
		{
    
    
			SMG[0]=24;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
			SMG[5]=outV/100+10;SMG[6]=outV%100/10;SMG[7]=outV%10;			
		}
		
		
		if(output_mode==0)//电压输出模式一
		{
    
    
			if(temp_var>(temp/10000))
			{
    
    
				outV=0;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
				IIC_write(PCF8591_address,Output_address,0);//输出0v
			}
			else {
    
    IIC_write(PCF8591_address,Output_address,255);outV=500;}//输出5v
		}
		else//电压输出模式二
		{
    
    
			//先把直线表示出来
			//(255/5*4-255/5)/20 x -z== y z=102
			//7.65x-102=y
			IIC_write(PCF8591_address,Output_address,((7.65*(temp/10000))-102));
			outV=(((7.65*(temp/10000))-102)*5/255)*100;
		}
		
		if(output_mode==0){
    
    led&=0xfe;}//l1点亮
		else led|=0x01;
		if(SMG_mode==0){
    
    led&=0xfd;led|=0x04;led|=0x08;}//l2点亮
		else if(SMG_mode==1){
    
    led&=0xfb;led|=0x02;led|=0x08;}//l3点亮
		else if(SMG_mode==2){
    
    led&=0xf7;led|=0x04;led|=0x02;}//l4点亮
		P2=0X80;P0=led;
		SMG_output();
		Jkey_scan();
	}
}

void Jkey_scan(void)
{
    
    
	unsigned char i,key;
	for(i=0x80;i>8;i >>=1)
	{
    
    
		if(i==0x80){
    
    P44=0;P42=1;P3=~i;}
		else if(i==0x40){
    
    P44=1;P42=0;P3=~i;}
		else {
    
    P44=1;P42=1;P3=~i;}
		if(i==0x80){
    
    key=P3;key&=0x7f;}
		else if(i==0x40){
    
    key=P3;key&=0xbf;}
		else {
    
    key=P3;}
		if((key&0x0f)!=0x0f)
		{
    
    
			Delay5ms();
			if((key&0x0f)!=0x0f)
			{
    
    
				switch(key)
				{
    
    
					case 0x7b: //s5
						if(output_mode==0)output_mode=1;
					else output_mode=0;
						break; //s5
					case 0x77: //s4
						if(SMG_mode==0)SMG_mode=1;
					else if(SMG_mode==1)SMG_mode=2;
					else if(SMG_mode==2)SMG_mode=0;
						break; 
					case 0xbb: //s9
						if(SMG_mode==1){
    
    
						temp_var+=1;}
						break;
					case 0xb7:	//s8
						if(SMG_mode==1){
    
    
						temp_var-=1;}
						break;
				}
			}
			while((key&0x0f)!=0x0f)
			{
    
    
				key=P3;SMG_output(); //按下按键不影响数码管显示
			}
		}
	}
}

void SMG_output(void)
{
    
    
	uchar i;
	for(i=0;i<8;i++)
	{
    
    
	P2=(P2&0X1F)|0Xc0;
	P0=(1<<i);
	P2=(P2&0X1F)|0Xe0;
	P0=tab[SMG[i]];
	Delay1ms();
	}
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void init(void)
{
    
    
	P2=(P2&0X1F)|0XA0;
	P0=0X00;
	P2=(P2&0X1F)|0X80;
	P0=0Xff;
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void Delay5ms()		//@11.0592MHz
{
    
    
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
    
    
		while (--j);
	} while (--i);
}


void Delay1ms(void)		//@11.0592MHz
{
    
    
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
    
    
		while (--j);
	} while (--i);
}

iic.c

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

#define DELAY_TIME 40

void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{
    
    
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);
	IIC_WaitAck();
	IIC_SendByte(num);
	IIC_WaitAck();	
	IIC_Stop();	
}	

uchar IIC_read(uchar hw_address,uchar reg_address)
{
    
    
	uchar num;
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);	
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(hw_address|0x01);
	IIC_WaitAck();
	num=IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();	
	
	return num;
}

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

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

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

iic.h

#ifndef _IIC_H
#define _IIC_H

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

#define uchar unsigned char
#define uint unsigned int

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

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 IIC_write(uchar hw_address,uchar reg_address,uchar num);
uchar IIC_read(uchar hw_address,uchar reg_address);


#endif

onewire.c

#include "onewire.h"

//小数和负数显示温度
signed long rd_temperature(void)
{
    
    
	unsigned char low,high;
	float point;
	signed long integer;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);	
	
	low=Read_DS18B20();
	high=Read_DS18B20();
	if(((high>>4)&0x0f)!=0x0f)
	{
    
    
	integer=((low >>4)|(high<<4));
	point=(((low&0x08)>>3)*0.5)+(((low&0x04)>>2)*0.25)+\
	(((low&0x02)>>1)*0.125)+((low&0x01)*0.0625);
	integer=(integer+point)*10000;
	}
	else
	{
    
    
	integer=((~(low >>4))|(~(high<<4)));
	point=((((~low+1)&0x08)>>3)*0.5)+((((~low+1)&0x04)>>2)*0.25)+\
	((((~low+1)&0x02)>>1)*0.125)+(((~low+1)&0x01)*0.0625);
	integer=(integer+point)*10000;
	integer=-integer;
	}
	
	return integer;
}

//
void Delay_OneWire(unsigned int t)  
{
    
    
	t=t*8;
	while(t--);
}

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

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

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

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

#include <stc15f2k60s2.h>

sbit DQ = P1^4;  

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

#endif

工程文件

工程文件(有注释讲解)

猜你喜欢

转载自blog.csdn.net/darlingqx/article/details/127937497