<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        無線射頻芯片CC1100e的編程

        作者:xuchen   來源:xuchen的blog   點擊數:  更新時間:2014年05月28日   【字體:
        CC1100e通過SPI方式與MSP430進行通信的。首先需要明白讀寫寄存器的過程:寫寄存器時,先寫寄存器的地址,然后寫數據,這樣數據就到了所要寫的寄存器當中了。同樣,讀寄存器時,先讀寄存器的地址,由于同步通訊,相應寄存器中的數據在讀寄存器地址的下個周期就自動讀出。

        SPI接口上進行所有事務均以一個報頭字節作為開始:BIT7~BIT0,在SPI總線上傳輸數據期間,CSN引腳必須保持低電平。

        寄存器的配置:
        CC1100 寄存器地址是0~0x3F,也就是BIT0~BIT5
        CC1100 讀寫控制是BIT7,BIT7 為1 時,為讀對應的寄存器,BIT7 為0 時,為寫相應的寄存器。
        BIT6 是突發訪問控制位,BIT6 為1 為突發訪問,BIT6為0 為單字節訪問。
        其中,SPI地址為0x00~0x2E之間的為配置寄存器,對于配置寄存器均能進行讀取和寫入操作。讀取還是寫入操作由上述的BIT7控制。寫入寄存器時,每當一個報頭字節或數據字節通過MOSI引腳發送時 狀態字節便會通過MISO 引腳完成發送。當讀取寄存器時,每當一個報頭字節通過MOSI引腳發送時狀態字節便會通過MISO引腳完成發送。通過設置報頭字節的突發位BIT6可以高效的存取帶連續地址的寄存器。地址位BIT5~BIT0在內部地址計數器內設置起始地址,每增加一個新的字節(8個時鐘脈沖),計數器便增加1.突發存取可以是一次讀取也可以是一次寫入,但必須通過設置CSN為高電平來進行終止。
        例如:配置IOCFG2寄存器,其地址0x00,我們突發訪問寫的話寫先數據0x40,再連續寫數據就可以了;如果單字節讀這個寄存器,先寫數據0x80,再讀一下就可讀出其值了。

        命令濾波(指令選通脈沖):
        通過尋址一條指令選通脈沖寄存器,啟動內部序列。即cc1100 只要寫一下對應的寄存器的地址,不用寫數據,它就內部自動執行相應的指令,比如重啟芯片,設置為發送模式等等,共有14 個濾波指令,地址從0x30~0x3D。
        而濾波指令的狀態寄存器是可讀不可寫的,也就是0x30~0x3D 的地址加上0xC0,比如寫數據0xF4,就可以讀到相應RSSI (0x34)狀態寄存器里面的值。

        狀態字節:
        狀態字節包含一些關鍵的狀態信號,當通過SPI接口發送報頭字節、數據字節或指令選通脈沖時,CC1100e的狀態字節通過MISO引腳發送。狀態字節的最后四位(3:0)FIFO_BYTES_AVAILABLE,進行讀取操作時,報頭字節的BIT7設置為1,FIFO_BYTES_AVAILABLE域包含了可從FIFO讀取的字節數。進行寫操作時,FIFO_BYTES_AVAILABLE字段包含了可寫至TX FIFO的字節數。當FIFO_BYTES_AVAILABLE=15時,表示15或更多的字節為可用字節。

        FIFO存。
        關于FIFO的訪問,其分為TX FIFO和RX FIFO。64字節的TX FIFO和64字節的RX FIFO均通過0x3F地址進行存取。對其既可以通過單字節訪問也可以通過突發訪問。當讀寫控制位BIT7為1時訪問的是RX FIFO,BIT7是0時訪問的TX FIFO。這樣得到下列報頭字節:0x3F為單字節訪問TX FIFO,0xBF為單字節訪問RX FIFO,0x7F為突發訪問TX FIFO,0xFF為突發訪問 RX FIFO。
        當對TX FIFO進行寫入操作時,每個數據字節的狀態字節均在MISO上輸出。該狀態字節用于檢測TX FIFO寫數據時的下溢。狀態字節包含將其寫入TX FIFO過程以前自由的字節數,當可寫入TX FIFO的最后一個字節在MOSI上發送時,與此同時在MISO引腳上接收到的狀態字節將表明TXFIFO中存在一個自由字節。TX FIFO可能會由于寫入一條SFTX指令選通脈沖而被刷新,同樣,一條SFRX指令選通脈沖也會刷新RX FIFO。

        PTABLE存。
        0x3E地址用于存取PATABLE,用來設置發射功率的。接收到此地址之后,SPI要求有高達8個數據字節。PATABLE是一個8字節表,其定義了PA控制設置。讀寫還是通過讀寫控制位BIT7控制,突發訪問還是單字節訪問還是通過突發位BIT6來控制。內部有個計數器用來控制對該表的存取,每讀取或寫入該表中一個字節,計數器就自動加1,當計數到7時會自動從0開始計數.當設置Csn為高電平時,內部計數器會變為0.如果向PTABLE寫入一個字節,并且要讀取該值,那么在讀取存取以前必須將CSN設置為高電平,以將計數器重新設置為0.

        數據包格式:
        由cc1100的datasheet可以知道,其數據包是由前導碼、同步字節、可選的數據包長度、可選的目標地址、數據區以及兩個字節的CRC校驗碼。前導碼的最小長度可以通過MDMCFG1.NUM_PREAMBLE的值進行編程。當開啟TX模式時,調制器將開始發送前導碼。當編程的前導字節數被發送完畢后,調制器將開始發送同步字節,然后發送來自TX FIFO的數據。若TXFIFO為空,調制器將繼續發送前導碼,知道第一個字節被寫入TX FIFO為止,調制器隨后發送同步字,然后發送數據字節。
        同步字是設置于SYNC1和SYNC0兩個寄存器中的2字節值。在可變數據包長度模式下,通過同步字后面的第一個字節來配置數據包長度。數據包長度被定義為有效負載數據,但不包括長度字節和可選CRC。PKTLEN寄存器用于設置RX模式中允許的最大數據包長度。任何長度字節值大于PKTLEN的接收數據包將被丟棄。

        接收模式下的數據包濾波:
        CC1100e支持三種不同類型的濾波:地址濾波、最大長度濾波和CRC濾波。
        地址濾波:設置PKTCTRL1.ADR_CHK為0以外的任何值均可開啟數據包的地址濾波器。radio將目標地址字節與ADDR寄存器中地址,以及PKTCTRL1.ADR_CHK=10時的0x00廣播地址或者PKTCTRL1.ADR_CHK=11時的0x00和0xff廣播地址進行比較。如果接收的地址匹配一個有效地址,則接收該數據包,并將其寫入RX FIFO,如果地址匹配失敗,則丟棄該數據包,并重新啟動接收模式。
        最大長度濾波:在可變數據包長度模式下,PKTLEN.PACKET_LENGTH寄存器的值用來設置最大允許數據包長度,當接收字節值比這個值大,則數據包被丟棄,并且重新啟動接收模式。
        CRC濾波:(不懂,不寫

        發送模式下的數據包處理:
        必須要將即將發送的有效數據長度寫入TX FIFO中,開啟可變數據包長度以后,長度字節必須最先被寫入。長度字節具有一個與數據包有效負載相當的值。如果接收機端開啟了地址識別,則寫入TX FIFO的第二個字節必須為地址字節。如果開啟了固定數據包長度,則寫入TX FIFO的第一個字節應為地址字節。
        調制器會首先發送編程的前導字節數,如果TX FIFO中的數據可用,則調制器會發送兩個字節同步字,之后是TX FIFO 中的有效負載。如果開啟了CRC,則在所有取自TXFIFO的數據上計算驗和,并在有效負載之后以兩個額外字節發送該結果。如果TXFIFO在發送完全部數據包以前變為空,那么該無線電設備將進入TXFIFO_UNDERFLOW狀態。退出該狀態的唯一方法是發出一個SFTX選通脈沖。

        接收模式下的數據包處理:
        在接收模式下,解調器和數據包處理器將會搜索一個有效的前導和同步字。如果找到,解調器就獲得了位和字節同步機制,并將接收第一個有效負載字節。當可變數據包長度模式開啟時,則第一個字節為長度字節。數據包處理器把這個值作為數據包長度存儲,并接收該長度字節線束數目的字節。

        固件中的數據包處理:
        在固件中執行數據包導向無線協議時,MSP430需要知道一個數據包何時被接收到、何時被發送出去。當數據包長度大于64字節時,需要在RX模式下讀取RX FIFO,需要在TX模式下重填TXFIFO。
        中斷驅動法:當通過設置IOCFGx.GDOx_CFG=0x06接收到或發送出去一個同步字或接收到發送出去一個完整的數據包時,在RX和TX模式下均可使用GDO引腳來實現中斷。
        SPI輪詢:可以某個給定速率對PKTSTATUS寄存器輪詢,以獲取GDO2和GDO0當前值的相關信息?梢阅硞給定速率對RXBYTES和TXBYTES寄存器輪詢,以獲取RXFIFO和TXFIFO中所含字節數的相關信息。另外,在SPI總線上每發送一個報頭字節、數據字節或指令選通脈沖時,可從MISO線路上返回的芯片狀態字節讀取到RXFIFO和TXFIFO中所含的字節數。


        具體編程時必須注意一下事項:
        1、拉低CSN引腳電平時,在開始傳輸報頭字節以前,msp430必須等待SISO引腳變為低電平為止,表明內部穩定。
        2、每當一個字節通過SI引腳寫入到寄存器時,狀態字節將被送到MISO引腳
        3、狀態字節的最后4位用來表示FIFO的可用字節,其最大值是15,此時表示15或更多的字節是可以使用的。
        4、只有radio處于XOSC空閑,并且數字中心的能量開啟,其他模塊處于功率降低狀態,這時候頻率和信道配置才能被更新。(不是很理解)
        5、寄存器的突發訪問時,內部計數器會自動設置起始地址,每增加一個字節,地址會自動加1,無論讀寫操作,必須通過拉高Csn終止操作。
        6、關于命令濾波,其實是單字節指令,通過指令對寄存器的選址,內部功能做出相應的啟動或關閉。不像對其他寄存器一樣必須先寫地址后寫數據。
        7、當radio進入休眠狀態時,兩個FIFO都被刷新為空。
        8、一般所有的濾波命令會立即執行,只有休眠濾波命令SPWD不會立即執行,它會延遲到Csn為高電平時執行。




        部分程序如下:
        //SPI讀取和發送函數
        unsigned int SpiTxRxByte(unsigned data)
        {
         unsigned char i,temp;
         temp=0;
         SCK_0;
         for(i=0;i<8;i++)
          {
           if(data&0x80)
             {
              MOSI_1; 
             }
           else
            {
             MOSI_0;
            }
           data<<=1;
           SCK_1;
           temp<<=1;
           if(MISO)temp++;
           SCK_0;
          }
         teturn temp;
        }

        //重啟芯片函數
        void RESET_CC1100(void)
        {
         CSN_0;
         while(MISO);
         SpiTxRxByte(SRES);
         while(MISO);
         CSN_1;
        }

        //上電重啟芯片函數
        void POWER_UP_RESET_CC1100(void)
        {
        CSN_1;
        delayus(1);
        CSN_0;
        delayus(1);
        CSN_1;
        delayus(41);
        ESET_CC1100();
        }

        //單字節寫寄存器函數
        void SpiWriteReg(unsigned char addr,unchar int value)
        {
         CSN_0;
         while(MISO);
         SpiTxRxByte(addr); //寫入地址
         SpiTxRxByte(value);//寫入配置
         CSN_1;
        }

        //突發訪問方式寫寄存器函數
        void SpiWriteBurstReg(unsigned int addr,unsigned int *buffer,unsigned int count)
        {
         unsigned int i,temp;
         temp=addr|0x40;//將突發訪問位置1
         CSN_0;
         while(MISO);
         SpiTxRxByte(temp);
         for(i=0;i<count;i++)
           {
            SpiTxRxByte(buffer[i]);
           }
         CSN_1;
        }

        //寫命令濾波函數
        void SpiStrobe(unsigned int strobe)
        {
         CSN_0;
         while(MISO);
         SpiTxRxByte(strobe);
         CSN_1;
        }

        //單字節讀寄存器函數
        unsigned int SpiReadReg(unsigned int addr)
        {
         unsigned int temp,value;
         temp=addr|0x80;
         CSN_0;
         while(MISO);
         SpiTxRxByte(temp);
         value=SpiTxRxByte(0);
         CSN_1;
         return value;
        }

        //突發訪問讀寄存器函數
        void SpiReadBurstReg(unsigned int addr,unsigned int *buffer,unsigned int count)
        {
         unsigned int i,temp;
         temp=addr|0xc0;
         CSN_0;
         while(MISO);
         SpiTxRxByte(temp);
         for(i=0;i<count;i++)
          {
           buffer[i]=SpiTxRxByte(0);
          }
        CSN_1;
        }

        //讀寄存器狀態函數
        unsigned int SpiReadStatus(unsigned int addr)
        {
         unsigned int value,temp;
         temp=addr|0xc0;
         CSN_0;
         while(MISO);
         SpiTxRxByte(temp);
         value=SpiTxRxByte(0);
         CSN_1;
         return value;
        }

        //
        //
        //CC1100發送一組數據的函數
        void RFSpiSendPacket(unsigned int *txbuffer,unsigned int size)
        {
         SpiWriteReg(TXFIFO,size);//是否和下句沖突?
         SpiWriteBurstReg(TXFIFO,txbuffer,size);//寫入要發送的數據
         SpiStrobe(STX);//進入發送模式發送數據
         //wait for GDO0 to be set--->sync transmitted
         while(!(GDO0));
        //wait for GDO0 to be cleared--->end of packet
         while(GDO0);
         SpiStrobe(SFTX);//沖洗 TXFIFO
        }

        //
        //
        //
        //CC1100接收一組數據
        unsigned int RFReceivePacket(unsigned int *rxbuffer,unsigned int *length)
        {
         unsigned int status[2];
         unsigned int packetlength;
         unsigned int i=(*length)*4;
         SpiStrobe(SRX);//進入接收狀態
         delayus(2);
         while(GDO0)
          {
            delayus(2);
            --i;
           if(i<1)
           return 0;
          }
        if((SpiReadStatus(RXBYTES)&0x7F))//如果接的字節數不為0
          {
           packetlength=SpiReadReg(RXFIFO);//讀出第一個字節,此字節為該幀數據長度
           if(packetlength<=*length)
               {
                SpiReadBurstReg(RXFIFO,rxbuffer,packetlength);//讀出所有接收到的數據
                *length=packetlength;
                SpiReadBurstReg(RXFIFO,status,2);//讀出CRC校驗位
                SpiStrobe(SFRX);//清洗接收緩沖區
                return(status[1]&0x80);//如果校驗成功 返回接收成功
               }
           else
               {
                *length=packetlength;
                SpiStrobe(SFRX);//清洗接收緩沖區
                return 0;
               }
         
         else
          return 0;
        }
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