官术网_书友最值得收藏!

第3章 流水燈重現(xiàn)——第一次操刀

第2章向讀者介紹了幾個工具(在以后的章節(jié)中會運(yùn)用到),本章主要是跟大家一起來學(xué)習(xí)AVR單片機(jī)的I/O相關(guān)知識并運(yùn)用——重現(xiàn)流水燈。讓咱們從現(xiàn)在開始真正踏上單片機(jī)之路吧!

3.1 I/O簡述

本節(jié)將對AVR單片機(jī)的I/O相關(guān)知識進(jìn)行介紹,并和5 1單片機(jī)的I/O進(jìn)行比較。這里具體介紹的類型是ATmega88V。

3.1.1 I/O寄存器

AVR單片機(jī)的I/O框圖如圖3.1所示。

圖3.1 AVR單片機(jī)的I/O框圖

AVR單片機(jī)的所有I/O端口都具有讀/寫修改功能,可以輸出或吸收大電流,并直接驅(qū)動LED。每個I/O端口都有3個寄存器(用來設(shè)置讀/寫操作),分別為數(shù)據(jù)寄存器PORTx、數(shù)據(jù)方向寄存器DDRx和端口輸入引腳寄存器PINx。其中數(shù)據(jù)寄存器和數(shù)據(jù)方向寄存器為讀/寫寄存器,而端口輸入引腳寄存器為只讀寄存器。將數(shù)據(jù)方向寄存器清零,數(shù)據(jù)寄存器置位,再將寄存器MCUCR(MCU控制寄存器)的PUD位置位,可使I/O端口處于高阻態(tài)。

ATmega88V有23個可編程的I/O端口,其中PORTB、PORTC和PORTD分別有7個、6個和7個I/O引腳,對于一般的應(yīng)用來說是足夠的。在運(yùn)用過程中,不一定所有的I/O引腳都會使用到。如果有引腳未被使用,建議給其一個確定電平。例如,在一般情況下,初始化設(shè)備時,應(yīng)將所有I/O端口統(tǒng)統(tǒng)設(shè)置一次,以確保I/O端口工作在已知的狀態(tài)下。

另外,大多數(shù)I/O端口都具有第二功能。

3.1.2 與51單片機(jī)的比較

使用AVR單片機(jī)時,需要設(shè)置I/O端口的方向,如果不設(shè)置,將以默認(rèn)的狀態(tài)存在。而51單片機(jī)的I/O端口是準(zhǔn)雙向輸出類型的。準(zhǔn)雙向輸出類型可用做輸出和輸入功能而不需要重新配置I/O端口的方向。5 1單片機(jī)的I/O端口只有一個寄存器Px。

舉例說明:需要設(shè)置某個I/O端口為輸出高電平,則AVR單片機(jī)需要設(shè)置DDRx和PORTx 2個寄存器;而5 1單片機(jī)只需要設(shè)置Px為高即可。對于輸入,AVR單片機(jī)仍需要設(shè)置2個寄存器,而5 1單片機(jī)直接讀取Px的值即可。

在此做這個比較,是為了讓讀者了解AVR單片機(jī)與5 1單片機(jī)I/O端口設(shè)置的不同,在編寫程序時,這是需要特別注意的地方,尤其是對于剛從5 1單片機(jī)轉(zhuǎn)過來準(zhǔn)備學(xué)習(xí)AVR單片機(jī)的工程師而言。長時間使用一款單片機(jī)會導(dǎo)致工程師將很多編寫習(xí)慣不知不覺地用在其他單片機(jī)上,這是大部分工程師都會犯的錯誤。

3.2 讓流水燈動起來

在很多不同種類的單片機(jī)教程中都是以流水燈作為第一個實驗的,最為突出的是在51單片機(jī)的教程中。這里也以它為例進(jìn)行介紹。

3.2.1 流水燈程序

