蓝桥杯单片机-国赛7——第十四届主观题代码参考

0.编程心得

本题中,要求测距能达到250cm,因此pca必须配置为0x01,但直接用会死机,因此需要使用CH作为判断量。
【iic的at24c02记录】:

读设备地址:0xA1 写设备地址:0xA0

非应答信号:sda先1,后还是1。本届直接实参传1就是非应答

02表示2k大小

时序操作可完全参考手册
【onewire的ds18b20】:

MSB | LSB 的高5位全0,则读取温度为正数。全1则读取温度为负数 精度为0.0625

时序要自己背:初始化、写入0xcc、写入0x44、延时800ms、初始化、写入0xcc、写入0xbe、读取数据

LSB = Read_DS18B20(); 先读出来的是低八位

MSB = Read_DS18B20();

temperature = MSB;

temperature = ( temperature << 8 ) | LSB;

temperature = (temperature >> 4)*10 + (LSB & 0x0f)*0.625;

刷新时间:2s刷新一次!!!!

数据如果闪烁,就在底层代码的读取函数中,在DQ电平变高后加一个5us
【led的刷新】:

刷新可以和数码管一起,40个50us刷新一次,2ms

涉及锁存器5的所有操作,都不要放while循环里。而且设置形参,直接调用
【iic的pcf8591记录】:

读设备地址:0x91 写设备地址:0x90

控制字:0 D/A-flag x x 0 x A/Dchannal

channal:00 外部模拟信号控制端

01 光敏电阻rd1 0x01

10 差分放大电路信号

11 滑动变阻器rb2 0x03

void dacrunning ( unsigned char value_dac ) //DAC输出,不能设置刷新位,要一直输出

{

I2CStart();

I2CSendByte( 0x90 );

I2CWaitAck();

I2CSendByte( 0x43 );

I2CWaitAck();

I2CSendByte( value_dac );

I2CWaitAck();

I2CStop();

}

输出DAC:0x43

1.比赛真题

2.特殊模块

字节反序程序

超声波程序

双按键程序

双按键下的delay函数要长一些,不然容易误判,因此人不可能做到100%同时按下

3.参考代码

main.c

cpp 复制代码
#include <REGX52.H>
#include <intrins.h>
#include "iic.h"
#include "onewire.h"

sfr AUXR = 0x8e;
sfr P4 = 0xc0;
sfr CCON        =   0xD8;   //00xx,xx00 PCA控制寄存器
sbit CF         =   CCON^7;
sbit CR         =   CCON^6;
sfr CMOD        =   0xD9;   //0xxx,x000 PCA 工作模式寄存器
sfr CL          =   0xE9;   //0000,0000 PCA计数器低字节
sfr CH          =   0xF9;   //0000,0000 PCA计数器高字节

sbit TX = P1^0;
sbit RX = P1^1;

sbit C1 = P4^4;
sbit C2 = P4^2;
sbit R3 = P3^2;
sbit R4 = P3^3;

unsigned char param_mode = 1;
unsigned char SMG_mode = 1;
unsigned char param_distance = 40;
unsigned char param_temperature = 30;
unsigned char param_dac = 10;
unsigned int param_V = 340;
unsigned char save_distance = 0;
unsigned char value_led = 0xff;
float value_sonic = 0.0;
int param_calibration = 0;
bit flag_reset = 0;
bit flag_dac = 0;
bit flag_m_distance = 0;
bit flag_save_distance = 0;
 
unsigned char code duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
                                 0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x8c};
unsigned char code duanma_dot[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

void scan_key ();
void value_work ();

unsigned char reverse_bit ( unsigned char dat )
{
	dat = (dat & 0xF0) >> 4 | (dat & 0x0F) << 4;
    dat = (dat & 0xCC) >> 2 | (dat & 0x33) << 2;
    dat = (dat & 0xAA) >> 1 | (dat & 0x55) << 1;
    return dat;
}

void select_HC573 ( unsigned char channal , unsigned char dat )
{
	P2 = (P2&0x1f)|0x00;
	P0 = dat;
	switch ( channal )
	{
		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;
	}
	P2 = (P2&0x1f)|0x00;
}

void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
	select_HC573 ( 6 , 0x01<<pos_SMG );
	select_HC573 ( 7 , value_SMG );
}

