性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

  • 回復(fù)
  • 收藏
  • 點(diǎn)贊
  • 分享
  • 發(fā)新帖

吳堅(jiān)鴻單片機(jī)程序技巧與模式連載

QQ截圖20140211133146

吳堅(jiān)鴻

擁有多年電子開發(fā)經(jīng)驗(yàn),功力深厚,目前經(jīng)營(yíng)獨(dú)立工作室。

主攻PIC,瑞薩,STC,51系列等各類單片機(jī)的開發(fā),擅長(zhǎng)使用VHDL語言開發(fā)CPLD,精通使用VC,VB開發(fā)電腦上位機(jī)軟件。

本文作者認(rèn)為傳授單片機(jī)技術(shù)最好要有一個(gè)學(xué)習(xí)板作為硬件平臺(tái),即使沒有硬件平臺(tái),至少每個(gè)程序也要有相對(duì)應(yīng)的硬件原理圖。但在本文當(dāng)中作者將所有的硬件原理都用中文來描述,盡可能確保讀者看文字就知道硬件電路大概的原理。

文章中所有程序都是用C語言并且基于PIC單片機(jī),因?yàn)閷?duì)于讀者來說,所有單片機(jī)的C語言都大同小異,只要學(xué)會(huì)一種,其他的都懂了。而相對(duì)的,程序側(cè)重點(diǎn)轉(zhuǎn)移到了教大家編程的模式與框架上。

本文文章每一節(jié)的程序里主要包含兩方面的內(nèi)容。一方面是程序框架,另一方面是項(xiàng)目中所遇到的某個(gè)具體技術(shù)難題的解決方法。

全部回復(fù)(5)
正序查看
倒序查看
一木01
LV.3
2
2014-02-11 13:41

一)按鍵行列掃描與蜂鳴器

 

(1)技術(shù)體會(huì):在行列式掃描結(jié)構(gòu)的薄膜按鍵里,干擾很大,按鍵掃描程序非常講究,尤其是去抖動(dòng)的處理。

(2)功能需求:每按一個(gè)按鍵,蜂鳴器就響一次。

(3)硬件原理:

(a)用4個(gè)IO來做2X2按鍵行列掃描,其中作為輸入的2個(gè)IO口必須接上拉電阻20K左右。

(b)用1個(gè)IO經(jīng)過8050三極管來驅(qū)動(dòng)有源蜂鳴器,有源蜂鳴器通電就一直響,斷電就停止。而無源蜂鳴器是要靠斷斷續(xù)續(xù)的開關(guān)信號(hào)來驅(qū)動(dòng)才能響,就是要頻率來驅(qū)動(dòng)。

(4)源碼適合的單片機(jī):PIC18F4620,晶振為22.1184MHz

(5)源代碼講解如下:

#include //包含芯片相關(guān)頭文件

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是輸出IO后綴都是_dr,凡是輸入的//IO后綴都//是_sr

#define beep_dr LATA1 //蜂鳴器輸出

#define key_dr1 LATB3 //2X2按鍵行輸出

#define key_dr2 LATB4 //2X2按鍵行輸出

#define key_sr1 RB6 //2X2按鍵行輸入

#define key_sr2 RB7 //2X2按鍵行輸入

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是做延時(shí)計(jì)數(shù)閥值的常量

//前綴都用cnt_表示。

#define cnt_delay_cnt1 25 //按鍵去抖動(dòng)延時(shí)閥值

#define cnt_delay_cnt2 5 //按鍵行輸出信號(hào)穩(wěn)定的小延時(shí)閥值

#define cnt_voice_time 60 //蜂鳴器響的聲音長(zhǎng)短的延時(shí)閥值

void delay1(unsigned int de) ;//小延時(shí)程序,時(shí)間不宜太長(zhǎng),因?yàn)閮?nèi)部沒有喂看門狗

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是按鍵掃描函數(shù)都放在定時(shí)中

//斷里,凡是按鍵服務(wù)程序都是放在main函數(shù)循環(huán)里。有人說不應(yīng)該把子程序//放在中斷里,別聽他們,信鴻哥無坎坷。

void key_scan(); //按鍵掃描函數(shù),放在定時(shí)中斷里

void key_service(); //按鍵服務(wù)函數(shù),放在main函數(shù)循環(huán)里

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是switch()語句括號(hào)里面的變量名

//后綴都用_step表示。

unsigned char key_step=1; //按鍵掃描步驟變量,在switch()語句的括號(hào)里

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是按鍵或者感應(yīng)輸入的自鎖變量名

//后綴都用_lock表示。

unsigned char key_lock1=0; //按鍵自鎖標(biāo)志

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是計(jì)數(shù)器延時(shí)的變量

