蓝桥杯单片机组——国赛1 各模块的基础模板

本文为续写个人专栏:蓝桥杯单片机组基础专栏

由于国赛代码体量较为庞大,各个模块涉及时序、消影、去鬼影、消冲突等操作

因此本文基于小蜜蜂老师代码风格编写,并根据实际有改动

本文用于汇总基础的模块程序,更进阶的操作请查看本专栏下其他文章


0.编程风格

        变量命令规则用“类型_流动方向”组合:value_led 表示这是一个变量的值,要传入led函数;key_value表示这是一个变量,从key函数中获取出来;flash_SMG表示这是一个刷新标志位,为1时刷新数码管;time5s_flag表示这是一个指示标志位,指示达到5s的时间间隔。

        函数命令规则主要分为两类。一类是,实时的运行函数,如value_running(),ds18b20_running()等,直接放入主函数的死循环中运行。另一类是功能性函数,如,flash_SMG()是不放入主函数,而是在其他函数中用于直接调用的。

        定时器0用于产生50us的中断,定时器1用于产生5ms的中断。对于标志位,直接在中断里改变其值,对于数据计算部分单独建立一个value_running()函数用于处理。

        51单片机处理负数可以定义“int”类型,普通变量定义“unsigned char”类型,标志变量定义“bit”类型。除了555定时计数器,其他所有的外设都要设置刷新的标志位,可以提升系统运行效率,以一定的时间间隔刷新,555定时器,除了要短接引脚,还要用RB3调节频率的数值。

        光敏电阻数字跳动太大:加1ms延时,加中断标志间隔时间后刷新,加最后一步等待应答,加临时变量判断数据正确再写入。
        ds1302,最好用中断,每隔1s提取一遍时间到变量中,再用数码管显示,减少资源占用。对于刷新频率为1s为单位的变量,可以直接读取ds1302的秒位,判断是否达到1s的整数倍
        对于led的操作。当led的变化有规律时——建立数组存放led的状态。当led没有规律时——一定要学会位运算,直接对变量value_led进行位操作,然后利用中断传入led处理函数。对于继电器的操作,也不要定义继电器的一个引脚,直接对P0口进行操作。对于io编程模式,要注意对锁存器常关闭。同时采用先赋值P0端口,再打开锁存器方式,这样有效防止数据冲突。
        定时计数器,选择12T模式!!!

编程流程:

  1. 搭建底层文件:把题目的外设添加好,数码管窗口切换做好
  2. 直接给SMG_flag变量赋值,逐个测试数码管各个窗口是否正常
  3. 开始运行各个外设,并挨个验证查看数值是够正确
  4. 逐个编写按键逻辑,并挨个检查界面变化、数值显示是否正常
  5. 测试按键逻辑是否正常,有没有影响其他部分
  6. 添加led,继电器等次要外设部分内容

1.基础代码

//锁存器通道选择函数
void select_HC573 ( unsigned char channal )
{
	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;
		case 0:
			P2 = ( P2 & 0x1f ) | 0x00;
		break;
	}
}
//初始化系统,关闭继电器和蜂鸣器
void init_sys ()
{
	select_HC573 ( 0 );
	P0 = 0xff;	
	select_HC573 ( 4 );
	select_HC573 ( 0 );
	P0 = 0x00;
	select_HC573 ( 5 );
	select_HC573 ( 0 );
}

2.led操作代码

//led灯光控制函数
void state_led ( unsigned char value_led )
{
	select_HC573 ( 0 );
	P0 = 0xff;
	select_HC573 ( 4 );
	P0 = value_led;
	select_HC573 ( 4 );	
	select_HC573 ( 0 );
}

3.数码管操作代码

SMG_flag为使用定时计数器设置的数码管刷新时间间隔

