蓝桥杯第十二届单片机省赛真题解析:IAP15F2K61S2实战探讨

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、代码
  • 1.头文件
  • 2.变量声明
  • 3.函数声明
  • 二、使用模块
  • 1.其他函数
  • 2.main函数
  • 3.iic函数
  • 4.onewire函数
  • 总结

  • 前言


    一、代码

    1、头文件

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

    2、变量声明

    sbit L1 = P0^0;
    sbit L2 = P0^1;
    sbit L3 = P0^2;
    sbit L4 = P0^3;
    
    sbit K1 = P4^4;
    sbit K2 = P4^2;
    sbit K3 = P3^3;
    sbit K4 = P3^2;
    
    //=====================数组定义======================
    code unsigned char Seg_Table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x8c};
    code unsigned char Seg_Dian_Table[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};
    //=====================变量定义======================
    unsigned char flag_s4;//按键s4按下三种界面
    unsigned char flag_s5;//按键s4按下两种模式
    unsigned char Temp_C = 25;//温度参数
    
    unsigned int Temp;//温度参数
    unsigned int U;//电压参数
    

    3、函数声明

    //=====================函数声明======================
    void Nixie_Show();//数码管显示函数
    void Scan_Key();//按键控制函数
    void LED_Show();//LED灯控制函数

    二、使用模块

     1、其他函数

    //=====================其他函数======================
    
    void delay(unsigned char i)//延时函数
    {
    	while(i--);
    }
    
    void hc(unsigned char n)//通道选择
    {
    	switch(n)
    	{
    		case 4:
    			P2 = (P2 & 0x1f) | 0x80;//LED
    			break;
    		case 5:
    			P2 = (P2 & 0x1f) | 0xa0;//蜂鸣器,继电器等
    			break;
    		case 6:
    			P2 = (P2 & 0x1f) | 0xc0;//数码管位选
    			break;
    		case 7:
    			P2 = (P2 & 0x1f) | 0xe0;//数码管段选
    			break;
    		case 0:
    			P2 = P2 & 0x1f;
    			break;
    	}
    }
    
    void System_Init()//系统初始化
    {
    	hc(4);
    	P0 = 0xff;//关闭所有LED灯
    	hc(5);
    	P0 = 0x00;//关闭蜂鸣器,继电器等
    	hc(0);
    }
    
    void Nixie_pos_num(unsigned char pos,num)//数码管显示位置,数字(不带小数点)
    {
    	hc(6);
    	P0 = 0x01 << (pos-1);
    	hc(7);
    	P0 = Seg_Table[num];
    	delay(500);
    	P0 = 0xff;//数码管消隐
    	hc(0);
    }
    
    void Nixie_Dian_pos_num(unsigned char pos,num)//数码管显示位置,数字(带小数点)
    {
    	hc(6);
    	P0 = 0x01 << (pos-1);
    	hc(7);
    	P0 = Seg_Dian_Table[num];
    	delay(500);
    	P0 = 0xff;//数码管消隐
    	hc(0);
    }

    2、数码管函数

    //=====================主要函数======================
    void Nixie_Show()//数码管显示函数
    {
    	if(flag_s4 == 0)//温度显示界面
    	{
    		Temp = Read_DS18B20_Temp();
    		Nixie_pos_num(1,12);
    		Nixie_pos_num(5,Temp/1000);
    		Nixie_Dian_pos_num(6,Temp/100%10);
    		Nixie_pos_num(7,Temp/10%10);
    		Nixie_pos_num(8,Temp%10);
    	}
    	if(flag_s4 == 1)//参数设置界面
    	{
    		Nixie_pos_num(1,16);
    		Nixie_pos_num(7,Temp_C/10);
    		Nixie_pos_num(8,Temp_C%10);
    	}
    	if(flag_s4 == 2)//DAC界面输出界面
    	{
    		Nixie_pos_num(1,16);
    		if(flag_s5 == 0)//模式1
    		{
    			if(Temp>Temp_C * 100)//采集到的温度大于温度参数,输出5
    			{
    				Nixie_Dian_pos_num(6,5);
    				Nixie_pos_num(7,0);
    				Nixie_pos_num(8,0);
    			}
    			if(Temp<Temp_C * 100)//采集到的温度小于温度参数,输出0
    			{
    				Nixie_Dian_pos_num(6,0);
    				Nixie_pos_num(7,0);
    				Nixie_pos_num(8,0);
    			}
    			
    		}
    		if(flag_s5 == 1)//模式2
    		{
    			Write_PCF(U);
    			U = 0.15 * Temp - 200;
    			if(Temp>=4000)
    			{
    				Nixie_Dian_pos_num(6,4);
    				Nixie_pos_num(7,0);
    				Nixie_pos_num(8,0);
    			}
    			if(Temp<=1000)
    			{
    				Nixie_Dian_pos_num(6,1);
    				Nixie_pos_num(7,0);
    				Nixie_pos_num(8,0);
    			}
    			if(Temp>1000 && Temp<4000)
    			{
    				Nixie_Dian_pos_num(6,U/100);
    				Nixie_pos_num(7,U/10%10);
    				Nixie_pos_num(8,U%10);
    			}
    		}
    	}
    }
    

    3、按键函数

    void Scan_Key()//按键控制函数
    {
    	K4 = K2 = K3 = 1;K1 = 0;
    	if(K3 == 0 || K4 == 0)
    	{
    		delay(100);//按键去抖
    		if(K3 == 0)//s4按下
    		{
    			flag_s4 = (flag_s4 + 1) % 3;
    			while(K3 == 0)delay(100);
    			{
    				Nixie_Show();
    				LED_Show();
    			}
    		}
    		if(flag_s4 == 2)
    		{
    			if(K4 == 0)//s5按下
    			{
    				flag_s5 = (flag_s5 + 1) % 2;
    				while(K4 == 0)delay(100);
    				{
    					Nixie_Show();
    					LED_Show();
    				}
    			}
    		}
    	}
    	
    	K4 = K1 = K3 = 1;K2 = 0;
    	if(K3 == 0 || K4 == 0)
    	{
    		delay(100);//按键去抖
    		if(flag_s4 == 1)//在参数界面
    		{
    			if(K3 == 0)//s8按下
    			{
    				Temp_C--;
    				while(K3 == 0)delay(100);
    				{
    					Nixie_Show();
    					LED_Show();
    				}
    			}
    			if(K4 == 0)//s9按下
    			{
    				Temp_C++;
    				while(K4 == 0)delay(100);
    				{
    					Nixie_Show();
    					LED_Show();
    				}
    			}
    		}
    		
    	}
    }

    4、LDE函数

    void LED_Show()//LED灯控制函数
    {
    	if(flag_s5 == 0)//在模式1下,L1灯亮
    	{
    		hc(4);
    		L1 = 0;
    		hc(0);
    	}
    	else
    	{
    		hc(4);
    		L1 = 1;
    		hc(0);
    	}
    	if(flag_s4 == 0)//在温度显示界面下,L2灯亮
    	{
    		hc(4);
    		L2 = 0;
    		hc(0);
    	}
    	else
    	{
    		hc(4);
    		L2 = 1;
    		hc(0);
    	}
    	if(flag_s4 == 1)//在参数设置界面下,L3灯亮
    	{
    		hc(4);
    		L3 = 0;
    		hc(0);
    	}
    	else
    	{
    		hc(4);
    		L3 = 1;
    		hc(0);
    	}
    	if(flag_s4 == 2)//在DAC输出界面下,L4灯亮
    	{
    		hc(4);
    		L4 = 0;
    		hc(0);
    	}
    	else
    	{
    		hc(4);
    		L4 = 1;
    		hc(0);
    	}
    }

    5、main函数

    void main()
    {
    	System_Init();
    	Temp = Read_DS18B20_Temp();
    	delay(100);//让温度传感器充分读取温度
    	while(1)
    	{
    		Write_PCF(U);
    		Temp = Read_DS18B20_Temp();
    		LED_Show();
    		Scan_Key();
    		Nixie_Show();
    	}	
    }

    6、iic函数

    iic.c

    /*	#   I2C代码片段说明
    	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
    	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
    		中对单片机时钟频率的要求,进行代码调试和修改。
    */
    
    #define DELAY_TIME	5
    #include <STC15F2K60S2.H>
    #include <intrins.H>
    
    sbit sda = P2^1;
    sbit scl = P2^0;
    //
    static void I2C_Delay(unsigned char n)
    {
        do
        {
            _nop_();_nop_();_nop_();_nop_();_nop_();
            _nop_();_nop_();_nop_();_nop_();_nop_();
            _nop_();_nop_();_nop_();_nop_();_nop_();		
        }
        while(n--);      	
    }
    
    //
    void I2CStart(void)
    {
        sda = 1;
        scl = 1;
    	I2C_Delay(DELAY_TIME);
        sda = 0;
    	I2C_Delay(DELAY_TIME);
        scl = 0;    
    }
    
    //
    void I2CStop(void)
    {
        sda = 0;
        scl = 1;
    	I2C_Delay(DELAY_TIME);
        sda = 1;
    	I2C_Delay(DELAY_TIME);
    }
    
    //
    void I2CSendByte(unsigned char byt)
    {
        unsigned char i;
    	
        for(i=0; i<8; i++){
            scl = 0;
    		I2C_Delay(DELAY_TIME);
            if(byt & 0x80){
                sda = 1;
            }
            else{
                sda = 0;
            }
    		I2C_Delay(DELAY_TIME);
            scl = 1;
            byt <<= 1;
    		I2C_Delay(DELAY_TIME);
        }
    	
        scl = 0;  
    }
    
    //
    unsigned char I2CReceiveByte(void)
    {
    	unsigned char da;
    	unsigned char i;
    	for(i=0;i<8;i++){   
    		scl = 1;
    		I2C_Delay(DELAY_TIME);
    		da <<= 1;
    		if(sda)
    			da |= 0x01;
    		scl = 0;
    		I2C_Delay(DELAY_TIME);
    	}
    	return da;    
    }
    
    //
    unsigned char I2CWaitAck(void)
    {
    	unsigned char ackbit;
    	
        scl = 1;
    	I2C_Delay(DELAY_TIME);
        ackbit = sda; 
        scl = 0;
    	I2C_Delay(DELAY_TIME);
    	
    	return ackbit;
    }
    
    //
    void I2CSendAck(unsigned char ackbit)
    {
        scl = 0;
        sda = ackbit; 
    	I2C_Delay(DELAY_TIME);
        scl = 1;
    	I2C_Delay(DELAY_TIME);
        scl = 0; 
    	sda = 1;
    	I2C_Delay(DELAY_TIME);
    }
    
    void Write_PCF(unsigned char dat)
    {
    	I2CStart();
    	I2CSendByte(0x90);
    	I2CWaitAck();
    	I2CSendByte(0x40);
    	I2CWaitAck();
    	I2CSendByte(dat);
    	I2CWaitAck();
    	I2CStop();
    }

    iic.h

    #ifndef __iic_H__
    #define __iic_H__
    void W_pcf(unsigned char dat);
    #endif

    7、onewire函数

    onewire.c

    /*	# 	单总线代码片段说明
    	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
    	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
    		中对单片机时钟频率的要求,进行代码调试和修改。
    */
    #include <STC15F2K60S2.H>
    sbit DQ = P1^4;
    //
    void Delay_OneWire(unsigned int t)  
    {
    	unsigned char i;
    	while(t--){
    		for(i=0;i<12;i++);
    	}
    }
    
    //
    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;
    }
    
    
    unsigned int Read_DS18B20_Temp()
    {
    	unsigned char LSB,MSB;
    	unsigned int Temp;
    	init_ds18b20();
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0x44);
    	init_ds18b20();
    	
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0xbe);
    	LSB = Read_DS18B20();
    	MSB = Read_DS18B20();
    	
    	Temp = (MSB << 8) | LSB;
    	
    	Temp = Temp >> 4;//把小数部分取出来
    	Temp = Temp * 100;//整数部分*100
    	Temp = Temp + (LSB & 0x0f) * 0.0625 * 100;//把温度放大100倍,int浮点数
    	
    	return Temp;
    }

    onewire.h

    #ifndef __onewire_H__
    #define __onewire_H__
    unsigned int Read_DS18B20_Temp();
    #endif

    总结

    蓝桥杯第十二届题目总体不难,关键是模块之间的联系。

    作者:Simon_note

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯第十二届单片机省赛真题解析:IAP15F2K61S2实战探讨

    发表回复