//后綴都用_cnt表示。

unsigned int delay_cnt1=0; //延時(shí)計(jì)數(shù)器的變量

unsigned int delay_cnt2=0; //延時(shí)計(jì)數(shù)器的變量

unsigned int voice_time_cnt; //蜂鳴器響的聲音長(zhǎng)短的計(jì)數(shù)延時(shí)

//補(bǔ)充說明:吳堅(jiān)鴻程序風(fēng)格是這樣的,凡是做類型的變量的分類

//后綴都用_sec表示。

Unsigned char key_sec=0; //哪個(gè)按鍵被觸發(fā)

//主程序

main()

{

ADCON0=0x00;

ADCON1=0x0f; //全部為數(shù)字信號(hào)

ADCON2=0xa1; //右對(duì)齊

RBPU=0; //上拉電阻

SSPEN=0; //決定RA5不作為串口

TRISB3=0; //配置按鍵行掃描IO為輸出

TRISB4=0; //配置按鍵行掃描IO為輸出

TRISB6=1; //配置按鍵列掃描IO為輸入

TRISB7=1; //配置按鍵列掃描IO為輸入

T1CON=0x24; //定時(shí)器中斷配置

TMR1H=0xF5;

TMR1L=0x5F;

TMR1IF=0;

TMR1IE=1;

TMR1ON=1;

TMR1IE=1;

//補(bǔ)充說明,以上的內(nèi)容為寄存器配置,每種不同的單片機(jī)會(huì)有點(diǎn)差異,

//大家不用過度關(guān)注以上寄存器的配置,只要知道有這么一回事即可

beep_dr=0; //關(guān)蜂鳴器,上電初始化IO

while(1)

{

CLRWDT(); //喂看門狗,大家不用過度關(guān)注此行

key_service(); //按鍵服務(wù)

}

}

void key_scan() //按鍵掃描函數(shù)

{

//補(bǔ)充說明:如果中斷一次就把所有的按鍵都掃描完,中斷占用的時(shí)間片就會(huì)太多,勢(shì)//必會(huì)影響main函數(shù)里其他子程序的運(yùn)行,為了避免一口氣把所//的按鍵都掃描完,此

//處用switch語句把4個(gè)按鍵分成2等分,一次中斷只掃描2個(gè)按鍵

switch(key_step) //按鍵掃描步驟,

{

case 1: //掃描1號(hào)鍵,2號(hào)鍵

key_dr1=0; //按鍵行掃描輸出第一行低電平

key_dr2=1;

delay_cnt2=0; //延時(shí)計(jì)數(shù)器清零

key_step++; //切換到下一個(gè)運(yùn)行步驟

break;

case 2:

delay_cnt2++;

if(delay_cnt2>cnt_delay_cnt2) //小延時(shí),但不是去抖動(dòng)延時(shí),替代一直受網(wǎng)友爭(zhēng)議的delay1(40)

{

delay_cnt2=0;

key_step++; //切換到下一個(gè)運(yùn)行步驟

}

break;

case 3:

if(key_sr1==1&&key_sr2==1)

{ //如果沒有按鍵按下,則2個(gè)IO輸入都是高電平

key_step++; //如果沒有按鍵按下,下一個(gè)中斷掃描下2個(gè)

0
回復(fù)
一木01
LV.3
3
2014-02-11 13:43

//按鍵

key_lock1=0; //按鍵自鎖標(biāo)志清零

delay_cnt1=0; //按鍵去抖動(dòng)延時(shí)計(jì)數(shù)器清零,此行非常巧妙

}

Else if(key_sr1==0&&key_sr2==1&&key_lock1==0)

{ // key_lock1按鍵自鎖,避免按鍵一直觸發(fā),下降沿有效

++delay_cnt1; //延時(shí)計(jì)數(shù)器

//補(bǔ)充說明:有按鍵觸發(fā)之后,不要馬上響應(yīng),要延時(shí)一段時(shí)間去抖動(dòng),此處本人設(shè)計(jì)非常

//巧妙,很多人僅僅知道按鍵延時(shí)的時(shí)候要保證還能去處理別的程序,這樣是還不夠的,

//在延時(shí)去抖動(dòng)的時(shí)候,還必須要監(jiān)控延時(shí)這段時(shí)間里,按鍵IO輸入口是否會(huì)由于受到某//種干擾突然由低變成高,如果一旦變成高,那么延時(shí)計(jì)數(shù)器delay_cnt1必須重新清零

//我當(dāng)年就是因?yàn)檫@樣處理,把賣給富士康100臺(tái)受干擾死機(jī)的設(shè)備修好了,老板馬上

//給我加薪1000元。

if(delay_cnt1>cnt_delay_cnt1) //延時(shí)計(jì)數(shù)器超過一定的數(shù)值

{

delay_cnt1=0;

key_lock1=1; //自鎖按鍵置位,避免一直觸發(fā),只有松開按鍵,

//此標(biāo)志位才會(huì)被清零

key_sec=1; //觸發(fā)1號(hào)鍵

}

}

else if(key_sr1==1&&key_sr2==0&&key_lock1==0)

{

++delay_cnt1;

if(delay_cnt1>cnt_delay_cnt1)

{

delay_cnt1=0;

key_lock1=1; //自鎖按鍵置位,避免一直觸發(fā)

key_sec=2; //觸發(fā)2號(hào)鍵

}

}

break;

case 4: //掃描//掃描3號(hào)鍵,4號(hào)鍵

key_dr1=1;

key_dr2=0; //按鍵行掃描輸出第二行低電平

delay_cnt2=0; //延時(shí)計(jì)數(shù)器清零

key_step++; //切換到下一個(gè)運(yùn)行步驟

break;

case 5:

delay_cnt2++;

if(delay_cnt2>cnt_delay_cnt2) //小延時(shí),但不是去抖動(dòng)延時(shí),替代一直受網(wǎng)友爭(zhēng)議的delay1(40)

{

delay_cnt2=0;

key_step++; //切換到下一個(gè)運(yùn)行步驟

}

break;

case 6:

if(key_sr1==1&&key_sr2==1)

{

key_step++;

key_lock1=0;

delay_cnt1=0;

}

Else if(key_sr1==0&&key_sr2==1&&key_lock1==0)

{

++delay_cnt1;

if(delay_cnt1>cnt_delay_cnt1)

{

delay_cnt1=0;

key_lock1=1;

key_sec=3; //觸發(fā)3號(hào)鍵

}

}

else if(key_sr1==1&&key_sr2==0&&key_lock1==0)

{

++delay_cnt1;

if(delay_cnt1>cnt_delay_cnt1)

{

delay_cnt1=0;

key_lock1=1; //自鎖按鍵置位,避免一直觸發(fā)

key_sec=4; //觸發(fā)4號(hào)鍵

}

}

break;

}

0
回復(fù)
一木01
LV.3
4
2014-02-11 13:44

if(key_step>6) //第1組按鍵與第2組按鍵反復(fù)輪流掃描

{

key_step=1;

}

}