void state_SMG_all ( unsigned char value_SMG )
{
	select_HC573 ( 6 , 0xff );
	select_HC573 ( 7 , value_SMG );
}

void init_pca () 
{
	CMOD = 0x01;
	CCON = 0x00;
}

void Delay13us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 38;
	while (--i);
}


bit flash_sonic = 0;
unsigned int dis_distance = 0;
void send_sonic ()
{
	unsigned char i;
	for ( i=0 ; i<8 ; i++ )
	{
		TX = 1;
		Delay13us();
		TX = 0;
		Delay13us();
	}
}

void recive_sonic ()
{
	if ( flash_sonic == 1 )
	{
		unsigned int tmp = 0;
		CL = CH = CF = 0;
		EA = 0;
		send_sonic ();
		EA = 1;
		CR = 1;
		while ( RX==1 && CH < 0x40 );
		CR = 0;
		
		if ( CH > 0x40 )
		{
			CF = 0;
			tmp = 999;
		}
		else
		{
			tmp = CH;
			tmp = (tmp<<8)|CL;
			tmp = (unsigned int)(tmp*value_sonic+param_calibration);					
		}
			
		dis_distance = tmp;
		flash_sonic = 0;
		
		if ( flag_save_distance == 1 )
			save_distance = tmp;
		
	}
}

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

	_nop_();
	_nop_();
	i = 37;
	j = 123;
	k = 92;
	do
	{
		do
		{
			value_work();
			scan_key ();
			while (--k);
		} while (--j);
	} while (--i);
}

bit flash_ds18b20 = 0;
unsigned int dis_temperature = 0;
void recive_ds18b20 ( )
{
	if ( flash_ds18b20 == 1 )
	{
		unsigned int tmp = 0;
		unsigned char MSB,LSB;
		init_ds18b20();
		Write_DS18B20(0xcc);
		Write_DS18B20(0x44);		
		Delay800ms();
		init_ds18b20();
		Write_DS18B20(0xcc);
		Write_DS18B20(0xbe);
		
		LSB = Read_DS18B20();
		MSB = Read_DS18B20();

		
		tmp = MSB;
		tmp = (tmp<<8)|LSB;
//		tmp = (tmp>>4)*10+(LSB&0x0f)*0.625;
		tmp = (unsigned int)tmp*0.625;
		
		dis_temperature = tmp;
		flash_ds18b20 = 0;
	}
}

unsigned char dac_value = 0;
void dac_work ( unsigned char dac_value )
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	I2CSendByte(dac_value);
	I2CWaitAck();
	I2CStop();
}

