蓝桥杯单片机第14届模拟赛2

有帮助的话点个赞吧~

4499b4e12cd44e34bd9b72ab06924772.png

e839bbafb75c443c8588c254354bd01d.png

8d0b2a4552424089a4aa9f2626084c88.png

a6d2f82d636d4e9a8ac497a5edc4e334.png

main.c 

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

typedef struct 
{
	unsigned char b1:1;
	unsigned char b2:1;
	unsigned char b3:1;
	unsigned char b4:1;
	unsigned char b5:1;
	unsigned char b6:1;
	unsigned char b7:1;
	unsigned char b8:1;
}Bits;

typedef union 
{
	unsigned char Hex;
	Bits B;
}HexToBit;

HexToBit led_ctrl;


unsigned char code smg_duanma[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char smg[8];
bit lock_smg=0;
bit busy;
unsigned char rx_buf;
unsigned int pwm_cnt; //0.1s为间隔点亮
bit pwm_flag=0;  //1就开始闪
unsigned char mode_smg=0;



void SendData(unsigned char dat);
void SendString(char *s);
void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
	P0 = p0dat;
	P2 = (P2&0x1f)|p2dat;
	P2 = P2&0x1f;
}

//定时器2
void Timer2Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x20;		//设置定时初值
	T2H = 0xD1;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	
	EA=1;
	IE2 |= 0x04;
}

//波特率设置
void UartInit(void)		//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xC7;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	
	EA=1;
	ES=1;
}


//继电器控制
unsigned char BR_cont=0x00;
bit flag_RELAY=0;
unsigned int cnt_Relay;
void vRELAY_Process()
{
	if(cnt_Relay>=500)
	{
		cnt_Relay=0;
		if(flag_RELAY==1)
		{
			BR_cont=BR_cont|0x10;
			vDevice_Process(0xa0, BR_cont);
		}
		else
		{
			BR_cont=BR_cont&0xef;
			vDevice_Process(0xa0, BR_cont);
		}
	}
}

//蜂鸣器控制
bit flag_buzz=0;
unsigned int cnt_Buzz;
void vBuzz_Process()
{
	if(cnt_Buzz>=500)
	{
		cnt_Buzz=0;
		if(flag_buzz==1)
		{
			BR_cont=BR_cont|0x40;
			vDevice_Process(0xa0, BR_cont);
		}
		else
		{
			BR_cont=BR_cont&0xbf;
			vDevice_Process(0xa0, BR_cont);
		}
	}
}

//LED控制
void vLED_Process()
{
	if(mode_smg==0)
	{
		led_ctrl.B.b1=0;  //L1点亮
		led_ctrl.B.b2=1;  //L2熄灭
	}
	else if(mode_smg==1)
	{
		led_ctrl.B.b1=1;  //L1熄灭
		led_ctrl.B.b2=0;  //L2点亮
	}
	vDevice_Process(0x80, led_ctrl.Hex);
}


//采集温度
unsigned int cnt_temp;
unsigned int temp;
void vRead_temperture()
{
	if(cnt_temp>=500)
	{
		cnt_temp=0;
		temp = vRead_temp()*10;//返回浮点数,乘10后转为整数就是三位数
		if(temp>=280)
		{
			flag_RELAY=1;
		}
		else 
		{
			flag_RELAY=0;
		}
	}
}

//采集RB2电压
unsigned int rb2_dat;
unsigned int cnt_rb2;
void vGet_rb2()
{
	if(cnt_rb2>=100)
	{
		cnt_rb2=0;
		rb2_dat = vRead_RB2();
		if(rb2_dat>=360)
		{
			flag_buzz=1;
		}
		else
		{
			flag_buzz=0;
		}
	}
}



//数码管操作函数

void vSMG_Process()
{
	if(mode_smg==0)
	{
		smg[0]=0xc1;
		smg[1]=smg_duanma[1];
		smg[2]=0xff;
		smg[3]=0xff;
		smg[4]=0xff;
		smg[5]=smg_duanma[temp/100];
		smg[6]=smg_duanma[temp/10%10]&0x7f;
		smg[7]=smg_duanma[temp%10];
	}
	
	if(mode_smg==1)
	{
		smg[0]=0xc1;
		smg[1]=smg_duanma[2];
		smg[2]=0xff;
		smg[3]=0xff;
		smg[4]=0xff;
		smg[5]=smg_duanma[rb2_dat/100]&0x7f;
		smg[6]=smg_duanma[rb2_dat/10%10];
		smg[7]=smg_duanma[rb2_dat%10];
	}	
}

