蓝桥杯比赛单片机设计与开发(2) 数码管的显示与闪烁

蓝桥杯单片机设计与开发(2) 数码管的显示与闪烁

今天我们介绍一下蓝桥杯开发板数码管模块的操作。
我们先来介绍一下数码管的动态扫秒原理:
数码管分为有两种,共阳数码管和共阴数码管。一个数码管上有段选和位选,位选是送入高低电平使得数码管显示,段选送入需要显示的数据。蓝桥杯比赛采用的是共阳数码管。

在这里插入图片描述
这是开发板的数码管原理图。Y7C控制数码管的段选,Y6C控制数码管的位选,有74HC138控制,当Y7C为高电平时可以送入数据,为低电平时处于索存状态。

void enable138(uchar x)
{
	P2&=0X1f;    //先将138 A B C 置位0 0 0输出Y0为低,其他为高
	P2|=(x<<5); //X左移5位后通过或非门对对应的74HC573送入数据
	
	_nop_();
	_nop_();
	P2&=0X1f;//在此将P2置位
}

这是上文中的HC138代码。
在这里插入图片描述
我们先建立好工程。
上代码了:
smg.c

# include "smg.h"
uchar code smgDU[34]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,//0 ~F 
					0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0E,//0.~F.
					0xff,0xbf}; 		//灭 -
uchar smgWE[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar displaydat[8]={1,2,3,4,5,6,7,8};//数码管一定会立刻显示的内容
uchar flashset=0x00;
uint flashT=400;//数码管闪烁周期为400ms,1ms进入一次定时器0中断


void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	EA=1;//开启总中断
	ET0=1;//开启定时器0中断	
}


void smgdisplay()//数码管子扫描函数,放入中断
{
	static uchar WhichWE=0;
	
	P0=0XFF;
	enable138(DU);
	
	P0=smgWE[WhichWE];
	enable138(WE);
	
	P0=smgDU[displaydat[WhichWE]];
	enable138(DU);
	
	WhichWE++;
	if(WhichWE==8)
	{
		WhichWE=0;
	}
}

void smg_set(uchar dat1,uchar dat2,uchar dat3,uchar dat4,uchar dat5,uchar dat6,uchar dat7,uchar dat8)//数据传送函数,放入main函数
{
	displaydat[0]=dat1;
	displaydat[1]=dat2;
	displaydat[2]=dat3;
	displaydat[3]=dat4;
	displaydat[4]=dat5;
	displaydat[5]=dat6;
	displaydat[6]=dat7;
	displaydat[7]=dat8;

}
void flash_service()
{
	uchar i;
	static uint flashcount=0;
	flashcount++;
	if(flashcount<flashT/2)//前半个周期给需要闪烁的无效位选
	{
		for(i=0;i<8;i++)
		{
			if(flashset&(0x80>>i))//如果是需要闪烁的给无效位选,
			{
				smgWE[i]=0x00;
			}
			else //如果不是需要闪烁的给有效位选
			{
				smgWE[i]=0x01<<i;
			}
		}
		
	}
	else if(flashcount<flashT)//后半个周期给有效位选
	{
		for(i=0;i<8;i++)
		{
			
				smgWE[i]=0x01<<i;
			
		}
	}
	else
	{
		flashcount=0;
	}
	
}

void Timer0() interrupt 1
{
	smgdisplay();
	flash_service();
}



smg.h

#ifndef _SMG_H_
#define _SMG_H_

# include "include.h"


extern uchar flashset;

void Timer0Init(void);
void flash_service();
void smgdisplay();
void smg_set(uchar dat1,uchar dat2,uchar dat3,uchar dat4,uchar dat5,uchar dat6,uchar dat7,uchar dat8);



#endif 

main函数

# include"include.h"

void suoyouwaishe_Init()
{

	P0=0xff;
	enable138(LED);
	P0=0x00;
	enable138(ULN2003);
	P0=0x00;
	enable138(WE);
	P0=0xff;
	enable138(DU);

}

void main()
{
	suoyouwaishe_Init();
	Timer0Init();
	flashset=0xc0;
	while(1)
	{
		smg_set(15,14,13,12,11,10,9,8);

	}
	
}






include.h

#ifndef _INCLUDE_H_
#define _INCLUDE_H_

#define uchar unsigned char 
#define uint unsigned int

#include "STC15F2K60S2.h"
#include "intrins.h"
# include "enable138.h"
# include "smg.h"





#endif 

如果想实现闪烁位置的改变,只需要修改flashset的值就可以。
拓展:
关于传参函数,还有一种通过指针的方式进行传递:

void smg_set(uchar *smgdatastore)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		displaydat[i]=*(smgdatastore+i);
	}
}

main函数

# include"include.h"
uchar smgdatastore[8]={1,2,3,4,5,6,7,8};

void suoyouwaishe_Init()
{

	P0=0xff;
	enable138(LED);
	P0=0x00;
	enable138(ULN2003);
	P0=0x00;
	enable138(WE);
	P0=0xff;
	enable138(DU);

}

void main()
{
	suoyouwaishe_Init();
	Timer0Init();
	flashset=0xc0;
	while(1)
	{
		smg_set(smgdatastore);

	}
	
}






若果是不需要计算的情况下可以这样写,其他的情况下可以修改为(例如):

void main()
{  
	uchar smgdatastore[8]={0};
	uchar keyvalue=244;
	suoyouwaishe_Init();
	Timer0Init();
	flashset=0xc0;
		while(1)
	{
		smgdatastore[5]=keyvalue/100%10;
		smgdatastore[6]=keyvalue/10%10;
		smgdatastore[7]=keyvalue%10;
		smg_set(smgdatastore);

	}
	
}
发布了2 篇原创文章 · 获赞 2 · 访问量 92

猜你喜欢

转载自blog.csdn.net/weixin_44874337/article/details/104313476