unsigned char flash_count = 0;
void flash_SMG ()
{
	state_SMG_all ( 0xff );
	
	if ( SMG_mode == 1 )
	{
		switch ( flash_count )
		{
			case 0:state_SMG ( 0 , duanma[dis_temperature/100] );break;
			case 1:state_SMG ( 1 , duanma_dot[dis_temperature/10%10] );break;
			case 2:state_SMG ( 2 , duanma[dis_temperature%10] );break;
			case 3:state_SMG ( 3 , duanma[16] );break;
			case 4:
				if ( dis_distance > 999 )
					state_SMG ( 4 , duanma[dis_distance/1000] );
				else
					state_SMG ( 4 , 0xff );
				break;
			case 5:
				if ( dis_distance > 99 && flag_m_distance == 0 )
					state_SMG ( 5 , duanma[dis_distance/100%10] );
				else if ( flag_m_distance == 1 )
					state_SMG ( 5 , duanma_dot[dis_distance/100%10] );
				else
					state_SMG ( 5 , 0xff );
				break;
			case 6:
				if ( dis_distance > 9 && flag_m_distance == 0 )
					state_SMG ( 6 , duanma[dis_distance/10%10] );
				else if ( flag_m_distance == 1 )
					state_SMG ( 6 , duanma[dis_distance/10%10] );
				else
					state_SMG ( 6 , 0xff );
				break;
			case 7:state_SMG ( 7 , duanma[dis_distance%10] );break;
		}
	}
	else if ( SMG_mode == 2 )
	{
		switch ( flash_count )
		{
			case 0:state_SMG ( 0 , duanma[17] );break;
			case 1:state_SMG ( 1 , duanma[param_mode] );break;
			case 2:
				if ( param_mode == 1 )
					state_SMG ( 6 , duanma[param_distance/10] );
				else
					state_SMG ( 6 , duanma[param_temperature/10] );
				break;
			case 3:
				if ( param_mode == 1 )
					state_SMG ( 7 , duanma[param_distance%10] );
				else
					state_SMG ( 7 , duanma[param_temperature%10] );
				break;
		}
	}
	else if ( SMG_mode == 3 )
	{
		switch ( flash_count )
		{
			case 0:state_SMG ( 0 , duanma[15] );break;
			case 1:state_SMG ( 1 , duanma[1] );break;
			case 2:
				if ( param_calibration > 99 )
					state_SMG ( 5 , duanma[param_calibration/100] );
				else if ( param_calibration < -9 )
					state_SMG ( 5 , duanma[16] );
				else
					state_SMG ( 5 , 0xff );
				break;		
			case 3:
				if ( param_calibration > 9 )
					state_SMG ( 6 , duanma[param_calibration/10%10] );
				else if ( param_calibration < 0 && param_calibration > -9 )
					state_SMG ( 6 , duanma[16] );
				else if ( param_calibration < 9 && param_calibration != 0 )
					state_SMG ( 6 , duanma[(-1)*param_calibration/10%10] );
				else
					state_SMG ( 6 , 0xff );
				break;	
			case 4:
				if ( param_calibration > 0)
					state_SMG ( 7 , duanma[param_calibration%10] );
				else
					state_SMG ( 7 , duanma[(-1*param_calibration)%10] );
				break;	
		}		
	}	
	else if ( SMG_mode == 4 )
	{
		switch ( flash_count )
		{
			case 0:state_SMG ( 0 , duanma[15] );break;
			case 1:state_SMG ( 1 , duanma[2] );break;
			case 2:
				if ( param_V > 999 )
					state_SMG ( 4 , duanma[param_V/1000] );
				else
					state_SMG ( 4 , 0xff );
				break;
			case 3:
				if ( param_V > 99 )
					state_SMG ( 5 , duanma[param_V/100%10] );
				else
					state_SMG ( 5 , 0xff );
				break;
			case 4:
				if ( param_V > 9 )
					state_SMG ( 6 , duanma[param_V/10%10] );
				else
					state_SMG ( 6 , 0xff );
				break;
			case 5:state_SMG ( 7 , duanma[param_V%10] );break;	
		}
	}	
	else if ( SMG_mode == 5 )
	{
		switch ( flash_count )
		{
			case 0:state_SMG ( 0 , duanma[15] );break;
			case 1:state_SMG ( 1 , duanma[3] );break;
			case 2:state_SMG ( 6 , duanma_dot[param_dac/10] );break;
			case 3:state_SMG ( 7 , duanma[param_dac%10] );break;
		}
	}
}	

void reset_work ()
{
	SMG_mode = 1;
	param_distance = 40;
	param_temperature = 30;
	param_calibration = 0;
	param_V = 340;
	param_dac = 10;		
}

void init_timer0(void)		//50微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x02;		//设置定时器模式
	TL0 = 0xCE;		//设置定时初始值
	TH0 = 0xCE;		//设置定时重载值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时

	ET0 = 1;
	EA = 1;
}

