藍橋杯(單片機組)學習筆記(三)--------LED/按鍵/數碼管/蜂鳴器/繼電器

基礎不是很好,所以程序思路只能說夠用就行,之後我會慢慢修改回來完善。
今晚跟人吵架了很難受QWQ
1.LED
在這裏插入圖片描述
在這裏插入圖片描述
上一節已經分析過,先操作鎖存器P2口,再操作P0口。不過這塊板子有些缺陷,要初始化把繼電器關了,再把LED關了。偷懶的話把LED初始化放在後面,這樣鎖存器依然是選中LED的,就可以直接進行LED的操作。(12MHZ)

#include <STC15F2K60S2.H>//流水燈程序
typedef unsigned long u32;
typedef unsigned int uint;	  //對數據類型進行聲明定義
typedef unsigned char uchar;

//N ms延時 
void delay_ms(uint n)
{
	uint i,j;
	for (i = n; i>0;i--)
	for (j = 114;j>0;j--);
}

void main(void)
{
	uchar i = 0;
	P2 = 0XA0,P0 = 0X00;//關閉繼電器
	P2 = 0X80;P0 = 0XFF;//關LED
	
	while(1)
	{
		for( i = 0;i <8;i++)
		{
			P0 = ~(1<<i);
			delay_ms(1000);
		}
	}
}

2.獨立按鍵
按鍵之前我研究了很多種辦法,比如什麼狀態標誌位判斷或者說是三行代碼得到TRG。然後經過這麼久的洗刷還是覺得比賽就用最簡單的消抖按鍵就行了(畢竟按鍵也不多,複製粘貼也比較輕鬆)這個唯一的毛病就是需要佔用定時器0(專門拿一個定時器來給按鍵)。後期如果遇到簡單好使的方就補充。(長短按鍵,如果是一般的,用swich也可以做)

/*長按一個燈亮,短按另一個燈亮*/
#include <STC15F2K60S2.H>
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long uint32;
sbit key1 = P3^0;
uint key_count;
uchar key_state;
uchar flag_key =0;

void Timer0Init(void);
void delay_ms(uint n)
{
	uint i,j;
	for (i = n; i>0;i--)
	for (j = 114;j>0;j--);
}

void  Key1_scan(void)
{
	if (!key1)
	{
		delay_ms(10);
		if (!key1)
		{
			TR0 = 1;
			while(!key1);
			if (flag_key)
			{
				key_state = 1;
				flag_key = 0;
			}
			else
			{
				key_state = 2;
			}
			
		}
	}
}


void main(void)
{
	uchar i = 0;
	P2 = 0XA0,P0 = 0X00;//關閉繼電器
	P2 = 0X80;P0 = 0XFF;//關LED
	Timer0Init();
	while(1)
	{
		 Key1_scan();
		 
		 switch(key_state)
		 {
			
			case 1:P0 = 0xFe;break;
			case 2:P0 = 0Xf7;break;
		 }
	}
	
	
	
}

void Timer0Init(void)		//5毫秒@11.0592MHz
{
	EA = 1;
	ET0 = 1;
	AUXR |= 0x80;		//定時器時鐘1T模式
	TMOD &= 0xF0;		//設置定時器模式
	TL0 = 0x00;		//設置定時初值
	TH0 = 0x28;		//設置定時初值
	TF0 = 0;		//清除TF0標誌
}

void  Timer0()  interrupt 1 
{
	key_count++;
	if (key_count = 500)
	{
		flag_key = 1;
		key_count = 0;
		TR0 = 0;
	}
}

3.矩陣按鍵
矩陣按鍵
跳線帽拔到BTN端。很容易得出這個矩陣按鍵就是X-Y格式排列的。所以定位行列就可以定位到對應的按鍵。

C語言中要用到的 switch語句

switch(表達式)
			{
				case(常量表達式1): 語句1; break;
				case(常量表達式2): 語句2; break;
				case(常量表達式3): 語句3; break;
				case(常量表達式4): 語句4; break;
				default:break;//默認..可以省略
			}