void key_service() //按鍵服務(wù)函數(shù)

{

switch(key_sec) //按鍵服務(wù)狀態(tài)切換

{

case 1:// 1號(hào)鍵

// 補(bǔ)充說明:voice_time_cnt只要不為0蜂鳴器就會(huì)響,中斷里判斷voice_time_cnt不為0

//時(shí),會(huì)不斷自減,一直到它為0時(shí),自動(dòng)把蜂鳴器關(guān)閉

voice_time_cnt= cnt_voice_time; //蜂鳴器響“滴”一聲就停

key_sec=0; //相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,

//避免一直觸發(fā)

break;

case 2:// 2號(hào)鍵

voice_time_cnt= cnt_voice_time; //蜂鳴器響“滴”一聲就停

key_sec=0; //相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,

//避免一直觸發(fā)

break;

case 3://3號(hào)鍵

voice_time_cnt= cnt_voice_time; //蜂鳴器響“滴”一聲就停

key_sec=0; //相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,

//避免一直觸發(fā)

break;

case 4://4號(hào)鍵

voice_time_cnt= cnt_voice_time; //蜂鳴器響“滴”一聲就停

key_sec=0; //相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,

//避免一直觸發(fā)

break;

}

}

//中斷

void interrupt timer1rbint(void)

{

if(TMR1IE==1&&TMR1IF==1) //定時(shí)中斷

{

TMR1IF=0; //定時(shí)中斷標(biāo)志位關(guān)閉

TMR1ON=0; //定時(shí)中斷開關(guān)關(guān)閉

key_scan(); //按鍵掃描函數(shù)

if(voice_time_cnt) //控制蜂鳴器聲音的長(zhǎng)短

{

beep_dr=1; //蜂鳴器響

--voice_time_cnt; //蜂鳴器響的聲音長(zhǎng)短的計(jì)數(shù)延時(shí)

}

else

{

beep_dr=0; //蜂鳴器停止

}

TMR1H=0xF5; //重新設(shè)置定時(shí)時(shí)間間隔

TMR1L=0x5F;

TMR1ON=1; //定時(shí)中斷開關(guān)打開

}

}

void delay1(unsigned int de)

