基礎不是很好,所以程序思路只能說夠用就行,之後我會慢慢修改回來完善。
今晚跟人吵架了很難受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;//繼電器/蜂鳴器開