程序思路:
先檢測是否有按鍵按下,再判斷按鍵的位置。(用於都是一個口上)

void jzKey(void)
{
	if (P3 != 0xFF)
	{
		Delay10ms();
		if(P3 != 0xFF)
		{
			P3 = 0X0F;//給KEY初值,先檢測行
			switch(P3)//先檢測行
			{
				case(0x0e): KeyValue=1;break;
				case(0x0d): KeyValue=2;break;
				case(0x0b): KeyValue=3;break;
				case(0x07): KeyValue=4;break;
				
			}
			P3 = 0XF0;//測試列
			switch(P3)
			{
				case(0xe0): KeyValue=KeyValue+12;break;
				case(0xd0): KeyValue=KeyValue+8;break;
				case(0xb0): KeyValue=KeyValue+4;break;
				case(0x70): KeyValue=KeyValue;break;					
			}
			while(!P3);	 //檢測按鍵鬆手檢測
		}
	}

}

發現自己犯了個錯,藍橋杯的板子上的轉接口把口的位置變了。在這裏插入圖片描述
所以按照某位大可愛給的CTRLCV辦法,乾脆就直接sbit了。

/*代碼片段:先判斷一行一行的判斷*/
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L1 = P4^4;//P3^7 = P4^4
sbit L2 = P4^2;//P3^6 = P4^2
sbit L3 = P3^5;
sbit L4 = P3^4;

uchar jzKey(void)
{
	static uchar key_value = 0;
	H1 = 0;
	H2 = H3 = H4 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 1;
		}while(!L1);
	}
	else if(!L2)//複製修改
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 2;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 3;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 4;
		}while(!L4);
	}
	//複製修改
	H2 = 0;
	H1 = H3 = H4 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 5;
		}while(!L1);
	}
	else if(!L2)
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 6;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 7;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 8;
		}while(!L4);
	}
	
	H3 = 0;
	H2 = H3 = H4 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 9;
		}while(!L1);
	}
	else if(!L2)
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 10;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 11;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 12;
		}while(!L4);
	}
	
	H4 = 0;
	H2 = H3 = H1 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 13;
		}while(!L1);
	}
	else if(!L2)
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 14;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 15;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 16;
		}while(!L4);
	}
	return key_value;
}
	

void main()
{
	uchar key = 0;
	All_Init();
	while(1)
	{
		key = jzKey();
		if(key == 6)
		{
			P2 = (P2 & 0X1F | 0X80);
			P0 = 0X00;
			key = 0;
		}
	}	
}


三.數碼管

在這裏插入圖片描述
數碼管一般考察都是動態,先位選再段選;
https://blog.csdn.net/zlllg/article/details/82119338可以參考一下這個老哥的博客,先碼着明天看~

//數碼管動態掃描核心代碼

code unsigned char Duan_Data[] = {0Xc0,0xf9,0xa4,0xb0,0X99,0X92,0X82,0XF8,0X80,0X90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共陽的段碼,會給的不用記
code unsigned char Wei_Data[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};//要記住的 
void Display(int dat)
{
	uchar i,j = 0;
	uchar str[3];
	
	str[0] = dat%10;//個位
	str[1] = dat/10%10;//十位
	str[2] = dat/100;//百位
	
	for(i = 0; i<3;i++)//要顯示幾位就循幾次
	{
		P2 = (P2&0X1F|0XC0);//位
		P0 = Wei_Data[7-i];
		P2= (P2&0X1F|0XE0);//段
		P0 = Duan_Data[str[i]];
		Delay_ms(3);//反覆試了幾次,比較穩定的延時
		P0 = 0XFF;//消影
	}
}

void main(void)
{
	All_Init();
	while(1)
	{
		Display(321);
	}
}

當要求加小數點的時候,我們知道共陽段選小數點是0X7F ,對特定位清零用&,所以只需要再加上 P0 = Duan_Data[str[i]]&0X7F。

四.蜂鳴器/繼電器

在這裏插入圖片描述

P2 = (P2&0X1F|0XA0);
P0 = 0X10|0X40;//繼電器/蜂鳴器開
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章