欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 4087|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)入門的一點(diǎn)心得

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:70481 發(fā)表于 2014-12-17 16:38 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
最近看到幾個(gè)尋求單片機(jī)入門的帖子,一時(shí)心血來潮,把自己的一些入門心得寫了下來,希望能對(duì)初學(xué)者有所幫助吧。
可能很多人學(xué)習(xí)單片機(jī)的開始都是一章一章的的去閱讀教程,我也這樣做過,結(jié)果就是沒多久就昏昏欲睡了。對(duì)于初學(xué)者來說,什么隨機(jī)存儲(chǔ)器啊,只讀存儲(chǔ)器啊,寄存器啊,尋址方式啊,周期啊,指令啊。。。等等等等,簡(jiǎn)直就跟看天書一樣。其實(shí),我認(rèn)為對(duì)于初學(xué)者來說,沒必要了解這么多,學(xué)習(xí)總是一個(gè)循序漸進(jìn)的過程,不要妄想著能一下子就把單片機(jī)的理解透了,然后再去動(dòng)手做實(shí)驗(yàn),做項(xiàng)目,這是很不現(xiàn)實(shí)的。
學(xué)習(xí)單片機(jī)的時(shí)候,要想著單片機(jī)能做什么我就學(xué)什么,我想要做什么就學(xué)什么,不懂,就翻書,再不行,就上網(wǎng)找。那么首先單片機(jī)能做些什么呢?單片機(jī)能做的事情很多很多,恐怕說個(gè)幾天幾夜都說不完。可能很多人會(huì)這么說,這么多的功能,這么多的例子,究竟從何學(xué)起啊!但是在我看來,單片機(jī)能做的只有兩件事而你要做的也只有這兩件事情:第一,輸出高低電平;第二,接收高低電平的輸入。假如單片機(jī)沒有輸入輸出功能,那么程序編得在怎么超凡脫俗,也沒有任何意義。因?yàn)椋瑳]有了跟外圍器件的通信,單片機(jī)還有什么用呢!那么跟外圍器件的通信靠的是什么呢?高電平(+3.3V或+5V)和低電平(0V)。那么我們的目的就很明確了,學(xué)習(xí)單片機(jī)的目的就是讓單片機(jī)的各個(gè)管腳輸入或輸出高或低電平。在程序上代表高低電平的就是數(shù)字量1和0。也就是說,程序的最終目的就是在各個(gè)管腳上輸入或輸出1或0。所有的程序都是為了達(dá)成這個(gè)目的而設(shè)計(jì)的。換句話來說,只要能在你想要的管腳輸入或輸出你想要實(shí)現(xiàn)的高或低電平,那么你的目的就已經(jīng)達(dá)到了,不要去管你的程序有多么的臃腫或是不堪入目,這個(gè)會(huì)隨著你學(xué)習(xí)的深入和經(jīng)驗(yàn)的積累而逐漸改善,不需要著急。
舉個(gè)最簡(jiǎn)單的例子,在單片機(jī)的P1.0的管腳上接一個(gè)LED燈,要讓LED燈點(diǎn)亮,就是在P1.0管腳上輸出高電平,要讓LED燈熄滅,就是在P1.0腳上輸出低電平。那么怎么樣才能在P1.0腳上輸出高或低電平呢?不知道,那就去翻書一條一條的去找指令。哦,找到一條SETB置位指令,置位P1.0那不就是把1賦給P1.0嗎,P1.0置1,不就是輸出高電平了嗎?至于是不是,誰試誰知道。不過,先不要著急,既然找到了輸出高電平的指令,那么順便找找輸出低電平的指令。好了,沒錯(cuò),就是你了CLR。那么現(xiàn)在就可以編程序了:
             ORG        0000H
             JMP         MAIN
             OGR        0030H               ;如果不能理解這幾條指令的意思,那就直接套用就可以了
MAIN:
             SETB       P1.0                  ;輸出高電平,點(diǎn)亮LED燈
             CLR         P1.0                  ;輸出低電平,熄滅LED燈
             END
好了,程序完成,很簡(jiǎn)單吧。可是,這個(gè)只是一亮一滅,我要它不停的閃爍怎么辦?簡(jiǎn)單!多加一句跳轉(zhuǎn)指令就行了,跳轉(zhuǎn)指令上面就有JMP,那好吧,再改一下程序
             ORG        0000H
             JMP         MAIN
             OGR        0030H
