A9139M0 星形組網 1Master to 512 Slave Node

SamYang2024-10-30M0核77
  • 本篇使用A9139M0 製作1 to 512 Network System ,Master (集中器)可以同時連接512個Slave(Node節點ex:溫溼度計) 傳送資料,本系統採用星形組網架構,Master會主動分配設備ID,並主動輪詢每個Slave是否有資料要回傳,當其中一個Slave離線,Master也會主動空出此Slave的ID給其他需要加入的Node分配新的ID

P.S.

1.此系統為1 Master與512 Slave做資料交換系統,彼此Slave Node間是"無法"交涉資料的,資料都需要經過Master轉發才可以,因此若有需要ex:第100 node Slave 要跟第 200 node Slave做資料交換,就需要先經過master才能互相轉發。

2.此組網系統比較適用於1個集中器收集n個Node資料時使用,Node跟Node間不需要做資料交換。

50a76225-38fb-4da3-9c89-dee755b4803f.webp

  • 整體系統的RF傳輸採用雙向的T/RX傳輸,Master會主動Request,Slave收到Request後會Response,也就是說Master負責調度與Slave設備之間的通信。Master決定何時、與哪個Slave設備進行通信,並控制RF資源的分配。

  • 而Slave設備處於被動狀態,它們等待主設備的命令,並根據收到的命令執行相應的操作,如傳輸數據或回應請求,Slave設備僅在Master設備允許或要求時才進行數據傳輸,這可以有效避免數據碰撞和通信衝突。

  • 此系統為一個固定1 to 512資源分配系統,經實測每個Node需要經過"41.31s"後才會主動被Master再次喚醒"做時序對準",時序對準後會再休眠 "0.154 "才會被喚醒進入接收 Master 資料與回傳Slave資料

  • 也就是當Node數未滿512個,每個Node之間還是需要經41.31s+0.154s後才會被動收到Master分配的資源

Demo Code:<RC_A9139M0_x1_433MHz Band Ref. Code for FIFO mode V0.4_1to512_NetworkSystemDemo_ADC_20241029.zip>

  • 此Demo Code為實現Slave端具有ADC Input檢測功能(模擬溫濕度計變化),Master請求Slave將每個Node的ADC 值做回傳收集動作

  • 底下為設定A9139M0的RF 參數與Load Config /InitRF等初始化RF動作,這邊就不再贅述

    ConfigType = SelectConfig;
    __disable_irq();
    // Clear reset flag

		//Initial HW
    InitMCU();
		CrystalSelect();
	
		RFLIB_InitCrystalCL ( 28 ); //CrystalCL 0x1C(20pF)
	  Delay100us ( 5 ); //Delay 500us For Regulator Stabilized   
		RFLIB_Reset ( RF_RST );			
		CalResult = RFLIB_InitRF();
    if ( CalResult ) //Check Return Value In A9139M0_RFLIB.h 
		    Err_State(); 
		
		RFLIB_StrobeCmd ( CMD_STBY );
		
		//User define
		UserRegister();
		PWRCTL1_Reg = A9139M0_Config[INDEX_PWRCTL1].load[ConfigType]; 
                POWER->PWR_TA = 0xAAAAAAAA;
                POWER->PWR_TA = 0x55555555;
                POWER->POWERCTRL1 = PWRCTL1_Reg & 0xFFBFFFFF ;//RGS Bit22 = 0
  •    一些RF基礎設定

    1.寫入RF協議ID,注意這裡的ID指的是RF協議層的ID Code,並非組網的設備ID

    2.設定RF TX power,相關的Tx Power可參考此份App Node,調整對應的TX power參數AN_A9129M0F7_HW_U00 V0.1.pdf 

    3. 設定RF FIFO 長度,這裡設定 55Byte = head 7(6+1) data 48(5+43)共55Byte的Tx/Rx Packet

    4. 需開啟FSK調變

    5. Enable CRC

    6.Enable RTC==>用於睡眠時的計時器

    A9139M0_WriteID();//此ID為RF協議的ID Code並非組網的Slave的ID Node
    TXPower ( 63, 2 , 1);// , SelectConfig); //TBG=12~63 TDC=0~3 PAC=0~1 

    FIFOLength ( RF_Length);
    TXModeSel ( FIFO);// , SelectConfig);
    TXModulation ( ENABLE);// , SelectConfig);

    CODE1_Reg = CODE1_Reg |0x00000009;
    RADIO->CODE1 = CODE1_Reg;//0x3D580309;//CODE1_Reg; CRCS MSCRC

    RTC_Enable();
  • 初始化Link模式,可以使用P0.11來選擇Master/Slave端,也可以不使用P0.11,直接開啟定義_MASTER_MODE_ & 關閉_MASTER_MODE_來定義Master/Slave端,最後將ID_MAC_ADDRESS[5]資料塞入AddressID[0],ID_MAC_ADDRESS[4]資料塞入AddressID[1],後面會將此2 Byte塞入要發射的TX 封包裡當作資料包頭

