蓝桥杯电子类单片机组模块——led显示(一般作用)

几乎每届蓝桥杯单片机组比赛都会考到led模块;特别是对于近几年的省赛来讲,led模块的使用显得更为灵活;即便led比较之简单,但是编写程序时还是很有可能出现错误。

现在来给大家介绍动态数码管的使用方法

1、对led模块进行操作,无需改变跳帽的位置。

2、led模块相关原理图如下
蓝桥杯单片机led模块

  • 在这里我只展示了led显示模块的主要部分。其他是一些门电路,大家可以参照官方给定的PDF。
  • 注意CT017D开发版上的led模块共Vcc。
  • 打开led有关锁存器的代码位P2=0X80;打开led有关锁存器的代码位P2=0X00;
  • led显示代码的编写同样利用到了状态机的思想,为了防止led模块对应的锁存器频繁开关,我们可以定义一个led_flag标志位对其进行控制。
  • led显示模块的一般操作:一、将操作led点亮的数码管代码送入锁存器。二、打开led有关锁存器。三、关闭led有关锁存器。

Q:为啥led的操作是先送数据再操作锁存器呢?
A:在执行点亮led点亮的代码时,P0口可能会随时发生改变;若此时先打开锁存器再发送数据,那么P0就有可能被多次赋值,从而导致led模块可能出现微亮现象。因此,为了杜绝此类事情发生,我们必须先送数据再操作相应锁存器。

总而言之,在编写代码的时候必须避开这两个坑

  • led模块微亮
  • 循环不间断访问led模块

3、如下,附上led显示代码块。

#include "STC15F2K60S2.h"

#define u8 unsigned char 
#define KEY_STATE0 0
#define KEY_STATE1 1
#define KEY_STATE2 2

#define led_0 0x00
#define led_1 ((0x01)<<(1-1))
#define led_2 ((0x01)<<(2-1))
#define led_3 ((0x01)<<(3-1))
#define led_4 ((0x01)<<(4-1))
#define led_5 ((0x01)<<(5-1))
#define led_6 ((0x01)<<(6-1))
#define led_7 ((0x01)<<(7-1))
#define led_8 ((0x01)<<(8-1))
//上述代码简单粗暴

void Timer0Init(void)		//配置定时器0,1ms中断
{
	AUXR |= 0x80;		
	TMOD &= 0xF0;		
	TL0 = 0xCD;		
	TH0 = 0xD4;		
	TF0 = 0;		
	TR0 = 1;		
	ET0=1;
	EA=1;
}


unsigned char key_scan()
{
		static char KEY_STATE=KEY_STATE0;
		u8 KEY=0;
		u8 key_value=0;
	
		P30=1;P31=1;P32=1;P33=1;
		if(P30==0) KEY=7;
		if(P31==0) KEY=6;
		if(P32==0) KEY=5;
		if(P33==0) KEY=4;
		if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1))  KEY=0;
	 
	  switch(KEY_STATE)
		{
				case KEY_STATE0: 
				if(KEY!=0)
				{
				KEY_STATE=KEY_STATE1;
				}
				break;
				
				case KEY_STATE1:  
				switch(KEY)
				{
				case 4: key_value=4;  break;
				case 5: key_value=5;  break;
				case 6: key_value=6;  break;
				case 7: key_value=7;  break;
				}
				KEY_STATE=KEY_STATE2;

				break;
				case KEY_STATE2: 
				if(KEY==0)
				{
				KEY_STATE=KEY_STATE0;
				}


				break;
		}
		return key_value;
	}

bit key_flag;
u8 key_val;

bit led_flag;
u8 led_COM[10]={led_0,led_1,led_2,led_3,led_4,led_5,led_6,led_7,led_8};//led显示数组

static char led_choose1=0;   //若每次只需要对于一个led进行操作
//static char led_choose2=0;  //每次需要对两个以上的led进行操作,可另外添加led_choosex


void main()
{
	P0=~0X00;P2=0X80;P2=0X00;
	P2=0XA0;P0=0X00;P2=0X00;
	Timer0Init();
			while(1)
			{
				if(led_flag)
				{
					led_flag=0;//状态置0,防止一直进行led模块的操作。
					P0=~(led_COM[led_choose1]/*|led_COM[led_choose2]*/);P2=0X80;P2=0X00;
					//特别注意,若需要操作多个led灯,则每个代码之间需相或。
				}
				
				if(key_flag)
				{
					key_flag=0;
					key_val=key_scan();
					switch(key_val)
					{
				case 4: led_flag=1;led_choose1=1; /*led_choose2=8;*/ break;
				case 5: led_flag=1;led_choose1=2; /*led_choose2=7;*/ break;
				case 6: led_flag=1;led_choose1=3; /*led_choose2=6;*/ break;
				case 7: led_flag=1;led_choose1=4; /*led_choose2=5;*/  break;
				//注意:不管键值如何,只要需对led进行操作,就必须使“led_flag”置1。
					}
				}

			}
}

void Timer0()	interrupt 1	//定时器0中断
{
		static int key_count=0;
		key_count++;
		if(key_count==10)
		{
			key_count=0;
			key_flag=1;
		}
		
}

4、这只是led模块最基本的操作,led流水灯等内容以后会提到。

祝大家在蓝桥杯比赛中获得优异的成绩!
——南昌大学 电子183刘昊

发布了3 篇原创文章 · 获赞 3 · 访问量 82

猜你喜欢

转载自blog.csdn.net/qq_44629819/article/details/104498166