MAIN:
             SETB       P1.0
             CLR         P1.0
             JMP         MAIN
             END
大功告成
可是,程序運(yùn)行之后,看不到LED燈一亮一滅啊!怎么回事?這是當(dāng)然了,單片機(jī)CUP的運(yùn)行速度是以微秒來計(jì)的,人的眼睛是反應(yīng)不過來的。那要怎么辦呢?讓CPU停一下等個(gè)一兩秒再執(zhí)行下一條指令?那顯然不行,地球人都知道。那就找點(diǎn)事情給CPU去忙吧,不管它干什么都行,只要再這段時(shí)間內(nèi)不要去碰P1.0管腳就行了。那么讓它去做什么呢,國(guó)際上-_-!!!通常讓它去數(shù)數(shù),因?yàn)镃PU每數(shù)一個(gè)數(shù)的時(shí)間都是一樣的,比如說1微秒,那么數(shù)1 000個(gè)數(shù),就是1毫秒,數(shù)1 000 000個(gè)數(shù)就是一秒。那么怎么樣讓CPU去數(shù)數(shù)呢?繼續(xù)找指令表,我找。。。找到一個(gè)INC,每執(zhí)行一次,操作數(shù)加1,那我要數(shù)到1 000 000的時(shí)候停止呢,怎么辦?不知道。不知道!那要你干什么,一邊去吧你,順便把你兄弟DEC也帶走,我不想再見到你們!我再找。。。這個(gè)好像有點(diǎn)用JZ,累加器A中為0就跳轉(zhuǎn),好像可以啊,我先讓CPU跳一邊去然后給A一個(gè)數(shù)1 000 000,讓A從1 000 000減到0,A為0時(shí)再跳轉(zhuǎn)回來不就行了?不過累加器A是什么?不知道?那就再翻書。。。哦,好像A最大只能到255,到不了1 000 000,怎么辦?255就255吧,先試試再說,看能不能看出變化。那么怎么給A送數(shù)呢?MOV唄!好了,那誰誰誰,你給我回來,DEC別看了,說的就是你!嗯,再改一下程序
             ORG        0000H
             JMP         MAIN
             OGR        0030H
MAIN:
             SETB       P1.0
             MOV        A,#255            ;給A一個(gè)數(shù),讓CPU去數(shù)
             JMP         WAIT               ;CPU給我一邊數(shù)數(shù)去
LED_OFF:
             CLR         P1.0
             MOV        A,#255            ;
             JMP         WAIT1             ;再來一個(gè)
LED_ON:
             JMP         MAIN
WAIT:
             DEC        A                     ;A-1
             JZ           LED_OFF         ;等于0就跳回去
             JMP         WAIT              ;不等于0就繼續(xù)減
WAIT1:
             DEC        A                     ;A-1
             JZ           LED_ON          ;等于0就跳回去
             JMP         WAIT1            ;不等于0就繼續(xù)減
             END
編譯,,排錯(cuò),運(yùn)行,大功告成
好了,程序編完了,也能運(yùn)行了,不過現(xiàn)在高興是不是太早了,你在JMP來JMP去的,JMP的我頭都暈了,那我要是要再延長(zhǎng)一點(diǎn)時(shí)間,你豈不是要JMP個(gè)沒完沒了了?!難道就沒有別的方法了嗎?那好吧,我在翻翻書。真是書到用時(shí)方恨少啊。。。咦,這個(gè)看起來有點(diǎn)意思,CALL,是不是跟打電話一樣,不管你在哪里,一個(gè)CALL,就能找到你啊。不過這個(gè)ACALL和LCALL又有神馬不同呢,難道還有國(guó)內(nèi)長(zhǎng)途和國(guó)際長(zhǎng)途之分?不管了,就用你了LCALL,反正不用花錢。
             ORG        0000H
             JMP         MAIN
             OGR        0030H
MAIN:
             SETB       P1.0
             MOV        A,#255
             LCALL     WAIT               ;我CALL
             LCALL     WAIT               ;我再CALL
             LCALL     WAIT               ;
             LCALL     WAIT               ;
             LCALL     WAIT               ;我CALL,CALL,CALL。。。
             CLR         P1.0
             LCALL     WAIT
             LCALL     WAIT
             LCALL     WAIT
             LCALL     WAIT              ;哈哈哈。。。CALL個(gè)夠,爽
             JMP         MAIN