InitLink();
void InitLink(void)
{
#ifdef _IO_SET_MODE_
    if ( GPIO0->DATA_PIN.P11 ) //master
    {
        InitMaster();
    }
    else  //P0.11=0, slave
    {
        InitSlave();
    }
#else

#ifdef _MASTER_MODE_
        InitMaster();
#else
        InitSlave();
#endif

#endif
    AddressID[0] = ID_MAC_ADDRESS[5];
    AddressID[1] = ID_MAC_ADDRESS[4];
    
}
  • 初始化Uart0 P0.16/P0.17 波特率Uart 8bit, Baud Rate 230400,目的是為了後面輸出UART資料使用

void InitUART0(void)
{
    Uint32 baudrate;

    // 12.8MHz, 230400KHz
    baudrate = 230400; 
    UART0->BAUDDIV = SystemCoreClock / baudrate; 
    UART0->CTRL = 0x0F; 
    GPIO0->ALTFUNCSET |=  BIT16 | BIT17;
    NVIC_EnableIRQ( UART0_IRQn );
}
  • RF_SetBBIO函數是開啟/關閉 gio1,gio2,cko這三隻Pin是要當作RF的State Pin或是普通i/o pin

RF_SetBBIO
  • 組網系統主要分成2大部分,分別為”配對模式” 與 “資料傳送模式

P.S. Master 在每個頻率與 Slave 配對/資料傳送前會先去偵測環境的 RSSI 值,環境的 RSSI 值大於設定值時該頻率不與 Slave 做配對/資料傳送之動作。

  • 開啟adc檢測rssi 值

//Auto Rssi
    ADC_Reg = ADC_Reg & 0xFFFFF0E7;
    ADC_Reg = ADC_Reg | 0x00000018;
    RADIO->ADC = ADC_Reg;//0x00200380;//0x50001240
  • RSSI檢測部分Amiccom已經封裝成"SetMasterTx_RSSI_Threshold"函數,用戶只需要調整此函數的Value則可改變檢測的門檻值預設=150約-75dBm,數值越大,表示檢測的RSSI Power越大,觸發門檻的環境干擾就要越大

SetMasterTx_RSSI_Threshold(150);

image.png

  • 檢測完Rssi後,Master可以主動檢測若未收到Slave Response 回來的次數滿幾次後,就主動認為此Slave已斷線,並將此設備ID讓出來給其他新的Slave使用,使用者可以調整"SetMasterDataLostBackLinkMode"函數來設定此功能

  • 預設=5,表示該Master連續3次發送Request後都未收到Slave端Response ,Master 會將 設備ID釋出。

SetMasterDataLostBackLinkMode(5);
  • 此系統設計Master/Slave的Data Len=48Byte,因此我們需要先執行TxDatatInit函數,將資料寫入MasterSlaveTxBuff,這邊只是先對MasterSlaveTxBuff寫入隨意資料,為了只是填充該數組而已,並非真實要發射的資料

