#include <reg51.h>
#include <intrins.h>
#include "spi.h"
#include "ds18b20.h"
/***************************************************/
//#define uchar unsigned char
//#define uint unsigned int
#define TX_ADR_WIDTH 5 // 收發(fā)地址5 字節(jié)寬TX(RX)
#define TX_PLOAD_WIDTH 20 // 發(fā)送數(shù)據(jù)包20 字節(jié)
uchar const TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};// 定義發(fā)送地址
uchar rx_buf[TX_PLOAD_WIDTH];//接收緩沖數(shù)組
uchar tx_buf[TX_PLOAD_WIDTH];//發(fā)送緩沖數(shù)組
uchar flag;//中斷標志
/**************************************************/
//nRF24L01 SPI口定義//
sbit CE = P1^7;
sbit CSN= P1^6;
sbit SCK= P1^5;
sbit MOSI= P1^4;
sbit MISO= P1^3;
sbit IRQ = P3^2;
sbit S2= P1^2;//發(fā)送按鈕
sbit LEDG= P3^7;
sbit LEDR= P3^5;
/**************************************************/
uchar bdata sta;
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT =sta^4;
/**************************************************/
/**************************************************
函數(shù): init_nRF24L01();
說明:
nRF24L01待機模式,
Spi 不能,Spi 時鐘線高
/**************************************************/
void init_nRF24L01(void)
{
CE=0; // 片選使能
CSN=1; // Spi 禁止
SCK=0; // Spi 時鐘初始化
}
/**************************************************/
/**************************************************
函數(shù): init_int0();
說明:
開int0中斷;
/**************************************************/
void init_int0(void)
{
EA=1;
EX0=1; //開int0中斷.
}
/**************************************************/
void delay_ms(unsigned int x) //ms延時
{
unsigned int i,j;
i=0;
for(i=0;i<x;i++)
{
j=108;
;
while(j--);
}
}
/**************************************************/
/**************************************************
函數(shù): SPI_RW();
說明:
寫單字節(jié)到nRF24L01, 同時返回從nRF24L01讀出的一字節(jié)
/**************************************************/
uchar SPI_RW(uchar byte)
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 輸出 8-bit
{
MOSI = (byte & 0x80); // 輸出字節(jié)到MOSI, 最高位開始
byte = (byte << 1); // 左移一位
SCK = 1; // 時鐘置高
byte |= MISO; // 由MISO讀入1bit
SCK = 0; // 時鐘置低
}
return(byte); // 返回讀入的字節(jié)
}
/**************************************************/
/**************************************************
函數(shù): SPI_RW_Reg();
說明:
寫一字節(jié)值'value'到地址為'reg'的寄存器
/**************************************************/
uchar SPI_RW_Reg(BYTE reg, BYTE value)
{
uchar status;
CSN = 0; // SPI 使能
status = SPI_RW(reg); // 選寄存器,并讀狀態(tài)值
SPI_RW(value); // 寫該寄存器
CSN = 1; // SPI禁止
return(status); // 返回狀態(tài)值
}
/**************************************************/
/**************************************************
函數(shù): SPI_Read();
說明:
從 nRF24L01內(nèi)地址為 'reg'的寄存器讀出一字節(jié)數(shù)據(jù)
/**************************************************/
BYTE SPI_Read(BYTE reg)
{
BYTE reg_val;
CSN = 0; // SPI 使能
SPI_RW(reg); // 選寄存器
reg_val = SPI_RW(0); // 讀寄存器
CSN = 1; // SPI 禁止
return(reg_val); // 返回寄存器值
}
/**************************************************/
/**************************************************
函數(shù): SPI_Read_Buf();
說明:
從地址為'reg'的寄存器中讀出若干字節(jié)的數(shù)據(jù)到數(shù)組,例如從
RX payload 中讀出數(shù)據(jù)包。
/**************************************************/
uchar SPI_Read_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
uchar status,byte_ctr;
CSN = 0; // SPI 使能
status = SPI_RW(reg); // 選寄存器,并讀狀態(tài)值
for(byte_ctr=0;byte_ctr<bytes;byte_ctr++)
pBuf[byte_ctr] = SPI_RW(0); // 由nRF24L01讀出若干字節(jié)數(shù)據(jù)到數(shù)組
CSN = 1; // SPI 禁止
return(status); // 返回狀態(tài)字
}
/**************************************************/
/**************************************************
函數(shù): SPI_Write_Buf();
說明:
把緩沖數(shù)組'*pBuf'中的數(shù)據(jù)寫入nRF24L01中的TX payload
/**************************************************/
uchar SPI_Write_Buf(BYTE reg, BYTE *pBuf, BYTE bytes)
{
uchar status,byte_ctr;
CSN = 0; // SPI 使能
status = SPI_RW(reg); // 選寄存器,并讀狀態(tài)值
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)// 把buffer(*pBuf)中的字節(jié)寫入
SPI_RW(*pBuf++);
CSN = 1; // SPI 禁止
return(status); // 返回狀態(tài)字節(jié)
}
/**************************************************/
/**************************************************
函數(shù): RX_Mode();
說明:
初始化nRF24L01 為RX Mode,設(shè)定接收地址、RX payload 長度,
選擇RF 通道, 數(shù)據(jù)速率和LNA HCURR。然后置CE為高, 等待接收數(shù)據(jù)包
/**************************************************/
void RX_Mode(void)
{
CE=0;
// 收發(fā)設(shè)置相同的地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能自動應(yīng)答Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Pipe0使能
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 選 射頻通道40
// 設(shè)置接收和發(fā)送 payload寬度相同
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);
// 發(fā)送功率:0dBm, 數(shù)據(jù)速率:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);
// 置位 PWR_UP, 使能CRC(2 bytes) 和主接收Prim:RX. 使能RX_DR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);
CE = 1; // 接收使能
// 器件已經(jīng)準備好由發(fā)送方發(fā)來的16字節(jié)數(shù)據(jù)
// 自動應(yīng)答'3443101001', 重發(fā)次數(shù)為10, 射頻通道為 40,數(shù)據(jù)速率 = 2Mbps.
}
/**************************************************/
/**************************************************
函數(shù): TX_Mode();
說明:
初始化 nRF24L01 為TX mode, 設(shè)置 TX 地址、接收地址、自動應(yīng)答,
向TX payload寫入數(shù)據(jù), 選擇 RF 通道, 數(shù)據(jù)速率和 TX 發(fā)送功率.
加電, CRC(2 字節(jié)) 使能, 發(fā)送為PRIM:TX.當CE置高(>10us)之后
即發(fā)送數(shù)據(jù)包,然后轉(zhuǎn)入接收模式等待接收方的應(yīng)答。
/**************************************************/
void TX_Mode(void)
{
CE=0;
// 寫發(fā)送地址TX_Address 到nRF24L01
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
// 自動應(yīng)答的接收地址RX_Addr0 和 TX_Adr 相同
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 寫數(shù)據(jù)到 TX payload
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能自動應(yīng)答到Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10次重發(fā)
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 選射頻通道 40
// 發(fā)送功率:0dBm, 數(shù)據(jù)速率:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);
// 置位 PWR_UP, 使能CRC(2 bytes) 和主發(fā)送Prim:TX. 使能MAX_RT 和 TX_DS
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);
CE=1;
}
/**************************************************/
/**************************************************
函數(shù): Send_uart();
說明:
寫數(shù)據(jù)到串口 SBUF
/**************************************************/
void Send_uart(uchar x)
{
SBUF=x;// write data x to SBUF
while(TI==0);
TI=0;
}
/**************************************************/
/**************************************************
函數(shù): display();
說明:
在 LED數(shù)碼管上顯示數(shù)據(jù)
/**************************************************/
void display(uchar idata *p)
{
uchar code table[23]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x8c,0xc1,0x89,0xc7,0x91,0xbf,0xff};
//共陽碼表,前16位是0~F,后面的如下:
//0x8c,0xc1,0x89,0xc7,0x91,0xbf,0xff
//P, U, H, L, Y, -, 不顯示
//10H, 11H, 12H, 13H, 14H, 15H, 16H
uchar adc,i;
for(i=0;i<4;i++)
{ adc=table[*p];//segement code
if(i==1)
{
adc=adc-0x80;//加小數(shù)點
}
Send_uart(adc);
p++;
}
}
/**************************************************/
/**************************************************
函數(shù): CheckButtons();
說明:
檢查按鈕 ,若按鈕按下讀ds18b20溫度值并發(fā)送,綠燈閃亮。
發(fā)送后清TX_DS中斷標志并轉(zhuǎn)入接收模式 RX Mode;
/**************************************************/
void CheckButtons()
{
if(S2==0)
{
delay_ms(10);
if(S2==0)
{
Do_Temp();//讀溫度數(shù)據(jù)
tx_buf[0]=dis_buf[0]; // 存溫度數(shù)據(jù)到顯示緩存
tx_buf[1]=dis_buf[1];
tx_buf[2]=dis_buf[2];
tx_buf[3]=dis_buf[3];
TX_Mode(); // 發(fā)送模式
display(dis_buf); //在LED顯示溫度數(shù)據(jù)
// 清中斷標志(TX_DS)
SPI_RW_Reg(WRITE_REG+STATUS,SPI_Read(READ_REG+STATUS));
RX_Mode(); // 轉(zhuǎn)入接收模式
LEDG=0; //綠LED:亮
delay_ms(200);
LEDG=1; //綠LED:滅
}
}
}
/**************************************************/
/**************************************************
函數(shù): main();
說明:
主函數(shù);
/**************************************************/
void main(void)
{
init_nRF24L01();// 初始化nRF24L01
init_int0(); // int0 中斷使能
RX_Mode(); // 接收模式
while(1)
{
CheckButtons(); // 等待發(fā)送按鍵并發(fā)送
if(flag) // 是否收到
{
flag=0; //收到標志清零
LEDR=0; //紅LED:亮
delay_ms(200);
LEDR=1; //紅LED:滅
dis_buf[0]=rx_buf[0];//小數(shù)位
dis_buf[1]=rx_buf[1];//個位
dis_buf[2]=rx_buf[2];//十位
dis_buf[3]=rx_buf[3];//百位或負號
display(dis_buf);//在LED顯示收到的溫度值
}
}
}
/**************************************************/
/**************************************************
函數(shù): ISR_int0() interrupt 0;
說明:中斷服務(wù)函數(shù)
若 RX_DR=1,由RX_FIFO 讀數(shù)據(jù)包并置位flag;
/**************************************************/
void ISR_int0(void) interrupt 0
{
sta=SPI_Read(STATUS); // 讀狀態(tài) STATUS'值
if(RX_DR) // 如果有接收數(shù)據(jù)中斷(RX_DR)
{ // 由 RX_FIFO 緩存讀數(shù)據(jù)
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);
flag=1;
}
if(MAX_RT) // 如果重發(fā)次數(shù)超過(MAX_RT)
{
SPI_RW_Reg(FLUSH_TX,0); //FLUSH_TX清零
}
// 清零RX_DR 或 TX_DS 或 MAX_RT 中斷標志
SPI_RW_Reg(WRITE_REG+STATUS,sta);
}
|