unsigned char count_50us = 0;
unsigned char count_10ms = 0;
bit flag_100ms = 0;
unsigned char count_save_10ms = 0;
unsigned char count_save_1s = 0;
unsigned char count_reset = 0;
void timer0_service () interrupt 1
{
	if ( ++count_50us == 200 )
	{
		count_50us = 0;	
		if ( ++count_10ms == 200 )
			count_10ms = 0;		
		
		if ( flag_save_distance == 1 )
		{
			if ( ++count_save_10ms == 100 )
			{
				count_save_10ms = 0;
				if ( ++count_save_1s == 6 )
					flag_save_distance = 0;
			}
		}
		else
		{
			count_save_10ms = 0;
			count_save_1s = 0;
		}
		
		if ( flag_reset == 1 )
		{
			if ( ++count_reset == 200 )
				reset_work();
		}
		else
			count_reset = 0;
			
				
	}
	
	if ( count_50us % 40 == 0 ) //刷新数码管和led
	{
		if ( SMG_mode == 1 )
		{
			if ( ++flash_count == 8 )
				flash_count= 0;
		}
		else if ( SMG_mode == 4 )
		{
			if ( ++flash_count > 5 )
				flash_count= 0;
		}
		else if ( SMG_mode == 2 || SMG_mode == 5 )
		{
			if ( ++flash_count > 3 )
				flash_count= 0;
		}
		else if ( SMG_mode == 3 )
		{
			if ( ++flash_count > 4 )
				flash_count= 0;
		}
		
		flash_SMG ();
		select_HC573 ( 4 , value_led );
	}
	
	if ( count_10ms % 50 == 0 )
	{
		flash_sonic = 1;
	}
	
	if ( count_10ms % 100 == 0 )//让温度和超声波不同时刷新,避免数据问题
	{
		flash_ds18b20 = 1;	
	}	
	
	
	if ( SMG_mode == 1 )
	{
		if ( dis_distance > 255 )
			value_led = 0x00;
		else
			value_led = reverse_bit( ~(dis_distance/8) );
	}
	else if ( SMG_mode == 2 )
		value_led = 0x7f;
	else if ( SMG_mode > 2 )
	{
		if ( count_10ms % 10 == 0 )
			value_led = 0xfe;
		else 
			value_led = 0xff;
	}
	
	
}