void TxDatatInit(void)
{
    Uint8 i;

    {
        for (i=0;i<DATA_Length;i++)
        {
            MasterSlaveTxBuff[i] = i;//MasterSlaveRxBuff[SlaveNodeNum][i];// | 0x80;
        }
    }
}
  • 啟動Timer0 ,該Timer被用來分配每個Slave交換時間,因此也被Amiccom給封裝起來,這裡只需調用即可

 EnableTimer0();

  • 再開始進入組網時我們還可以調整頻率參數" FreqChannel_Tab[3] ",系統預測使用3個頻點進行跳頻,關於如何設定頻點對應相應的PLL2 PLL3 PLL4 Reg值,可以參考之前介紹過使用Amiccom EK Tool去計算該頻點對應的Value,這邊也會根據之前設定的RSSI_Threshold去決定是否要拋棄某個不乾淨的頻點

const Uint32 FreqChannel_Tab[3] =
{  
  //PLL2  PLL3  PLL4
    0x00875014,  //freq 433.001MHz
    0x00879014,  //freq 433.801MHz
    0x0087D014,  //freq 434.601MHz
};
  • 配對模式介紹:

因為組網的配對流程與如何篩選配對Slave的部分,被Amiccom封裝在MasterProcess()函數裡,這邊只能介紹整體配對的設計概念

  • Master上電後為配對模式,Master系統會自動生成一設備ID與 Slave 端連接後,會將此ID分配給該 Slave,而此 Slave會進入資料傳送模式,Master 工作於資料傳送模式中亦會不定時去偵測有無新的 Slave 加入,並進行配對。

  • 如何配對 :

  • Master 第一次使用時需依序與slave配對,配對方式為Slave上電後收到Master配對Response後完成配對。

  • Master 與Slave 配對後,若有重新上電或是Reset時會重新進入配對連線。

  • Master 在未配對滿全部slave (512 Slave Node)時,都可隨時跟新的Slave 配對。


如何確認該設備ID 狀態 :

使用者可自行透過讀取資料陣列變數NodeState[slot] 確認現在 所有/個別Slot(ID設備)的狀態(可利用迴圈確認所有Slot狀態,單一值確認單個Slot狀態,Slot範圍為0~511)。值為0x01時表示該ID是空的,為0x02時表示該ID已配對已連線傳送資料,為0x04時表示該ID正在配對。

image.png

使用者可從 NodeReceive[slot]、NodeLost[slot]、NodeDisconnect[slot]得知對應Slot(ID設備)的資訊。

NodeReceive[slot]:在資料傳送模式收到資料就會加1,一旦NodeLost[slot]加1就會清為0。

NodeLost[slot]:未接收到資料就會加1,一旦NodeReceive[slot]加1就會清為0。

NodeDisconnect[slot]:從資料傳送模式離開就會加1。

附註:以上三者為8 bit counter 超過255就變為0。

這些數據也都會輸出到UART供使用者Check連線狀態

  • 程式碼會構造 "Data" 開頭的字串,並將節點的"編號"、"接收數據"、"丟失數據"和"斷開數據"格式化後加入到 UartBuffer,同時,若 Flag1.bit.MasterDataOkFlag 為真,則會將主從通信緩衝區(MasterSlaveRxBuff)的數據轉換為十六進制格式,並加入到 UartBuffer 中,最後,使用 UartTx(receive) 將完整的數據發送出去

  • Master Uart內容(目的是為了解測與Slave的連線狀況 & 輸出master要發給slave的資料內容):

