产品名:ZigBee模块
型号:ZICM2410 PO-2
厂商:广州周立功公司代理(美国CEL公司的MeshConnect模块)
参数:
* 103db链路预算;
* 接收灵敏度:-97dbm@ 1.5V
* 发送功率:+6dbm@1.5V
* 3000英尺无障碍传输距离
* 最低睡眠电流:<1μA
* 工作电压:2.1~3.3V
* 接收电流:35mA
* 发送电流:44mA
* 速率:ZigBee (250 kbps)、Turbo(500 kbps)、Premium (1 Mbps)
* 接口类型:SPI(主从)、UART(2路)、I2S/PCM
支持语音传送:
语音编解码器支持u律、a律、ADPCM
16条射频通道
传送范围:3000英尺 = 914.4米
支持AES128位加密
ZICM2410 支持的数据通信接口:
UART0\UART1(1M)、I2S、SPI(2M)、GPIO、AD(4路)、IIS
描述:Zigbee网络基于IEEE 802.15.4国际标准、上层协议为ZigBee协议栈,具有低功耗,低速率,高可靠性,网络路由功能强大,自恢复及冗余性能优异等特点,广泛应用低数据率监控的各个领域。
ZigBee 物理连接:
ZigBee 模块是通过串口的形式与微处理器通讯,在LPC11C14 开发板这里是通过 SC16IS752IPW 芯片 转成 SPI 协议与 微处理器通讯。
ZigBee 模块(ZICM2410 PO-2) <------串口-----> SC16IS752IPW 芯片 <------SPI-----> LC11C14(ARM M0内核)
从原理图可以看出,ZigBee模块的RXD\TXD接在了SC16IS752IPW芯片的RXB\TXB上,而该芯片的CS\SI\SO\SCLK接在LPC11C14的PIO2_0\PIO2_1\PIO2_2\PIO2_3\PIO3_3上。
/* 初始化响应PIO引脚 ssp.c *//* arg1:SSPI0或SSPI1 */void SPI_IOConfig(uint8_t portNum){if(portNum == 0){/* 此处为通道0的代码 未贴出 */}else/* port number 1 */{ // 主要设置 SSP1 使之能与 SC16IS752IPW 通信 间接与 ZigBee 通信LPC_SYSCON->PRESETCTRL |= (0x1<<2); // bit2=1 SSP1复位取消 bit2=0 复位SSP1LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18);// 使能SSP1的时钟LPC_SYSCON->SSP1CLKDIV = 0x02;/* Divided by 2 设置 SSP1 时钟分频 48Mhz/2=24Mhz*/LPC_IOCON->PIO2_2 &= ~0x07;/* SSP I/O config */LPC_IOCON->PIO2_2 |= 0x02;/* SSP MISO 将PIO2_2设置为 SSP MISO 模式*/LPC_IOCON->PIO2_3 &= ~0x07;LPC_IOCON->PIO2_3 |= 0x02;/* SSP MOSI 将PIO2_3设置为 SSP MOSI 模式*/LPC_IOCON->PIO2_1 &= ~0x07;LPC_IOCON->PIO2_1 |= 0x02;/* SSP CLK 将PIO2_1设置为 SSP 时钟 *//* Enable AHB clock to the GPIO domain. */LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); // 使能GPIO时钟 使之产生时钟LPC_IOCON->PIO2_0 &= ~0x07;/* SSP SSEL is a GPIO pin 设置PIO2_0 作为普通IO管脚功能 *//* port2, bit 0 is set to GPIO output and high */GPIOSetDir( PORT2, 0, 1 ); // 设置为输出GPIOSetValue( PORT2, 0, 1 ); // 输出高电平 暂时不使能 该器件 是片选引脚}}
LPC_SSP1->CR0 = 0x0700 | (Bit-1); // (Bit-1)=0b0111 8位传输 串行时钟速率、总线类型、数据长度LPC_SSP1->CPSR = EvenDiv; // 时钟预分频寄存器 设置为2分频 -> 48Mhz/2=24Mhzfor ( i = 0; i < SSP_FIFOSIZE; i++ ){Dummy = LPC_SSP1->DR;/* clear the RxFIFO 数据寄存器,读空则接受FIFO 写满则发送 FIFO */}NVIC_EnableIRQ( SSP1_IRQn );// 使能中断LPC_SSP1->CR1 = SSPCR1_SSE; // SSP1以正常模式与串行总线上的其它设备相互通信。LPC_SSP1->IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM; // 中断触发条件:接受上溢 接受超时触发中断
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控制器不忙 发送FIFO未满、发送FIFO不为空 就跳出循环while((LPC_SSP1->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF);LPC_SSP1->DR = SendData;//写入数据/* Wait until the Busy bit is cleared. */while(LPC_SSP1->SR & SSPSR_BSY); // 等待总线不忙/* Wait until the Busy bit is cleared */// 等到接受FIFO不为空后跳出循环while((LPC_SSP1->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE);return LPC_SSP1->DR;// 将数据读出}}
1、片选选中 SC16IS752IPW2、往SPI数据寄存器写数据2.1 MIOS 写 SC16IS752IPW THR 寄存器地址写位(1bit) + SC16IS752IPW THR 寄存器地址(4bit) + 通道选择(2bit) + X2.2 写 8位数据3、取消片选/* 往指定的 SC16IS752IPW 寄存器中写数据 *//* arg1:SSPI0或SSPI1 arg2:SC16IS752IPW 寄存器 arg3:写入的数据*/void SPI752_RegWrite(uint8_t Channel, uint8_t Reg, uint8_t Data){SPI_UART_CS(0);// 片选选中 SC16IS752IPWSPI_PutGet(1, SPI752_WRITE | (Reg<<3) | (Channel<<1));// 写寄存器SPI_PutGet(1, Data);// 写数据SPI_UART_CS(1);// 取消片选}
1、片选选中 SC16IS752IPW2、往SPI数据寄存器写数据2.1 MIOS 写 SC16IS752IPW RHR 寄存器地址读位(1bit) + SC16IS752IPW RHR 寄存器地址(4bit) + 通道选择(2bit) + X2.2 MOSI 读出 8位数据3、取消片选/* 读数据 *//* arg1:SSPI0或SSPI1 arg2:SC16IS752IPW 寄存器 */uint8_t SPI752_RegRead(uint8_t Channel, uint8_t Reg){uint8_trd;SPI_UART_CS(0);// 片选选中 SC16IS752IPWSPI_PutGet(1, SPI752_READ | (Reg<<3) | (Channel<<1)); // 写寄存器地址rd = SPI_PutGet(1, 0);// 取出数据SPI_UART_CS(1);// 取消片选return rd;}
/******************************************************************************** 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// 设置 数据通信的格式 1 0 1 1 1 1 11 奇葩的设置。。。// 除数锁存使能 没有TX间隔条件 奇偶位强制为0 偶数格式 奇偶位 1个停止位 8位SPI752_RegWrite(Channel, SPI752_LCR_RW, 0xBF);// 使能增强型功能rd = SPI752_RegRead(Channel, SPI752_EFR_RW);SPI752_RegWrite(Channel, SPI752_EFR_RW, rd | 0x10);// 设置通信格式为 8位数据传送 奇葩的设置SPI752_RegWrite(Channel, SPI752_LCR_RW, 0x03);// 使能RHR、THR中断、使能接收器线状态中断、使能modem状态寄存器中断rd = SPI752_RegRead(Channel, SPI752_IER_RW);SPI752_RegWrite(Channel, SPI752_IER_RW, rd & (~0x10));// DTR、RTS输出有效、TCR\TLR使能、使能局部环回模式、使能Xon Any功能 1分频 奇葩why?rd = SPI752_RegRead(Channel, SPI752_MCR_RW);SPI752_RegWrite(Channel, SPI752_MCR_RW, rd & (~0x80));// Set baud rate & 8N1 format// 设置为 8位 除数所存使能估计为设置波特率准备SPI752_RegWrite(Channel, SPI752_LCR_RW, 0x83);// 设置波特率rd = (14745600/16) / Baud;SPI752_RegWrite(Channel, SPI752_DLL_RW, rd); // 写入除数最低字节SPI752_RegWrite(Channel, SPI752_DLH_RW, rd>>8); // 写入除数最高字节// 8位 又来设置通讯格式。。 奇葩。。。SPI752_RegWrite(Channel, SPI752_LCR_RW, 0x03);SPI752_RegRead(Channel, SPI752_RHR_R);// use port3_3 as input event, ZigBee interrupt.// 设置为输入模式GPIOSetDir(PORT3, 3, 0);// port3_3 interrupt. edge, single trigger, falling edges.// 设置为中断功能GPIOSetInterrupt(PORT3, 3, 0, 0, 0);// 使能该中断 当Zig有数据接受时,该中断被触发GPIOIntEnable(PORT3, 3);// Set SPI752 RXDx interrupt Enable.//rd = SPI752_RegRead(1, SPI752_IER_RW);//SPI752_RegWrite(Channel, SPI752_IER_RW, rd | 0x01);// 使能RHR中断又设置了一次 RHR中断 还能再奇葩点吗?SPI752_RegWrite(Channel, SPI752_IER_RW, 0x01);// 读取中断Why?SPI752_RegRead(Channel, SPI752_RHR_R);}
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控制器不忙 发送FIFO未满、发送FIFO不为空 就跳出循环while((LPC_SSP1->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF);LPC_SSP1->DR = SendData;//写入数据/* Wait until the Busy bit is cleared. */while(LPC_SSP1->SR & SSPSR_BSY); // 等待总线不忙/* Wait until the Busy bit is cleared */// 等到接受FIFO不为空后跳出循环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位数据 */void SPI752_PutChar(uint8_t Channel, uint8_t Ch){// 等待发送保存寄存器为空while(!(SPI752_RegRead(Channel, SPI752_LSR_R)&0x20));// 往发送保存寄存器写入数据SPI752_RegWrite(Channel, SPI752_THR_W, Ch);}
/* 当PIO3 组引脚产生中断时 此中断函数被执行 gpio.c */void PIOINT3_IRQHandler(void){/* 此处为其他引脚需要的代码 未贴出*/// 判断是不是 PORT3_3 引脚产生的if(GPIOIntStatus(PORT3, 3)){ZigBee_IRQ_Process(); // 是则说明ZigBee触发的GPIOIntClear(PORT3, 3); // 清中断}return;}/* ZigBee 中断服务程序 读取数据 spi_uart.c */void ZigBee_IRQ_Process(void){uint8_trd;/* 此处为0通道的读取数据的代码 未贴出*/rd = SPI752_RegRead(1, SPI752_IIR_R);rd &= 0x3f;if(rd == 0x04) // 判断是否为RHR中断 是则读取数据{// 读取RHR寄存器值存入数组缓冲区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); // 从接受保存寄存器读空数据 估计是清空该寄存器}}
6.2:应用程序读取数据
/* 当程序读取数据时,从缓冲区里取数据 spi_uart.c *//* arg1:SSPI0或SSPI1 arg2:执行可写的1字节的空间的指针*/uint8_t SPI752_GetChar(uint8_t Channel, uint8_t *Ch){/* 此处为0通道的读取数据的代码 未贴出*/// SPI752_rbuf_1_ip 是在中断里面记录的读取的字节数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;}