WAIT:  
             DEC        A                     ;A-1
             JNZ         WAIT              ;沒數(shù)完,繼續(xù)。。。
             RET                               ;數(shù)完了,那我掛電話了,有時(shí)間再CALL你啊
             END
好了,這回看起來舒服多了。不過累加器A,看起來你有點(diǎn)意見?A:“廢話!你不知道老子很忙的嗎!分分鐘幾十萬上下,你叫我給你數(shù)數(shù)?你確定,你的腦袋沒被驢給踢過?老子縱橫機(jī)湖幾十年,閱人無數(shù),就沒見過你這么白的程序員!”好吧,大哥,你牛,我惹不起你我躲的起。我再翻書,幸好這不是在考試,我想怎么翻就怎么翻。。。有了!就是你了DJNZ,減1不為0就跳轉(zhuǎn)。咦,怎么沒有減1為0跳轉(zhuǎn)的呢?也不知道創(chuàng)造匯編的那位大神是怎么想的。好吧,這不是我們這些小菜鳥該管的,還是改我的程序比較靠譜一點(diǎn)
             ORG        0000H
             JMP         MAIN
             OGR        0030H
MAIN:
             SETB       P1.0
             MOV        R0,#255         ;那就換一個(gè)唄
             LCALL     WAIT               ;我CALL
             LCALL     WAIT               ;我再CALL
             LCALL     WAIT               ;
             LCALL     WAIT               ;
             LCALL     WAIT               ;我CALL,CALL,CALL。。。
             CLR         P1.0
             LCALL     WAIT
             LCALL     WAIT
             LCALL     WAIT
             LCALL     WAIT              ;哈哈哈。。。
             JMP         MAIN
WAIT:  
             DJNZ       R0,WAIT        ;沒數(shù)完,繼續(xù)
             RET                               ;數(shù)完了,那我掛電話了,有時(shí)間再CALL你啊
             END
好了,終于終于終于編完了,其實(shí)單片機(jī)也不怎么難嘛,呵呵。
最后,再介紹一句,其實(shí)
DJNZ       R0,WAIT
這句,還可以換成
DJNZ       R0,$
這樣,減1不為0就等待,其實(shí)我想介紹的是這一句
JMP         $
這是個(gè)死循環(huán),原地跳步,用來調(diào)試程序是非常好用的。不知道創(chuàng)造這句的大神是不是要告訴全世界的程序員,美元的魅力連CPU也擋不住,看到它,誰也跑不動(dòng)。好了,言歸正傳,這一句其實(shí)用來調(diào)試程序是非常好用的,不知道怎么用,就先記住吧,或許以后有用,或許永遠(yuǎn)也沒用,一家之言,每個(gè)人有每個(gè)人的方法。
好了,就講到這里了,一時(shí)興起講了這么多,以后可能再也沒有這么好的興致寫這么多東西了,就這樣吧
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:70481 發(fā)表于 2014-12-17 17:03 | 只看該作者
(二)I2C協(xié)議

如果CCAV要舉辦“菊花郎杯我最喜愛的單片機(jī)通信協(xié)議”的話,我以菊花郎集團(tuán)首席執(zhí)行官名譽(yù)擔(dān)保,I2C一定會(huì)摘得

桂冠。什么?你說SPI應(yīng)用更廣泛?但是,對(duì)于初學(xué)者來說SPI在很多時(shí)候往往數(shù)據(jù)發(fā)送過去之后,就如石沉大海,完

全不知所以。當(dāng)年,小菜鳥我操控SPI協(xié)議的時(shí)候,簡(jiǎn)直就像是中了七傷拳的至尊寶:“二當(dāng)家的,老子踩了你那么久

,就算不痛也隨便應(yīng)付兩聲嘛!”相比之下I2C就乖巧多了,至少你踩他8腳,他會(huì)回應(yīng)一聲。現(xiàn)在,大家知道我為什

么要選I2C了吧!

好了,我們言歸正傳,I2C的ACK確實(shí)是非常的好用,I2C有沒有寫對(duì),請(qǐng)看ACK!一目了然,真的是太方便了!I2C真的

