BlackfinDSP的寄存器是通過指針操作的,與51、ARM等MCU一樣,通過“或”操作來置1,通過“與”操作清零。
在DSP上最簡單的外設非IO口莫屬,但是由於其功能強大,遠非一般IO口可比,因此區別的稱之為“GPIO”(general purpose IO),也稱為PF(programmable flagas)口,本文通過GPIO控制LED來演示寄存器的操作方式。
//=============== 開發環境 ======================
上位機: win7 旗艦版
DSP環境: CCES1.0.2 (用Blackfin DSP第一節:新建工程一文中的Visual DSP++完全一樣)
開發板 : ADSP-BF561 EZKIT(用561的原因是,手頭的533EZKIT的GPIO連接到了FLASH上,想驅動LED,必須先對FLASH進行操作,比較麻煩,以后會盡量采 用533,雖然用561,但是操作方式是一致的,只不過寄存器的定義不同)
//================ 原理圖 =====================
由圖可見,LED1~LED8分別連接在PF40~PF47口,當PFx輸出為高電平時,可點亮相應的LED。
//================ 寄存器定義 =====================
1.方向寄存器(參考Hardware reference)
首先,必須將PFx的方向設置為輸出;
2.設置輸出電平
輸出高電平是通過FLAG_SET寄存器來進行設置的,在相應的位寫1,即可設置為高電平。定義如下:
輸出低電平是通過FLAG_CLEAR寄存器實現,寫1清除相應的端口電平值。(圖就不貼了)
//=================== 寄存器的操作 ======================
blackfin系列的寄存器定義都是在安裝目錄下的cdefbf5xx.h中定義的,為此,在程序的開始部分要包含相應的頭文件。比如cdefbf561.h包含了所有561寄存器的定義:
…… #define pFIO2_FLAG_D ((volatile unsigned short *)FIO2_FLAG_D) #define pFIO2_FLAG_C ((volatile unsigned short *)FIO2_FLAG_C) #define pFIO2_FLAG_S ((volatile unsigned short *)FIO2_FLAG_S) #define pFIO2_FLAG_T ((volatile unsigned short *)FIO2_FLAG_T) ……
#define FIO2_FLAG_D 0xFFC01700 /* Flag Data register (mask used to directly */ #define FIO2_FLAG_C 0xFFC01704 /* Flag Clear register */ #define FIO2_FLAG_S 0xFFC01708 /* Flag Set register */ #define FIO2_FLAG_T 0xFFC0170C /* Flag Toggle register (mask used to */
這是一個地址指針,因此可以直接當作指針來操作,比如置1操作如下:
*pFIO2_DIR |= 0xFF00; /*將pFIO2_DIR的高8位置為1*/
//=================== 代碼示例=======================
以下代碼中包含了GPIO的輸出、輸入、反轉 這三個功能的設置方法,對於其它功能,可以查看硬件手冊。
#include <cdefbf561.h> /* C POINTERS TO SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF561 */ #include <adi_types.h> /* type defines */ #include <ccblkfn.h> /* include the async() function prototype */ void TurnOnLed(uint8_t nLed); void msDelay(uint32_t msec) ; void TurnOffAllLed(void); void ToggleLed(uint8_t nLed); void delay(int i); void main(void) { TurnOnLed(1); // 打開LED1 (PF40) TurnOnLed(2); // 打開LED2 (PF41) msDelay(100); TurnOffAllLed(); // 關閉所有LED TurnOnLed(1); // 打開LED1 (PF40) TurnOnLed(2); // 打開LED2 (PF41) msDelay(100); TurnOffAllLed(); // 關閉所有LED while(1) //blink { ToggleLed(1); //翻轉LED msDelay(100); } } /* GPIO as output */ void TurnOnLed(uint8_t nLed) { *pFIO2_DIR |= 0xFF00; /*set PF40~PF47 as output */ ssync(); *pFIO2_FLAG_S = ( 1 << (nLed+7) ); /*set the corresponding bit in FLAG_SET register as high*/ ssync(); } /* GPIO as input */ void TurnOffAllLed(void) { *pFIO2_DIR |= 0xFF00; /*set PF40~PF47 as output */ ssync(); *pFIO2_FLAG_C = 0xFF00; /*set Flag_clear register to clear the PFx */ ssync(); } /* Toggle GPIO */ void ToggleLed(uint8_t nLed) { *pFIO2_DIR |= 0xFF00; ssync(); *pFIO2_FLAG_T = (1 << (nLed+7) ); // write 1 to toggle ssync(); } /********************************************************************* Function: ezDelay Description: Delays for approximately 1 msec when running at 600 MHz *********************************************************************/ void msDelay(uint32_t msec) { volatile uint32_t i,j; // value of 0x3000000 is about 1 sec so 0xc49b is about 1msec for (j = 0; j < msec; j++) { for (i = 0; i < 0xc49b; i++) ; } }
P.S:要想用好DSP,首先最重要的就是把寄存器的定義讀懂,那Hardware reference 必不可少,做到哪都到哪,才能有所領悟~不看手冊,那是不行地。。。