//单位数码管显示函数
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
	select_HC573 ( 0 );
	P0 = 0x01 << pos_SMG;	
	select_HC573( 6 );
	select_HC573 ( 0 );
	P0 = value_SMG;
	select_HC573( 7 );
	select_HC573 ( 0 );
}

//全位数码管静态显示
void state_SMG_all ( unsigned char value_SMG_all )
{
	select_HC573 ( 0 );
	P0 = 0xff;	
	select_HC573( 6 );
	select_HC573 ( 0 );
	P0 = value_SMG_all;
	select_HC573( 7 );
	select_HC573 ( 0 );
}

void SMG_flash ()
{
	state_SMG_all ( 0xff );
	
	if ( SMG_flag == 0 )
	{
		switch ( flash_count )
		{
			case 0:				
				state_SMG ( 0 , duanma[1] );
			break;
			case 1:				
				state_SMG ( 1 , duanma[1] );
			break;
			case 2:				
				state_SMG ( 2 , duanma[1] );
			break;
			case 3:				
				state_SMG ( 3 , duanma[1] );
			break;
			case 4:				
				state_SMG ( 4 , duanma[1] );
			break;
			case 5:				
				state_SMG ( 5 , duanma[1] );
			break;
			case 6:				
				state_SMG ( 6 , duanma[1] );
			break;
			case 7:	
				state_SMG ( 7 , duanma[1] );
			break;
 
		}
	}
	else if ( SMG_flag == 1 )
	{
		switch ( flash_count )
		{
			case 0:				
				state_SMG ( 6 , duanma[2] );
			break;
			case 1:				
				state_SMG ( 7 , duanma[2] );
			break;
		}
	}	
}

4.按键操作代码

void keyrunning ()
{
	C1 = 0;
	C2 = H1 = H2 = 1;
	if ( H1 == 0 )
	{
		Delay4ms();
		if ( H1 == 0 )//S4
		{
			while ( H1 == 0 );
		}
	}
	else if ( H2 == 0 )
	{
		Delay4ms();
		if ( H2 == 0 )//S5
		{
			if ( SMG_flag != 1 )
			{

			}
			while ( H2 == 0 );	
		}
	}

	C2 = 0;
	C1 = H1 = H2 = 1;
	if ( H1 == 0 )
	{
		Delay4ms();
		if ( H1 == 0 )//S8
		{

			while ( H1 == 0 );
		}
	}
	else if ( H2 == 0 )
	{
		Delay4ms();
		if ( H2 == 0 )//S9
		{
			while ( H2 == 0 );

		}
	}
}

5.ds18b20代码

bit flash_ds18b20 = 0;
unsigned char pld_temperature = 0;
unsigned int temperature = 0;
unsigned int set_temperature =  300;
void flash_temperature ()
{
	if ( flash_ds18b20 == 1 )
	{
		unsigned char LSB,MSB;
		old_temperature = temperature;
		
		init_ds18b20();
		Write_DS18B20(0xcc);	
		Write_DS18B20(0x44);
		Delay700ms();
		init_ds18b20();
		Write_DS18B20(0xcc);	
		Write_DS18B20(0xbe);
		
		LSB = Read_DS18B20();
		MSB = Read_DS18B20();
		
	 
		temperature = MSB;
		temperature = ( temperature << 8 ) | LSB;
		temperature = (temperature >> 4)*10 + (LSB & 0x0f)*0.625;
		
		flash_ds18b20 = 0;
	}
 
}

6.ds1302代码

void init_ds1302 ()
{
	unsigned char i;
	Write_Ds1302_Byte ( 0x8e , 0x00 );
	for ( i=0 ; i<7 ; i++ )
	{
		Write_Ds1302_Byte ( Write_address[i] , date_ds1302[i] );
	}
	Write_Ds1302_Byte ( 0x8e , 0x80 );

}