{

unsigned int t;

for(t=0;t

}

(6)小結(jié):

以上是我常用的編程結(jié)構(gòu)。后續(xù)我做的所有項(xiàng)目基本上是這樣一種編程結(jié)構(gòu)。這一節(jié)技術(shù)上要特別重視按鍵掃描。有按鍵觸發(fā)之后,不要馬上響應(yīng),要延時(shí)一段時(shí)間去抖動(dòng),此處本人設(shè)計(jì)非常巧妙,很多人僅僅知道按鍵延時(shí)的時(shí)候要保證還能去處理別的程序,這樣是還不夠的,在延時(shí)去抖動(dòng)的時(shí)候,還必須要監(jiān)控延時(shí)這段時(shí)間里,按鍵IO輸入口是否會(huì)由于受到某種干擾突然由低變成高,如果一旦變成高,那么延時(shí)計(jì)數(shù)器delay_cnt1必須重新清零,我當(dāng)年就是因?yàn)檫@樣處理,把賣給富士康100臺(tái)受干擾死機(jī)的設(shè)備修好了,老板馬上給我加薪1000元。

 

 

待續(xù)

0
回復(fù)
tanik
LV.5
5
2017-03-07 22:44
@一木01
if(key_step>6)//第1組按鍵與第2組按鍵反復(fù)輪流掃描{key_step=1;}}voidkey_service()//按鍵服務(wù)函數(shù){switch(key_sec)//按鍵服務(wù)狀態(tài)切換{case1://1號(hào)鍵//補(bǔ)充說明:voice_time_cnt只要不為0蜂鳴器就會(huì)響,中斷里判斷voice_time_cnt不為0//時(shí),會(huì)不斷自減,一直到它為0時(shí),自動(dòng)把蜂鳴器關(guān)閉voice_time_cnt=cnt_voice_time;//蜂鳴器響“滴”一聲就停key_sec=0;//相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,//避免一直觸發(fā)break;case2://2號(hào)鍵voice_time_cnt=cnt_voice_time;//蜂鳴器響“滴”一聲就停key_sec=0;//相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,//避免一直觸發(fā)break;case3://3號(hào)鍵voice_time_cnt=cnt_voice_time;//蜂鳴器響“滴”一聲就停key_sec=0;//相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,//避免一直觸發(fā)break;case4://4號(hào)鍵voice_time_cnt=cnt_voice_time;//蜂鳴器響“滴”一聲就停key_sec=0;//相應(yīng)完按鍵處理程序之后,把按鍵選擇變量清零,//避免一直觸發(fā)break;}}//中斷voidinterrupttimer1rbint(void){if(TMR1IE==1&&TMR1IF==1)//定時(shí)中斷{TMR1IF=0;//定時(shí)中斷標(biāo)志位關(guān)閉TMR1ON=0;//定時(shí)中斷開關(guān)關(guān)閉key_scan();//按鍵掃描函數(shù)if(voice_time_cnt)//控制蜂鳴器聲音的長(zhǎng)短{beep_dr=1;//蜂鳴器響--voice_time_cnt;//蜂鳴器響的聲音長(zhǎng)短的計(jì)數(shù)延時(shí)}else{beep_dr=0;//蜂鳴器停止}TMR1H=0xF5;//重新設(shè)置定時(shí)時(shí)間間隔TMR1L=0x5F;TMR1ON=1;//定時(shí)中斷開關(guān)打開}}voiddelay1(unsignedintde){unsignedintt;for(t=0;t}(6)小結(jié):以上是我常用的編程結(jié)構(gòu)。后續(xù)我做的所有項(xiàng)目基本上是這樣一種編程結(jié)構(gòu)。這一節(jié)技術(shù)上要特別重視按鍵掃描。有按鍵觸發(fā)之后,不要馬上響應(yīng),要延時(shí)一段時(shí)間去抖動(dòng),此處本人設(shè)計(jì)非常巧妙,很多人僅僅知道按鍵延時(shí)的時(shí)候要保證還能去處理別的程序,這樣是還不夠的,在延時(shí)去抖動(dòng)的時(shí)候,還必須要監(jiān)控延時(shí)這段時(shí)間里,按鍵IO輸入口是否會(huì)由于受到某種干擾突然由低變成高,如果一旦變成高,那么延時(shí)計(jì)數(shù)器delay_cnt1必須重新清零,我當(dāng)年就是因?yàn)檫@樣處理,把賣給富士康100臺(tái)受干擾死機(jī)的設(shè)備修好了,老板馬上給我加薪1000元。  待續(xù)
這么好的文章,居然沒有人贊?等待后續(xù)。
0
回復(fù)
ruohan
LV.9
6
2017-03-23 13:17
@tanik
這么好的文章,居然沒有人贊?等待后續(xù)。

推薦本書看看了

0
回復(fù)
發(fā)