專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

ZigBee模塊通信實(shí)現(xiàn)(電路介紹與程序分析)

作者:未知   來源:不詳   點(diǎn)擊數(shù):  更新時(shí)間:2015年01月10日   【字體:

 產(chǎn)品名:ZigBee模塊

型號(hào):ZICM2410 PO-2

廠商:廣州周立功公司代理(美國CEL公司的MeshConnect模塊)

參數(shù):

 

*  103db鏈路預(yù)算;

*  接收靈敏度:-97dbm@ 1.5V

*  發(fā)送功率:+6dbm@1.5V

*  3000英尺無障礙傳輸距離

*  最低睡眠電流:<1μA

*  工作電壓:2.1~3.3V

*  接收電流:35mA

*  發(fā)送電流:44mA

*  速率:ZigBee (250 kbps)、Turbo(500 kbps)、Premium (1 Mbps)

*  接口類型:SPI(主從)、UART(2路)、I2S/PCM

 

支持語音傳送:

        語音編解碼器支持u律、a律、ADPCM

16條射頻通道

傳送范圍:3000英尺  = 914.4米

支持AES128位加密

ZICM2410 支持的數(shù)據(jù)通信接口:

    UART0\UART1(1M)、I2S、SPI(2M)、GPIO、AD(4路)、IIS


描述:Zigbee網(wǎng)絡(luò)基于IEEE 802.15.4國際標(biāo)準(zhǔn)、上層協(xié)議為ZigBee協(xié)議棧,具有低功

            耗,低速率,高可靠性,網(wǎng)絡(luò)路由功能強(qiáng)大,自恢復(fù)及冗余性能優(yōu)異等特點(diǎn),廣泛應(yīng)用低

            數(shù)據(jù)率監(jiān)控的各個(gè)領(lǐng)域。


ZigBee 物理連接:

     ZigBee 模塊是通過串口的形式與微處理器通訊,在LPC11C14 開發(fā)板這里是通過 SC16IS752IPW 芯片 轉(zhuǎn)成 SPI 協(xié)議與 微處理器通訊。

     ZigBee 模塊(ZICM2410 PO-2) <------串口-----> SC16IS752IPW 芯片 <------SPI-----> LC11C14(ARM M0內(nèi)核)










 
 
從原理圖可以看出,ZigBee模塊的RXD\TXD接在了SC16IS752IPW芯片的RXB\TXB上,
而該芯片的CS\SI\SO\SCLK接在LPC11C14的PIO2_0\PIO2_1\PIO2_2\PIO2_3\PIO3_3上。
 
 
說明LPC11C14主控芯片是通過SPI間接與ZigBee模塊通訊,所以我們只需要關(guān)注SC16IS752IPW芯片即可,
往該芯片發(fā)送數(shù)據(jù),ZigBee自然也能收到數(shù)據(jù)。
 
數(shù)據(jù)流向:應(yīng)用程序 <---讀寫寄存器---> M0的SPI控制器  <---SPI---> SC16IS752IPW  <---串口---> ZigBee模塊
 
程序流程:
    1、初始化LPC11C14的SSP1 的GPIO引腳,即 PIO2_0\PIO2_1\PIO2_2\PIO2_3
/* 初始化響應(yīng)PIO引腳 ssp.c  */ 
 /* arg1:SSPI0或SSPI1  */