流水燈程序用于實現(xiàn)對PD口下的8個LED燈進(jìn)行操作:每500ms亮一個,當(dāng)全部燈點亮后,每500ms滅一個,如此重復(fù)。這里還沒接觸到定時器的相關(guān)知識,因此可以使用庫文件來實現(xiàn)延時500ms,不過由于該延時不是很準(zhǔn)確,所以需要在代碼工程中的2個地方做相應(yīng)的設(shè)置:在源文件中添加#include<util/delay.h>;在工程選項中寫入當(dāng)前使用的晶振頻率,如圖3.2所示。圖3.2中給出了一些重要信息,如工程所選擇的器件型號“atmega88”,使用的晶振頻率為“7372800”,優(yōu)化級別默認(rèn)為-0s。優(yōu)化級別有以下幾種。

(1)-00:無優(yōu)化。

(2)-01:減少代碼尺寸和執(zhí)行時間,不進(jìn)行需要大量編譯時間的優(yōu)化。

(3)-02:幾乎執(zhí)行所有優(yōu)化,而不考慮代碼大小和執(zhí)行時間。

(4)-03:執(zhí)行“-02”所有的優(yōu)化及內(nèi)聯(lián)函數(shù),重命名寄存器的優(yōu)化。

(5)-0s:針對代碼大小的優(yōu)化,執(zhí)行所有“-02”優(yōu)化而不增加代碼的大小。

開發(fā)時,應(yīng)選擇適合自己的一個優(yōu)化級別。圖3.2中框選標(biāo)出的1 ~4這4個復(fù)選框的意義依次如下:

(1)所有char認(rèn)為是unsined char;

(2)所有bitfields認(rèn)為是unsigned;

(3)定義結(jié)構(gòu)體時,連續(xù)存儲;

(4)定義枚舉類型時,使用最大需要的存儲空間。

圖3.2 工程選項

流水燈程序如下:

            /**********************************************
            project:流水燈工程
            IDE:AVR Studio 4+Winavr20070525
            device:atmega88
            author:lg
            date:2012-07-11 21:10
            Goal:點亮LED,掌握GPIO的運(yùn)用
            ***********************************************/
            #include "main.h"
            /*****************************
                設(shè)備初始化
            *****************************/
            void DEVICE_init(void)
            {
                //----------PB口
                DDRB=0X00;     //未使用也定義
                PORTB=0X00;
                //----------PC口
                DDRC=0X00;   //未使用也定義
                PORTC=0X00;
                //----------PD口
                DDRD| =0XFF;  //設(shè)置PD口的0~7口方向為輸出
                PORTD=0X00;  //設(shè)置PD口的0~3口電平為低
            }
            //----------------------MAIN-----------------------
            int main(void)
            {
                //------設(shè)備初始化
                DEVICE_init();
                //-----------循環(huán)-----------
                while(1)
                {
                //-------------點亮LED0~7----------------
                    PORTD| =_BV(0);        //點亮LED0
                    _delay_ms(500);         //延時500ms
                    PORTD| =_BV(1);        //點亮LED1
                    _delay_ms(500);
                    PORTD| =_BV(2);        //點亮LED2
                    _delay_ms(500);
                    PORTD| =_BV(3);        //點亮LED3
                    _delay_ms(500);
                    PORTD| =_BV(4);        //點亮LED4
                    _delay_ms(500);
                    PORTD| =_BV(5);        //點亮LED5
                    _delay_ms(500);
                    PORTD| =_BV(6);        //點亮LED6
                    _delay_ms(500);
                    PORTD| =_BV(7);        //點亮LED7
                    _delay_ms(500);
                //-------------滅掉LED0~7----------------
                    PORTD&=~_BV(0);       //點亮LED0
                    _delay_ms(500);         //延時500ms
                    PORTD&=~_BV(1);       //點亮LED1
                    _delay_ms(500);
                    PORTD&=~_BV(2);       //點亮LED2
                    _delay_ms(500);
                    PORTD&=~_BV(3);       //點亮LED3
                    _delay_ms(500);
                    PORTD&=~_BV(4);      //點亮LED4
                    _delay_ms(500);
                    PORTD&=~_BV(5);      //點亮LED5
                    _delay_ms(500);
                    PORTD&=~_BV(6);      //點亮LED6
                    _delay_ms(500);
                    PORTD&=~_BV(7);      //點亮LED7
                    _delay_ms(500);
                }
            }

