蓝桥杯单片机 14届模拟题(4T平台)第二套

 

 

 

#include <STC15F2K60S2.H>
#include <intrins.h>
#include <stdio.h>
code unsigned char Seg_Table[27] = 
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e, // +16.
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,//.
0xc1
};
sbit DQ = P1^4;
sbit scl = P2^0;
sbit sda = P2^1;
unsigned char uc_mod1,uc_10ms,uc_led = 0xff,uc_Y5C = 0x00;
unsigned int ui_tep,ui_v,ui_command = 0;
bit flag_18b20 = 0;
bit flag_L3;
bit flag_firstlock;
void smg_led();
bit lock;
#define DELAY_TIME	5
void UartInit(void)		//9600bps@12.000MHz			波特率发生器
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE6;		//设定定时初值
	TH1 = 0xFF;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	
	ES = 1;
	EA = 1;
}
void Timer0Init(void)		//10毫秒@12.000MHz		计时时钟
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xF0;		//设置定时初值
	TH0 = 0xD8;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	EA = 1;			
	ET0 = 1;
}
void timer0() 	interrupt 1		//计时闪烁
{
	uc_10ms++;
	if(uc_10ms == 10)
	{
		uc_10ms = 0;
		flag_L3 = ~flag_L3;
	}
}
void uart_receive() 	interrupt 4		//串口接收
{
	while(RI == 0);
	ui_command = SBUF;
	RI = 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 PCF8591_adc()		//adc模块,并且对电位器采样
{
	unsigned char uc_v;
	float f_v;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	uc_v = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	f_v = uc_v / 255.0 * 5.0;
	ui_v = f_v * 100;
}
void PCF8591_dac()			//dac模块
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	I2CSendByte(ui_v);		//对采样值进行输出
	I2CWaitAck();
	I2CStop();
}
void Delay30ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 2;
	j = 95;
	k = 43;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay600us()		//@12.000MHz
{
	unsigned char i, j;

	i = 7;
	j = 254;
	do
	{
		while (--j);
	} while (--i);
}
void Delay700ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 32;
	j = 236;
	k = 16;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
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;
}
void ds18b20()			
{
	float f_tep;
	unsigned char low,high;
	smg_led();					//保持亮度
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	smg_led();
	if(flag_18b20 == 0)			//首次进入标志,进行延时,避免默认值的出现
	{
		Delay700ms();
		flag_18b20 = 1;
	}
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low = Read_DS18B20();
	high = Read_DS18B20();
	smg_led();
	ui_tep = (high << 8) | low;
	if(ui_tep < 0xf800)			//正负判断(实际我没有用到负的,也就略过了负数的输出
	{
		f_tep = ui_tep * 0.0625;
		ui_tep = f_tep * 10;
	}
	else
	{
		ui_tep = ~ui_tep;
		ui_tep += 1;
		f_tep = ui_tep * 0.0625;
		ui_tep = f_tep;
	}
}
void HC138_choose(unsigned char k)
{
	switch(k)
	{
		case 0:
		{
			P2 =(P2 & 0x1f) | 0x00;
			break;
		}
		case 4:
		{
			P2 =(P2 & 0x1f) | 0x80;
			break;
		}
		case 5:
		{
			P2 =(P2 & 0x1f) | 0xa0;
			break;
		}
		case 6:
		{
			P2 =(P2 & 0x1f) | 0xc0;
			break;
		}
		case 7:
		{
			P2 =(P2 & 0x1f) | 0xe0;
			break;
		}
	}
}
void smg_show(unsigned char wei,duan)
{
	HC138_choose(6);
	P0 = 0x01 << (wei - 1);
	HC138_choose(7);
	P0 = Seg_Table[duan];
	Delay600us();
	P0 = 0xff;
}
void smg_led()
{
	switch(uc_mod1)		//两种显示模式切换
	{
		case 0:
		{
			smg_show(1,26);
			smg_show(2,1);
			smg_show(6,ui_tep / 100);
			smg_show(7,ui_tep / 10 % 10 +16);
			smg_show(8,ui_tep % 10);
			break;
		}
		case 1:
		{
			smg_show(1,26);
			smg_show(2,2);
			smg_show(6,ui_v / 100 + 16);
			smg_show(7,ui_v / 10 % 10);
			smg_show(8,ui_v % 10);
			break;
		}
	}				
	if(uc_mod1 == 0)			//led模块
	{
		HC138_choose(4);
		P0 = uc_led;
		P00 = 0;
		P01 = 1;
		uc_led = P0;
	}
	else if(uc_mod1 == 1)
	{
		HC138_choose(4);
		P0 = uc_led;
		P00 = 1;
		P01 = 0;
		uc_led = P0;
	}
	if(lock == 1)			
	{
		if(flag_firstlock == 0)		//首次进入进行计时器清零,防止误差
		{
			flag_firstlock = 1;
			uc_10ms = 0;
		}
		HC138_choose(4);
		P0 = uc_led;
		P02 = flag_L3;
		uc_led = P0;
	}
	else
	{
		flag_firstlock = 0;
		HC138_choose(4);
		P0 = uc_led;
		P02 = 1;
		uc_led = P0;
	}
}
void init()
{
	HC138_choose(6);
	P0 = 0x00;
	HC138_choose(7);
	P0 = 0xff;
	HC138_choose(4);
	P0 = 0xff;
	HC138_choose(5);
	P0 = 0x00;
}
void uart_send(unsigned m)				//这段代码与putchar绑定,用来利用printf发送字符串
{
	SBUF = m;
	while(TI == 0);
	TI = 0;
}