void SPI_IOConfig(uint8_t portNum)
{
  if(portNum == 0)
  {
       /* 此處為通道0的代碼 未貼出 */
  }
  else/* port number 1 */
  {  // 主要設(shè)置 SSP1 使之能與 SC16IS752IPW 通信 間接與 ZigBee 通信
LPC_SYSCON->PRESETCTRL    |= (0x1<<2);  // bit2=1 SSP1復(fù)位取消 bit2=0 復(fù)位SSP1
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18);// 使能SSP1的時(shí)鐘
LPC_SYSCON->SSP1CLKDIV     = 0x02;/* Divided by 2 設(shè)置 SSP1 時(shí)鐘分頻 48Mhz/2=24Mhz*/
LPC_IOCON->PIO2_2         &= ~0x07;/*  SSP I/O config */
LPC_IOCON->PIO2_2         |= 0x02;/* SSP MISO  將PIO2_2設(shè)置為 SSP MISO 模式*/
LPC_IOCON->PIO2_3         &= ~0x07;
LPC_IOCON->PIO2_3         |= 0x02;/* SSP MOSI  將PIO2_3設(shè)置為 SSP MOSI 模式*/
LPC_IOCON->PIO2_1         &= ~0x07;
LPC_IOCON->PIO2_1         |= 0x02;/* SSP CLK  將PIO2_1設(shè)置為 SSP 時(shí)鐘 */
 
/* Enable AHB clock to the GPIO domain. */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);  // 使能GPIO時(shí)鐘 使之產(chǎn)生時(shí)鐘
 
LPC_IOCON->PIO2_0 &= ~0x07;/* SSP SSEL is a GPIO pin 設(shè)置PIO2_0 作為普通IO管腳功能 */
/* port2, bit 0 is set to GPIO output and high */
GPIOSetDir( PORT2, 0, 1 );   // 設(shè)置為輸出
GPIOSetValue( PORT2, 0, 1 );   // 輸出高電平 暫時(shí)不使能 該器件 是片選引腳
  }
}

    2、初始化 SSP1 寄存器 ssp.c 
             /* arg1:SSPI0或SSPI1       arg2:傳送位數(shù)          arg3:時(shí)鐘分配 */
        void SPI_Init(uint8_t portNum, uint8_t Bit, uint8_t EvenDiv)
        {
              uint8_ti, Dummy=Dummy;
              if(portNum == 0)
              {
                     /* 此處為通道0的代碼 未貼出 */
              }
              else
             {
LPC_SSP1->CR0 = 0x0700 | (Bit-1); // (Bit-1)=0b0111 8位傳輸 串行時(shí)鐘速率、總線類型、數(shù)據(jù)長度
LPC_SSP1->CPSR = EvenDiv;  // 時(shí)鐘預(yù)分頻寄存器 設(shè)置為2分頻  -> 48Mhz/2=24Mhz
for ( i = 0; i < SSP_FIFOSIZE; i++ )
{
  Dummy = LPC_SSP1->DR;/* clear the RxFIFO 數(shù)據(jù)寄存器,讀空則接受FIFO 寫滿則發(fā)送 FIFO */
}
NVIC_EnableIRQ( SSP1_IRQn );// 使能中斷
LPC_SSP1->CR1 = SSPCR1_SSE; // SSP1以正常模式與串行總線上的其它設(shè)備相互通信。
LPC_SSP1->IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM; // 中斷觸發(fā)條件:接受上溢 接受超時(shí)觸發(fā)中斷
              }
        }

    3、SSP1讀寫 SC16IS752IPW 芯片
        3.0:SC16IS752IPW  時(shí)序圖
                寫寄存器時(shí)序圖:
 

                  
 
                讀寄存器時(shí)序圖
                   
 
              數(shù)據(jù)格式:
                  
 
        3.1:SSP1 讀寫寄存器
                /* 操作*/
                 /* arg1:SSPI0或SSPI1       arg2:數(shù)據(jù) */