void MasterUartOut(void)
{
    Uint16 i;
    Uint8 lost;
    Uint8 receive;
    Uint8 disconnect;
    Uint16 slot;
    
    slot = MasterSlot;   
    {
        lost = NodeLost[slot];
        receive = NodeReceive[slot];
        disconnect = NodeDisconnect[slot];
        
        if (NodeState[slot]==DATA_STATE)
        {
            UartBuffer[0] = 'D';
            UartBuffer[1] = 'a';
            UartBuffer[2] = 't';
            UartBuffer[3] = 'a';
            UartBuffer[4] = '_';
            i = slot;
            if (i>999)
            {
                i = i/1000;
                UartBuffer[5] = '0'+i;
                
            }
            else
            {
                UartBuffer[5] = '0';
            }
            
            i = slot%1000;
            if (i>99)
            {
                i = i/100;
                UartBuffer[6] = '0'+i;
                
            }
            else
            {
                UartBuffer[6] = '0';
            }

            i = slot%100;
            if (i>9)
            {
                i = i/10;
                UartBuffer[7] = '0'+i;
                
            }
            else
            {
                UartBuffer[7] = '0';
            }
            
            i = slot%10;
            UartBuffer[8] = '0'+ i;

            UartBuffer[9] = ' ';
            if (receive>99)
            {
                i = receive/100;
                UartBuffer[10] = '0' + i;
                receive = receive % 100;
            }
            else
                UartBuffer[10] = ' ';
            
            if (NodeReceive[slot]>9)
            {
                i = receive/10;
                UartBuffer[11] = '0' + i;
                receive = receive % 10;
            }
            else
                UartBuffer[11] = ' ';
            UartBuffer[12] = '0'+receive;
            UartBuffer[13] = ' ';
            if (lost>99)
            {
                i = lost/100;
                UartBuffer[14] = '0' + i;
                lost = lost % 100;
            }
            else
                UartBuffer[14] = ' ';
            
            if (NodeLost[slot]>9)
            {
                i = lost/10;
                UartBuffer[15] = '0' + i;
                lost = lost % 10;
            }
            else
                UartBuffer[15] = ' ';
            UartBuffer[16] = '0'+lost;
            UartBuffer[17] = ' ';
            if (disconnect>99)
            {
                i = disconnect/100;
                UartBuffer[18] = '0' + i;
                disconnect = disconnect % 100;
            }
            else
                UartBuffer[18] = ' ';
            
            if (NodeDisconnect[slot]>9)
            {
                i = disconnect/10;
                UartBuffer[19] = '0' + i;
                disconnect = disconnect % 10;
            }
            else
                UartBuffer[19] = ' ';
            UartBuffer[20] = '0'+disconnect;

            receive = 21;
            if (Flag1.bit.MasterDataOkFlag)
            {
                //for (i=0;i<5;i++)
                for (i=0;i<DATA_Length;i++)
                {
                    UartBuffer[receive] = ' ';
                    receive++;
                    lost = (MasterSlaveRxBuff[i])>>4;
                    if (lost>9)
                        UartBuffer[receive] = 'A'+lost-10;
                    else
                        UartBuffer[receive] = '0'+lost;
                    receive++;
                    lost = (MasterSlaveRxBuff[i])&0x0F;
                    if (lost>9)
                        UartBuffer[receive] = 'A'+lost-10;
                    else
                        UartBuffer[receive] = '0'+lost;
                    receive++;
                }
            }
    
            UartBuffer[receive++] = 0x0D;
            UartBuffer[receive++] = 0x0A;
            UartTx(receive);
        
        }
        else
        {
            if (NodeState[slot]==LINK_STATE)
            {
                UartBuffer[0] = 'L';
                UartBuffer[1] = 'i';
                UartBuffer[2] = 'n';
                UartBuffer[3] = 'k';
            }
            else
            {
                UartBuffer[0] = 'A';
                UartBuffer[1] = 's';
                UartBuffer[2] = 's';
                UartBuffer[3] = 'i';
            }

            UartBuffer[4] = '_';

            i = slot;
            if (i>999)
            {
                i = i/1000;
                UartBuffer[5] = '0'+i;
                
            }
            else
            {
                UartBuffer[5] = '0';
            }
            
            i = slot%1000;
            if (i>99)
            {
                i = i/100;
                UartBuffer[6] = '0'+i;
                
            }
            else
            {
                UartBuffer[6] = '0';
            }

            i = slot%100;
            if (i>9)
            {
                i = i/10;
                UartBuffer[7] = '0'+i;
                
            }
            else
            {
                UartBuffer[7] = '0';
            }
            
            i = slot%10;
            UartBuffer[8] = '0'+ i;

            UartBuffer[9] = ' ';
            if (receive>99)
            {
                i = receive/100;
                UartBuffer[10] = '0' + i;
                receive = receive % 100;
            }
            else
                UartBuffer[10] = ' ';
            
            if (NodeReceive[slot]>9)
            {
                i = receive/10;
                UartBuffer[11] = '0' + i;
                receive = receive % 10;
            }
            else
                UartBuffer[11] = ' ';
            UartBuffer[12] = '0'+receive;
            UartBuffer[13] = ' ';
            if (lost>99)
            {
                i = lost/100;
                UartBuffer[14] = '0' + i;
                lost = lost % 100;
            }
            else
                UartBuffer[14] = ' ';
            
            if (NodeLost[slot]>9)
            {
                i = lost/10;
                UartBuffer[15] = '0' + i;
                lost = lost % 10;
            }
            else
                UartBuffer[15] = ' ';
            UartBuffer[16] = '0'+lost;
            UartBuffer[17] = ' ';
            if (disconnect>99)
            {
                i = disconnect/100;
                UartBuffer[18] = '0' + i;
                disconnect = disconnect % 100;
            }
            else
                UartBuffer[18] = ' ';
            
            if (NodeDisconnect[slot]>9)
            {
                i = disconnect/10;
                UartBuffer[19] = '0' + i;
                disconnect = disconnect % 10;
            }
            else
                UartBuffer[19] = ' ';
            UartBuffer[20] = '0'+disconnect;
            UartBuffer[21] = 0x0D;
            UartBuffer[22] = 0x0A;
            UartTx(23);
        }
    }
}

