從2015年5月15號開始做無線通訊的。開始我并沒有重視這個無線通信,但是偶爾一次去工地的路上看見一個城建鋼筋場地里的龍門吊,那個傻逼竟然用遙控器控制龍門吊!!開始驚奇,轉而又想我能不能做呢?我分析其實關于控制部分早在技校里就學了,正反轉嗎,不難,但是中間你要實現遙控就不易了,我還是模塊化思路,我搞到了RF模塊,開始進入了漫漫的實驗之路,射頻信號我在此之前根本不懂,也不知道是個什么東西,只是知道手機里有那個東西,數據手冊有兩種一種是英文的,一種是翻譯的中文,因為在這方面我還是有經驗的,不能盡心中文資料,要信英文資料,但是翻譯太麻煩了要用中文資料為參考。
我的第一個實驗便是RF模塊與主控芯片之間的通信問題,因為無線通信的流程大概是這樣的:發送端 數據和信號送入模塊的數據區,CRC效驗后打包,然后打包后的信號送往調制器進行調制,調制完畢后進入射頻功率放大,然后通過天線發射出去;接收端 實時監測空中信號,如果有信號那么接收回來,解調處理,然后對包進行逆打包,CRC效驗,地址是否匹配,如果一切正確那么就把數據信號送入數據緩沖區。也就完成了一次通信!和電視和收音機差不多,所以模塊與主控通信的重要性關系到你能否駕馭它了!!可喜可賀的是我沒用幾天就解決這一問題了,因為它使用的外圍數據接口以前我用的很多,解決了主機和模塊之間的對話下一步是對RF模塊的設置和通信的程序,我沒想到這可是難倒我了,任憑我怎樣設置怎樣修改,就是無法發射,沒有接收,沒有任何的檢測工具,我開始懷疑芯片的好壞!是不是壞了?那為什么還能讀寫呢?又上網找資料找朋友,但是這個東西可不像別的,沒有任何教學視頻可參考,網上的程序也很爛,說實話我看不下去,我只會用我的思路來編程,他們的太精致了,各種猜測,輾轉反側,夜不能寐。很快就過春節了,我和爸爸1月27號回的家,本想著在家里搞,可是到家后沒時間搞,和老爸弄自來水管,寫春聯,收拾房屋,打掃衛生,可以這么說,今年的春節我是最累的,過了春季有忙著和朋友們玩DOTA,走親戚,來親戚,轉眼初九了,又極不情愿的踏上了北上打工的旅途!哎!!!人啊!!!
接收機:
- /*無線模塊定義*/
- sbit CE=P1^3;//nrf24l01d的模式控制線在 CSN 為低的情況下,CE 協同NRF24L01 的CONFIG 寄存器共同決定NRF24L01 的狀態(參照NRF24L01 的狀態機)
- sbit CSN=P1^4;//nrf24l01d的片選線,低電平有效
- sbit IRQ=P1^5;//nrf24l01d的中斷信號
- /*SPI定義
- */
- sbit SI=P1^0;//MOSI主出-從入
- sbit SO=P1^1;//MISO主入-從出
- sbit SCK=P1^2;// 時鐘信號
- /*定義無線模塊的收發狀態位
- */
- unsigned char bdata FLAGE;
- sbit MAX_RT=FLAGE^4; //達到最大發送次數置1
- sbit TX_DS=FLAGE^5;//數據發送被置1
- sbit RX_DR=FLAGE^6;//數據接收被置1
- /*可謂操作字節dat定義,用來構成最底層的SPT讀寫函數使用
- */
- unsigned char bdata dat;
- sbit dat_0=dat^0;
- sbit dat_1=dat^1;
- sbit dat_2=dat^2;
- sbit dat_3=dat^3;
- sbit dat_4=dat^4;
- sbit dat_5=dat^5;
- sbit dat_6=dat^6;
- sbit dat_7=dat^7;
- /*串口程序*/
- void InitUART(void)
- {
- TMOD = 0x20;
- SCON = 0x50;
- TH1 = 0xFD;
- TL1 = TH1;
- PCON = 0x00;
- EA = 1;
- ES = 1;
- TR1 = 1;
- }
- void UARTInterrupt(void) interrupt 4
- {
- if(RI)
- {
- RI = 0;
-
- //add your code here!
- }
- else
- TI = 0;
- }
- void SendOneByte(unsigned char c)
- {
- SBUF = c;
- while(!TI);
- TI = 0;
- }
- /*串口程序*/
- /*SPI最底層寫一個字節函數
- 無返回值
- 有參
- 帶形參H
- */
- void delay1ms(uchar time)//1ms
- {
- unsigned char a,b,c,d;
- for(d=time;d>0;d--)
-
- for(c=8;c>0;c--)
- for(b=197;b>0;b--)
- for(a=2;a>0;a--);
- }
-
- void delay10us(uchar time)//10us
- {
- unsigned char a,b,c;
- for(c=time;c>0;c--)
- for(b=1;b>0;b--)
- for(a=52;a>0;a--);
- }
-
-
- /*************************
- *
- SPI寫一個字節的最底層函數 *
- 有參 *
- 無返回值 *
- ***************************/
- void write_spi_2401(uchar h)//SPI寫一字節函數
- {
- dat=h;
-
- SI=dat_7;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_6;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_5;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
-
- SI=dat_4;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_3;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_2;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_1;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_0;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- }
- /************************
- SPI最底層讀取一個字節 *
- 返回值是讀出的這一個字節 *
- 無參 *
- *
- *************************/
- uchar read_spi_2401()//SPI讀一字節函數
- {
- SO=1;//初始化SO線
- SCK=1;
- SCK=0;
-
- dat_7=SO;
-
- SCK=1;
- SCK=0;
-
- dat_6=SO;
-
- SCK=1;
- SCK=0;
-
- dat_5=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_4=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_3=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_2=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_1=SO;
-
- SCK=1;
- SCK=0;
-
- dat_0=SO;
-
- return (dat);//返回讀取數值
- }
- /****************************
- *
- 寫入寄存器命令函數 *
- 有參 *
- 無返回值 *
- *
- m:表示要操作的寄存器地址 *
- date:表示要向內不寫入的數據 *
- *****************************/
- void write_rge_nrf24l01(uchar m,uchar date)
- {
- SCK=0;//時鐘預選拉低
- CSN=1;
- CSN=0; //SPI開
- write_spi_2401((0x20+m));//寫入寫寄存器命令
- write_spi_2401(date);//寫入date指向的寄存器數據
- CSN=1;//SPI關
- }
- /*************************
- *
- 度寄存器子函數 *
- 將寄存器的數值讀出 *
- 有參 M表示要讀的寄存器 *
- 有返回值 返回讀出的數據 *
- *
- **************************/
- uchar read_reg_nrf24l01(uchar m)
- { uchar date;
-
- SCK=0;
- CSN=1;
- CSN=0;
- write_spi_2401(m);//讀寄存器
- date=read_spi_2401();
- CSN=1;
- return (date);
- }
-
- /***************************
- *
- 待機模式進入后相關對寄存器 *
- 的設置函數 *
- *
- ****************************/
- void set_Register_tx()//"待機-I模式下的對寄存器的設置 接收機 接收地址是ABABABABAB,通道0,一字節有效數據
- {
-
-
-
-
- // 下段是寄存器設置在待機-I模式完成
-
-
- write_rge_nrf24l01(0x01,0x3f);/*允許所有自動應答開啟*///EN_AA使能自動應答功能
-
- write_rge_nrf24l01(0x02,0x3f);/*允許所有接收地址開啟*///EN_RXADDR接收地址允許
- write_rge_nrf24l01(0x03,0x03);/*所有地址通道的收發地址寬度設為5字節*///STEUP_AW設置地址寬度所有通道
-
- write_rge_nrf24l01(0x04,0x28);/*允許建立自動重發延時為(750+86us)自動重發計數次數為8次*///STEUP_RETR建立自動重發
-
- write_rge_nrf24l01(0x11,0x01);/*接收數據通道0 有效數據寬度 一字節*///RX_PW_P0接收通道0有效數據寬度
-
-
-
-
-
-
-
-
-
- /**********************************************/
- // 本段是對接收機的地址設置在待機-I模式完成
- //
- /**********************************************/
-
-
- /*這里有必要說明下,由于以上的設置寄存器都是一個字節的所以我使用了子函數,這個是發射/接收地址 我沒使用因為上面的只能寫一個字節*/
- SCK=0;//時鐘預選拉低
- CSN=1;
- CSN=0; //SPI開
- write_spi_2401(0x2a);//寫入寫寄存器命令 /* RX_ADDR_P0 數據通道0接收地址設為0xABABABABAB */
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- CSN=1;//SPI關
-
- }
-
-
- void main () //主函數
- {
- uchar i;
- InitUART();//初始化串口
-
-
- SendOneByte(0xf8);//發送標志位
- FLAGE=read_reg_nrf24l01(0x17);//狀態寄存器讀取
- SendOneByte(FLAGE);
- FLAGE=read_reg_nrf24l01(0x07);//狀態寄存器讀取;發射前讀取狀態寄存器
- SendOneByte(FLAGE);
- delay1ms(200);//開機上電復位延時200毫秒后進入掉電模式
-
-
- CSN=1;
- SCK=0;
- CE=0; //發射使能關閉或叫初始化
- write_rge_nrf24l01(0x00,0x0f);/*只允許中斷開啟,CRC使能,16位,PWR_UP=1(上電),PRIM_RX=1(接收模式)*///配置寄存器
-
- delay1ms(50);//此處指著個延時很管用,標志著24L01由掉電模式向待機-I模式轉換的過程,以上是掉電模式一下就是待機-I模式了
-
-
-
-
- set_Register_tx();// 待機1模式下的寄存器配置
-
-
- while(1)
- {
-
-
-
-
- //***********************************************************************
-
-
-
-
-
- CE=1;//進入接收模式
-
- //*888888888888888888888888888888888888888888888888888888
-
- do
- {
- // SendOneByte(0xe8);//發送標志位
- FLAGE=read_reg_nrf24l01(0x07);//狀態寄存器讀取;
- //SendOneByte(FLAGE);
- }
- while((~RX_DR)); //檢查是否接收數據?如果接收到向下,接收不到等待
- CE=0;//進入待機一I模式
-
- write_rge_nrf24l01(0x07,0x4e);/*清除接收中斷信號*/
-
-
- //***********************************
- //這一步是讀FIFO數據,讀完FIFO清空
-
- CE=0;
- SCK=0;
- CSN=1;
- CSN=0;
-
- write_spi_2401(0x61);//讀FIFO寄存器
-
- i=read_spi_2401();
-
- //數據 注意這里我只要發送一個字節的數據,可以最大一次發送32字節 從0字節開始讀
-
-
- CSN=1;
-
- //****************************************
-
- SendOneByte(0xe8);//發送標志位
- FLAGE=read_reg_nrf24l01(0x07);//狀態寄存器讀取;
- SendOneByte(FLAGE);
-
- SendOneByte(i); //發送接收到的數據到PC
-
- }
-
- }
復制代碼
發射機程序:
- /*無線模塊定義*/
- sbit CE=P1^3;//nrf24l01d的模式控制線在 CSN 為低的情況下,CE 協同NRF24L01 的CONFIG 寄存器共同決定NRF24L01 的狀態(參照NRF24L01 的狀態機)
- sbit CSN=P1^4;//nrf24l01d的片選線,低電平有效
- sbit IRQ=P1^5;//nrf24l01d的中斷信號
- /*SPI定義
- */
- sbit SI=P1^0;//MOSI主出-從入
- sbit SO=P1^1;//MISO主入-從出
- sbit SCK=P1^2;// 時鐘信號
- /*無線模塊的狀態位定義
- */
- unsigned char bdata FLAGE;
- sbit MAX_RT=FLAGE^4; //達到最大發送次數置1
- sbit TX_DS=FLAGE^5;//數據發送被置1
- sbit RX_DR=FLAGE^6;//數據接收被置1
- /*可謂操作字節dat定義,用來構成最底層的SPT讀寫函數使用
- */
- unsigned char bdata dat;
- sbit dat_0=dat^0;
- sbit dat_1=dat^1;
- sbit dat_2=dat^2;
- sbit dat_3=dat^3;
- sbit dat_4=dat^4;
- sbit dat_5=dat^5;
- sbit dat_6=dat^6;
- sbit dat_7=dat^7;
- /*串口程序*/
- void InitUART(void)
- {
- TMOD = 0x20;
- SCON = 0x50;
- TH1 = 0xFD;
- TL1 = TH1;
- PCON = 0x00;
- EA = 1;
- ES = 1;
- TR1 = 1;
- }
- void UARTInterrupt(void) interrupt 4
- {
- if(RI)
- {
- RI = 0;
-
- //add your code here!
- }
- else
- TI = 0;
- }
- void SendOneByte(unsigned char c)
- {
- SBUF = c;
- while(!TI);
- TI = 0;
- }
- /*串口程序*/
- /*SPI最底層寫一個字節函數
- 無返回值
- 有參
- 帶形參H
- */
- void delay1ms(uchar time)//1ms
- {
- unsigned char a,b,c,d;
- for(d=time;d>0;d--)
-
- for(c=8;c>0;c--)
- for(b=197;b>0;b--)
- for(a=2;a>0;a--);
- }
- void delay10us(uchar time)//10us
- {
- unsigned char a,b,c;
- for(c=time;c>0;c--)
- for(b=1;b>0;b--)
- for(a=52;a>0;a--);
- }
-
-
- /**********************
- SPI寫一個字節的最底層函數
- 有參
- 無返回值
- ***********************/
- void write_spi_2401(uchar h)//SPI寫一字節函數
- {
- dat=h;
-
- SI=dat_7;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_6;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_5;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
-
- SI=dat_4;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_3;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_2;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_1;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- SI=dat_0;
- delay10us(10);
-
- SCK=0;
- SCK=1;
-
-
- }
- /*****************************
- SPI最底層讀取一個字節
- 返回值是讀出的這一個字節
- 無參
- ******************************/
- uchar read_spi_2401()//SPI讀一字節函數
- {
- SO=1;//初始化SO線
- SCK=1;
- SCK=0;
-
- dat_7=SO;
-
- SCK=1;
- SCK=0;
-
- dat_6=SO;
-
- SCK=1;
- SCK=0;
-
- dat_5=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_4=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_3=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_2=SO;
-
- SCK=1;
- SCK=0;
-
-
- dat_1=SO;
-
- SCK=1;
- SCK=0;
-
- dat_0=SO;
-
- return (dat);//返回讀取數值
- }
- /***************************
- 寫入寄存器命令函數
- 有參
- 無返回值
- m:表示要操作的寄存器地址
- date:表示要向內不寫入的數據
- ****************************/
- void write_rge_nrf24l01(uchar m,uchar date)
- {
- SCK=0;//時鐘預選拉低
- CSN=1;
- CSN=0; //SPI開
- write_spi_2401((0x20+m));//寫入寫寄存器命令
- write_spi_2401(date);//寫入date指向的寄存器數據
- CSN=1;//SPI關
- }
- /**********************
- 度寄存器子函數
- 將寄存器的數值讀出
- 有參 M表示要讀的寄存器
- 有返回值 返回讀出的數據
- ************************/
- uchar read_reg_nrf24l01(uchar m)
- { uchar date;
-
- SCK=0;
- CSN=1;
- CSN=0;
- write_spi_2401(m);//讀寄存器
- date=read_spi_2401();
- CSN=1;
- return (date);
- }
- /*
- 在待機模式下對發射機的寄存器的設置
- 定義了發送地址和應答信號的接收通道和地址*/
- void set_Register_tx()//"待機-I模式下的對寄存器的設置 發射機
- {
-
-
- uchar i;
- /**********************************************/
- // 本段是寄存器設置在待機-I模式完成
- //
- /**********************************************/
-
- write_rge_nrf24l01(0x01,0x3f);/*允許所有自動應答開啟*///EN_AA使能自動應答功能
-
- write_rge_nrf24l01(0x02,0x3f);/*允許所有接收地址開啟*///EN_RXADDR接收地址允許
- write_rge_nrf24l01(0x03,0x03);/*所有地址通道的收發地址寬度設為5字節*///STEUP_AW設置地址寬度所有通道
-
- write_rge_nrf24l01(0x04,0x28);/*允許建立自動重發延時為(750+86us)自動重發計數次數為8次*///STEUP_RETR建立自動重發
-
- write_rge_nrf24l01(0x11,0x01);/*接收數據通道0 有效數據寬度 一字節*///RX_PW_P0接收通道0有效數據寬度
-
-
-
-
-
- /**********************************************/
- // 本段是對FIF0寫入要發送的數據也在在待機-I模式完成
- //
- /**********************************************/
-
-
-
- //***********************************
- for(i=32;i;i--) //這一步是寫32字節的數據到FIFO中,必須使CE=0;重復一次寫一字節,
- { //重復N此寫N字節當然最大是32字節;
- CE=0; //困擾我多日的寫FIFO數據問題解決了2011/2/24/18:47于天津第四項目部宿舍
- SCK=0; //原來那個手冊里的狀態圖是這么的重要啊I服了游!!!!(radio control state diagram)
- CSN=1;
- CSN=0;
-
- write_spi_2401(0xa0);//寫FIFO寄存器
-
-
-
- write_spi_2401(0xcc);//數據 注意這里我只要發送一個字節的數據,可以最大一次發送32字節
-
-
- CSN=1;
- }
- //****************************************
-
-
-
- /**********************************************/
- // 本段是對接收機的地址設置在待機-I模式完成
- //
- /**********************************************/
-
-
- /*這里有必要說明下,由于以上的設置寄存器都是一個字節的所以我使用了子函數,這個是發射/接收地址 我沒使用因為上面的只能寫一個字節*/
- SCK=0;//時鐘預選拉低
- CSN=1;
- CSN=0; //SPI開
- write_spi_2401(0x2a);//寫入寫寄存器命令 /* RX_ADDR_P0 數據通道0接收地址設為0xABABABABAB */
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據 /*這里其實是用來接收接收機的應答的所以要和發送的地址一樣,*/
- write_spi_2401(0xab);//寫入date指向的寄存器數據 /*你想,你要找王均偉,那么你要發送王均偉,王均偉聽見后要回應王均偉*/
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- CSN=1;//SPI關
-
-
- SCK=0;//時鐘預選拉低
- CSN=1;
- CSN=0; //SPI開
- write_spi_2401(0x30);//寫入寫寄存器命令
- write_spi_2401(0xab);//寫入date指向的寄存器數據 /* TX_ADDR 發送地址設為0xABABABABAB */
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- write_spi_2401(0xab);//寫入date指向的寄存器數據
- CSN=1;//SPI關
-
-
-
- }
-
-
- void main () //主函數
- {
-
- InitUART();//初始化串口
- delay1ms(200);//開機上電復位延時200毫秒后進入掉電模式
- delay1ms(200);//開機上電復位延時200毫秒后進入掉電模式
-
-
- CSN=1;
- SCK=0;
- CE=0; //初始化端口
- SendOneByte(0xf8); //發送個標志
- FLAGE=read_reg_nrf24l01(0x17);//狀態寄存器讀取;發射前讀取狀態寄存器
- SendOneByte(FLAGE);
- FLAGE=read_reg_nrf24l01(0x07);//狀態寄存器讀取;發射前讀取狀態寄存器
- SendOneByte(FLAGE);
- write_rge_nrf24l01(0x00,0x0e);/*只允許中斷開啟,CRC使能,8位,PWR_UP=1(上電),PRIM_RX=0(發射模式)*///配置寄存器
-
- delay1ms(50);//此處指著個延時很管用,標志著24L01由掉電模式向待機-I模式轉換的過程,以上是掉電模式一下就是待機-I模式了
-
- while(1)
- {
-
- set_Register_tx();// 待機1模式下的寄存器配置
-
-
-
-
-
-
- //***********************************************************************
-
-
-
-
- CE=1;
- delay10us(2); //進入發射模式數據進行打包準備發送
- CE=0;
- delay10us(15); //130微秒后進入發射模式CE=0;發送完畢后轉到待機一I模式
- //*888888888888888888888888888888888888888888888888888888
-
- do
- {
- SendOneByte(0x88);//發送標志位
- FLAGE=read_reg_nrf24l01(0x07);
- //P0=FLAGE;
- SendOneByte(FLAGE);
- }
- while((~TX_DS)); //檢查是否發送成功?成功向下,否則等待
-
- //*********************************************
- CE=0;//轉到待機-I模式
- write_rge_nrf24l01(0x07,0x2e);/*清除發送中斷信號*/
-
- SCK=0;
- CSN=1;
- CSN=0;
- write_spi_2401(0xe1);//清除TX的FIFO寄存器為下一個包發送做準備
- CSN=1;
-
- SendOneByte(0xe8);//發送標志位
- FLAGE=read_reg_nrf24l01(0x17);//狀態寄存器讀取
- SendOneByte(FLAGE);
- FLAGE=read_reg_nrf24l01(0x07);//狀態寄存器讀取;發射前讀取狀態寄存器
- SendOneByte(FLAGE);
-
- wk=0;
- }
-
- while(1);
-
- }
復制代碼
|