char putchar(unsigned char c)			//注意,这次程序用到了uart的发送和接受
{										//发送我采用了stdio.h的头文件中的printf
	uart_send(c);						//如果不需要接收,那这段代码和上面的uart_send都不需要
	return c;							//因为要同时使用接收发送,则必须重新写一下putchar
}


void scan_key()
{
	float f_tep,f_v;
	P44 = 0;
	P32 = 1;
	P33 = 1;
	
	P34 = 1;
	P35 = 1;
	P42 = 1;
	if(lock == 1)
	{
		if(P32 == 0)		//S5
		{
			while(P32 == 0)
			{
				ds18b20();
				smg_led();
			}
			Delay30ms();
			lock = 0;
			ui_command = 0;
		}
	}
	if(P33 == 0)		//S4
	{
		while(P33 == 0)
		{
			ds18b20();
			smg_led();
		}
		Delay30ms();
		lock = 1;
		ES = 0;
	}
	
	P35 = 1;
	P33 = 0;
	
	P30 = 1;
	P31 = 1;
	P32 = 1;
	if(P35 == 0)		//S12
	{
		ES = 0;						//此时发送不能打开中断,因此在发送按钮提前关闭串口中断
		while(P35 == 0)				//我也不太理解为什么中断不能开启,我自认为是发送后TI置1进        
		{							//入中断但实际测试下来,就算串口中断函数不写,程序也会卡死
			ds18b20();				//这里希望懂的大佬可以解释一下
			smg_led();
		}
		if(uc_mod1 == 0)
		{
			f_tep = ui_tep / 10.0;
			printf("TEMP:%.1f℃\r\n",f_tep);	//利用了stdio.h中的printf进行字符串的发送
		}
		else if(uc_mod1 == 1)
		{
			f_v = ui_v / 100.0;
			printf("Voltage:%.2fV\r\n",f_v);
		}
		Delay30ms();
		ES = 1;								//重新开启串口中断
	}
}
void ADC_DAC()				//调用一下dac,adc
{
	PCF8591_adc();
	PCF8591_dac();
}
void command_read()			//接收串口指令判断
{
	if(ui_command == 0x41)
	{
		uc_mod1 = 0;
	}
	else if(ui_command == 0x42)
	{
		uc_mod1 = 1;
	}
}
void buzz_relay()			//蜂鸣器继电器检测
{
	if(ui_tep / 10 >= 28)
	{
		HC138_choose(5);
		P0 = uc_Y5C;
		P04 = 1;
		uc_Y5C = P0;
	}
	else
	{
		HC138_choose(5);
		P0 = uc_Y5C;
		P04 = 0;
		uc_Y5C = P0;
	}
	
	if(ui_v / 10 >= 36 )
	{
		HC138_choose(5);
		P0 = uc_Y5C;
		P06 = 1;
		uc_Y5C = P0;
	}
	else
	{
		HC138_choose(5);
		P0 = uc_Y5C;
		P06 = 0;
		uc_Y5C = P0;
	}
}
void main()
{
	init();
	ds18b20();
	UartInit();
	Timer0Init();
	while(1)
	{
		command_read();
		scan_key();
		ADC_DAC();
		ds18b20();
		smg_led();
		buzz_relay();
	}
}

以上,感谢阅读,如有错误恳请指正,另外串口部分等待大佬的解惑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值