最近用到TSL2591,并需要将检测数据完成点对点无线传输,其核心是基于Zstack协议栈利用CC2430模拟IIC信号,与传感器通信,由于之前有CC2530的开发经验,对ZSTACK协议栈也相对熟悉,觉得应该不是一件难事,开始做的时候才发现一步一坑。
首先就是开发环境的问题,由于CC2430这个工程文件用的是低版本的环境创建的,之前开发CC2530时用的IAR版本与此不兼容。
不得以在网上找到了IAR7.20H,按照步骤安装,破解,然后打开CC2430带有Zstack协议栈的工程,将开发板通过SmartRF与PC相连,准备测试代码,点击debugger,一直显示没有发现设备,反复确认驱动已安装的情况下,开始怀疑是不是其他问题。
也是网上搜有没有相同的情况,然后找到一个说明文档发现可能是系统的问题,其实可以安装一个XP的虚拟机,但到这一步,花在配置环境上的时间就已经折磨我够久的了,心态爆炸,准备更改方案,换CC2530。
换到CC2530这个芯片,移植的过程还是挺舒服的,参照正点原子IIC例程,写了基于CC2530的模拟IIC程序,具体程序如下:
/*******************************************************************************
* File : IIC.h
* Description : IIC
* Version : v0.1
* Author : Newbit_Msming
* Date : 2018/6/13
* Change Logs :
*******************************************************************************/
#ifndef _IIC_H_
#define _IIC_H_
/*******************************************************************************
* INCLUDES
*/
/*******************************************************************************
* MACROS
*/
/*******************************************************************************
* CONSTANTS
*/
/*******************************************************************************
* TYPEDEFS
*/
/*******************************************************************************
* GLOBAL VARIABLES
*/
/*******************************************************************************
* EXTERNAL VARIABLES
*/
/*******************************************************************************
* EXTERNAL FUNCTIONS
*/
/*******************************************************************************
* LOCAL VARIABLES
*/
#include "ioCC2530.h"
#include "HalHardwareApi_CC2530.h"
#include "HalHardwareDefine_CC2530.h"
#include "stdio.h"
#include "hal_types.h"
#include "DEV_Config.h"
#define SDA_PIN P1_2
#define SDA_GEN() HAL_GEN_P12()
#define SDA_INPUT() HAL_INPUT_P12()
#define SDA_OUTPUT() HAL_OUTPUT_P12()
#define SDA_PULL_UP() HAL_PULL_UP_P12()
#define SDA_HIGH() HAL_SET_P12()
#define SDA_LOW() HAL_CLR_P12()
#define SCL_PIN P1_1
#define SCL_GEN() HAL_GEN_P11()
#define SCL_INPUT() HAL_INPUT_P11()
#define SCL_OUTPUT() HAL_OUTPUT_P11()
#define SCL_HIGH() HAL_SET_P11()
#define SCL_LOW() HAL_CLR_P11()
/*******************************************************************************
*为了代码的高效性建议你使用以下的宏进行配置中断,不建议使用 vHAL_DioWakeEnable()
********************************************************************************/
#define SCL_INT_ENABLE() st( P1IEN |= BV(1); \
P1IFG &= ~BV(1);\
IEN2 |= BV(4); \
EA = TRUE;)
#define SCL_INT_RISINGEDGE() st( PICTL &= ~BV(1);)
#define SCL_INT_DISABLE() st( P1IEN &= ~BV(1); P1IFG &= ~BV(1);)
#define SCL_INT_FLAG BV(1)
#define SDA_INT_ENABLE() st( P1IEN |= BV(2); \
P1IFG &= ~BV(2);\
IEN2 |= BV(4); \
EA = TRUE;)
#define SDA_INT_FALLINGEDGE() st( PICTL |= BV(1);)
#define SDA_INT_DISABLE() st( P1IEN &= ~BV(2); P1IFG &= ~BV(2);)
#define SDA_INT_FLAG BV(2)
extern void vDelay_us(uint16 u16us);
extern void vDelay_ms(uint16 u16ms);
extern void IIC_Start (void);
extern void IIC_Stop (void);
extern uint8 IIC_Wait_Ack(void);
extern void IIC_Ack (void);
extern void IIC_NAck (void);
void IIC_Write_Byte(uint8 txd);
unsigned char IIC_Read_Byte(void);
uint8 Write_Device_Addr(uint8 addr);
uint8 Device_Read_One_Byte(uint8 IC_Addr,uint8 Addr);
void Device_Write_One_Byte(uint8 IC_Addr,uint8 Addr,uint8 data);
void Device_Read_Bytes(uint8 IC_Addr,uint8 Addr,uint8 *buf,uint8 len);
void Device_Write_Bytes(uint8 IC_Addr,uint8 Addr,uint8 *buf,uint8 len);
void vIIC_WriteData(uint8 u8Data);
extern bool bIIC_GetAck (void);
extern void vIIC_Init (void);
extern void vIIC_WriteOneByte (uint8 u8Data);
extern uint8 u8IIC_ReadOneByte (void);
void IIC_Init(void);
void vIIC_SendAck (void);
void vIIC_SendNAck (void);
uint8 u8IIC_ReadData(void);
uint8 u8IIC_ReadData(void);
void vIIC_Reset (void);
void Device_Write_Bytes(uint8 IC_Addr,uint8 Addr,uint8 *buf,uint8 len);
#endif
/*******************************************************************************
Copyright 2018 Newbit Studio. All rights reserved.
*******************************************************************************/
void I2C_Init(void);
/*******************************************************************************
* File : IIC.c
* Description : IIC Drivers
* Version : v0.1
* Author : Newbit_Msming
* Date : 2018/3/29
* Change Logs :
*******************************************************************************/
/*******************************************************************************
* INCLUDES
*/
#include "IIC.h"
#include "OnBoard.h"
/*******************************************************************************
* MACROS
*/
/*******************************************************************************
* CONSTANTS
*/
/*******************************************************************************
* TYPEDEFS
*/
/*******************************************************************************
* GLOBAL VARIABLES
*/
/*******************************************************************************
* EXTERNAL VARIABLES
*/
/*******************************************************************************
* EXTERNAL FUNCTIONS
*/
/*******************************************************************************
* LOCAL VARIABLES
*/
/* xus延迟 */
void vDelay_us(uint16 u16us)
{
while(u16us--)
{
MicroWait (1);
}
}
/* xms延时 */
void vDelay_ms(uint16 u16ms)
{
while(u16ms--)
{
vDelay_us(1000);
}
}
/*******************************************************************************
* Function: vIIC_Start
* Description: IIC启动时序
* Input parameter:
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void IIC_Start (void)
{
SDA_GEN();
SCL_GEN();
SDA_OUTPUT();
SCL_OUTPUT();
SDA_PULL_UP();
SDA_HIGH();
SCL_HIGH(); //拉高时钟线和数据线
vDelay_us(1); //延时
SDA_LOW(); //产生下降沿
vDelay_us(1); //延时
SCL_LOW(); //拉低时钟线
vDelay_us(1);
}
/*******************************************************************************
* Function: vIIC_Stop
* Description: IIC停止时序
* Input parameter:
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void IIC_Stop (void)
{
SDA_OUTPUT();
SCL_LOW(); //拉低时钟线
SDA_LOW();
vDelay_us(1); //延时
SCL_HIGH(); //拉高时钟线
vDelay_us(1); //延时
SDA_HIGH(); //产生上升沿
vDelay_us(1); //延时
}
uint8 IIC_Wait_Ack(void)
{
unsigned char ack = 0;
SDA_INPUT();
SDA_HIGH(); vDelay_us(1);
SCL_HIGH(); vDelay_us(1);
while(SDA_PIN)
{
ack++;
if(ack>250)
{
IIC_Stop();
return 1;
}
}
SCL_LOW();
return 0;
}
/*******************************************************************************
* Function: vIIC_Reset
* Description: 释放IIC总线
* Input parameter:
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void vIIC_Reset (void)
{
SDA_GEN();
SCL_GEN();
SDA_OUTPUT();
SCL_OUTPUT();
SDA_HIGH();
SCL_HIGH();
}
void IIC_Ack(void)
{
SCL_LOW();
SDA_OUTPUT();
SDA_LOW();
vDelay_us(2);
SCL_HIGH();
vDelay_us(2);
SCL_LOW();
}
void IIC_NAck(void)
{
SCL_LOW();
SDA_OUTPUT();
SDA_HIGH();
vDelay_us(2);
SCL_HIGH();
vDelay_us(2);
SCL_LOW();
}
void IIC_Write_Byte(uint8 u8Data)
{
SDA_OUTPUT();
SCL_LOW();
for(uint8 i=0; i<8; i++)
{
if(u8Data & 0x80)
SDA_HIGH();
else
SDA_LOW();
vDelay_us(1);
SCL_HIGH();
vDelay_us(1);
SCL_LOW();
vDelay_us(1);
u8Data <<= 1;
}
SDA_HIGH();
SCL_HIGH(); //
}
uint8 IIC_Read_Byte(void)
{
uint8 u8Data =0;
uint8 i =0;
SCL_LOW();
vDelay_us(1);
SDA_INPUT();
for(i=0;i<8;i++)
{
u8Data <<= 1;
SCL_HIGH();
if(SDA_PIN)
u8Data |= 0x01;
vDelay_us(1);
SCL_LOW();
vDelay_us(1);
}
return u8Data;
}
uint8 Device_Read_One_Byte(uint8 IC_Addr,uint8 Addr)
{
uint8 dat;
IIC_Start();
IIC_Write_Byte(IC_Addr);
IIC_Wait_Ack();
printf("1");
IIC_Write_Byte(Addr);
IIC_Wait_Ack();
IIC_Start();
IIC_Write_Byte((IC_Addr) | 0x01);
IIC_Wait_Ack();
dat = IIC_Read_Byte();
IIC_NAck();
IIC_Stop();
return dat;
}
void Device_Write_One_Byte(uint8 IC_Addr,uint8 Addr,uint8 data)//
{
IIC_Start();
IIC_Write_Byte(IC_Addr);
IIC_Wait_Ack();
IIC_Write_Byte(Addr);
IIC_Wait_Ack();
IIC_Write_Byte(data);
IIC_Wait_Ack();
IIC_Stop();
}
void Device_Read_Bytes(uint8 IC_Addr,uint8 Addr,uint8 *buf,uint8 len)
{
IIC_Start();
IIC_Write_Byte(IC_Addr);
IIC_Wait_Ack();
IIC_Write_Byte(Addr);
IIC_Wait_Ack();
IIC_Start();
IIC_Write_Byte((IC_Addr) | 0x01);
IIC_Wait_Ack();
while(len > 1)
{
*buf++ = IIC_Read_Byte();
IIC_Ack();
len--;
}
*buf = IIC_Read_Byte();
IIC_NAck();
IIC_Stop();
}
void Device_Write_Bytes(uint8 IC_Addr,uint8 Addr,uint8 *buf,uint8 len)
{
while(len > 0)
{
IIC_Start();
IIC_Write_Byte(IC_Addr);
IIC_Wait_Ack();
IIC_Write_Byte(Addr++);
IIC_Wait_Ack();
IIC_Write_Byte(*buf++);
IIC_Wait_Ack();
IIC_Stop();
vDelay_us(10000);
len--;
}
}
void I2C_Init(void)
{
SCL_OUTPUT();
SDA_OUTPUT();
SCL_HIGH();
SCL_LOW();
SDA_HIGH();
SDA_LOW();
vDelay_ms(1);
//SHT30_Periodic_Measure(SHT30_PERIODOC_H_MEASURE_1S);
}
/*******************************************************************************
* Function: vIIC_SendAck
* Description: IIC 发送ack
* Input parameter:
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void vIIC_SendAck (void)
{
SDA_OUTPUT();
SDA_LOW(); //ACK
SCL_HIGH();
vDelay_us(1);
SCL_LOW();
vDelay_us(1);
SDA_HIGH();
vDelay_us(1);
}
/*******************************************************************************
* Function: vIIC_SendNAck
* Description: IIC 发送 no ack
* Input parameter:
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void vIIC_SendNAck (void)
{
SDA_OUTPUT();
SDA_HIGH(); //NACK
SCL_HIGH();
vDelay_us(1);
SCL_LOW();
vDelay_us(1);
SDA_HIGH();
vDelay_us(1);
}
/*******************************************************************************
* Function: bIIC_GetAck
* Description: 检查是否有应答
* Input parameter:
* Return parameter: bool, 1 is ack, 0 is no ack
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
bool bIIC_GetAck (void)
{
SDA_INPUT();
vDelay_us(1);
if(!SDA_PIN)//有应答
{
vDelay_us(1);
SCL_LOW();
return 1;
}
else
{
SCL_LOW();
printf(" no ack!\n");
return 0;
}
}
/*******************************************************************************
* Function: IIC_Init
* Description: 初始化IIC
* Input parameter:
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void IIC_Init(void)
{
SDA_GEN();
SCL_GEN();
SDA_OUTPUT();
SCL_OUTPUT();
SDA_HIGH();
SCL_HIGH();
}
/*******************************************************************************
* Function: vIIC_WriteData
* Description: 写数据
* Input parameter: uint8 u8Data
* Return parameter:
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
void vIIC_WriteData(uint8 u8Data)
{
SDA_OUTPUT();
SCL_LOW();
for(uint8 i=0; i<8; i++)
{
if(u8Data & 0x80)
SDA_HIGH();
else
SDA_LOW();
vDelay_us(1);
SCL_HIGH();
vDelay_us(1);
SCL_LOW();
vDelay_us(1);
u8Data <<= 1;
}
SDA_HIGH();
SCL_HIGH(); //
}
/*******************************************************************************
* Function: u8IIC_ReadData
* Description: 读取数据
* Input parameter:
* Return parameter: uint8 读到的数据
* Author: Newbit_Msming
* Date@@2018/5/11
* Other:
*******************************************************************************/
uint8 u8IIC_ReadData(void)
{
uint8 u8Data =0;
uint8 i =0;
SCL_LOW();
vDelay_us(1);
SDA_INPUT();
for(i=0;i<8;i++)
{
u8Data <<= 1;
SCL_HIGH();
if(SDA_PIN)
u8Data |= 0x01;
vDelay_us(1);
SCL_LOW();
vDelay_us(1);
}
return u8Data;
}
然后找商家要了传感器的驱动代码,这个代码是基于32位处理器的,首先用STM32跑了一下,得出以下结果:
然后就是往工程里面加移植代码了,这个代码可移植性很强,改下相应的IIC接口函数,以及相应的引脚定义即可,然后得出以下结果:
Lux和红外线数据好像没什么问题,能见度和光谱数据好像太小了,这就涉及到之前提到的,商家给的例程代码是基于32位处理器的,而CC2530是集成了一个增强型的8051单片机,是16位处理器,所以当要传输8位数字时,long变量就不够用了,所以将光谱和能见度的相关函数和变量改为long long再次运行程序,得到正确结果。