//数码管显示
void vSMG_Show()
{
	static unsigned char i;
	vDevice_Process(0xc0, 0x00);
	vDevice_Process(0xe0, smg[i]);
	vDevice_Process(0xc0, 0x01<<i);
	i=(i+1)%8;
}

//矩阵键盘扫描
unsigned char Scan_Keys()
{
	unsigned char key_io=0xff;
	P32=0;P33=0;
	P34=1;P35=1;P42=1;P44=1;
	if(P44==0) key_io=0x70;
	if(P42==0) key_io=0xb0;
	if(P35==0) key_io=0xd0;
	if(P34==0) key_io=0xe0;
	
	P32=1;P33=1;
	P34=0;P35=0;P42=0;P44=0;
	if(P33==0) key_io = key_io|0x07;
	if(P32==0) key_io = key_io|0x0b;
	
	return key_io;
}

//三行按键
unsigned char Trg,Cont;
void vThreeLine_Key()
{
	unsigned char keyio;
	unsigned char ReadData;
	keyio = Scan_Keys();
	ReadData = keyio^0xff;
	Trg = ReadData&(ReadData^Cont);
	Cont = ReadData;
}

//按键处理
unsigned int cnt_key;
void vKeys_Process()
{
	if(cnt_key>=20)
	{
		cnt_key=0;
		vThreeLine_Key();
		if(Trg == 0x88)//S4
		{
			lock_smg=1;  //打开锁 进入锁定状态
		}
		
		if(Trg == 0x84)//S5
		{
			if(lock_smg==1) 
			{
				lock_smg=0;
			  led_ctrl.B.b3=1;  //L3熄灭 解锁后要熄灭
			}
			
		}
		
		if(Trg == 0x28)//S12
		{
			if(mode_smg==0)
			{
				SendString("TEMP:");
	      SendData(temp/100+'0');SendData(temp/10%10+'0');SendData('.');SendData(temp%10+'0');
				SendData('C');
			}
			if(mode_smg==1)
			{
				SendString("Voltage:");
	      SendData(rb2_dat/100+'0');SendData('.');SendData(rb2_dat/10%10+'0');SendData(rb2_dat%10+'0');
				SendData('V');
			}
		}
		
	}
}

/*----------------------------
发送串口数据
----------------------------*/
void SendData(unsigned char dat)
{
    while (busy);               //等待前面的数据发送完成
    busy = 1;
    SBUF = dat;                 //写数据到UART数据寄存器
}

/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
    while (*s)                  //检测字符串结束标志
    {
        SendData(*s++);         //发送当前字符
    }
}

//串口接收处理函数
void vUartRx_Process()
{
	 if(lock_smg==0) //如果锁定关闭 才根据指令切换界面
	 {
		 if(rx_buf=='A') mode_smg=0;   //发送A 进入温度显示
		 if(rx_buf=='B') mode_smg=1;   //发送B 进入电压显示		 
	 }
	 rx_buf=0; 
}


//系统初始化
void vSystem_Init()
{
	led_ctrl.Hex=0xff;
	vDevice_Process(0x80,0xff);
	vDevice_Process(0xa0,0x00);
}

void main()
{
	Timer2Init();
	vSystem_Init();
	UartInit();
	SendString("hello");
	while(1)
	{
		vSMG_Process();
		vRead_temperture();
		vGet_rb2();
		vRELAY_Process();
		vBuzz_Process();
		vKeys_Process();
		vUartRx_Process();
	
	}
}

void Timer2() interrupt 12
{
	cnt_temp++;cnt_rb2++;cnt_Relay++;cnt_Buzz++;cnt_key++;
	vSMG_Show();
	vLED_Process();
	if(lock_smg==1)
	{
		pwm_cnt++;
		if(pwm_cnt<100)
		{
			led_ctrl.B.b3=0;  //L3点亮
		}
		else if(pwm_cnt<200)
		{
			led_ctrl.B.b3=1;  //L3熄灭
		}
		else 
		{
			pwm_cnt=0;
		}
		vDevice_Process(0x80, led_ctrl.Hex);
	}
	
}

/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4
{
    if (RI)
    {
        RI = 0;                 //清除RI位
			SBUF=SBUF;
			rx_buf=SBUF;
    }
    if (TI)
    {
        TI = 0;                 //清除TI位
        busy = 0;               //清忙标志
    }
}

 iic.c

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/

#include <reg52.h>
#include <intrins.h>

#define DELAY_TIME	5

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

//读取电压

unsigned int vRead_RB2()
{
	unsigned char rb2;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	rb2 = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return rb2*100/51;
}

onewire.c

/*	# 	单总线代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.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;
}

//获取温度
float vRead_temp()
{
	unsigned char LSB,MSB;
	float 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)*0.0625;
	return temp;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值