輸出欄位介紹:

Uart輸出“Link_xxx RRR LLL DDD ” ,表示xxx節點在等待Slave配對模式,RRR表示接收到過幾筆資料,LLL表示未接收到過幾筆資料,DDD表示斷線過次數,如下圖。

1.jpg

  • Uart輸出“Assi_xxx RRR LLL DDD ” ,表示xxx節點在Slave配對模式,RRR表示接收到過幾筆資料,LLL表示未接收到過幾筆資料,DDD表示斷線過次數,如下圖。

2.jpg

  • Uart輸出“Data_xxx RRR LLL DDD HH HH HH …..” ,表示xxx節點在Slave 已配對資料傳送模式,RRR表示接收到過幾筆資料,LLL表示未接收到過幾筆資料,DDD表示斷線過次數,HH為MasterSlaveRxBuff[]接收的資料內容。

3.jpg

  • 傳送資料模式

資料傳送模式下Master會在每個Slave傳送48 Bytes 資料,MasterSlaveTxBuff[48]為存放要傳送出去的資料陣列變數,位於MasterTxDatatSet 函數裡

  •  MasterSlaveTxBuff[0] &  MasterSlaveTxBuff[1]被先前介紹的AddressID[0] & AddressID[1]給佔用,因此這裡從 MasterSlaveTxBuff[2]開始填

