新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > avrI/O 端口操作和上拉電阻

        avrI/O 端口操作和上拉電阻

        作者: 時間:2016-11-24 來源:網絡 收藏
        AVR單片機端口操作

        說明:本節重點介紹真正雙向端口操作的方法,及與偽雙向端口操作的不同。跑馬燈例子。建議先看跑馬燈,再繞回來看前面的介紹。

        本文引用地址:http://www.104case.com/article/201611/320591.htm

        AVR端口是真正的雙向端口,不像51偽雙向。這也是AVR的一項優勢,只是操作時大家注意DDRn就可以了。真正雙向端口在模擬時序方面不如偽雙向的方便。
        DDRn PORTn PINn 解釋:n為端口號:ABCDE
        DDRn:控制端口是輸入還是輸出,0為輸入,1為輸出。個人記憶方法:一比零大所以往外擠,即1為輸出,0為輸入。
        PORTn:從引腳輸出信號,當DDRn為1時,可以通過PORTn=x等端口操作語句給引腳輸出賦值。
        PINn:從引腳讀輸入信號,無論DDRn為何值,都可以通過x=PINn獲得端口n的外部電平。
        當引腳配置為輸入時,若PORTxn 為"1“,上拉電阻將使能。內部上拉電阻的使用在鍵盤掃描的時候還要說到。
        端口更詳細功能及介紹以及端口第二功能請參考數據手冊。
        端口引腳配置
        DDxn PORTxn PUD (in SFIOR) I/O 上拉電阻 說明
        0 0 X 輸入 No 高阻態 (Hi-Z)
        0 1 0 輸入 Yes 被外部電路拉低時將輸出電流
        0 1 1 輸入 No 高阻態(Hi-Z)
        1 0 X 輸出 No 輸出低電平 ( 漏電流)
        1 1 X 輸出 No 輸出高電平 ( 源電流)

        如果有引腳未被使用,建議給這些引腳賦予一個確定電平。最簡單的保證未用引腳具有確定電平的方法是使能內部上拉電阻。但要注意的是復位時上拉電阻將被禁用。如果復位時的功耗也有嚴格要求則建議使用外部上拉或下拉電阻。不推薦直接將未用引腳與VCC 或GND 連接,因為這樣可能會在引腳偶然作為輸出時出現沖擊電流。
        下面我們來看例子:
        void port_init(void)
        {
        PORTA = 0x03;
        DDRA = 0x03;
        PORTB = 0x00;
        DDRB = 0x01;
        PORTC = 0x00;
        DDRC = 0x00;
        PORTD = 0x00;
        DDRD = 0x00;// 建議賦值為零
        }

        PORTA = 0x03;DDRA = 0x03;這兩句使PA口的PA1和PA0處于輸出狀態,PA7—PA2處于輸入狀態,因為先定義了PORTA=0x03,PA1和PA0的內部上拉電阻也使能了,雖然后來DDRA = 0x03。為什么捏,也許我們可以這么認為:DDRA默認都是輸入的,但只要先定義PORTxn的某些位為1,就使能了上拉電阻,不需要管后面的DDRA設置為輸入還是輸出.這里的0x03即二進制的00000011,從左到右對應于Pn7--Pn0八個IO口。

        通過跑馬燈程序來深入理解IO口的操作:
        // ICC-AVR application builder : 2007-9-14 2:26:57
        // Target : M16
        // Crystal: 11.059Mhz
        // 出處:arm9.cn/article.asp?articleid=202">http://www.arm9.cn/article.asp?articleid=202
        #include
        #include

        void port_init(void)
        {
        PORTA = 0x00;
        DDRA = 0x00;
        PORTB = 0x0F; //PB0-3口設為輸出高電平,燈滅
        DDRB = 0x0F; //PB0-3口設為輸出
        PORTC = 0x00; //m103 output only
        DDRC = 0x00;
        PORTD = 0x00;
        DDRD = 0x00;
        }

        //Crystal: 7.3728Mhz下的延時100us的延時函數
        void _delay(unsigned char n)
        {
        unsigned char i,j;
        for(;n!=0;n--) //n*10ms
        {
        for(j=100;j!=0;j--) //100us*100=10ms
        {
        for(i=147;i!=0;i--) //delay 100us
        ;
        }
        }
        }
        // 這個是精確的11.059Mhz下的延時函數
        // http://www.willar.com/forum_view.asp?forum_id=25&view_id=6356
        void delay_ms(unsigned int n)
        {
        unsigned int i;
        for(i=n;i>0;i--)
        delay_1ms();
        }

        void delay_1ms(void)
        {
        unsigned char i;
        for(i=114;i>0;i--);
        }

        //call this routine to initialize all peripherals
        void init_devices(void)
        {
        //stop errant interrupts until set up
        CLI(); //disable all interrupts
        port_init();

        MCUCR = 0x00;
        GICR = 0x00;
        TIMSK = 0x00; //timer interrupt sources
        SEI(); //re-enable interrupts
        //all peripherals are now initialized
        }

        void main(void)
        {
        unsigned char i,j,k;
        //init_devices();
        PORTB=0x0F; //PB口設為輸出高電平,燈滅
        DDRB=0x0F; //PB口設為輸出
        while(1)
        {
        i=1;
        for (j=0;j<4;j++) //循環4次,即PB0~~PB3輪流閃亮
        {
        PORTB=~i; //反相輸出,低電平有效,對應的燈亮
        for (k=0;k<10;k++)
        delay_ms(1000); //延時 100*10=1秒,可自行調節
        i=i<<1; //左移一位,I的值將向下面的列表那樣變化
        // 0b00000001 PB0
        // 0b00000010 PB1
        // 0b00000100 PB2
        // 0b00001000 PB3

        // 0b00010000 PB4
        // 0b00100000 PB5
        // 0b01000000 PB6
        // 0b10000000 PB7
        }
        }
        }

        其他IO口操作指令:

        void main(void)
        {
        PORTA=0xff;
        DDRA=0xff; //輸出 模式 ,IO口上拉電阻有效,1為輸出,0為輸入。
        PORTA=0xf0; //等以下三條指令只對操作符號右邊的數字位是一的位操作。
        PORTA&=~0x70; //清零 0x70為 01110000 ,即把654三位清零,其余數位不變。
        PORTA|=0x77; //置一 0x77為 01110111 ,即把654210六位置一,其余數位不變。
        PORTA^=0x70; //翻轉 如果是零變成1,是一變成0。
        (P & 0x80)==0x80; //按位與 判斷p的第七位是否是一,是則成立
        }

        實踐出真知:只看這樣的說明是很枯燥的,從實踐中去學習會是更好的途徑,把這些代碼都寫到單片機里,一步一步調試運行,看看各個端口以及寄存器的效果,也鍛練程序調試能力,和樂而不為呢?關于上拉電阻,有的時候需要使用,有的時候不能用,尤其是I/O端口操作的時候.上拉就是在IO口線上面接一個到VCC的電阻,很簡單,什么地方需要那可就廣了,作用也很大。上接電阻一般來說就是幫助某根線上面確定電平,比如一個懸空的信號線,由于是懸空的所以它可以是任何狀態、并極易受到外界的干擾,這樣對我們產品來說是不利的,只要接一個有上拉電阻,它的電平就會是可知的了。

        它一般在信號線不確定的情況下使用,那么輸入信號就需要了。當為輸出時因為輸出狀態是確定的,所以就不需要上拉電阻了.

        http://forum.eetchina.com/FORUM_POST_1100011897_0.HTM

        有些總線協議會將一些信號釋放為高阻態,但是實際上電路的狀態應該事確定的0或1,所以上拉電阻可以提供一個確定的狀態。
        上拉電阻還可以提供一個邏輯電平;以及供匹配用等~

        上拉電阻接電源(一般是為電源高電位),下拉電阻接地(一般是為電源0電位)。

        接了電阻之后就能把電壓拉高了嗎,比如原來輸出3V,接了上拉電阻之后就能變4v了嗎,有點想不明白,能不能詳細說說啊 ,

        上拉電阻本上當然不會提高電壓,但是上拉電阻的一端會接著VDD,另一端就是電路,所以會起到提高電壓的作用^_^

        我也是從學校學到的一點淺薄知識.....自己理解...請大師指點...
        前面的回復有說過上拉電阻實際上是集電極輸出的負載電阻,而一般三極管是控制集電極電流,基極電流確定,集電極電流也就確定,而為了把電流轉化成電壓,所以有了上拉電阻,計算方式是Vo=Vcc-Ic*R(R就是上拉電阻)....
        所以可以用上拉電阻提高帶負載能力和提高噪聲容限

        上拉電阻原理:http://blog.21ic.com/user1/349/archives/2007/36202.html

        *****************************************************************************************

        上拉電阻一般是指用一個電阻接到正電源上來得來正電,推挽是用三極管或場效應管等來輸出電壓!

        (一)上拉電阻:
        1、當TTL電路驅動COMS電路時,如果TTL電路輸出的高電平低于COMS電路的最低高電平(一般為3.5V),這時就需要在TTL的輸出端接上拉電阻,以提高輸出高電平的值。
        2、OC門電路必須加上拉電阻,才能使用。
        3、為加大輸出引腳的驅動能力,有的單片機管腳上也常使用上拉電阻。
        4、在COMS芯片上,為了防止靜電造成損壞,不用的管腳不能懸空,一般接上拉電阻產生降低輸入阻抗,提供泄荷通路。
        5、芯片的管腳加上拉電阻來提高輸出電平,從而提高芯片輸入信號的噪聲容限增強抗干擾能力。
        6、提高總線的抗電磁干擾能力。管腳懸空就比較容易接受外界的電磁干擾。
        7、長線傳輸中電阻不匹配容易引起反射波干擾,加上下拉電阻是電阻匹配,有效的抑制反射波干擾。
        (二)上拉電阻阻值的選擇原則包括:
        1、從節約功耗及芯片的灌電流能力考慮應當足夠大;電阻大,電流小。
        2、從確保足夠的驅動電流考慮應當足夠小;電阻小,電流大。
        3、對于高速電路,過大的上拉電阻可能邊沿變平緩。綜合考慮
        以上三點,通常在1k到10k之間選取。對下拉電阻也有類似道理
        (三)對上拉電阻和下拉電阻的選擇應結合開關管特性和下級電路的輸入特性進行設定,主要需要考慮以下幾個因素:
        1. 驅動能力與功耗的平衡。以上拉電阻為例,一般地說,上拉電阻越小,驅動能力越強,但功耗越大,設計是應注意兩者之間的均衡。
        2.下級電路的驅動需求。同樣以上拉電阻為例,當輸出高電平時,開關管斷開,上拉電阻應適當選擇以能夠向下級電路提供足夠的電流。
        3.高低電平的設定。不同電路的高低電平的門檻電平會有不同,電阻應適當設定以確保能輸出正確的電平。以上拉電阻為例,當輸出低電平時,開關管導通,上拉電阻和開關管導通電阻分壓值應確保在零電平門檻之下。
        4.頻率特性。以上拉電阻為例,上拉電阻和開關管漏源級之間的電容和下級電路之間的輸入電容會形成RC延遲,電阻越大,延遲越大。上拉電阻的設定應考慮電路在這方面的需求。
        (四)下拉電阻的設定的原則和上拉電阻是一樣的。
        OC門輸出高電平時是一個高阻態,其上拉電流要由上拉電阻來提供,設輸入端每端口不大于100uA,設輸出口驅動電流約500uA,標準工作電壓是5V,輸入口的高低電平門限為0.8V(低于此值為低電平);2V(高電平門限值)。
        選上拉電阻時:
        500uA x 8.4K= 4.2即選大于8.4K時輸出端能下拉至0.8V以下,此為最小阻值,再小就拉不下來了。如果輸出口驅動電流較大,則阻值可減小,保證下拉時能低于0.8V即可。
        當輸出高電平時,忽略管子的漏電流,兩輸入口需200uA
        200uA x15K=3V即上拉電阻壓降為3V,輸出口可達到2V,此阻值為最大阻值,再大就拉不到2V了。選10K可用。COMS門的可參考74HC系列
        設計時管子的漏電流不可忽略,IO口實際電流在不同電平下也是不同的,上述僅僅是原理,一句話概括為:輸出高電平時要喂飽后面的輸入口,輸出低電平不要把輸出口喂撐了(否則多余的電流喂給了級聯的輸入口,高于低電平門限值就不可靠了)
        在數字電路中不用的輸入腳都要接固定電平,通過1k電阻接高電平或接地。
        1. 電阻作用:
        l 接電組就是為了防止輸入端懸空
        l 減弱外部電流對芯片產生的干擾
        l 保護cmos內的保護二極管,一般電流不大于10mA
        l 上拉和下拉、限流
        l 1. 改變電平的電位,常用在TTL-CMOS匹配
        2. 在引腳懸空時有確定的狀態
        3.增加高電平輸出時的驅動能力。
        4、為OC門提供電流
        l 那要看輸出口驅動的是什么器件,如果該器件需要高電壓的話,而輸出口的輸出電壓又不夠,就需要加上拉電阻。
        l 如果有上拉電阻那它的端口在默認值為高電平你要控制它必須用低電平才能控制如三態門電路三極管的集電極,或二極管正極去控制把上拉電阻的電流拉下來成為低電平。反之,
        l 尤其用在接口電路中,為了得到確定的電平,一般采用這種方法,以保證正確的電路狀態,以免發生意外,比如,在電機控制中,逆變橋上下橋臂不能直通,如果它們都用同一個單片機來驅動,必須設置初始狀態.防止直通!

        2、定義:
        l 上拉就是將不確定的信號通過一個電阻嵌位在高電平!電阻同時起限流作用!下拉同理!
        l 上拉是對器件注入電流,下拉是輸出電流
        l 弱強只是上拉電阻的阻值不同,沒有什么嚴格區分
        l 對于非集電極(或漏極)開路輸出型電路(如普通門電路)提升電流和電壓的能力是有限的,上拉電阻的功能主要是為集電極開路輸出型電路輸出電流通道。

        3、為什么要使用拉電阻:
        l 一般作單鍵觸發使用時,如果IC本身沒有內接電阻,為了使單鍵維持在不被觸發的狀態或是觸發后回到原狀態,必須在IC外部另接一電阻。
        l 數字電路有三種狀態:高電平、低電平、和高阻狀態,有些應用場合不希望出現高阻狀態,可以通過上拉電阻或下拉電阻的方式使處于穩定狀態,具體視設計要求而定!
        l 一般說的是I/O端口,有的可以設置,有的不可以設置,有的是內置,有的是需要外接,I/O端口的輸出類似與一個三極管的C,當C接通過一個電阻和電源連接在一起的時候,該電阻成為上C拉電阻,也就是說,如果該端口正常時為高電平,C通過一個電阻和地連接在一起的時候,該電阻稱為下拉電阻,使該端口平時為低電平,作用嗎:
        比如:當一個接有上拉電阻的端口設為輸如狀態時,他的常態就為高電平,用于檢測低電平的輸入。
        l 上拉電阻是用來解決總線驅動能力不足時提供電流的。一般說法是拉電流,下拉電阻是用來吸收電流的,也就是灌電流。

        高阻態:從邏輯器件內部電路結構來說,就是其輸出電阻很大,該狀態即不是高電平,也不是低電平。當三態門處于高阻態時,無論該門的輸入如何變化,都不會對其輸出有貢獻。

        高阻態時引腳對地電阻無窮,電阻大到類似開路。

        對于三態來說就是“0”,“1”,高阻態。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 社会| 霍林郭勒市| 英吉沙县| 荔波县| 兴海县| 杂多县| 陕西省| 云和县| 都兰县| 大埔县| 吴江市| 会理县| 乌拉特中旗| 怀集县| 呈贡县| 朝阳区| 定州市| 莱西市| 石城县| 衡阳市| 田林县| 利川市| 台前县| 肇东市| 长春市| 丹东市| 富平县| 双柏县| 台前县| 永和县| 西安市| 天等县| 灵石县| 璧山县| 鄂托克前旗| 称多县| 西乌珠穆沁旗| 顺义区| 宣城市| 雷山县| 酉阳|