蓝桥杯之单片机设计与开发(5)——数码管动态显示/独立按键和流水灯

解决的编译错误

昨天学会使用EXTERN在子函数中声明主函数定义的变量。今天在用位变量的时候,报错说我未定义此变量。

  • 原因:sbit映射到IO口(P1^1这种IO口的“位”) bit在RAM中的可位寻址空间中,一般用作程序判断的标志位。 可以认为它们一个对外(sbit),一个对内(bit)。
  • 解决方法:直接在子函数中重新定义一遍即可,不会存在定义重复。

接着昨天的所学,今天完成了如标题所示的学习任务。

数码管动态显示

/****************************************************************
@功能模块:主函数
@作    者:朱明
@时    间:202024****************************************************************/
#include <reg52.h>
#include "mode.h"
#include "delay.h"
#include "delaya.h"
#include "test.h"
#include "testa.h"

unsigned char yue = 1 ;         //被除以后取整和取余分别对应月和日 
unsigned char code SMG_duanma[18]=
		{	/*0*/ 0xc0 ,/*1*/ 0xf9 ,/*2*/ 0xa4 ,
			/*3*/ 0xb0 ,/*4*/ 0x99 ,/*5*/ 0x92 ,
			/*6*/ 0x82 ,/*7*/ 0xf8 ,/*8*/ 0x80 ,
			/*9*/ 0x90 ,/*a*/ 0x88 ,/*b*/ 0x80 ,
			/*c*/ 0xc6 ,/*d*/ 0xc0 ,/*e*/ 0x86 ,
			/*f*/ 0x8e ,/*g*/ 0xbf ,/*h*/ 0x7f };

void main()
{	
	while(1)
		{
			testa();
			yue++;
			if(yue > 12)
			{
				yue = 1;
			}
			delaya(200);
			
	}
}
						
/*************************************************************
@功能模块:工程函数
@作    者:朱明
@时    间:202024**************************************************************/

#include "test.h"
#include "mode.h"              //今天学会如何在子函数中调用子函数


void test(unsigned char dat, unsigned pos)  //单片机使用核心工程文件
{
	 
	mode(6);			//数码管的位置
	P0 = 0x01 << pos;
	mode(7);			//数码管的内容
	P0 = dat;
//在的函数原型中,调用这个函数时有两个参数dat,pos
//可是在你在写函数体和实际调用时,啥参数都没给,所以编译器傻眼了. 
}

/**********************************************************
@功能模块:模式函数
@作    者:朱明
@时    间:202024***********************************************************/
#include "mode.h"

void mode(unsigned char n)  //单片机使用前清零以及模式选择
{
 
	switch(n)                 //选择所需的工程
	{
		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;
	}
}
/**********************************************************
@功能模块:工程函数
@作    者:朱明
@时    间:2020129************************************************************/

#include "testa.h"
#include "test.h"
#include "delay.h"

extern unsigned char yue  ;           //被除以后取整和取余分别对应月和日 
extern unsigned char code SMG_duanma[];       //extern声明变量不能赋值
			
void testa(void)  //单片机使用核心工程文件
{	
	test(SMG_duanma[2],0);
	delay(500);
	test(SMG_duanma[0],1);
	delay(500);
	test(SMG_duanma[1],2);
	delay(500);
	test(SMG_duanma[8],3);
	delay(500);
	
	test(SMG_duanma[16],4);
	delay(500);
	test(SMG_duanma[16],5);
	delay(500);
	
	test(SMG_duanma[yue/10],6);
	delay(500);
	test(SMG_duanma[yue%10],7);
	delay(500);
	
}

程文件延时函数定义两个不同一个整型变量一个字符型变量,用于产生余晖效应(短时间)另外一个较长时间的延时。

按键

按键是我今天重点学习的部分。
在之前老师的视频中,他讲解的很详细。
我将所阐述的内容在代码块中讲解。