在這里有一個地方需要注意,就是_BV是在sfr_defs.h中定義的,其定義為#define _BV (bit)(1 <<(bit))。當(dāng)沒有其他編譯,而在移植時希望盡可能減少修改量時,就可以將該定義添加到代碼中。

3.2.2 流水燈重現(xiàn)

流水燈最早是用5 1單片機(jī)實現(xiàn)的,這里將其在AVR單片機(jī)上重現(xiàn)。由于沒有實際的板子,故這里采用仿真軟件來實現(xiàn)。

下面根據(jù)前面介紹的Proteus的運(yùn)用,重新建立一個流水燈的工程。首先添加MCU、晶振、電阻、電壓表和示波器。在這里,電壓表用來查看引腳的電壓,示波器用來觀察各個引腳的延時。仿真電路如圖3.3所示。注意:仿真電路跟實際電路是有區(qū)別的,如仿真電路中的晶振需要接2個匹配的負(fù)載電容。

圖3.3 仿真電路

然后向MCU添加流水燈程序的可執(zhí)行文件,并將晶振的頻率設(shè)置為7.3728MHz,其他根據(jù)需要進(jìn)行相應(yīng)的設(shè)置。完成一系列設(shè)置后,單擊界面右下角中的,開始仿真,如圖3.4所示。從圖中可以看到電壓表的值一直在變化(從0到3.3V變化),說明I/O端口在來回不停地被置高清零。還可以通過示波器來查看仿真結(jié)果。一個示波器只能有4個輸入源,則8個I/O端口需要使用2個示波器。在仿真中選中示波器后單擊鼠標(biāo)右鍵,再單擊“Digital Oscilloscope”,會彈出如圖3.5所示的界面。

圖3.4 仿真界面

圖3.5 虛擬示波器界面1

在圖3.5中顯示出了4條不同顏色的線,黃色、藍(lán)色、紅色、綠色(從上到下)分別對應(yīng)的是PD0、PD1、PD2和PD3。界面的右側(cè)是示波器的相關(guān)設(shè)置,4個通道選擇的都是DC源,電壓單位是1 V/格,掃描時間為50ms/格。將掃描時間調(diào)整為20ms/格,如圖3.6所示,這樣就比較容易看出延時的間隔。3.2.1節(jié)介紹的流水燈程序中實現(xiàn)的是500ms的間隔,而從圖3.6中得到的只有40ms左右的一個間隔,與程序要求相差太多,但是在這里先不做調(diào)整,只是簡單地給讀者介紹一下這個可以用來測量程序中所要求的時序的工具而已。實際中也有類似的工具,可以用來代替示波器,如邏輯分析儀,其在價格和使用方面都是比較適合單片機(jī)工程師的。在程序運(yùn)行過程中可以看到LED0 ~LED7不停地來回亮滅,這樣流水燈便得以重現(xiàn)了。如果你手上有硬件調(diào)試板,則可以直接在板上運(yùn)行以查看效果。

圖3.6 虛擬示波器界面2

3.3 小結(jié)

本章對AVR單片機(jī)的I/O相關(guān)知識做了一些簡單敘述,并通過實際程序工程來說明了I/O端口的一些設(shè)置及運(yùn)用。本章還回顧了第2章提到的Proteus軟件的運(yùn)用,并且簡單介紹了如何運(yùn)用它來查看程序所實現(xiàn)的功能。希望讀者在程序運(yùn)行過程中積累出一套屬于自己的調(diào)整步驟或方法。

主站蜘蛛池模板: 富平县| 长岛县| 德保县| 如东县| 白玉县| 绿春县| 鹿泉市| 伊宁市| 奈曼旗| 时尚| 信丰县| 赫章县| 台东县| 兴城市| 林芝县| 咸宁市| 乌苏市| 合作市| 定兴县| 唐山市| 嘉荫县| 金川县| 白水县| 柯坪县| 安溪县| 雷州市| 清水县| 巢湖市| 韩城市| 赤峰市| 马山县| 高雄县| 阿拉善盟| 双江| 莱阳市| 河东区| 宁安市| 张家港市| 阿城市| 徐水县| 竹北市|