1前言
contiki是一款非常有意思的无线传感网络操作系统。认真学习了一段时间,跟踪了contiki的发展深知国内和国外在无线传感网方面的差距(这个以后可以慢慢分析)。contiki中支持的平台很多,但是和国内的情况差别较大。国人喜欢使用STM32,无线芯片多使用CC1100或SI4432,这就使得很难把contiki支持的平台直接拿来使用,需要经过很多步骤的修改。但是contiki的资料太少,国内缺少对contiki的研究和使用。本文简要分析contiki的SPI模块,SPI模块是STM32和无线芯片例如CC2520或CC1100或SI4432的重要接口。
2.SPI宏定义
contiki源码的特点便是宏定义多,很多时候找不到该宏在哪里定义,如果把这个宏理解为开关的话真不知道关闭这个宏会发生什么可怕的事情。
#ifndef __SPI_H__
#define __SPI_H__
#ifdef SPI_WAITFORTxREADY
#define SPI_WAITFORTx_BEFORE() SPI_WAITFORTxREADY()
#define SPI_WAITFORTx_AFTER()
#define SPI_WAITFORTx_ENDED() SPI_WAITFOREOTx()
#else /* SPI_WAITFORTxREADY */
#define SPI_WAITFORTx_BEFORE()
#define SPI_WAITFORTx_AFTER() SPI_WAITFOREOTx()
#define SPI_WAITFORTx_ENDED()
#endif /* SPI_WAITFORTxREADY */
extern unsigned char spi_busy;
void spi_init(void);
/* Write one character to SPI */
#define SPI_WRITE(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFOREOTx(); \
} while(0)
/* Write one character to SPI - will not wait for end
useful for multiple writes with wait after final */
#define SPI_WRITE_FAST(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFORTx_AFTER(); \
} while(0)
/* Read one character from SPI */
#define SPI_READ(data) \
do { \
SPI_TXBUF = 0; \
SPI_WAITFOREORx(); \
data = SPI_RXBUF; \
} while(0)
/* Flush the SPI read register */
#define SPI_FLUSH() \
do { \
SPI_RXBUF; \
} while(0);
#endif /* __SPI_H__ */
3.platform-conf.h中SPI宏定义
contiki中有两个至关重要的头文件,一个是contiki-conf.h,一个便是platform-conf.h。该头文件中存在所有和平台有关的宏定义,其中包括SPI接口。下面列举两个平台SPI定义。
【MSP430平台(exp5438)】
#define SPI_TXBUF UCB0TXBUF
#define SPI_RXBUF UCB0RXBUF
/* USART0 Tx ready? */
#define SPI_WAITFOREOTx() while ((UCB0STAT & UCBUSY) != 0) // 发送或接收正在尽心 UCBUSY置位
/* USART0 Rx ready? */
#define SPI_WAITFOREORx() while ((UCB0IFG & UCRXIFG) == 0) // 当RXBUF接收到一个字符,UCRXIFG置位
/* USART0 Tx buffer ready? */
#define SPI_WAITFORTxREADY() while ((UCB0IFG & UCTXIFG) == 0) // 当TXBUF为空时,UCTXIFG置位
【AVR平台(micaz)】
#define SPI_TXBUF SPDR
#define SPI_RXBUF SPDR
#define SPI_WAITFOREOTx() do { while (!(SPSR & BV(SPIF))); } while (0)
#define SPI_WAITFOREORx() do { while (!(SPSR & BV(SPIF))); } while (0)
/* Write one character to SPI */
#define SPI_WRITE(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFOREOTx(); \
} while(0)
#define SPI_WRITE(data) \
do { \
\
UCB0TXBUF = data; \
while((UCB0STAT&UCBUSY)!=0); \
} while(0)
/* Write one character to SPI - will not wait for end
useful for multiple writes with wait after final */
#define SPI_WRITE_FAST(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFORTx_AFTER(); \
} while(0)
#define SPI_WRITE_FAST(data) \
do { \
\
UCB0TXBUF = data; \
while((UCB0STAT&UCBUSY)!=0); \
} while(0)
/* Read one character from SPI */
#define SPI_READ(data) \
do { \
SPI_TXBUF = 0; \
SPI_WAITFOREORx(); \
data = SPI_RXBUF; \
} while(0)
#define SPI_READ(data) \
do { \
UCB0RXBUF = 0; \
while((UCB0IFG&UCRXIFG) == 0); \
data = SPI_RXBUF; \
} while(0)
5.STM32平台(假想未检验)
换句话说如果STM32连接CC2520,那么SPI几个关键定义如下(暂无硬件平台,未调试,并假设使用SPI1)#define SPI_TXBUF SPI1->DR
#define SPI_RXBUF SPI1->DR
// 等待发送完成
#define SPI_WAITFOREOTx() while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
// 等待接收完成
#define SPI_WAITFOREORx() while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
// 同为等待发送完成
#define SPI_WAITFORTxREADY() while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
6.总结
很长时间没有更新contiki方面的博文,最近才重新开始应用contiki。我猜想在国内研究无线传感网络一般就两条路,第一条研习zigbee的路线,虽然觉得这条路不一定好,但是至少很多公司都靠这个赚了钱,例如上海顺舟;另一条路便是独立开发无线传感网络协议栈,这条路比较艰辛不知能否走到终点,从而开花结果(我所在的公司选择了这条路)。还有就是contiki这条路,国外貌似越来越火,国内好像才刚刚起步。(想起看期刊论文的经历,99%的论文都说XX研究国内才刚刚起步)。呵呵,重新给contiki开个头,希望以后继续努力。