/*********************************************************
@功能模块:主函数
@作    者:朱明
@时    间:202024**********************************************************/
#include <reg52.h>
#include "mode.h"
#include "delay.h"
#include "test.h"
#include "key.h"

//记住sbit与bit完全不同,它不是传统c语言的声明变量的关键词,
//你可以简单地把sbit ,sfr语句理解为宏定义。而宏定义是可以重复声明的。

sbit S7 = P3^0;//声明按键的操作位
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

sbit L1 = P0^0;//声明LED灯操作位
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;

void main()
	{
	mode(4);
	while(1)
	{
		test();
	}
}

/***********************************************************
@功能模块:模式函数
@作    者:朱明
@时    间:2020128***********************************************************/

#include "mode.h"

void mode(unsigned char channel)  //单片机使用前清零以及模式选择
{
	switch(channel)               //通道选择
	{
		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;
	}
}

/*************************************************************
@功能模块:工程函数1
@作    者:朱明
@时    间:202024**************************************************************/

#include "test.h"//可重复声明,此代码中主函数声明部分可以删掉
#include "delay.h"

sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;

void test()  //单片机使用核心工程文件
{
	if(S7 == 0)//按下按键S7
	{
		delay(100);//消抖
		if(S7 == 0)//确认S7依然按下
		{
			L1 = 0;//灯亮
			while(S7 == 0);//按住保持的状态
			L1 = 1;//灯灭
		}
	}
	if(S6 == 0)
	{
		delay(100);
		if(S6 == 0)
		{
			L2 = 0;
			while(S6 == 0);
			L2 = 1;
		}
	}
	if(S5 == 0)
	{
		delay(100);
		if(S5 == 0)
		{
			L3 = 0;
			while(S5 == 0);
			L3 = 1;
		}
	}
	if(S4 == 0)
	{
		delay(100);
		if(S4 == 0)
		{
			L4 = 0;
			while(S4 == 0);
			L4 = 1;
		}
	}
}

另外一种形式–工程函数1/2选择一种即可

/*********************************************************
@功能模块:工程函数2
@作    者:朱明
@时    间:202024**********************************************************/

#include "test.h"
#include "delay.h"

sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;

unsigned char stat_k = 0;     //定义的变量,使得按键互相有影响

void test()  //单片机使用核心工程文件

/***********************************************************
//按键S7和S6为选择键,确定控制键控制那组LED指示灯。
//简单来说就是S7按下后,S6/S5/S4无效,再按下S7后按键S6方才有效。
//只有当S6按键有效的时候(S7无效)S5/S4按键的控制才有效
************************************************************/

{
	if(S7 == 0)
	{
		delay(100);            //消抖
		if(S7 == 0)
		{
			if(stat_k == 0)
			{
				L1 = 0;
				stat_k = 1;         //当第二次按下的时候可熄灭
			}
			else if(stat_k == 1)
			{
				L1 = 1;
				stat_k = 0;
			}
			while(S7 == 0);        //保持在这条语句
		}
	}
	if(S6 == 0)
	{
		delay(100);
		if(S6 == 0)
		{
			if(stat_k == 0)
			{
				L2 = 0;
				stat_k = 2;
			}
			else if(stat_k == 2)
			{
				L2 = 1;
				stat_k = 0;
			}
			while(S6 == 0);
		}
	}
	if(S5 == 0)
	{
		delay(100);
		if(S5 == 0)
		{
			if(stat_k == 1)
			{
				L3 = 0;
				while(S5 == 0);
				L3 = 1;
			}
			else if(stat_k == 2)
			{
				L5 = 0;
				while(S5 == 0);
				L5 = 1;
			}
		}
	}
	if(S4 == 0)
	{
		delay(100);
		if(S4 == 0)
		{
			if(stat_k == 1)
			{
				L4 = 0;
				while(S4 == 0);
				L4 = 1;
			}
			else if(stat_k == 2)
			{
				L6 = 0;
				while(S4 == 0);
				L6 = 1;
			}
		}
	}
}

你可能感兴趣的:(蓝桥杯)