新聞中心

AVR I/O口使用方法

作者: 時(shí)間:2013-12-10 來(lái)源:網(wǎng)絡(luò) 收藏

主控電路原理圖(點(diǎn)擊圖片放大,不需要放大鏡! )

LED控制電路原理圖(點(diǎn)擊圖片放大,不需要放大鏡! )
軟件設(shè)計(jì)

下面部分從TXT拷出,拷到網(wǎng)頁(yè),代碼部分缺省了很多空格,比較凌亂,請(qǐng)諒解!

//目標(biāo)系統(tǒng): 基于單片機(jī)
//應(yīng)用軟件: ICC
/*01010101010101010101010101010101010101010101010101010101010101010101
----------------------------------------------------------------------
實(shí) 驗(yàn)內(nèi)容:
點(diǎn)燈,讓燈左閃右閃,拼命閃。
----------------------------------------------------------------------
硬 件連接:
將PD口的LED指示燈使能開(kāi)關(guān)切換到"ON"狀態(tài)。
----------------------------------------------------------------------
注 意事項(xiàng):
(1)若有加載庫(kù)程序,請(qǐng)將光盤(pán)根目錄下的“庫(kù)程序”下的“ICC_H”文件夾拷到D盤(pán)
(2)請(qǐng)?jiān)敿?xì)閱讀:光盤(pán)根目錄下的“產(chǎn)品資料開(kāi) 發(fā)板實(shí)驗(yàn)板SMK系列SMK1632說(shuō)明資料”
----------------------------------------------------------------------
10101010101010101010101010101010101010101010101010101010101010101010*/

#include iom16v.h>
#include "D:ICC_HCmmICC.H"
#define LED_DDR DDRD
#define LED_PORT PORTD
/*--------------------------------------------------------------------
程 序名稱(chēng):
程序功能:
注意事項(xiàng):
提示說(shuō)明:
輸 入:
返 回:
--------------------------------------------------------------------*/
void main(void)
{
uint8 i,j;
LED_DDR=0XFF;
while(1)
{
for(i=0;i4;i++)
{
LED_PORT^=0xFF; //我閃!拚命閃!
delay50ms(10);
}
j=0x01;
for(i=0;i8;i++)
{
j=1;
LED_PORT=j; //我左閃!
delay50ms(10);
}
j=0x80;
for(i=0;i8;i++)
{
j>>=1;
LED_PORT=j; //我右閃!
delay50ms(10);
}
}
}

系統(tǒng)調(diào)試
本節(jié)的目的在于學(xué)習(xí)AVR的IO輸出功能,對(duì)于AVR來(lái)說(shuō),它和傳統(tǒng)的51單片機(jī)不 同,需要設(shè)置IO引腳方向。
作如下調(diào)試:
(1)改變IO方向,即將“LED_DDR=0XFF;”改為“0X00”,觀察現(xiàn)象。
(2) 將語(yǔ)句:delay50ms(10);改為語(yǔ)句:delay50ms(1);可以看到LED閃的更快,眼都花了!

東西在于靈活運(yùn)用,下面是用LED做的手表,內(nèi)部是用AVR,ATmega48做的,請(qǐng)思考實(shí)現(xiàn)如何下 面的功能。

AVR 單片機(jī)的是標(biāo)準(zhǔn)的雙向端口,首先要設(shè)置的狀態(tài),即:輸入還是輸出

DDRx就是AVR單片機(jī)的端口方向,通過(guò)設(shè)置DDRx可以設(shè)置x端口的狀態(tài)。
DDRx 端口方向相應(yīng)位設(shè)置為1則對(duì)應(yīng)的x端口相應(yīng)位為輸出狀態(tài),DDRx端口方向寄存器相應(yīng)位設(shè)置為0則對(duì)應(yīng)的x端口相應(yīng)位為輸入狀態(tài)。
例如:
DDRA = 0xFF; //設(shè)置端口A所有口為輸出狀態(tài),因?yàn)?xFF對(duì)應(yīng)的二進(jìn)制為11111111b

DDRA = 0x0F //設(shè)置端口A高4位為輸入狀態(tài),低4位為輸出狀態(tài),因?yàn)?x0F對(duì)應(yīng)的二進(jìn)制為00001111b


PORTx寄存器是AVR單片機(jī)的輸出寄存器,端口輸出狀態(tài)設(shè)定好后通過(guò)設(shè)置PORTx可以使 端口x的相應(yīng)位輸入高電平或低電平來(lái)控制外部設(shè)備。
例如:
PORTA = 0xFF; //端口A所有口線(xiàn)輸出高電平

PORTA = 0x0F; //端口A高4位輸出低電平,低4位輸出高電平

小貼士:
利用位邏輯運(yùn)算符對(duì)特定的端口進(jìn)行設(shè)定。

PORTA = 13; //端口A第4位置為高電平,其它為低電平,應(yīng)為00000001左移3位后是00001000
PORTA = 17; //同理,第8位置高電平

有時(shí)候我們期望端口某一位設(shè)置成高電平,但是其它位的高低電平要保持不變,如何做呢?C語(yǔ)言是很強(qiáng)大 的,有辦法!如下:

PORTA |=13; //實(shí)現(xiàn)端口A第4位置為高電平,其它位的高低電平不受影響
上面的語(yǔ)句是簡(jiǎn)化的寫(xiě)法,分解一下就是:
PORTA = PORTA | (13); //數(shù)字1左移3位后與端口A進(jìn)行按位或,結(jié)果就是端口A第4位置為高電平,其它位的高低電平不受影響