這么簡(jiǎn)單嗎?是不是參照著協(xié)議圖寫完就OK了呢?未必!以我自己的經(jīng)歷來看,曾經(jīng)無數(shù)次的,拿著仿真器,對(duì)著I2C

協(xié)議時(shí)序圖,一個(gè)時(shí)鐘一個(gè)時(shí)鐘的校驗(yàn),或是在客戶那里對(duì)著示波器一個(gè)脈沖一個(gè)脈沖的讀I2C數(shù)據(jù)。那時(shí)候,總是擔(dān)

心著是不是多了或是少了一個(gè)脈沖啊,究竟是在上升沿還是下降沿讀寫數(shù)據(jù)啊。。。等等,總之,就是心里沒底。哎

,小菜鳥真是傷不起,傷不起啊傷不起。。。

咦,又跑題了。對(duì)于I2C,我總結(jié)了3點(diǎn)原則。自從有了這3點(diǎn)(怎么聽起來這么別扭呢),再也不用為I2C協(xié)議

擔(dān)心啦!請(qǐng)看:
(1)、在I2C起始信號(hào)之前,和結(jié)束信號(hào)之后,確保SCL和SDA腳為高電平;
(2)、在每個(gè)函數(shù)(結(jié)束信號(hào)函數(shù)除外)之后,確保SCL為低電平;
(3)、請(qǐng)參考以上兩條(哈哈,其實(shí)只有兩點(diǎn)啦,但是我要是說只有兩點(diǎn)那豈不是很沒面子
是不是不明覺厲呢。別著急,我們慢慢來分析。
我們先從起始和結(jié)束信號(hào)函數(shù)開始分析,
void I2c_Start(void)
{
        SCL_HIGH;
        SDA_HIGH;
        nop();
        SDA_LOW;
        nop();
        SCL_LOW;
}
void I2c_Stop(void)
{
        SDA_LOW;
        nop();
        SCL_HIGH;
        nop();
        SDA_HIGH;
}
對(duì)照這兩個(gè)函數(shù)請(qǐng)看第一點(diǎn),對(duì)于I2c_Stop()的SCL_HIGH和SDA_HIGH,這兩個(gè)沒什么可說的,這是協(xié)議的結(jié)束信號(hào),

只要沒寫反了就行,連這個(gè)也寫反了的童鞋,自己面壁思過去。這里要說明一下的是I2c_Start()開始的兩個(gè)SCL_HIGH

和SDA_HIGH,有沒有童鞋覺得每次結(jié)束信號(hào)都把SCL和SDA拉高了,還有沒有必要每次都在I2c_Start()里面再寫一遍啊

,太浪費(fèi)了,勤儉節(jié)約是中華民族的光榮傳統(tǒng),都說了要節(jié)約嘛!可是我要說的是,可能在某個(gè)不為人知

的陰暗角落,或許I2C的某根線就被偷偷的改變了狀態(tài)。這怎么可能!我自己編的程序難度有沒有用到I2C還不知道嗎

?可是,在工作中可能你接手的程序已經(jīng)不知道經(jīng)過了多少人的縫縫補(bǔ)補(bǔ),特別是在一些大型企業(yè)中尤為如此。So,

安全第一,安全第一!還有就是你編寫的I2C程序可能會(huì)有他人調(diào)用,與人方便自己方便吧!對(duì)了,還有第2點(diǎn),這點(diǎn)

跟I2c_Stop()沒就關(guān)系,你可以涼涼去了。當(dāng)然對(duì)于I2c_Start()也沒什么可說的,協(xié)議寫了嘛,SCL為低,必須的!

好了,你們兩個(gè)可以去領(lǐng)盒飯了,下一個(gè)I2c_Write(u8 uByte)輪到你了,還看,說的就是你了!上來躺好,放心不用

解剖,我們只看兩點(diǎn),好吧,就看一點(diǎn)
void I2c_write(u8 uByte)        //unsigned char 定義為u8,以后不在說明
{
        u8 i;
        
        for(i=0; i<8; i++)
        {
                if(uByte & 0x80)
                {
                        SDA_HIGH;
                }
                else
                {
                        SDA_LOW;
                }
                SCL_HIGH;        //我高,劃破長(zhǎng)空,前面的一切不管
                nop();
                SCL_LOW;        //我低,一場(chǎng)春夢(mèng),生與死一切成空
                uByte <<= 1;
        }
}
寫數(shù)據(jù)其實(shí)就是8個(gè)時(shí)鐘脈沖,這個(gè)做個(gè)循環(huán)就行了,依次把一個(gè)字節(jié)的數(shù)據(jù)寫到SDA腳。關(guān)鍵是SCL的時(shí)鐘脈沖怎么寫

,根據(jù)第二點(diǎn)準(zhǔn)則,所有I2C通信函數(shù)都以SCL低電平結(jié)束(結(jié)束信號(hào)除外),所以,寫脈沖首先就是把SCL拉高,然后

再拉低,這就是一個(gè)bit的寫時(shí)序了,循環(huán)8次,結(jié)束寫字節(jié)操作。你看,最后還是以SCL低為結(jié)束,完美收官!耶!真是太有默契了,贊一個(gè)先

當(dāng)當(dāng)當(dāng)當(dāng),下面有請(qǐng)我們今天的男豬腳I2c_WriteAck()隆重登場(chǎng)!咦,你腳下踩的是什么?
u8 I2c_WriteAck(void)
{
        u8 ack;

        SDA_IN;                //對(duì)于51單片機(jī)來說,設(shè)置為輸入其實(shí)就是把管腳置1,所以這句等同于SDA_HIGH,
                        //這句很重要,因?yàn)槟憧赡茉趯憯?shù)據(jù)的時(shí)候把SDA拉低了,所以比不可少
        SCL_HIGH;
        nop();
        if(READ_SDA)        //Only you 能保護(hù)我,讓螃蟹和蚌精無法吃我
                ack;= 1;
        else
                ack;= 0;
        SCL_LOW;
        SDA_OUT;        //對(duì)于51來說,這句為空

        return ack;
}
根據(jù)第二準(zhǔn)則,寫操作必定是以SCL低為結(jié)束,那么,SCL也是以拉高為開始。現(xiàn)在大家知道我為什么要強(qiáng)調(diào)必須以SCL

低為函數(shù)的結(jié)束了吧!這樣一來對(duì)于每一個(gè)函數(shù),都可以獨(dú)立去分析,不必去理會(huì)在這之前的時(shí)鐘是什么狀態(tài)。別看

ACK這么簡(jiǎn)單,I2C協(xié)議是生是死就看他的臉色了!對(duì)于用I2C通信的所有產(chǎn)品,不管別人對(duì)我說的是什么問題,我首先

聞到第一句就是ACK有沒有響應(yīng)?嗯,調(diào)試等一下再說,先看讀操作。“O~O~Only you!”O(jiān)你個(gè)頭。。。

好了,輪到你們了,I2c_Read()、I2c_ReadAck()和I2c_ReadNAck(),都以前上來吧
u8 I2c_Read(void)
{
        u8 i;
        u8 uByte;
        
        SDA_IN;                //親,別忘了倫家哦
        for(i=0; i<8; i++)
        {
                uByte <<= 1;
                SCL_HIGH;
                if(READ_SDIO)
                        uByte |= 0x01;
                SCL_LOW;
                nop();
        }
        
        SDA_OUT;        //“我呢,我呢!”你啊,看情況吧
        
        return uByte;
}
void I2c_ReadAck(void)
{
        SDA_LOW;
        nop();
        SCL_HIGH;
        nop();
        SCL_LOW;
}
void I2c_ReadNack(void)
{
        SDA_HIGH;
        nop();
        SCL_HIGH;
        nop();
        SCL_LOW;
}
這三個(gè)函數(shù)就不一一分析了,大家以此類推吧。

呼,I2C協(xié)議至此大功告成了,照此分析,童鞋們?cè)僖膊挥脫?dān)心出錯(cuò)了!大家想怎么玩就怎么玩,即使是量大的日子也

不用擔(dān)心側(cè)漏了(咦,這句好像在哪里聽過)!

好了,高興三分鐘就夠了。是不是I2C協(xié)議寫好就完事OK了呢?我可以很負(fù)責(zé)任的告訴你:NO!
嗯,今天就先講到這里吧。欲知后事,請(qǐng)聽下回分解。。。

回復(fù)

使用道具 舉報(bào)

板凳
ID:188935 發(fā)表于 2017-10-10 15:54 | 只看該作者
6666,你可以去大學(xué)當(dāng)老師,講的好有默契
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表