uint16_t SPI_PutGet(uint8_t portNum, uint16_t SendData)
{
  if(portNum == 0)
  {
 /* 此處為通道0的代碼 未貼出 */
  }
  else
  {
/* Move on only if NOT busy and TX FIFO not full. */
// SSP1控制器不忙 發(fā)送FIFO未滿、發(fā)送FIFO不為空 就跳出循環(huán)
while((LPC_SSP1->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF);
LPC_SSP1->DR = SendData;//寫入數(shù)據(jù)
/* Wait until the Busy bit is cleared. */
while(LPC_SSP1->SR & SSPSR_BSY); // 等待總線不忙
 
/* Wait until the Busy bit is cleared */
// 等到接受FIFO不為空后跳出循環(huán)
while((LPC_SSP1->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE);
return LPC_SSP1->DR;// 將數(shù)據(jù)讀出
  }
}
 
        3.2:寫寄存器時(shí)序流程(主要涉及 SCLK、MIOS)
1、片選選中 SC16IS752IPW
2、往SPI數(shù)據(jù)寄存器寫數(shù)據(jù)
2.1 MIOS 寫 SC16IS752IPW THR 寄存器地址
    寫位(1bit) + SC16IS752IPW THR 寄存器地址(4bit) + 通道選擇(2bit) + X
2.2 寫 8位數(shù)據(jù)
3、取消片選
    /* 往指定的 SC16IS752IPW 寄存器中寫數(shù)據(jù) */
       /* arg1:SSPI0或SSPI1       arg2:SC16IS752IPW 寄存器     arg3:寫入的數(shù)據(jù)*/
void SPI752_RegWrite(uint8_t Channel, uint8_t Reg, uint8_t Data)
{
  SPI_UART_CS(0);// 片選選中 SC16IS752IPW 
  SPI_PutGet(1, SPI752_WRITE | (Reg<<3) | (Channel<<1));// 寫寄存器
  SPI_PutGet(1, Data);// 寫數(shù)據(jù)
  SPI_UART_CS(1);// 取消片選
}
 
3.3:讀寄存器時(shí)序(主要涉及 SCLK、MIOS、MOIS)
1、片選選中 SC16IS752IPW
2、往SPI數(shù)據(jù)寄存器寫數(shù)據(jù)
2.1 MIOS 寫 SC16IS752IPW RHR 寄存器地址
    讀位(1bit) + SC16IS752IPW  RHR 寄存器地址(4bit) + 通道選擇(2bit) + X
2.2 MOSI 讀出 8位數(shù)據(jù)
3、取消片選
        /* 讀數(shù)據(jù) */
        /* arg1:SSPI0或SSPI1       arg2:SC16IS752IPW 寄存器 */
uint8_t SPI752_RegRead(uint8_t Channel, uint8_t Reg)
{
  uint8_trd;
 
  SPI_UART_CS(0);// 片選選中 SC16IS752IPW
  SPI_PutGet(1, SPI752_READ | (Reg<<3) | (Channel<<1)); // 寫寄存器地址
  rd = SPI_PutGet(1, 0);// 取出數(shù)據(jù)
  SPI_UART_CS(1);// 取消片選
  return rd;
}
 
 
   4、通過SSP1 初始化  SC16IS752IPW
        完成SSP1初始化后,就能通過SSP1與 SC16IS752IPW 通訊,,從而初始化該芯片
/*******************************************************************************
* Function Name  : SPI752_Init
* Description    : Set channel 0 & 1 baud rate. The range is 300-230400 Baud.
*                  The crystal input frequency is 14745600Hz.
*   The default value of prescaler after reset is divide-by-1.
*                  The format is: 8N1
* Input          : - Channel : 0 & 1.
*                  - Baud : 300-230400 Baud.
* Output         : None
* Return         : None
* file           :ssp.c 
*******************************************************************************/
/* arg1:SSPI0或SSPI1       arg2:波特率 */
void SPI752_Init(uint8_t Channel, uint32_t Baud)
{
  uint16_trd;
 
  // Disable sleep
  // 設(shè)置 數(shù)據(jù)通信的格式 1 0 1 1 1 1 11   奇葩的設(shè)置。。。
  // 除數(shù)鎖存使能 沒有TX間隔條件 奇偶位強(qiáng)制為0 偶數(shù)格式 奇偶位 1個(gè)停止位 8位
  SPI752_RegWrite(Channel, SPI752_LCR_RW, 0xBF);
 
  // 使能增強(qiáng)型功能
  rd = SPI752_RegRead(Channel, SPI752_EFR_RW);
  SPI752_RegWrite(Channel, SPI752_EFR_RW, rd | 0x10);
 
  // 設(shè)置通信格式為 8位數(shù)據(jù)傳送   奇葩的設(shè)置
  SPI752_RegWrite(Channel, SPI752_LCR_RW, 0x03);
 
  // 使能RHR、THR中斷、使能接收器線狀態(tài)中斷、使能modem狀態(tài)寄存器中斷 
  rd = SPI752_RegRead(Channel, SPI752_IER_RW);
  SPI752_RegWrite(Channel, SPI752_IER_RW, rd & (~0x10));
 
  // DTR、RTS輸出有效、TCR\TLR使能、使能局部環(huán)回模式、使能Xon Any功能  1分頻  奇葩why?
  rd = SPI752_RegRead(Channel, SPI752_MCR_RW);
  SPI752_RegWrite(Channel, SPI752_MCR_RW, rd & (~0x80));
 
  // Set baud rate & 8N1 format
  // 設(shè)置為 8位 除數(shù)所存使能估計(jì)為設(shè)置波特率準(zhǔn)備
  SPI752_RegWrite(Channel, SPI752_LCR_RW, 0x83);
 
  // 設(shè)置波特率
  rd = (14745600/16) / Baud;
  SPI752_RegWrite(Channel, SPI752_DLL_RW, rd); // 寫入除數(shù)最低字節(jié)
  SPI752_RegWrite(Channel, SPI752_DLH_RW, rd>>8);  // 寫入除數(shù)最高字節(jié)
  // 8位  又來設(shè)置通訊格式。。 奇葩。。。
  SPI752_RegWrite(Channel, SPI752_LCR_RW, 0x03);
 
  SPI752_RegRead(Channel, SPI752_RHR_R);
 
  // use port3_3 as input event, ZigBee interrupt. 
  // 設(shè)置為輸入模式
  GPIOSetDir(PORT3, 3, 0);
  // port3_3 interrupt. edge, single trigger, falling edges.
  // 設(shè)置為中斷功能
  GPIOSetInterrupt(PORT3, 3, 0, 0, 0);
  // 使能該中斷 當(dāng)Zig有數(shù)據(jù)接受時(shí),該中斷被觸發(fā)
  GPIOIntEnable(PORT3, 3);
 
  // Set SPI752 RXDx interrupt Enable.
  //rd = SPI752_RegRead(1, SPI752_IER_RW);  
  //SPI752_RegWrite(Channel, SPI752_IER_RW, rd | 0x01);
  // 使能RHR中斷又設(shè)置了一次 RHR中斷  還能再奇葩點(diǎn)嗎?
  SPI752_RegWrite(Channel, SPI752_IER_RW, 0x01);
  // 讀取中斷Why? 
  SPI752_RegRead(Channel, SPI752_RHR_R);
}
 
   5、發(fā)送1字節(jié)數(shù)據(jù) (實(shí)現(xiàn)了發(fā)送1字節(jié)就可以發(fā)送多字節(jié)數(shù)據(jù)了)
            /* 操作M0的SPI控制器 */
        /* arg1:SSPI0或SSPI1      arg2:數(shù)據(jù) */
uint16_t SPI_PutGet(uint8_t portNum, uint16_t SendData)
{
  if(portNum == 0)
  {
      /* 此處為通道0的代碼 未貼出 */
  }
 
  else
  {
    /* Move on only if NOT busy and TX FIFO not full. */
    // SSP1控制器不忙 發(fā)送FIFO未滿、發(fā)送FIFO不為空 就跳出循環(huán)
    while((LPC_SSP1->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF);
    LPC_SSP1->DR = SendData;//寫入數(shù)據(jù)
    /* Wait until the Busy bit is cleared. */
    while(LPC_SSP1->SR & SSPSR_BSY); // 等待總線不忙
 
    /* Wait until the Busy bit is cleared */
// 等到接受FIFO不為空后跳出循環(huán)
    while((LPC_SSP1->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE);
    return LPC_SSP1->DR;
  }
}
 
/*******************************************************************************
* Function Name  : SPI752_PutChar
* Description    : Use SPI572 channel 0 & 1 send a byte.
* Input          : - Channel : 0 & 1.
*                  - Ch : 8bit data.
* Output         : None
* Return         : None
* file           :spi_uart.c 
*******************************************************************************/
/* arg1:SSPI0或SSPI1       arg2:8位數(shù)據(jù) */
void SPI752_PutChar(uint8_t Channel, uint8_t Ch)
{
  // 等待發(fā)送保存寄存器為空
  while(!(SPI752_RegRead(Channel, SPI752_LSR_R)&0x20));
  // 往發(fā)送保存寄存器寫入數(shù)據(jù)
  SPI752_RegWrite(Channel, SPI752_THR_W, Ch);
}
 
    6、接受數(shù)據(jù) 需要借助中斷
        6.1:中斷讀取、保存數(shù)據(jù)
      /*  當(dāng)PIO3 組引腳產(chǎn)生中斷時(shí) 此中斷函數(shù)被執(zhí)行 gpio.c */
void PIOINT3_IRQHandler(void)
{
    /*  此處為其他引腳需要的代碼  未貼出*/

  // 判斷是不是 PORT3_3 引腳產(chǎn)生的
  if(GPIOIntStatus(PORT3, 3))
  {
        ZigBee_IRQ_Process();            // 是則說明ZigBee觸發(fā)的
GPIOIntClear(PORT3, 3);        // 清中斷
  }
  return;
}
           /* ZigBee 中斷服務(wù)程序 讀取數(shù)據(jù)  spi_uart.c  */
void ZigBee_IRQ_Process(void)
{
  uint8_trd;

 /*  此處為0通道的讀取數(shù)據(jù)的代碼  未貼出*/

  rd = SPI752_RegRead(1, SPI752_IIR_R);
  rd &= 0x3f;  
  if(rd == 0x04)   // 判斷是否為RHR中斷  是則讀取數(shù)據(jù)
  {
        // 讀取RHR寄存器值存入數(shù)組緩沖區(qū)
        SPI752_rbuf_1[SPI752_rbuf_1_ip] = SPI752_RegRead(1, SPI752_RHR_R);
        SPI752_rbuf_1_ip ++;
if(SPI752_rbuf_1_ip >= SPI752_RBUF_1_NUMB)
  SPI752_rbuf_1_ip = 0;
  }
  else
  {
        rd = SPI752_RegRead(1, SPI752_RHR_R);   // 從接受保存寄存器讀空數(shù)據(jù) 估計(jì)是清空該寄存器
  }
}
6.2:應(yīng)用程序讀取數(shù)據(jù)
/* 當(dāng)程序讀取數(shù)據(jù)時(shí),從緩沖區(qū)里取數(shù)據(jù)   spi_uart.c */
/* arg1:SSPI0或SSPI1       arg2:執(zhí)行可寫的1字節(jié)的空間的指針*/
uint8_t SPI752_GetChar(uint8_t Channel, uint8_t *Ch)
{
   /*  此處為0通道的讀取數(shù)據(jù)的代碼  未貼出*/

   // SPI752_rbuf_1_ip 是在中斷里面記錄的讀取的字節(jié)數(shù)
    if(SPI752_rbuf_1_op != SPI752_rbuf_1_ip)
{
  *Ch = SPI752_rbuf_1[SPI752_rbuf_1_op];
  SPI752_rbuf_1_op ++;
  if(SPI752_rbuf_1_op >= SPI752_RBUF_1_NUMB)
    SPI752_rbuf_1_op = 0;
  return 1;
}
  return 0;
}
 
 
關(guān)閉窗口

相關(guān)文章