void MasterTxDatatSet(void)
{
    Uint16 slot;
    Uint8  i;
    
    slot = MasterSlot;

    {
        if (NodeState[slot]==DATA_STATE)
        {
            MasterSlaveTxBuff[2] = MasterSlaveTxBuff[2]+1;
            MasterSlaveTxBuff[3] = MasterSlaveTxBuff[2];
            MasterSlaveTxBuff[4] = MasterSlaveTxBuff[3];
        }
    }
 //使用者可以利用MasterSlaveTxBuff[5]後面的空間buffer塞入想傳送給Slave端的資料,這裡只是假設用個for迴圈++ 5~48的數組而已,使用者可以自行替換掉
    for (i=5;i<DATA_Length;i++)
    {
        MasterSlaveTxBuff[i] = i;//MasterSlaveRxBuff[SlaveNodeNum][i];// | 0x80;
    }
}

當Flag1.bit.MasterDataOkFlag = 1時表示有收到Slave傳送過來的資料,此Flag會在下個slot開始時清除,使用者可自行在系統非忙碌時處理Slave回傳資料。

程式中MasterProcessBusyFlag旗標等於1時表示系統處與送收資料忙碌中,使用者要操作系統需在旗標等於0時操作。


Slave Node端:

  • Slave 第一次使用一樣會處於配對模式,會在三個不同頻率切換連線Master,連線後進入資料傳送模式,Slave設的頻率方式與Master一樣。

  • 配對的流程Code,一樣被寫入SlaveProcess();函數裡,這裡只能介紹說明其流程

1. Slave 一開始會進入Rx搜尋Master作對準時間。

2. 收到MasterData 對準時間後,會隨意產生1~512的數值,之後的1~512 slot(ID設備)來做回應Master配對請求,並得到可配對的slot。

3. 在回應Master配對請求後,會進入休眠到可配對的ID後,才喚醒確認是否可跟Master配對,如果失敗則重新配對。

4. 如果Slave同時多的上電時,則需考慮Slave同時回應問題,同一時間勿超過32個Slave上電,Slave數量越少越少配對碰撞配對失敗狀況

  • 這區塊猜測是在做Slave接收Master的Request資料,因Amiccom原廠並沒有對此區塊多做說明,且代碼函數被封裝起來,無法做詳細說明,姑且先當在做Slave Node Receive的部分

                    if(NodeReceive[SlaveNodeNum] != TestReceiveCnt )
                    {
                        TestReceiveCnt = NodeReceive[SlaveNodeNum];
                        TestDataCnt0++;
                        if (TestDataCnt0==0)
                        {
                            TestDataCnt1++;
                            if (TestDataCnt1==0)
                                TestDataCnt2++;
                        }
                    }
  • 這邊是當Slave收完Master的Request時,開始要向Master Response資料,這裡使用的是一adc輸入值當作是要Response給master的資料內容

                else
                {
                    //Uart output
                    if ((UartOutFlag))
                    {
                        UartOutFlag = 0;
                        SlaveUartOut();
                        
                        while (Uart_TxLen<Uart_TxCnt)
                        {
                            __NOP();//_nop_();
                        }
                        ADC_Val = ADC12B_Measure ( ADC12B, 1 );
                        SlaveTxDatatSet();
                    }
                    SlavePowerDown();
                }
  • SlaveUartOut函數為輸出master傳輸過來的資料,如SlaveNodeNum & Master Request 資料

