20141227 【 RFID 2.4GHz 讀寫器及標籤程式碼 】
阿新 • • 發佈:2019-02-17
結構:
AppDemo /* 讀寫器及標籤應用功能實現 */
RFID_2.4GHz_Reader_Demo.c // RFID的2.4G讀寫器應用程式
RFID_2.4GHz_Tag_Demo.c // RFID的2.4G標籤應用程式
READER /* 讀寫器及標籤硬體驅動 */
hal_2.4GHz_Reader.c // RFID的2.4G讀寫器硬體層驅動
hal_2.4GHz_Tag.c // RFID的2.4G標籤硬體層驅動
SYSCLK /* 系統時鐘 */
SYSCLK.c // MCU時鐘選擇
UART0 /* 串列埠通訊UART0驅動 */
UART0.c // CC2530的 UART0驅動
/******************************************************************************* * 檔名稱:RFID_2.4GHz_Reader_Demo.c * 功 能:RFID基礎實驗工程 --- 2.4GHz RFID 讀卡器演示 * 將接收到的Tag資訊通過CC2530的UART0輸出,波特率為115200 * 作 者: * 公 司: ******************************************************************************/ #if !defined ( TAG_FLAG ) /* 包含標頭檔案 */ /*************************************************************/ #include "hal_2.4GHz_Reader.h" // RFID-2.4GHz-Reader硬體抽象層標頭檔案 #include "UART0.h" // CC2530的UART0驅動的標頭檔案 #include "SYSCLK.h" // CC2530的時鐘選擇標頭檔案 #include "stdlib.h" // C語言標準庫檔案 #include "stdio.h" // C語言標準輸入/輸出庫檔案 /*************************************************************/ /* RFID Reader的資料管道0接收地址為"READR" */ /*************************************************************/ unsigned char RFID_READER_ADDR_P0[] = {'R', 'D', 'A', 'E', 'R'}; /*************************************************************/ /* XXTEA加密塊數量 */ /*************************************************************/ #define TEA_ENCRYPTION_BLOCK_COUNT 4 /*************************************************************/ /* XXTEA金鑰 */ /*************************************************************/ const long XXTEA_KEY[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; /*************************************************************/ /* XXTEA演算法相關變數和巨集定義 */ /*************************************************************/ unsigned long z, y, sum, tmp, mx; unsigned char e; #define TEA_ROUNDS_COUNT (6+52/4) #define MX ((((z>>5)^(y<<2))+((y>>3)^(z<<4)))^((sum^y)+(XXTEA_KEY[(p&3)^e]^z))) #define DELTA 0x9E3779B9 /*************************************************************/ /* 資料包結構體型別 */ /*************************************************************/ typedef struct { unsigned char len; // 資料包的長度欄位(單位:位元組) unsigned char protocol; // 資料包的協議型別欄位 unsigned char flags; // 資料包的標誌欄位(按下Tag上的按鍵,flag為0x02;否則為0x00) unsigned char txpower; // 資料包的傳送功率欄位 unsigned long seq; // 資料包的序號欄位 unsigned long oid; // 資料包的物件識別符號欄位 unsigned short reserved; // 資料包的保留欄位 unsigned short crc; // 資料包的CRC欄位 }PKT; /*************************************************************/ /* 加密資料包結構體型別 */ /*************************************************************/ typedef union { PKT pkt; unsigned long dataUL[TEA_ENCRYPTION_BLOCK_COUNT]; unsigned char dataB[TEA_ENCRYPTION_BLOCK_COUNT * sizeof (unsigned long)]; }ENCRYPTED_PKT; /*************************************************************/ /* 用於Tag的加密資料包結構體變數 */ /*************************************************************/ static ENCRYPTED_PKT g_Tag; /*************************************************************/ /* "打亂"功能巨集 — SHUFFLE */ /*************************************************************/ #define SHUFFLE(a,b) tmp = g_Tag.dataB[a];\ g_Tag.dataB[a] = g_Tag.dataB[b];\ g_Tag.dataB[b] = tmp; /*************************************************************/ /********************************************************************* * 函式名稱:htonl * 功 能:將主機位元組順序表達的32位無符號長整形數轉換成網路位元組順序 * 表達的32位無符號長整形數 * 入口引數:hostlong 主機位元組順序表達的32位無符號長整形數 * 出口引數:無 * 返 回 值:網路位元組順序表達的32位無符號長整形數 ********************************************************************/ static unsigned long htonl (unsigned long hostlong) { unsigned long res; ((unsigned char *) &res)[0] = ((unsigned char *) &hostlong)[3]; ((unsigned char *) &res)[1] = ((unsigned char *) &hostlong)[2]; ((unsigned char *) &res)[2] = ((unsigned char *) &hostlong)[1]; ((unsigned char *) &res)[3] = ((unsigned char *) &hostlong)[0]; return res; } /********************************************************************* * 函式名稱:htons * 功 能:將主機位元組順序表達的16位無符號短整形數轉換成網路位元組順序 * 表達的16位無符號短整形數 * 入口引數:hostlong 主機位元組順序表達的16位無符號短整形數 * 出口引數:無 * 返 回 值:網路位元組順序表達的16位無符號短整形數 ********************************************************************/ static unsigned short htons (unsigned short hostshort) { unsigned short res; ((unsigned char *) &res)[0] = ((unsigned char *) &hostshort)[1]; ((unsigned char *) &res)[1] = ((unsigned char *) &hostshort)[0]; return res; } /********************************************************************* * 函式名稱:Shuffle_TX_ByteOrder * 功 能:"打亂"待發送資料的位元組順序 * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ static void Shuffle_TX_ByteOrder (void) { unsigned char tmp; SHUFFLE (0 + 0, 3 + 0); SHUFFLE (1 + 0, 2 + 0); SHUFFLE (0 + 4, 3 + 4); SHUFFLE (1 + 4, 2 + 4); SHUFFLE (0 + 8, 3 + 8); SHUFFLE (1 + 8, 2 + 8); SHUFFLE (0 + 12, 3 + 12); SHUFFLE (1 + 12, 2 + 12); } /********************************************************************* * 函式名稱:CRC16 * 功 能:CRC16計算 * 入口引數:buffer 指向儲存待進行CRC16計算的資料的緩衝區的指標 * size 待進行CRC16計算的資料的長度 * 出口引數:無 * 返 回 值:CRC16計算結果 * 注 意:CC2530自身帶有CRC計算功能,但為了提高程式碼的可移植性,我們 * 不使用CC2530自身帶有的CRC計算功能,而使用該函式。 ********************************************************************/ static unsigned short CRC16 (const unsigned char *buffer, unsigned char size) { unsigned short crc = 0xFFFF; if(buffer) { while(size--) { crc = (crc >> 8) | (crc << 8); crc ^= *buffer++; crc ^= ((unsigned char) crc) >> 4; crc ^= crc << 12; crc ^= (crc & 0xFF) << 5; } } return crc; } /********************************************************************* * 函式名稱:MX_Update * 功 能:XXTEA演算法的MX更新 * 入口引數:p * 出口引數:無 * 返 回 值:無 ********************************************************************/ static void MX_Update (unsigned char p) { mx = MX; } /********************************************************************* * 函式名稱:MX_Decode * 功 能:XXTEA演算法的MX解碼 * 入口引數:p * 出口引數:無 * 返 回 值:無 ********************************************************************/ static void MX_Decode (unsigned char p) { MX_Update (p); y = tmp - mx; } /********************************************************************* * 函式名稱:MX_Decode * 功 能:XXTEA解碼 * 入口引數:p * 出口引數:無 * 返 回 值:無 ********************************************************************/ void XXTEA_Decode (void) { y = g_Tag.dataUL[0]; sum = DELTA * TEA_ROUNDS_COUNT; while (sum != 0) { e = sum >> 2 & 3; z = g_Tag.dataUL[2]; tmp = g_Tag.dataUL[3]; MX_Decode (3); g_Tag.dataUL[3] = y; z = g_Tag.dataUL[1]; tmp = g_Tag.dataUL[2]; MX_Decode (2); g_Tag.dataUL[2] = y; z = g_Tag.dataUL[0]; tmp = g_Tag.dataUL[1]; MX_Decode (1); g_Tag.dataUL[1] = y; z = g_Tag.dataUL[3]; tmp = g_Tag.dataUL[0]; MX_Decode (0); g_Tag.dataUL[0] = y; sum -= DELTA; } } void changeToAscii (unsigned char *pUString, unsigned char teData) { unsigned char temp8i; temp8i = teData >> 4; if ( temp8i < 0x0a) *pUString = temp8i + 0x30; else *pUString = temp8i + 0x37; pUString++; temp8i = teData & 0x0f; if ( temp8i < 0x0a) *pUString = temp8i + 0x30; else *pUString = temp8i + 0x37; } /********************************************************************* * 函式名稱:InitNRF4Reader * 功 能:針對RFID Reader功能初始化nRF24L01+ * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ void InitNRF4Reader(void) { hal_nrf_nop(); hal_nrf_write_reg(CONFIG, 0x00); hal_nrf_write_reg(EN_AA, 0x00); hal_nrf_write_reg(SETUP_AW, 0x03); hal_nrf_set_address(HAL_NRF_PIPE0, RFID_READER_ADDR_P0); hal_nrf_write_reg(EN_RXADDR, 0x01); hal_nrf_write_reg(RX_PW_P0, 16); hal_nrf_write_reg(RF_CH, 81); hal_nrf_write_reg(STATUS, 0x70); hal_nrf_write_reg(CONFIG, 0x01); } /********************************************************************* * 函式名稱:calcFCS * 功 能:該函式用來驗證GPS資料FCS校驗和。 * 入口引數:pBuf 指向被校驗的資料 * len 資料長度 * 出口引數:無 * 返 回 值:無 ********************************************************************/ unsigned char calcFCS(unsigned char *pBuf, unsigned char len) { unsigned char rtrn = 0; while (len--) { rtrn ^= *pBuf++; } return rtrn; } /********************************************************************* * 函式名稱:main * 功 能:2.4GHz RFID 讀卡器演示 * 將接收到的Tag資訊通過CC2530的UART0輸出,波特率為115200 * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ int main(void) { /* 定義相關變數 */ unsigned char i; unsigned short crc; unsigned long oid; unsigned char uartString[64]; /* 選擇32MHz晶體振盪器作為系統時鐘源(主時鐘源) */ SystemClockSourceSelect(XOSC_32MHz); /* RFID-2.4GHz-Reader硬體抽象層初始化 */ hal_2G4Hz_Reader_Init(); /* UART0初始化 */ InitUART0(); /* LED1和LED2閃爍指定次數 */ for(i = 0; i <= 20; i++) { if(i & 1) { HAL_2G4Hz_LED1_TURN_ON(); HAL_2G4Hz_LED2_TURN_ON(); } else { HAL_2G4Hz_LED1_TURN_OFF(); HAL_2G4Hz_LED2_TURN_OFF(); } CC2530SleepTimer_Delay(100); } /* 針對RFID Reader功能初始化nRF24L01+ */ InitNRF4Reader(); /* 永久迴圈 */ while(1) { hal_nrf_set_power_mode(HAL_NRF_PWR_UP); CC2530SleepTimer_Delay(RF_POWER_UP_DELAY); HAL_2G4Hz_CE = 1; SetCC2530PowerMode(2); /* 點亮LED1 */ HAL_2G4Hz_LED1_TURN_ON(); /* 讀取接收到的資料 */ for(i = 0; i < 16; i++) { g_Tag.dataB[i] = Radio_Get_Pload_Byte(i); } /* 解碼接收到的資料 */ Shuffle_TX_ByteOrder(); XXTEA_Decode(); Shuffle_TX_ByteOrder(); /* 校驗接收到的資料 */ crc = CRC16(g_Tag.dataB, sizeof(g_Tag.pkt) - sizeof (g_Tag.pkt.crc)); /* 接收到的g_Tag資料包CRC16校驗錯誤 */ if(htons(g_Tag.pkt.crc) != crc) { /* 使用者自行處理 */ } /* 接收到的g_Tag資料包CRC16校驗正確 */ else { /* 點亮LED2 */ HAL_2G4Hz_LED2_TURN_ON(); /* 從CC2530的UART0輸出接收到來自Tag的資訊 */ oid = htonl(g_Tag.pkt.oid); // sprintf(uartString,"OID:%08lx\nTX power:%d\nButton push:%d\n\n", oid, g_Tag.pkt.txpower, g_Tag.pkt.flags); uartString[0] = 0x5a; uartString[1] = 14; uartString[2] = 0;//g_Tag.dataB[7]; uartString[3] = 0x01; uartString[4] = 0x0a; changeToAscii (&uartString[5], g_Tag.dataB[8]); changeToAscii (&uartString[7], g_Tag.dataB[9]); changeToAscii (&uartString[9], g_Tag.dataB[10]); changeToAscii (&uartString[11], g_Tag.dataB[11]); uartString[13] = g_Tag.dataB[2]; uartString[14] = calcFCS(&uartString[1], 13); uartString[15] = 0xa5; uartString[16] = 0; UART0SendString((unsigned char *)uartString, 16); } /* 設定nrf24L01+的RF為IDLE */ Radio_Set_Status(RF_IDLE); /* 熄滅LED1和LED2 */ HAL_2G4Hz_LED1_TURN_OFF(); HAL_2G4Hz_LED2_TURN_OFF(); } } #endif
/******************************************************************************* * 檔名稱:RFID_2.4GHz_Tag_Demo.c * 功 能:RFID基礎實驗工程 --- 2.4GHz RFID 的Tag * 作 者: * 公 司: ******************************************************************************/ #if defined ( TAG_FLAG ) /* 包含標頭檔案 */ /*************************************************************/ #include "hal_2.4GHz_Tag.h" // RFID-2.4GHz-Tag硬體抽象層標頭檔案 #include "SYSCLK.h" // CC2530的時鐘選擇標頭檔案 #include "stdlib.h" // C語言標準庫檔案 #include "stdio.h" // C語言標準輸入/輸出庫檔案 /*************************************************************/ unsigned char keyFlag; unsigned int txNumber; /* RFID Reader的資料管道0接收地址為"READR" */ /*************************************************************/ unsigned char RFID_READER_ADDR_P0[] = {'R', 'D', 'A', 'E', 'R'}; /*************************************************************/ /* XXTEA加密塊數量 */ /*************************************************************/ #define TEA_ENCRYPTION_BLOCK_COUNT 4 /*************************************************************/ #define DATA_LONG 0x10 #define DATA_PROTOCOL 0x01 /* XXTEA金鑰 */ /*************************************************************/ const long XXTEA_KEY[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; /*************************************************************/ /* XXTEA演算法相關變數和巨集定義 */ /*************************************************************/ unsigned long z, y, sum, tmp, mx; unsigned char e; #define TEA_ROUNDS_COUNT (6+52/4) #define MX ((((z>>5)^(y<<2))+((y>>3)^(z<<4)))^((sum^y)+(XXTEA_KEY[(p&3)^e]^z))) #define DELTA 0x9E3779B9 /*************************************************************/ #define KEYDELAY 80 /* 資料包結構體型別 */ /*************************************************************/ typedef struct { unsigned char len; // 資料包的長度欄位(單位:位元組) unsigned char protocol; // 資料包的協議型別欄位 unsigned char flags; // 資料包的標誌欄位(按下Tag上的按鍵,flag為0x02;否則為0x00) unsigned char txpower; // 資料包的傳送功率欄位 unsigned long seq; // 資料包的序號欄位 unsigned long oid; // 資料包的物件識別符號欄位 unsigned short reserved; // 資料包的保留欄位 unsigned short crc; // 資料包的CRC欄位 }PKT; /*************************************************************/ /* 加密資料包結構體型別 */ /*************************************************************/ typedef union { PKT pkt; unsigned long dataUL[TEA_ENCRYPTION_BLOCK_COUNT]; unsigned char dataB[TEA_ENCRYPTION_BLOCK_COUNT * sizeof (unsigned long)]; }ENCRYPTED_PKT; /*************************************************************/ /* 用於Tag的加密資料包結構體變數 */ /*************************************************************/ static ENCRYPTED_PKT g_Tag; /*************************************************************/ /* "打亂"功能巨集 — SHUFFLE */ /*************************************************************/ #define SHUFFLE(a,b) tmp = g_Tag.dataB[a];\ g_Tag.dataB[a] = g_Tag.dataB[b];\ g_Tag.dataB[b] = tmp; /*************************************************************/ /********************************************************************* * 函式名稱:Shuffle_TX_ByteOrder * 功 能:"打亂"待發送資料的位元組順序 * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ static void Shuffle_TX_ByteOrder (void) { unsigned char tmp; SHUFFLE (0 + 0, 3 + 0); SHUFFLE (1 + 0, 2 + 0); SHUFFLE (0 + 4, 3 + 4); SHUFFLE (1 + 4, 2 + 4); SHUFFLE (0 + 8, 3 + 8); SHUFFLE (1 + 8, 2 + 8); SHUFFLE (0 + 12, 3 + 12); SHUFFLE (1 + 12, 2 + 12); } /********************************************************************* * 函式名稱:CRC16 * 功 能:CRC16計算 * 入口引數:buffer 指向儲存待進行CRC16計算的資料的緩衝區的指標 * size 待進行CRC16計算的資料的長度 * 出口引數:無 * 返 回 值:CRC16計算結果 * 注 意:CC2530自身帶有CRC計算功能,但為了提高程式碼的可移植性,我們 * 不使用CC2530自身帶有的CRC計算功能,而使用該函式。 ********************************************************************/ static unsigned short CRC16 (const unsigned char *buffer, unsigned char size) { unsigned short crc = 0xFFFF; if(buffer) { while(size--) { crc = (crc >> 8) | (crc << 8); crc ^= *buffer++; crc ^= ((unsigned char) crc) >> 4; crc ^= crc << 12; crc ^= (crc & 0xFF) << 5; } } return crc; } /********************************************************************* * 函式名稱:XXTEA_Encode * 功 能:XXTEA編碼 * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ void XXTEA_Encode (void) { long n = 4; long p, q ; z=g_Tag.dataUL[n-1], y=g_Tag.dataUL[0], sum=0; q = 6 + 52/n; while (q-- > 0) { sum += DELTA; e = (sum >> 2) & 3; for (p=0; p<n-1; p++) y = g_Tag.dataUL[p+1], z = g_Tag.dataUL[p] += MX; y = g_Tag.dataUL[0]; z = g_Tag.dataUL[n-1] += MX; } } /********************************************************************* * 函式名稱:InitNRF4Reader * 功 能:針對RFID Reader功能初始化nRF24L01+ * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ void InitNRF4Reader(void) { hal_nrf_nop(); hal_nrf_write_reg(CONFIG, 0x20); //使用與nRF2401/ nRF2402/ nRF24E1/ nRF24E2 相同的CRC 配置 //設定PRIM_RX 位為0 hal_nrf_write_reg(EN_AA, 0x00); hal_nrf_write_reg(SETUP_RETR, 0); //設定自動重發計數器為0 禁止自動重發功能 hal_nrf_write_reg(SETUP_AW, 0x03);//與nRF2401/ nRF2402/ nRF24E1/ nRF24E2 使用相同的地址寬度 hal_nrf_set_address(HAL_NRF_PIPE0, RFID_READER_ADDR_P0); hal_nrf_set_address(HAL_NRF_TX, RFID_READER_ADDR_P0); hal_nrf_write_reg(RF_CH, 81); //與nRF2401/ nRF2402/ nRF24E1/ nRF24E2 使用相同的頻道 hal_nrf_write_reg(EN_RXADDR, 0x00); hal_nrf_set_power_mode(HAL_NRF_PWR_UP);//設定PWR_UP 為高 } void delay65ms(unsigned int microSecs) { while(microSecs--) { /* 32 NOPs == 1 usecs */ asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); } } void keyScan () { unsigned char keyCount,temp8i; keyCount = 0; temp8i = 0; while ( temp8i < KEYDELAY ) { delay65ms(500); if ( P2_0 == 1 ) keyCount++; else keyCount = 0; temp8i++; } if ( keyCount >= KEYDELAY) keyFlag = 0x31; else keyFlag = 0x30; } unsigned char secondAddr[8]; void HalFlashRead() { // Calculate the offset into the containing flash bank as it gets mapped into XDATA. unsigned char memctr = MEMCTR; // Save to restore. unsigned char i; // Calculate and map the containing flash bank into XDATA. MEMCTR = (MEMCTR & 0xF8) | 7; asm("push DPH"); asm("push DPL"); asm("push A"); asm("push B"); asm("mov DPH,#0xff"); asm("mov DPL,#0xe8"); i = 0; while (i < 8) { asm("movx A,@DPTR"); asm("mov B,A"); secondAddr[i] = B; asm("inc DPTR"); i++; } asm("pop B"); asm("pop A"); asm("pop DPL"); asm("pop DPH"); MEMCTR = memctr; } /********************************************************************* * 函式名稱:main * 功 能:2.4GHz RFID 讀卡器演示 * 將接收到的Tag資訊通過CC2530的UART0輸出,波特率為115200 * 入口引數:無 * 出口引數:無 * 返 回 值:無 ********************************************************************/ int main(void) { /* 定義相關變數 */ unsigned char i; unsigned short crc; /* 選擇32MHz晶體振盪器作為系統時鐘源(主時鐘源) */ SystemClockSourceSelect(XOSC_32MHz); /* RFID-2.4GHz-Reader硬體抽象層初始化 */ hal_2G4Hz_Tag_Init(); /* 使能P2.0為通用I/O,且為輸入 */ P2SEL = P2SEL & 0xfe; P2DIR = P2DIR & 0xfe; /* P2.0為下拉模式 */ P2INP = P2INP & 0xfe; P2INP = P2INP | 0x80; /* LED1和LED2閃爍指定次數 */ for(i = 0; i <= 20; i++) { if(i & 1) { HAL_2G4Hz_LED1_TURN_ON(); HAL_2G4Hz_LED2_TURN_ON(); } else { HAL_2G4Hz_LED1_TURN_OFF(); HAL_2G4Hz_LED2_TURN_OFF(); } CC2530SleepTimer_Delay(100); } /* 針對RFID Tag功能初始化nRF24L01+ */ InitNRF4Reader(); do { HalFlashRead (); delay65ms(60000); P1_1 = !P1_1; }while ( (secondAddr[0] == 0xff) && (secondAddr[1] == 0xff) && (secondAddr[2] == 0xff) && (secondAddr[3] == 0xff) ); P1_1 = 0; /* 永久迴圈 */ while(1) { g_Tag.dataB[0] = DATA_LONG; g_Tag.dataB[1] = DATA_PROTOCOL; g_Tag.dataB[4] = 0x00; g_Tag.dataB[5] = 0x3a; g_Tag.dataB[8] = secondAddr[3];//0x08; g_Tag.dataB[9] = secondAddr[2];//0x86; g_Tag.dataB[10] = secondAddr[1];//0x00; g_Tag.dataB[11] = secondAddr[0];//0x4d; g_Tag.dataB[12] = 0x0; g_Tag.dataB[13] = 0x0; /* 點亮LED1 */ HAL_2G4Hz_LED1_TURN_ON(); g_Tag.dataB[2] = keyFlag; g_Tag.dataB[3] = hal_nrf_get_output_power (); g_Tag.dataB[3]++; if ( g_Tag.dataB[3] >= 0x04 ) { g_Tag.dataB[3] = 0; txNumber++; } hal_nrf_set_output_power(g_Tag.dataB[3]); g_Tag.dataB[6] = (char)(txNumber >> 8); g_Tag.dataB[7] = (char)txNumber; crc = CRC16(g_Tag.dataB, sizeof(g_Tag.pkt) - sizeof (g_Tag.pkt.crc)); g_Tag.dataB[14] = (char)(crc >> 8); g_Tag.dataB[15] = (char)crc; /* 編碼接收到的資料 */ Shuffle_TX_ByteOrder(); XXTEA_Encode(); Shuffle_TX_ByteOrder(); hal_nrf_write_tx_pload(g_Tag.dataB, DATA_LONG); /* RF傳送 */ HAL_2G4Hz_CE_PULSE(); /* 熄滅LED1和LED2 */ HAL_2G4Hz_LED1_TURN_OFF(); HAL_2G4Hz_LED2_TURN_OFF(); keyScan (); } } #endif
/*******************************************************************************
* 檔名稱:hal_2.4GHz_Tag.c
* 功 能:RFID-2.4GHz-Reader硬體抽象層
* 作 者:蟲蟲
* 公 司:
******************************************************************************/
#if !defined ( TAG_FLAG )
/* 包含標頭檔案 */
/********************************************************************/
#include "ioCC2530.h" // CC2530的標頭檔案,包含對CC2530的暫存器、中斷向量等的定義
#include "hal_2.4GHz_Reader.h" // RFID-2.4GHz-Reader硬體抽象層標頭檔案
/********************************************************************/
/*
通過RF傳送的資料載荷。也包含接收資料。
使用Radio_Get_Pload_Byte()函式讀取
*/
/********************************************************************/
static unsigned char pload[16];
/********************************************************************/
/*
RF的當前狀態
使用Radio_Set_Status函式來設定該變數;
使用Radio_Get_Status函式來讀取該變數。
*/
/********************************************************************/
static radio_status_t status;
/********************************************************************/
/*********************************************************************
* 函式名稱:SetCC2530SleepTime
* 功 能:設定CC2530睡眠時間,即設定CC2530的睡眠定時器的比較值。
* 入口引數:ms 處於功耗模式IDLE、PM0、PM1或PM2的時間。
* 出口引數:無
* 返 回 值:無
* 注 意:使用外部32.768KHz晶體
********************************************************************/
static void
SetCC2530SleepTime(unsigned short ms)
{
unsigned long sleeptime = 0;
/* 讀取睡眠定時器的當前計數值 */
sleeptime |= ST0;
sleeptime |= (unsigned long)ST1 << 8;
sleeptime |= (unsigned long)ST2 << 16;
/* 根據指定的睡眠時間計算出應設定的比較值 */
sleeptime += (ms * (unsigned long)(32768 / 1000));
/* 設定比較值 */
while((STLOAD & 0x01) == 0); // 等待允許載入新的比較值
ST2 = (unsigned char)(sleeptime >> 16);
ST1 = (unsigned char)(sleeptime >> 8);
ST0 = (unsigned char) sleeptime;
}
/*********************************************************************
* 函式名稱:SetCC2530PowerMode
* 功 能:設定CC2530功耗模式
* 入口引數:pm : 0 空閒模式
* 1 功耗模式PM1
* 2 功耗模式PM2
* 3 功耗模式PM3
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
SetCC2530PowerMode(unsigned char pm)
{
if(pm == 0)
{
SLEEPCMD &= ~0x03;
}
else if(pm == 3)
{
SLEEPCMD |= ~0x03;
}
else
{
SLEEPCMD &= ~0x03;
SLEEPCMD |= pm;
}
/* 進入所選擇的功耗模式 */
PCON |= 0x01;
asm("NOP");
}
/*********************************************************************
* 函式名稱:CC2530SleepTimer_Delay
* 功 能:延時函式,延時過程中CC2530處於PM2模式。
* 入口引數:nMs 延時時長
* 出口引數:無
* 返 回 值:無
********************************************************************/
void CC2530SleepTimer_Delay(unsigned nMs)
{
SetCC2530SleepTime(nMs);
IRCON &= ~0x80;
IEN0 |= (0x01 << 5);
SetCC2530PowerMode(2);
}
/*********************************************************************
* 函式名稱:ST_ISR
* 功 能:CC2530睡眠定時器中斷服務函式
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
#pragma vector=ST_VECTOR
__interrupt void ST_ISR(void)
{
/* 清除CC2530睡眠定時器中斷標誌 */
IRCON &= ~0x80;
/* 禁止CC2530睡眠定時器中斷 */
IEN0 &= ~(0x01 << 5);
}
/*********************************************************************
* 函式名稱:SW_SPI_RW
* 功 能:CC2530模擬SPI匯流排傳送1位元組資料並從SPI匯流排讀取1位元組資料。
* 入口引數:value 待發送的1位元組資料
* 出口引數:無
* 返 回 值:讀回的1位元組資料
********************************************************************/
unsigned char
SW_SPI_RW(unsigned char value)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
HAL_2G4Hz_MOSI = (value & 0x80)? 1 : 0;
value <<= 1;
HAL_2G4Hz_SCK = 1;
value |= HAL_2G4Hz_MISO;
HAL_2G4Hz_SCK = 0;
}
HAL_2G4Hz_MOSI = 0;
return(value);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_irq_mode
* 功 能:使能或禁止nRF24L01+的指定中斷源
* 入口引數:int_source nRF24L01+的指定中斷源
* irq_state 使能或禁止
* 出口引數:無
* 返 回 值:無
********************************************************************/
void hal_nrf_set_irq_mode(hal_nrf_irq_source_t int_source, bool irq_state)
{
if(irq_state)
{
hal_nrf_write_reg(CONFIG, hal_nrf_read_reg(CONFIG) & ~SET_BIT(int_source));
}
else
{
hal_nrf_write_reg(CONFIG, hal_nrf_read_reg(CONFIG) | SET_BIT(int_source));
}
}
/*********************************************************************
* 函式名稱:hal_nrf_get_clear_irq_flags
* 功 能:獲取並清除nRF24L01+的中斷標誌
* 入口引數:無
* 出口引數:無
* 返 回 值:中斷標誌
* 0x10 最大重傳次數中斷
* 0x20 TX資料傳送中斷
* 0x40 RX資料接收中斷
********************************************************************/
unsigned char
hal_nrf_get_clear_irq_flags(void)
{
return hal_nrf_write_reg(STATUS, (BIT_6|BIT_5|BIT_4)) & (BIT_6|BIT_5|BIT_4);
}
/*********************************************************************
* 函式名稱:hal_nrf_clear_irq_flag
* 功 能:清除nRF24L01+的指定中斷標誌
* 入口引數:int_source 指定中斷源
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_clear_irq_flag(hal_nrf_irq_source_t int_source)
{
hal_nrf_write_reg(STATUS, SET_BIT(int_source));
}
/*********************************************************************
* 函式名稱:hal_nrf_get_irq_mode
* 功 能:獲取指定中斷的模式
* 入口引數:int_type 指定中斷源
* 出口引數:無
* 返 回 值:FALSE 禁止
* TRUE 使能
********************************************************************/
bool
hal_nrf_get_irq_mode(unsigned char int_type)
{
if(hal_nrf_read_reg(CONFIG) & SET_BIT(int_type))
return false;
else
return true;
}
/*********************************************************************
* 函式名稱:hal_nrf_nop
* 功 能:呼叫該函式接收nRF24L01+的狀態暫存器
* 入口引數:無
* 出口引數:無
* 返 回 值:狀態暫存器的值
********************************************************************/
unsigned char
hal_nrf_nop(void)
{
return hal_nrf_write_reg(NOP,0);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_irq_flags
* 功 能:獲取nRF24L01+的中斷標誌
* 入口引數:無
* 出口引數:無
* 返 回 值:中斷標誌
* 0x10 最大重傳次數中斷
* 0x20 TX資料傳送中斷
* 0x40 RX資料接收中斷
********************************************************************/
unsigned char
hal_nrf_get_irq_flags(void)
{
return hal_nrf_nop() & (BIT_6|BIT_5|BIT_4);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_crc_mode
* 功 能:設定nRF24L01+的CRC模式
* 入口引數:crc_mode 禁止
* 1位元組
* 2位元組
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_crc_mode(hal_nrf_crc_mode_t crc_mode)
{
hal_nrf_write_reg(CONFIG, (hal_nrf_read_reg(CONFIG) & ~(BIT_3|BIT_2)) |
(UINT8(crc_mode)<<2));
}
/*********************************************************************
* 函式名稱:hal_nrf_open_pipe
* 功 能:開啟nRF24L01+的1個或所有管道,並設定帶有/不帶自動ACK特性。
* 入口引數:pipe_num 管道號
* auto_ack 自動ACK特性開/關
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_open_pipe(hal_nrf_address_t pipe_num, bool auto_ack)
{
switch(pipe_num)
{
case HAL_NRF_PIPE0:
case HAL_NRF_PIPE1:
case HAL_NRF_PIPE2:
case HAL_NRF_PIPE3:
case HAL_NRF_PIPE4:
case HAL_NRF_PIPE5:
hal_nrf_write_reg(EN_RXADDR, hal_nrf_read_reg(EN_RXADDR) | SET_BIT(pipe_num));
if(auto_ack)
hal_nrf_write_reg(EN_AA, hal_nrf_read_reg(EN_AA) | SET_BIT(pipe_num));
else
hal_nrf_write_reg(EN_AA, hal_nrf_read_reg(EN_AA) & ~SET_BIT(pipe_num));
break;
case HAL_NRF_ALL:
hal_nrf_write_reg(EN_RXADDR, ~(BIT_7|BIT_6));
if(auto_ack)
hal_nrf_write_reg(EN_AA, ~(BIT_7|BIT_6));
else
hal_nrf_write_reg(EN_AA, 0);
break;
default:
break;
}
}
/*********************************************************************
* 函式名稱:hal_nrf_close_pipe
* 功 能:關閉nRF24L01+的1個或所有管道
* 入口引數:pipe_num 管道號
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_close_pipe(hal_nrf_address_t pipe_num)
{
switch(pipe_num)
{
case HAL_NRF_PIPE0:
case HAL_NRF_PIPE1:
case HAL_NRF_PIPE2:
case HAL_NRF_PIPE3:
case HAL_NRF_PIPE4:
case HAL_NRF_PIPE5:
hal_nrf_write_reg(EN_RXADDR, hal_nrf_read_reg(EN_RXADDR) & ~SET_BIT(pipe_num));
hal_nrf_write_reg(EN_AA, hal_nrf_read_reg(EN_AA) & ~SET_BIT(pipe_num));
break;
case HAL_NRF_ALL:
hal_nrf_write_reg(EN_RXADDR, 0);
hal_nrf_write_reg(EN_AA, 0);
break;
default:
break;
}
}
/*********************************************************************
* 函式名稱:hal_nrf_set_address
* 功 能:設定RX或TX地址
* 入口引數:address 設定哪個地址
* addr 指向儲存地址值的緩衝區的指標
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_address(hal_nrf_address_t address, unsigned char *addr)
{
switch(address)
{
case HAL_NRF_TX:
case HAL_NRF_PIPE0:
case HAL_NRF_PIPE1:
hal_nrf_write_multibyte_reg((unsigned char) address, addr, 0);
break;
case HAL_NRF_PIPE2:
case HAL_NRF_PIPE3:
case HAL_NRF_PIPE4:
case HAL_NRF_PIPE5:
hal_nrf_write_reg(RX_ADDR_P0 + (unsigned char) address, *addr);
break;
default:
break;
}
}
/*********************************************************************
* 函式名稱:hal_nrf_set_auto_retr
* 功 能:設定重傳次數和重傳延時
* 入口引數:retr 重傳次數
* delay 重傳延時(單位:us)
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_auto_retr(unsigned char retr, unsigned short delay)
{
hal_nrf_write_reg(SETUP_RETR, (((delay/250)-1)<<4) | retr);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_address_width
* 功 能:設定地址寬度
* 入口引數:address_width 地址寬度
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_address_width(hal_nrf_address_width_t address_width)
{
hal_nrf_write_reg(SETUP_AW, (UINT8(address_width) - 2));
}
/*********************************************************************
* 函式名稱:hal_nrf_set_rx_pload_width
* 功 能:設定指定管道上期望接收的資料長度(單位:位元組)
* 入口引數:pipe_num 管道
* pload_width 期望接收的位元組數量
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_rx_pload_width(unsigned char pipe_num, unsigned char pload_width)
{
hal_nrf_write_reg(RX_PW_P0 + pipe_num, pload_width);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_crc_mode
* 功 能:獲取所使用的CRC模式
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 無CRC
* 0x02 CRC-8
* 0x03 CRC-16
********************************************************************/
unsigned char
hal_nrf_get_crc_mode(void)
{
return (hal_nrf_read_reg(CONFIG) & (BIT_3|BIT_2)) >> CRCO;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_pipe_status
* 功 能:獲取指定管道的狀態
* 入口引數:pipe_num 管道號
* 出口引數:無
* 返 回 值:0x00 管道關閉,自動ACK禁止
* 0x01 管道開啟,自動ACK禁止
* 0x03 管道開啟,自動ACK開啟
********************************************************************/
unsigned char
hal_nrf_get_pipe_status(unsigned char pipe_num)
{
unsigned char en_rx, en_aa;
en_rx = hal_nrf_read_reg(EN_RXADDR) & (1<<pipe_num);
en_aa = hal_nrf_read_reg(EN_AA) & (1<<pipe_num);
en_rx >>= pipe_num;
en_aa >>= pipe_num;
return (en_aa << 1) + en_rx;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_address
* 功 能:獲取指定管道的地址
* 入口引數:address 要獲取哪一種地址,PIPE或TX地址
* addr 獲取到得地址資料將寫入該指標指向的緩衝區
* 出口引數:無
* 返 回 值:地址寬度(單位:位元組)
********************************************************************/
unsigned char
hal_nrf_get_address(unsigned char address, unsigned char *addr)
{
switch(address)
{
case HAL_NRF_PIPE0:
case HAL_NRF_PIPE1:
case HAL_NRF_TX:
return hal_nrf_read_multibyte_reg(address, addr);
default:
*addr = hal_nrf_read_reg(RX_ADDR_P0 + address);
return hal_nrf_get_address_width();
}
}
/*********************************************************************
* 函式名稱:hal_nrf_get_auto_retr_status
* 功 能:獲取自動重傳引數,即重傳次數和重傳延時。
* 入口引數:無
* 出口引數:無
* 返 回 值:高4位 重傳延時
* 低4位 重傳次數
********************************************************************/
unsigned char
hal_nrf_get_auto_retr_status(void)
{
return hal_nrf_read_reg(OBSERVE_TX);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_packet_lost_ctr
* 功 能:獲取丟包計數器的值
* 入口引數:無
* 出口引數:無
* 返 回 值:丟包計數器的值
********************************************************************/
unsigned char
hal_nrf_get_packet_lost_ctr(void)
{
return (hal_nrf_read_reg(OBSERVE_TX) & (BIT_7|BIT_6|BIT_5|BIT_4)) >> 4;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_rx_pload_width
* 功 能:獲取所指定管道上所期望接收的資料寬度(單位:位元組)
* 入口引數:pipe_num 管道號
* 出口引數:無
* 返 回 值:資料寬度(單位:位元組)
********************************************************************/
unsigned char
hal_nrf_get_rx_pload_width(unsigned char pipe_num)
{
return hal_nrf_read_reg(RX_PW_P0 + pipe_num);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_operation_mode
* 功 能:進入 PTX (primary TX) 或 PRX (primary RX)模式
* 入口引數:op_mode 執行模式
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_operation_mode(hal_nrf_operation_mode_t op_mode)
{
if(op_mode == HAL_NRF_PRX)
{
hal_nrf_write_reg(CONFIG, (hal_nrf_read_reg(CONFIG) | (1<<PRIM_RX)));
}
else
{
hal_nrf_write_reg(CONFIG, (hal_nrf_read_reg(CONFIG) & ~(1<<PRIM_RX)));
}
}
/*********************************************************************
* 函式名稱:hal_nrf_set_power_mode
* 功 能:上電或掉電RF
* 入口引數:pwr_mode POWER_UP 或 POWER_DOWN
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_power_mode(hal_nrf_pwr_mode_t pwr_mode)
{
if(pwr_mode == HAL_NRF_PWR_UP)
{
hal_nrf_write_reg(CONFIG, (hal_nrf_read_reg(CONFIG) | (1<<PWR_UP)));
}
else
{
hal_nrf_write_reg(CONFIG, (hal_nrf_read_reg(CONFIG) & ~(1<<PWR_UP)));
}
}
/*********************************************************************
* 函式名稱:hal_nrf_set_rf_channel
* 功 能:選擇所使用的RF通道
* 入口引數:channel RF通道
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_rf_channel(unsigned char channel)
{
hal_nrf_write_reg(RF_CH, channel);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_output_power
* 功 能:選擇RF TX輸出功率
* 入口引數:power RF TX輸出功率
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_output_power(hal_nrf_output_power_t power)
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) &
~((1<<RF_PWR1)|(1<<RF_PWR0))) | (UINT8(power)<<1));
}
/*********************************************************************
* 函式名稱:hal_nrf_set_datarate
* 功 能:設定無線通訊資料速率
* 入口引數:datarate 無線通訊資料速率
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_datarate(hal_nrf_datarate_t datarate)
{
if(datarate == HAL_NRF_1MBPS)
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) & ~(1<<RF_DR)));
}
else
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) | (1<<RF_DR)));
}
}
/*********************************************************************
* 函式名稱:hal_nrf_get_operation_mode
* 功 能:獲取執行模式
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 Primary RX (PRX)
* 0x01 Primary TX (PTX)
********************************************************************/
unsigned char
hal_nrf_get_operation_mode(void)
{
return (hal_nrf_read_reg(CONFIG) & (1<<PRIM_RX)) >> PRIM_RX;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_power_mode
* 功 能:獲取功耗模式
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 POWER_DOWN
* 0x01 POWER_UP
********************************************************************/
unsigned char
hal_nrf_get_power_mode(void)
{
return (hal_nrf_read_reg(CONFIG) & (1<<PWR_UP)) >> PWR_UP;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_rf_channel
* 功 能:獲取所使用的RF通道
* 入口引數:無
* 出口引數:無
* 返 回 值:RF通道
********************************************************************/
unsigned char
hal_nrf_get_rf_channel(void)
{
return hal_nrf_read_reg(RF_CH);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_output_power
* 功 能:獲取所使用的RF TX輸出功率
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 -18dBm
* 0x01 -12dBm
* 0x02 -6dBm
* 0x03 0dBm
********************************************************************/
unsigned char
hal_nrf_get_output_power(void)
{
return (hal_nrf_read_reg(RF_SETUP) & ((1<<RF_PWR1)|(1<<RF_PWR0))) >> RF_PWR0;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_datarate
* 功 能:獲取所使用的無線通訊資料速率
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 1Mbps
* 0x01 2Mbps
********************************************************************/
unsigned char
hal_nrf_get_datarate(void)
{
return (hal_nrf_read_reg(RF_SETUP) & (1<<RF_DR)) >> RF_DR;
}
/*********************************************************************
* 函式名稱:hal_nrf_rx_fifo_empty
* 功 能:檢查RX FIFO是否為空
* 入口引數:無
* 出口引數:無
* 返 回 值:FALSE RX FIFO 不空
* TRUE RX FIFO 空
********************************************************************/
bool
hal_nrf_rx_fifo_empty(void)
{
if(hal_nrf_get_rx_data_source()==7)
{
return true;
}
else
{
return false;
}
}
/*********************************************************************
* 函式名稱:hal_nrf_rx_fifo_full
* 功 能:檢查RX FIFO是否為滿
* 入口引數:無
* 出口引數:無
* 返 回 值:FALSE RX FIFO 不滿
* TRUE RX FIFO 滿
********************************************************************/
bool
hal_nrf_rx_fifo_full(void)
{
return (bool)((hal_nrf_read_reg(FIFO_STATUS) >> RX_EMPTY) & 1);
}
/*********************************************************************
* 函式名稱:hal_nrf_tx_fifo_empty
* 功 能:檢查TX FIFO是否為空
* 入口引數:無
* 出口引數:無
* 返 回 值:FALSE TX FIFO 不空
* TRUE TX FIFO 空
********************************************************************/
bool
hal_nrf_tx_fifo_empty(void)
{
return (bool)((hal_nrf_read_reg(FIFO_STATUS) >> TX_EMPTY) & 1);
}
/*********************************************************************
* 函式名稱:hal_nrf_tx_fifo_full
* 功 能:檢查TX FIFO是否為滿
* 入口引數:無
* 出口引數:無
* 返 回 值:FALSE TX FIFO 不滿
* TRUE TX FIFO 滿
********************************************************************/
bool
hal_nrf_tx_fifo_full(void)
{
return (bool)((hal_nrf_read_reg(FIFO_STATUS) >> TX_FIFO_FULL) & 1);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_tx_fifo_status
* 功 能:檢查TX FIFO的狀態
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 TX FIFO 不空, 也不滿
* 0x01 TX FIFO 空
* 0x02 TX FIFO 滿
********************************************************************/
unsigned char
hal_nrf_get_tx_fifo_status(void)
{
return ((hal_nrf_read_reg(FIFO_STATUS) &
((1<<TX_FIFO_FULL)|(1<<TX_EMPTY))) >> 4);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_rx_fifo_status
* 功 能:檢查RX FIFO的狀態
* 入口引數:無
* 出口引數:無
* 返 回 值:0x00 RX FIFO 不空, 也不滿
* 0x01 RX FIFO 空
* 0x02 RX FIFO 滿
********************************************************************/
unsigned char
hal_nrf_get_rx_fifo_status(void)
{
return (hal_nrf_read_reg(FIFO_STATUS) & ((1<<RX_FULL)|(1<<RX_EMPTY)));
}
/*********************************************************************
* 函式名稱:hal_nrf_get_fifo_status
* 功 能:檢查FIFO狀態
* 入口引數:無
* 出口引數:無
* 返 回 值:FIFO狀態暫存器的值
********************************************************************/
unsigned char
hal_nrf_get_fifo_status(void)
{
return hal_nrf_read_reg(FIFO_STATUS);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_transmit_attempts
* 功 能:獲取重傳嘗試的次數和丟包數量
* 入口引數:無
* 出口引數:無
* 返 回 值:重傳嘗試計數器的值
********************************************************************/
unsigned char
hal_nrf_get_transmit_attempts(void)
{
return hal_nrf_read_reg(OBSERVE_TX) & (BIT_3|BIT_2|BIT_1|BIT_0);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_carrier_detect
* 功 能:獲取載波檢測標誌
* 入口引數:無
* 出口引數:無
* 返 回 值:FALSE 未檢測到載波
* TRUE 檢測到載波
********************************************************************/
bool
hal_nrf_get_carrier_detect(void)
{
return hal_nrf_read_reg(CD) & 1;
}
/*********************************************************************
* 函式名稱:hal_nrf_write_tx_pload
* 功 能:寫資料包的資料載荷部分到RF
* 入口引數:tx_pload 指向儲存資料載荷的緩衝區的指標
* length 資料載荷的長度(單位:位元組)
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_write_tx_pload(unsigned char *tx_pload, unsigned char length)
{
hal_nrf_write_multibyte_reg(UINT8(HAL_NRF_TX_PLOAD), tx_pload, length);
}
/*********************************************************************
* 函式名稱:hal_nrf_setup_dyn_pl
* 功 能:設定接收管道的動態資料負載特性。
* 入口引數:setup 管道特性位掩碼
* 例如:bit0設定為1時,管道0使用ACK資料負載。
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_setup_dyn_pl(unsigned char setup)
{
hal_nrf_write_reg(DYNPD, setup & ~0xC0);
}
/*********************************************************************
* 函式名稱:hal_nrf_enable_dynamic_pl
* 功 能:使能動態資料負載特性。
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_enable_dynamic_pl(void)
{
hal_nrf_write_reg(FEATURE, (hal_nrf_read_reg(FEATURE) | 0x04));
}
/*********************************************************************
* 函式名稱:hal_nrf_disable_dynamic_pl
* 功 能:禁止動態資料負載特性。
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_disable_dynamic_pl(void)
{
hal_nrf_write_reg(FEATURE, (hal_nrf_read_reg(FEATURE) & ~0x04));
}
/*********************************************************************
* 函式名稱:hal_nrf_enable_ack_pl
* 功 能:使能ACK資料負載特性。
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_enable_ack_pl(void)
{
hal_nrf_write_reg(FEATURE, (hal_nrf_read_reg(FEATURE) | 0x02));
}
/*********************************************************************
* 函式名稱:hal_nrf_disable_ack_pl
* 功 能:禁止ACK資料負載特性。
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_disable_ack_pl(void)
{
hal_nrf_write_reg(FEATURE, (hal_nrf_read_reg(FEATURE) & ~0x02));
}
/*********************************************************************
* 函式名稱:hal_nrf_enable_dynamic_ack
* 功 能:使能no-ack特性
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_enable_dynamic_ack(void)
{
hal_nrf_write_reg(FEATURE, (hal_nrf_read_reg(FEATURE) | 0x01));
}
/*********************************************************************
* 函式名稱:hal_nrf_disable_dynamic_ack
* 功 能:禁止no-ack特性
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_disable_dynamic_ack(void)
{
hal_nrf_write_reg(FEATURE, (hal_nrf_read_reg(FEATURE) & ~0x01));
}
/*********************************************************************
* 函式名稱:hal_nrf_write_ack_pload
* 功 能:給指定管道寫入帶ACK特性的資料負載。
* 入口引數:pipe 管道號
* tx_pload 指向儲存待寫入資料的緩衝區的指標
* length 待寫入資料的長度(單位:位元組)
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_write_ack_pload(unsigned char pipe, unsigned char *tx_pload,
unsigned char length)
{
HAL_2G4Hz_CSN = 0;
SW_SPI_RW(WR_ACK_PLOAD | pipe);
while(length--)
{
SW_SPI_RW(*tx_pload++);
}
HAL_2G4Hz_CSN = 1;
}
/*********************************************************************
* 函式名稱:hal_nrf_read_rx_pl_w
* 功 能:讀取接收到的ACK資料負載的寬度
* 入口引數:無
* 出口引數:無
* 返 回 值:接收到的ACK資料負載的寬度
********************************************************************/
unsigned char
hal_nrf_read_rx_pl_w()
{
unsigned char temp;
HAL_2G4Hz_CSN = 0;
SW_SPI_RW(RD_RX_PLOAD_W);
temp = SW_SPI_RW(0);
HAL_2G4Hz_CSN = 1;
return temp;
}
/*********************************************************************
* 函式名稱:hal_nrf_lock_unlock
* 功 能:給nRF24L01+傳送ACTIVATE命令
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_lock_unlock()
{
HAL_2G4Hz_CSN = 0;
SW_SPI_RW(LOCK_UNLOCK);
SW_SPI_RW(0x73);
HAL_2G4Hz_CSN = 1;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_rx_data_source
* 功 能:獲取當前哪一個管道接收的資料包是當前最高級別資料包
* 入口引數:無
* 出口引數:無
* 返 回 值:管道號
********************************************************************/
unsigned char
hal_nrf_get_rx_data_source(void)
{
return ((hal_nrf_nop() & (BIT_3|BIT_2|BIT_1)) >> 1);
}
/*********************************************************************
* 函式名稱:hal_nrf_read_reg
* 功 能:讀取nRF24L01+的暫存器內容
* 入口引數:reg 要讀取的暫存器
* 出口引數:無
* 返 回 值:讀出的暫存器內容
********************************************************************/
unsigned char
hal_nrf_read_reg(unsigned char reg)
{
unsigned char temp;
HAL_2G4Hz_CSN = 0;
SW_SPI_RW(reg);
temp = SW_SPI_RW(0);
HAL_2G4Hz_CSN = 1;
return temp;
}
/*********************************************************************
* 函式名稱:hal_nrf_read_rx_pload
* 功 能:讀取RX FIFO中可用的最高級別資料載荷
* 入口引數:rx_pload 指向儲存讀出資料的緩衝區的指標
* 出口引數:無
* 返 回 值:高8位 管道號
* 低8位 資料長度(單位:位元組)
* 資料長度為0且管道號為7意味著FIFO為空
********************************************************************/
unsigned short
hal_nrf_read_rx_pload(unsigned char *rx_pload)
{
return hal_nrf_read_multibyte_reg(UINT8(HAL_NRF_RX_PLOAD), rx_pload);
}
/*********************************************************************
* 函式名稱:hal_nrf_reuse_tx
* 功 能:設定RF使用最後一次傳送的資料載荷作為下一個資料包
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_reuse_tx(void)
{
hal_nrf_write_reg(REUSE_TX_PL, 0);
}
/*********************************************************************
* 函式名稱:hal_nrf_get_reuse_tx_status
* 功 能:檢查reuse_tx功能的狀態
* 入口引數:無
* 出口引數:無
* 返 回 值:FALSE 未啟用
* TRUE 啟用
********************************************************************/
bool
hal_nrf_get_reuse_tx_status(void)
{
return (bool)((hal_nrf_get_fifo_status() & (1<<TX_REUSE)) >> TX_REUSE);
}
/*********************************************************************
* 函式名稱:hal_nrf_flush_rx
* 功 能:清空RX FIFO
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_flush_rx(void)
{
hal_nrf_write_reg(FLUSH_RX, 0);
}
/*********************************************************************
* 函式名稱:hal_nrf_flush_tx
* 功 能:清空TX FIFO
* 入口引數:無
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_flush_tx(void)
{
hal_nrf_write_reg(FLUSH_TX, 0);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_pll_mode
* 功 能:LOCK或UNLOCK RF PLL
* 入口引數:pll_mode PLL locked: TRUE 或 FALSE
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_pll_mode(hal_nrf_pll_mode_t pll_mode)
{
if(pll_mode == HAL_NRF_PLL_LOCK)
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) | (1<<PLL_LOCK)));
}
else
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) & ~(1<<PLL_LOCK)));
}
}
/*********************************************************************
* 函式名稱:hal_nrf_get_pll_mode
* 功 能:獲取 RF PLL的當前模式
* 入口引數:無
* 出口引數:無
* 返 回 值:RF PLL的當前模式
********************************************************************/
hal_nrf_pll_mode_t
hal_nrf_get_pll_mode(void)
{
return (hal_nrf_pll_mode_t)((hal_nrf_read_reg(RF_SETUP) &
(1<<PLL_LOCK)) >> PLL_LOCK);
}
/*********************************************************************
* 函式名稱:hal_nrf_set_lna_gain
* 功 能:設定RF使用的LNA增益模式
* 入口引數:lna_gain LNA增益模式
* 出口引數:無
* 返 回 值:無
********************************************************************/
void
hal_nrf_set_lna_gain(hal_nrf_lna_mode_t lna_gain)
{
if(lna_gain == HAL_NRF_LNA_HCURR)
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) | (1<<LNA_HCURR)));
}
else
{
hal_nrf_write_reg(RF_SETUP, (hal_nrf_read_reg(RF_SETUP) & ~(1<<LNA_HCURR)));
}
}
/*********************************************************************
* 函式名稱:hal_nrf_get_lna_gain
* 功 能:獲取RF當前使用的LNA增益模式
* 入口引數:lna_gain LNA增益模式
* 出口引數:無
* 返 回 值:0 LNA 低電流
* 1 LNA 高電流
********************************************************************/
hal_nrf_lna_mode_t
hal_nrf_get_lna_gain(void)
{
return (hal_nrf_lna_mode_t) ( (hal_nrf_read_reg(RF_SETUP) &
(1<<LNA_HCURR)) >> LNA_HCURR );
}
/*********************************************************************
* 函式名稱:hal_nrf_read_multibyte_reg
* 功 能:從nRF24L01+的指定暫存器讀取多位元組資料
* 入口引數:reg nRF24L01+的指定暫存器
* pbuf 指向儲存讀出資料的緩衝區的指標
* 出口引數:無
* 返 回 值:高8位:接收資料的管道號(用於hal_nrf_read_rx_pload函式)
* 低8位:讀取資料的長度(用於hal_nrf_read_rx_pload 或hal_nrf_get_address函式)
********************************************************************/
unsigned short
hal_nrf_read_multibyte_reg(unsigned char reg, unsigned char *pbuf)
{
unsigned char ctr, length;
switch(reg)
{
case HAL_NRF_PIPE0:
case HAL_NRF_PIPE1:
case HAL_NRF_TX:
length = ctr = hal_nrf_get_address_width();
HAL_2G4Hz_CSN = 0;
SW_SPI_RW(RX_ADDR_P0 + reg);
break;
case HAL_NRF_RX_PLOAD:
if( (reg = hal_nrf_get_rx_data_source()) < 7)
{
length = ctr = hal_nrf_read_rx_pl_w();
HAL_2G4Hz_CSN = 0;
SW_SPI_RW(RD_RX_PLOAD);
}
else
{
ctr = length = 0;
}
break;
default:
ctr = length = 0;
break;
}
while(ctr--)
{
*pbuf++ = SW_SPI_RW(0);
}
HAL_2G4Hz_CSN = 1;
return (((unsigned short) reg << 8) | length);
}
/*********************************************************************
* 函式名稱:hal_nrf_write_reg
* 功 能:寫一個新值到nRF24L01+的指定暫存器
* 入口引數:reg 待寫入新值的暫存器
* value 待寫入的新值
* 出口引數:無
* 返 回 值:1位元組返回值
********************************************************************/
unsigned char
hal_nrf_write_reg(unsigned char reg, unsigned char value)
{
unsigned char retval;
HAL_2G4Hz_CSN = 0;
if(reg < WRITE_REG)
{
retval = SW_SPI_RW(WRITE_REG + reg);
SW_SPI_RW(value);
}
else
{
if(!(reg == FLUSH_TX) && !(reg == FLUSH_RX) && !(reg == REUSE_TX_PL) && !(reg == NOP))
{
retval = SW_SPI_RW(reg);
SW_SPI_RW(value);
}
else
{
retval = SW_SPI_RW(reg);
}
}
HAL_2G4Hz_CSN = 1;
return retval;
}
/*********************************************************************
* 函式名稱:hal_nrf_get_address_width
* 功 能:獲取nRF24L01+射頻使用的地址寬度,包括RX和TX
* 入口引數:無
* 出口引數:無
* 返 回 值:地址寬度(單位:位元組)
********************************************************************/
unsigned char
hal_nrf_get_address_width(void)
{
return (hal_nrf_read_reg(SETUP_AW) + 2);
}
/*********************************************************************
* 函式名稱:hal_nrf_write_multibyte_reg
* 功 能:寫多個位元組資料