bit flash_ds1302 = 0;
void flash_date()
{
	if ( flash_ds1302 == 1 )
	{
		unsigned char i;
		for ( i=0 ; i<7 ; i++ )
		{
			date_ds1302[i] = Read_Ds1302_Byte ( Read_address[i] );
		}
		
		flash_ds1302 = 0;
	}
}

7.pcf5951操作

bit flash_rd1 = 0;
unsigned char rd1_value = 0;
void rd1running()
{
	unsigned char tmp = 0;
	if ( flash_rd1 == 1 )
	{
		I2CStart();
		I2CSendByte(0x90);
		I2CWaitAck();
		I2CSendByte(0x01);
		I2CWaitAck();
		I2CStop();
		Delay1ms();
		I2CStart();
		I2CSendByte(0x91);
		I2CWaitAck();
		tmp = I2CReceiveByte();
		I2CWaitAck();
		I2CSendAck(1);
		I2CStop();
		
		flash_rd1 = 0;
	}
	
	if ( tmp<220 && tmp>0 )
	{
		rd1_value = tmp;
	}
}

unsigned char rb2_value = 0;
void rb2running()
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x03);
	I2CWaitAck();
	I2CStop();
	
	Delay2ms();
		
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	rb2_value = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	
}

void dacrunning ( unsigned char value_dac )
{
	if ( flash_dac == 1 )
	{
		I2CStart();
		I2CSendByte( 0x90 );
		I2CWaitAck();
		I2CSendByte( 0x43 );
		I2CWaitAck();
		I2CSendByte( value_dac );
		I2CWaitAck();
		I2CStop();
	}
}

8.at24c02

void write_at24c02 ( unsigned char addr_write , unsigned char value_write )
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr_write);
	I2CWaitAck();
	
	I2CSendByte(value_write);
	I2CWaitAck();
	I2CStop();
}
 
unsigned char read_at24c02 ( unsigned char addr_read )
{
	unsigned char power_count_temp;
	
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr_read);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	power_count_temp = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	
	return power_count_temp;
}

9.555定时计数器

void init_timer(void)		//50毫秒@11.0592MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x00;		//设置定时器模式
	TMOD |= 0x16;		//设置定时器模式
	TL1 = 0x00;		//设置定时初始值
	TH1 = 0x4C;		//设置定时初始值
	TH0 = 0xff;
	TL0 = 0xff;
	TF1 = 0;		//清除TF1标志
	TF0 = 0;
 
	TR1 = 1;		//定时器1开始计时
	TR0 = 1;
	EA = 1;
	ET1 = 1;
	ET0 = 1;
}
 
unsigned int count_timer0 = 0;
void timer0_service () interrupt 1
{
	count_timer0++;
}
 
unsigned int count_fre = 0;
unsigned char count_50ms = 0;
void timer1_service () interrupt 3
{
	count_50ms++;
	TL1 = 0x00;		//设置定时初始值
	TH1 = 0x4C;		//设置定时初始值
	
	if ( count_50ms == 20 )
	{
		count_50ms = 0;
		count_fre = count_timer0;
		count_timer0 = 0;
	}
}

10.超声波传感器

void send_sonic ()
{
	unsigned char i;
	for ( i=0 ; i<8 ; i++ )
	{
		TX = 1;
		Delay14us();
		TX = 0;
		Delay14us();
	}
}
 
unsigned int value_distance = 0;
void read_sonicrunning ()
{
	TL0 = 0x00;
	TH0 = 0x00;
 
	send_sonic ();
	TR0 = 1;
	
	//当超声波未接受到返回信号,且计时器没有溢出
	while ( (RX ==1) && (TF0 == 0) );
	TR0 = 0;
	
	if ( TF0 == 0 )    //如果接收到了返回信号,且定时器未溢出
	{
		value_distance = TH0;
		value_distance = (value_distance<<8) | TL0;
		value_distance = value_distance * 0.0184;
		
	}
	else    //如果定时器溢出,却还没返回信号
	{
		TF0 = 0;
		value_distance = 999;
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值