void SlaveUartOut(void)
{
    Uint8 i;
    Uint8 j;
    Uint8 tmp;
    
        
    UartBuffer[0] = 'D';
    UartBuffer[1] = 'a';
    UartBuffer[2] = 't';
    UartBuffer[3] = 'a';
    UartBuffer[4] = '_';
    if (SlaveNodeNum>9)
    {
        i = SlaveNodeNum/10;
        UartBuffer[5] = '0'+i;
        i = SlaveNodeNum%10;
        UartBuffer[6] = '0'+ i;
        //UartBuffer[5] = '1';
        //UartBuffer[6] = '0'+ SlaveNodeNum-10;
    }
    else
    {
        UartBuffer[5] = '0'+ SlaveNodeNum;
        UartBuffer[6] = ' ';
    }
    UartBuffer[7] = ' ';

    j = 8;
    for (i=0;i<DATA_Length;i++)
    {
        UartBuffer[j] = ' ';
        j++;
        tmp = (MasterSlaveRxBuff[i])>>4;
        if (tmp>9)
            UartBuffer[j] = 'A'+tmp-10;
        else
            UartBuffer[j] = '0'+tmp;
        j++;
        tmp = (MasterSlaveRxBuff[i])&0x0F;
        if (tmp>9)
            UartBuffer[j] = 'A'+tmp-10;
        else
            UartBuffer[j] = '0'+tmp;
        j++;
    }

    UartBuffer[j++] = 0x0D;
    UartBuffer[j++] = 0x0A;
    UartBuffer[j++] = 0xFF;
    UartTx(j);
}
  • ADC使用A9139M0的Pin 0.19當作輸入pin,這部分可以根據使用者的需求加入應用代碼,不一定是ADC功能,也可以是其他SPI/I2C/IO中斷檢測等(這裡只是用ADC當作Demo而已)

ADC_Val = ADC12B_Measure ( ADC12B, 1 );
uint32_t ADC12B_Measure(ADC12B_Type *adc12b, uint32_t ch)
{
    uint32_t control = 0;
    uint32_t mvadc;

    adc12b->Control = ADC12B_CONTROL_ADC12RN_Msk;   // ADC reset
    control = ADC12B_CONTROL_ADCE_Msk |         // start ADC measure
            (6 << ADC12B_CONTROL_VADS_Pos) |    // Ref Voltage = 1.8V
            (3 << ADC12B_CONTROL_MVS_Pos) |     // Average 8 times
            (0 << ADC12B_CONTROL_CKS_Pos) |     // clock 3.2MHz
            ADC12B_CONTROL_ENADC_Msk |          // ADC clock on
            ADC12B_CONTROL_MODE_Msk;            // continue mode

    switch(ch)
    {
        case 0:
            GPIO0->OUTENABLECLR = ( 1 << 18 );  // set to input
            GPIO0->PUN_PIN.P18 = 1;             // disable pull-high
            break;
        case 1:
            GPIO0->OUTENABLECLR = ( 1 << 19 );  // set to input
            GPIO0->PUN_PIN.P19 = 1;             // disable pull-high
            break;
        case 2:
            GPIO0->OUTENABLECLR = ( 1 << 8 );   // set to input
            GPIO0->PUN_PIN.P08 = 1;             // disable pull-high
            break;
        case 3:
            GPIO0->OUTENABLECLR = ( 1 << 9 );   // set to input
            GPIO0->PUN_PIN.P09 = 1;             // disable pull-high
            break;
        case 4:
            GPIO0->OUTENABLECLR = ( 1 << 12 );  // set to input
            GPIO0->PUN_PIN.P12 = 1;             // disable pull-high
            break;
        case 5:
            GPIO0->OUTENABLECLR = ( 1 << 13 );  // set to input
            GPIO0->PUN_PIN.P13 = 1;             // disable pull-high
            break;
        case 6:
            GPIO0->OUTENABLECLR = ( 1 << 14 );  // set to input
            GPIO0->PUN_PIN.P14 = 1;             // disable pull-high
            break;
        case 7:
            GPIO0->OUTENABLECLR = ( 1 << 15 );  // set to input
            GPIO0->PUN_PIN.P15 = 1;             // disable pull-high
            break;
    }
    adc12b->ADCIOS = ((ch << ADC12B_IOSEL_CH_Pos) & ADC12B_IOSEL_CH_Msk) | ADC12B_IOSEL_EN_Msk;

    adc12b->Control = control;                  // ADC measure start

    //-----------------------------------------------------
    // Delay for ADC measure
    // delay time = 2*(32*8)/3.2M = 160us
    Delay10us(16);
    //-----------------------------------------------------

    mvadc = adc12b->ValueItem.MVADC;            // read mvadc value
    adc12b->Control = 0;                        // close ADC 12Bits
    adc12b->ADCIOS = 0;                          // close ADC channel

    return mvadc;
}
  • 檢測完ADC後再將其值塞入SlaveTxDatatSet函數中的MasterSlaveTxBuff裡,這裡是ADC的Low Byte寫在 MasterSlaveTxBuff[5],High Byte寫在 MasterSlaveTxBuff[6]傳給Master,前面[0]~[1]為ID MAC固定格式,[2]~[4]為計算接收到過幾筆資料,未接收到過幾筆資料,斷線過次數,[5]~[6]=ADC檢測值,[7]~[47]=使用者可自行定義封包值