那么大家就會(huì)問(wèn)了,如何實(shí)現(xiàn)設(shè)置某一位為低電平,其它位的高低電平不變呢?建議大家思考1分鐘再看下面 的內(nèi)容。
PORTA =~(13); //解釋一下,首先將1左移3位變成00001000b,然后再按位取反變成11110111b,然后再與端口A做按位與運(yùn)算,這樣就實(shí)現(xiàn)了設(shè)置端口A第 4位為低電平,其它位的高低電平不變。
分解后的語(yǔ)句為:
PORTA = PORTA (~(13)); //結(jié)果是一樣的

將某端口相應(yīng)位的高低電平翻轉(zhuǎn),即原來(lái)高電平變?yōu)榈碗娖剑碗娖阶優(yōu)楦唠娖?,呵呵!好?jiǎn)單呦!

PORTA = ~PORTA; //將PORTA按位取反后再賦值給PORTA

按位邏輯運(yùn)算還有一個(gè)異或,這個(gè)也非常有意思,它能實(shí)現(xiàn)電平翻轉(zhuǎn),有興趣大家看看書(shū),算是給大家留個(gè)想 頭吧!

再出個(gè)小題目!
大家都知道已知a,b兩個(gè)變量,再編程中要交換兩個(gè)變量常用的方法是定義一個(gè)中 間變量c,然后:

c=a;
a=b;
b=c;

通過(guò)中間變量c完成a、b變量?jī)?nèi)容的交換!
不過(guò)大家想一想使用C語(yǔ)言能不能不用中間變量來(lái)完成 a、b變量的交換呢?答案肯定是能,因?yàn)镃語(yǔ)言很強(qiáng)大!
不過(guò)還是希望大家先想一想再看答案,看完答案后再認(rèn)真分析一下,體會(huì)編程的巧妙之處!
答 案:
使用到了C語(yǔ)言的按位異或邏輯操作,由于沒(méi)有中間變量,同時(shí)邏輯運(yùn)算的速度很快,整個(gè)交換過(guò)程比常規(guī)方法要快不少!

a ^= b;
b ^= a;
a ^= b;

過(guò)程就是a異或b,b異或a,然后a再異或b就完成了!

異或的邏輯表
1 ^ 1 0
0 ^ 1 1
1 ^ 0 1
0 ^ 0 0

adm 真厲害,這個(gè)你都知道,看來(lái)是編程的行家。

交換變量這樣的問(wèn)題,如果你沒(méi)看過(guò)相關(guān)的資料,初學(xué)者很難自己想出來(lái)的。

int a,b;

a=3;

b=5;

a=a+b //a=8 b=5

b=a-b //a=8 b=3

a=a-b //a=5 a=3

這樣僅僅是算法技巧的問(wèn)題,現(xiàn)在很難遇到內(nèi)存不夠 的情況了。

交換變量這樣的問(wèn)題,如果你沒(méi)看過(guò)相關(guān)的資料,初學(xué)者很難自己想出來(lái)的。

int a,b;
a=3;
b=5;

a=a+b //a=8 b=5
b=a-b //a=8 b=3
a=a-b //a......


又學(xué)一招,確實(shí)也很巧妙!有異曲同工之處。
我這些是看資料從別人那學(xué)來(lái)的,不過(guò)邏輯運(yùn) 算要比算術(shù)運(yùn)算快一倍以上,寫(xiě)了個(gè)程序在AVR Studio 中軟件仿真了一下!
程序如下:
#include iom16v.h>

void main (void)
{
int a=10,b=20;
unsigned char x=30,y=40;

a = a + b;
b = a - b;
a = a - b;

x ^= y;
y ^= x;
x ^= y;
while (1);
}
首先僅僅運(yùn)算,算術(shù)運(yùn)算用了8個(gè)時(shí)鐘單位,邏輯運(yùn)算用了3個(gè)時(shí)鐘單位,因?yàn)樗阈g(shù)運(yùn)算牽扯到了負(fù)數(shù)。
那變量賦值 呢,int 賦值用了4個(gè)時(shí)鐘單位,unsigned char賦值用了2個(gè)時(shí)鐘單位。
綜合一下,算術(shù)運(yùn)算用時(shí)12個(gè)單位,邏輯運(yùn)算用時(shí)5個(gè)單位,效率要高 2.4倍! 項(xiàng)目編譯完后會(huì)生成一個(gè).cof的調(diào)試文件(我是用ICC,CV應(yīng)該也有),用AVR Studio打開(kāi)這個(gè).cof文件,選好處理器型號(hào)(M16)就會(huì)進(jìn)入軟件仿真,按Alt+O快捷鍵設(shè)置處理器的頻率,這樣可以看運(yùn)行的時(shí)間,否則只能看 運(yùn)行時(shí)鐘,時(shí)間就不準(zhǔn)了。再下來(lái)就是按F11單步執(zhí)行,F(xiàn)10是一下執(zhí)行完一個(gè)過(guò)程,如:循環(huán)、函數(shù)等。時(shí)鐘和運(yùn)行時(shí)間可以在任意時(shí)間用鼠標(biāo)右鍵清零,這 樣數(shù)字比較直觀,不用再加減。

c語(yǔ)言相關(guān)文章:c語(yǔ)言教程



上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: AVR IO口 寄存器

評(píng)論


相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