void value_work ()
{
	
	if ( flag_dac == 1 && save_distance != 0 )
	{	
		if ( save_distance > 90 )
			dac_value = 255;
		else if ( save_distance > 10 )
			dac_value = (3.2-0.05*param_dac)*save_distance;
		else
			dac_value = param_dac*5.1;
		
		flag_dac = 0;
	}
	

	if ( dis_distance <= param_distance+5 && dis_distance >= param_distance-5 && dis_temperature <= param_temperature*10 )
			select_HC573 ( 5 , 0x10 );
	else 
		select_HC573 ( 5 , 0x00 );	

	
}

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

	i = 24;
	j = 85;
	do
	{
		while (--j);
	} while (--i);
}

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 scan_key ()
{
	if ( flag_save_distance == 1 )
		return;
	
	C1 = 0;
	C2 = R3 = R4 = 1;
	if ( R3 == 0 )
	{
		Delay2ms();
		if ( R3 == 0 )	//5
		{
			
			//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
			if ( SMG_mode == 1 )
			{
				if ( flag_m_distance == 0 )
					flag_m_distance = 1;
				else if ( flag_m_distance == 1 )
					flag_m_distance = 0;
			}
			else if ( SMG_mode == 2 )
			{				
				if ( param_mode == 1 )
					param_mode = 2;
				else if ( param_mode == 2 )
					param_mode = 1;				
			}
			else 
			{
				switch ( SMG_mode )
				{
					case 3:SMG_mode = 4;break;
					case 4:SMG_mode = 5;break;
					case 5:SMG_mode = 3;break;
				}
			}			
			
			while ( R3 == 0 );
		}
	}
	else if ( R4 == 0 )
	{
		Delay2ms();
		if ( R4 == 0 )	//4
		{	
			switch ( SMG_mode )
			{
				//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
				case 1:SMG_mode = 2;param_mode = 1;break;
				case 2:SMG_mode = 3;break;
				case 3:case 4:case 5:SMG_mode = 1;break;
			}				
			while ( R4 == 0 );
		}
	}
	
	C2 = 0;
	C1 = R3 = R4 = 1;
	if ( R3 == 0 || R4 == 0 )
	{
		Delay30ms();
		if ( R3 == 0 && R4 == 0 )
		{
			flag_reset = 1;	
			while ( R3 == 0 && R4 == 0 )
			{
				flag_reset = 1;	
			}
			flag_reset = 0;	
		}
		else if ( R3 == 0 )	//9
		{
			//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
			if ( SMG_mode == 2 && param_mode == 1 )
				param_distance -= 10;
			else if ( SMG_mode == 2 && param_mode == 2 )
				param_temperature -= 10;
			else if ( SMG_mode == 3 )
				param_calibration -= 5;
			else if ( SMG_mode == 4 ){
				param_V -= 10;value_sonic = (float)param_V/2/100;}
			else if ( SMG_mode == 5 )
				param_dac -=1;
			else if ( SMG_mode == 1 )
				flag_dac = 1;			
					
			if ( param_distance < 10 )
				param_distance = 10;
			else if ( param_temperature > 100 ) //越位了会变成255
				param_temperature = 0;
			else if ( param_calibration < -90 )
				param_calibration = -90;
			else if ( param_V < 10 )
				param_V = 10;
			else if ( param_dac < 1 )
				param_dac = 1;
				
			value_sonic = (float)(param_V)*0.00005;
			
			while ( R3 == 0 );
		}
		else if ( R4 == 0 )	//8
		{
			
			//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
			if ( SMG_mode == 2 && param_mode == 1 )
				param_distance += 10;
			else if ( SMG_mode == 2 && param_mode == 2 )
				param_temperature += 10;
			else if ( SMG_mode == 3 )
				param_calibration += 5;
			else if ( SMG_mode == 4 ){
				param_V += 10;value_sonic = (float)param_V*0.00005;}
			else if ( SMG_mode == 5 )
				param_dac +=1;
			else if ( SMG_mode == 1 )
				flag_save_distance = 1;		


			if ( param_distance > 90 )
				param_distance = 90;
			else if ( param_temperature > 80 ) //越位了会变成255
				param_temperature = 80;
			else if ( param_calibration > 90 )
				param_calibration = 90;
			else if ( param_V > 9990 )
				param_V = 9990;
			else if ( param_dac > 20 )
				param_dac = 20;			
			
			value_sonic = (float)(param_V)*0.00005;
			while ( R4 == 0 );
		}
	}
}
	
void init_sys ()
{
	select_HC573 ( 4 , 0xff );
	select_HC573 ( 5 , 0x00 );
	value_sonic = (float)(param_V)*0.00005;
}

void main ()
{
	init_sys ();
	init_timer0 ();
	init_pca ();
	while ( 1 )
	{
		scan_key ();
		value_work();
		recive_sonic ();
		recive_ds18b20 ();
		dac_work ( dac_value );	
	}
}
相关推荐
stm 学习ing24 分钟前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
wenchm4 小时前
细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
stm32·单片机·嵌入式硬件
茶猫_5 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
编码追梦人5 小时前
如何实现单片机的安全启动和安全固件更新
单片机
电子工程师UP学堂5 小时前
电子应用设计方案-16:智能闹钟系统方案设计
单片机·嵌入式硬件
ö Constancy6 小时前
Linux 使用gdb调试core文件
linux·c语言·vim
lb36363636366 小时前
介绍一下strncmp(c基础)
c语言·知识点
wellnw6 小时前
[linux] linux c实现共享内存读写操作
linux·c语言
飞凌嵌入式6 小时前
飞凌嵌入式T113-i开发板RISC-V核的实时应用方案
人工智能·嵌入式硬件·嵌入式·risc-v·飞凌嵌入式
blessing。。7 小时前
I2C学习
linux·单片机·嵌入式硬件·嵌入式