void SlaveTxDatatSet(void)
{
    Uint8 i;
    
    /*for (i=0;i<DATA_Length;i++)
    {
        MasterSlaveTxBuff[SlaveNodeNum][i] = MasterSlaveRxBuff[SlaveNodeNum][i];// | 0x80;
    }*/
    MasterSlaveTxBuff[0] = AddressID[1];//ID_MAC_ADDRESS[6];
    MasterSlaveTxBuff[1] = AddressID[0];//ID_MAC_ADDRESS[7];
    MasterSlaveTxBuff[2] = TestDataCnt0;
    MasterSlaveTxBuff[3] = TestDataCnt1;
    MasterSlaveTxBuff[4] = TestDataCnt2;
    
    ADC_Val_L = (Uint8)ADC_Val;
    ADC_Val_H = (Uint8)(ADC_Val>>8);
    MasterSlaveTxBuff[5] = ADC_Val_L;
    MasterSlaveTxBuff[6] = ADC_Val_H;
    
    for (i=7;i<DATA_Length;i++)
    {
        MasterSlaveTxBuff[i] = i;//MasterSlaveRxBuff[SlaveNodeNum][i];// | 0x80;
    }
}
  • Slave發送完1包給master後主動進入休眠模式SlavePowerDown,等待下次Master的Request 

SlavePowerDown();

補充Slave端還有以下參數可以調整

設定連續未收到資料次數:

使用者可以利用SetSlaveDataLostBackLinkMode fucntion來設定連續未收到資料次數,預設連續5次喚醒都未收到則會重新進入配對模式。

SetSlaveDataLostBackLinkMode(5);

設定配對時間:

使用者可以利用 SetSlaveLinkTimeout function 來設定配對時間,預設如果 6000 秒內都未連線 Master,則會離開配對模式進入休眠模式。

SetSlaveLinkTimeout(6000);

image.png

  • 設定休眠時間與配對周期 :

    Slave休眠一段時間後會重新醒來配對,使用者可以利用"SetSlaveReLinkSleepTimer"設定重新配對周期。配對周期是配對時間加上休眠時間,預設6000秒配對時間與10秒休眠時間,則配對周期是6010秒。

SetSlaveReLinkSleepTimer(10);

image.png

  • 設定配對周期次數 :

使用者可以利用SetSlaveReLinkTime function來設定配對周期次數,預設3週期未連線後則完全休眠不再喚醒,需重新上電或Reset才可回到配對模式。(也就是徹底放棄掉此Slave端設備,直到Slave重新上電進入配對)

SetSlaveReLinkTime(5);
  • 配對成功時會得到分配的節點編號存放在"SlaveNodeNum"變數中

傳送資料模式:

  • 在資料傳送模式下可以接收Master傳送的48 Bytes 資料,資料存放在MasterSlaveRxBuff[]數組裡,使用者可在系統非忙碌時處理接收Master傳送的資料。

  • 在接收完也可以傳送48 Bytes資料給Master。使用者可在SlaveTxDatatSet 函數中透過MasterSlaveTxBuff[]數組夾帶要傳給master端的資料內容


到此我們就完成1跟Master如何Request Slave Node,並且Slave如何Response資料給Master,也算是一種多次Request/ Response來回傳遞的組網系統。

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。