2021单片机省赛第一场蓝桥杯真题:另一种代码风格

2021单片机省赛第一场

  • 有关题目
  • 实现代码
  • ①main.c
  • ②main.c
  • iic.h
  • iic.c
  • onewire.h
  • onewire.c
  • 有关题目






    实现代码

    注意:

    代码实现方面
    ①注意控制温度参数temp_para范围
    ②DAC输出时,注意写入的数字IIC_SendByte(temp)中temp范围在0~255;
    源文件修改方面
    ①官方给的iic.h中使用的时C51的头文件"reg52.h",我们需要修改为对应的15系列头文件"STC15F2K60S2.h",这样才可以使用其中的一些特殊位寄存器
    ②注意修改驱动代码时要留意一下onewire.h中单总线延时函数,是STC89C52RC,还是15系列的,15系列的单片机速度比51快8~12倍,需要修改对应的延时函数。如下
    //单总线内部延时函数
    void Delay_OneWire(unsigned int t)
    {
    char i;
    while(t–)
    for (i = 0; i < 12; i++);
    }

    ①main.c

    #include "STC15F2K60S2.h"
    #include "onewire.h"  									
    #include "iic.h"  									
    
    #define uchar unsigned char
    #define uint unsigned int
    
    sbit L1 = P0^0;
    sbit L2 = P0^1;
    sbit L3 = P0^2;
    sbit L4 = P0^3;
    
    uchar jm = 0;
    code uchar tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xff, 0xc6, 0x8c, 0x88};
    //c p  A 11 12 13
    
    bit flag_mod;
    uchar temp_para = 25;//温度参数
    
    float curr_temp, Vdac;//当前温度,DAC输出电压
    
    void sys_init();
    float rd_temp();
    void dac_pcf8591(uchar da);
    void key_handle();
    void mod_handle();
    void led();
    
    void dsp_smg_bit(uchar pos, val, dot);//dot = 1,添加小数点
    void display();//显示功能,分三个大块
    void dsp_temp();
    void dsp_para();
    void dsp_dac();
    void Delay1ms()	;	//1ms@12.000MHz,延时1ms用于给足数码管足够显示时间
    void delay_k(uchar t);//延时t * 10us
    
    void main()
    {
    	sys_init();
    	while(1)
    	{
    		curr_temp = rd_temp();
    		key_handle();
    		mod_handle();
    		display();
    		dac_pcf8591((uchar)(Vdac * 51));
    		led();
    	}
    }
    void mod_handle()
    {
    	if (!flag_mod)
    	{
    		if (curr_temp < temp_para)
    			Vdac = 0.0;
    		else 
    			Vdac = 5.0;
    	}
    	else 
    	{
    		if (curr_temp <= 20)
    			Vdac = 1.0;
    		else if (curr_temp >= 40)
    			Vdac = 4.0;
    		else 
    			Vdac = 0.15 * curr_temp - 2;
    	}
    }
    void led()
    {
    	if (!flag_mod)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L1 = 0;
    	}
    	
    	if (0 == jm)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L2 = 0;
    	}
    	else if (1 == jm)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L3 = 0;
    	}
    	else if (2 == jm)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L4 = 0;
    	}
    	
    }
    void key_handle()
    {
    	P44 = P42 = P33 = 1;
    	P32 = 0;
    	if (!P44)//s5 模式切换
    	{
    		delay_k(15);
    		if (!P44)
    		{
    			flag_mod = !flag_mod;
    			while(!P44)
    				display();
    		}
    	
    	}
    	if (!P42)//s9 +
    	{
    		delay_k(15);
    		if (!P42)
    		{
    			if (1 == jm)
    			{
    				if (++temp_para > 99)
    					temp_para = 99;
    				
    			}
    			
    			while(!P42)
    				display();
    		}
    	
    	}
    	
    	P44 = P42 = P32 = 1;
    	P33 = 0;
    	if (!P44)//s4 界面调整
    	{
    		delay_k(15);
    		if (!P44)
    		{
    			if (++jm >= 3)
    				jm = 0;
    			
    			while(!P44)
    				display();
    		}
    	
    	}
    	if (!P42)//s8 -
    	{
    		delay_k(15);
    		if (!P42)
    		{
    			if (1 == jm)
    			{
    				if (--temp_para < 10)
    					temp_para = 10;
    			}
    			
    			while(!P42)
    				display();
    		}
    	}
    }
    
    void dsp_dac()
    {	
    	uint x = (uint)(Vdac * 100);
    	dsp_smg_bit(1, 13, 0);
    	
    	dsp_smg_bit(6, x / 100 % 10, 1);
    	dsp_smg_bit(7, x / 10 % 10, 0);
    	dsp_smg_bit(8, x % 10, 0);
    }
    
    
    void dsp_para()
    {
    	dsp_smg_bit(1, 12, 0);
    	dsp_smg_bit(7, temp_para / 10 % 10, 0);
    	dsp_smg_bit(8, temp_para % 10, 0);
    }
    
    void dsp_temp()
    {
    	uint x = (uint)(curr_temp * 100);
    	if (x != 8500)
    	{
    		dsp_smg_bit(1, 11, 0);	
    		dsp_smg_bit(5, x / 1000 % 10, 0);
    		dsp_smg_bit(6, x / 100 % 10, 1);
    		dsp_smg_bit(7, x / 10 % 10, 0);
    		dsp_smg_bit(8, x % 10, 0);
    	}
    }
    
    void display()
    {
    	if (0 == jm)
    		dsp_temp();
    	else if (1 == jm)
    		dsp_para();
    	else if (2 == jm)
    		dsp_dac();			
    }
    void dsp_smg_bit (uchar pos, val, dot)
    {
    	P2 = (P2 & 0x1f) | 0xc0;
    	P0 = 1 << (pos - 1);
    	
    	P2 = (P2 & 0x1f) | 0xe0;
    	if (!dot)
    		P0 = tab[val];
    	else 
    		P0 = tab[val] & 0x7f;
    	
    	Delay1ms();
    	P0 = 0xff;
    	P2 &= 0x1f;
    }
    void Delay1ms()		//@12.000MHz
    {
    	unsigned char i, j;
    
    	i = 12;
    	j = 169;
    	do
    	{
    		while (--j);
    	} while (--i);
    }
    void delay_k(uchar t)
    {
    	while(t--)
    		display();
    }
    void dac_pcf8591(uchar da)
    {
    	IIC_Start();
    	IIC_SendByte(0x90);
    	IIC_WaitAck();
    	
    	IIC_SendByte(0x40);
    	IIC_WaitAck();
    	
    	IIC_SendByte(da);
    	IIC_WaitAck();
    	IIC_Stop();
    }
    float rd_temp()
    {
    	uchar l, h;
    	uint temp;
    	init_ds18b20();
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0x44);
    	
    	init_ds18b20();//
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0xbe);
    	
    	l = Read_DS18B20();
    	h = Read_DS18B20();
    	
    	temp = (h & 0x0f);
    	temp <<= 8;
    	temp |= l;
    	
    	return (float)(temp * 0.0625);
    }	
    
    void sys_init()
    {
    	P2 = (P2 & 0x1f) | 0xa0;
    	P0 = 0xaf;
    	
    	P2 = (P2 & 0x1f) | 0x80;
    	P0 = 0xff;
    	P2 &= 0x1f;
    }
    

    ②main.c

    #include "STC15F2K60S2.h"
    #include "iic.h"
    #include "onewire.h"
    
    #define uchar unsigned char
    #define uint unsigned int
    
    sbit L1 = P0^0;
    sbit L2 = P0^1;
    sbit L3 = P0^2;
    sbit L4 = P0^3;
    
    uchar jm = 0;//界面初始化温度界面
    code uchar tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff, 0xc6, 0x8c, 0x88}; 
    //C P A 11 12 13
    
    bit mod_flag;//0为模式1,1为模式2;
    
    char temp_para = 25;//温度参数
    float curr_temp, Vdac;//当前温度,DAC输出电压
    
    void sys_init();
    float rd_temperature();
    void key_handle();
    void dac_pcf8591(uchar da);
    void led();
    
    void dsp_smg_bit(uchar pos, val, sta);//sta = 1,添加小数点
    void display();//显示功能,分三个大块
    void dsp_temp();
    void dsp_para();
    void dsp_dac();
    void delay_k(uchar t);//延时t * 10us
    void Delay1ms();		//1ms@12.000MHz,延时1ms用于给足数码管足够显示时间
    
    void main()
    {
    	sys_init();
    	while(1)
    	{
    		curr_temp = rd_temperature();
    		key_handle();
    		display();
    		led();
    	}
    }
    void led()
    {
    	if (!mod_flag)
    	{	
    		P2 = (P2 & 0x1f) | 0x80;
    		L1 = 0;
    	}
    	
    	if (0 == jm)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L2 = 0;
    	}
    	else if (1 == jm)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L3 = 0;
    	}
    	else if (2 == jm)
    	{
    		P2 = (P2 & 0x1f) | 0x80;
    		L4 = 0;
    	}	
    }
    
    void key_handle()
    {
    	P44 = P42 = P33 = 1;
    	P32 = 0;
    	if (!P44)//s5--模式切换
    	{
    		delay_k(15);
    		if (!P44)
    		{
    			while(!P44)
    				display();
    			mod_flag = !mod_flag;
    			if (!mod_flag)
    			{
    				if (curr_temp * 10 < temp_para * 10)
    				{
    					Vdac = 0.0;
    				}
    				else 
    					Vdac = 5.0;
    			}
    			else 
    			{
    				if (curr_temp * 10 < 200)
    					Vdac = 1.0;
    				else if (curr_temp * 10 > 400)
    					Vdac = 4.0;
    				else 
    				{
    					Vdac = 0.15 * curr_temp - 2;
    				}
    			}
    			dac_pcf8591((uchar)(Vdac * 51));//注意写入pcf8591时范围
    		}
    	}
    	
    	if (!P42)//s9 +
    	{
    		delay_k(15);
    		if (!P42)
    		{
    			while(!P42)
    				display();
    			if (1 == jm)
    			{
    				if (++temp_para > 99)
    					temp_para = 99;
    			}
    		}
    	}
    	
    	P44 = P42 = P32 = 1;
    	P33 = 0;
    	if (!P44)//s4 jm
    	{
    		delay_k(15);
    		if (!P44)
    		{
    			while(!P44)
    				display();
    			if (++jm >= 3)
    				jm = 0;
    		}
    	}
    	
    	if (!P42)//s8 -
    	{
    		delay_k(15);
    		if (!P42)
    		{
    			while(!P42)
    				display();
    				
    			if (1 == jm)
    			{
    				if (--temp_para < 0)
    					temp_para = 0; 
    			}
    		}
    	}
    }
    void display()
    {
    	if (0 == jm)
    		dsp_temp();
    	else if (1 == jm)
    		dsp_para();	
    	else if (2 == jm)
    		dsp_dac();
    }
    
    void dsp_dac()
    {
    	uint x = (uint) (Vdac * 100);
    	dsp_smg_bit(1, 13, 0);
    	
    	dsp_smg_bit(6, x / 100 % 10, 1);
    	dsp_smg_bit(7, x / 10 % 10, 0);
    	dsp_smg_bit(8, x % 10, 0);
    
    }
    void dsp_para()
    {
    	dsp_smg_bit(1, 12, 0);
    	
    	dsp_smg_bit(7, temp_para / 10 % 10, 0);
    	dsp_smg_bit(8, temp_para % 10, 0);
    }
    void dsp_temp()
    {
    	uint x = (uint) (curr_temp * 100);//当前温度扩大100倍
    	dsp_smg_bit(1, 11, 0);
    	
    	dsp_smg_bit(5, x / 1000 % 10, 0);
    	dsp_smg_bit(6, x / 100 % 10, 1);
    	dsp_smg_bit(7, x / 10 % 10, 0);
    	dsp_smg_bit(8, x % 10, 0);
    }
    
    void dsp_smg_bit(uchar pos, val, sta)
    {
    	P2 = (P2 & 0x1f) | 0xc0;
    	P0 = 1 << (pos - 1);
    	
    	P2 = (P2 & 0x1f) | 0xe0;
    	if (sta)
    		P0 = tab[val] & 0x7f;
    	else 
    		P0 = tab[val];
    	
    	Delay1ms();
    	
    	P0 = 0xff;
    	P2 &= 0x1f;
    }
    void Delay1ms()		//@12.000MHz
    {
    	unsigned char i, j;
    
    	i = 12;
    	j = 169;
    	do
    	{
    		while (--j);
    	} while (--i);
    }
    void delay_k(uchar t)
    {
    	while(t--)
    		display();
    }
    void dac_pcf8591(uchar da)
    {
    	IIC_Start();
    	IIC_SendByte(0x90);
    	IIC_WaitAck();
    
    	IIC_SendByte(0x40);  //DAC输出模式,允许 DAC, ADC 通道 0
    	IIC_WaitAck();
    
    	IIC_SendByte(da);
    	IIC_WaitAck();
    	IIC_Stop();
    }
    float rd_temperature()
    {
    	uchar l, h;
    	uint t;
    	float temp;
    	init_ds18b20();
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0x44);
    	
    	init_ds18b20();
    	Write_DS18B20(0xcc);
    	Write_DS18B20(0xbe);
    	
    	l = Read_DS18B20();
    	h = Read_DS18B20();
    	
    	t = (h & 0x0f);
    	t <<= 8;
    	t |= l;
    	temp = t * 0.0625;
    	
    	return temp;
    }
    
    void sys_init()
    {
    	//关蜂鸣器,继电器
    	P2 = (P2 & 0x1f) | 0xa0;
    	P0 = 0xaf;
    	
    	P2 = (P2 & 0x1f) | 0x80;
    	P0 = 0xff;
    	P2 &= 0x1f;
    }
    

    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_SendAck(bit ackbit); 
    void IIC_SendByte(unsigned char byt); 
    //unsigned char IIC_RecByte(void); 
    
    
    #endif
    

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

    onewire.h

    #ifndef __ONEWIRE_H
    #define __ONEWIRE_H
    
    #include "STC15F2K60S2.h"
    
    sbit DQ = P1^4;  
    
    //unsigned char rd_temperature(void);  
    void Delay_OneWire(unsigned int t);
    bit init_ds18b20(void);
    unsigned char Read_DS18B20(void);
    void Write_DS18B20(unsigned char dat);
    
    #endif
    
    

    onewire.c

    #include "onewire.h"
    
    //单总线内部延时函数
    void Delay_OneWire(unsigned int t)  
    {	
    	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;
    }
    
    //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;
    }
    
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 2021单片机省赛第一场蓝桥杯真题:另一种代码风格

    发表评论