⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radiocontrol.c

📁 adhoc汇聚节点程序源代码(点对多点)——for atmega128
💻 C
字号:
/*
****************************************************************************  
*                        
*              宁波中科集成电路设计中心  版权所有 Copyright 2005
*
*文件名:  Radiocontrol.c
*程序员:  
*主要内容:射频通信物理层硬件控制
*完成日期:2005.5.25
****************************************************************************
*/

#include "radiocontrol.h"
#include "physical.h"
#include "adc.h"
#include "fun.h"
#include "cc1000.h"
#include "mac.h"
#include "led.h"


enum {
	INIT,
	SLEEP,
	IDLE,
	SYNC_START,
	RECEIVE,
	TRANSMIT
};							// 射频控制模块状态值

enum {
   SYNC_WORD = 0x33cc,
   NSYNC_WORD = 0xcc33
};

enum {
   PREAMBLE_LEN = 18,
   VALID_PRECURSOR = 5,
   BUSY_THRESHOLD = 0xef,	// 表示信道忙的RSSI门限值,值越小,信号强度越大
   EW_THRESHOLD = 0x120,	// 需要进行扩展监听的门限值
   NUM_EXT_BYTES = 3
};					

uint8_t  state;				// 状态变量
uint16_t carrSenTime;		// 载波监听次数
uint16_t csVal1;			// 上次监听值
uint16_t csValAve;			// 上次与本此监听平均值
uint8_t  extFlag;			// 载波监听扩展标识
uint8_t  nextByte;			// 缓存下一个要发送的字节
static uint8_t  txCount;			// 发送字节计数
   
bool bManchesterBad;
bool bInvertRxData;			// CC1000传来的数据是否反转
bool bRSSIEnable;			// RSSI使能标识
   
uint8_t PreambleCount;		// 导频计数
uint8_t SOFCount;			// 同步偏移计数

union {
    uint16_t W;
    struct {
        uint8_t LSB;
        uint8_t MSB;
    };
} RxShiftBuf;				// 移位缓存,用于同步

char start[2] = {0x33, 0xcc}; // 同步字节
uint8_t RxBitOffset;		//同步结果,即偏移的比特数

uint16_t LocalAddr;

/*************************************************************************
*功能描述:射频控制模块初始化,CC1000、SPI初始化
*参数说明:无
*返回值:  成功
**************************************************************************/
result_t RadiocontrolInit()
{
	//  状态变量初始化;
	state = INIT;
	OSH_MAKE_SPI_SCK_INPUT();							// SPI SCK为输入
	CC1000ControlStdControlInit();						// CC1000初始化配置
	CC1000ControlSelectLock(0x9);						// CC1000PLL设置
	bInvertRxData = CC1000ControlGetLOStatus();			// CC1000数据是否需要反转

	ADCBindPort(OS_ADC_CC_RSSI_PORT, OSH_ACTUAL_CC_RSSI_PORT);
    ADCControlInit();									// 打开ADC RSSI通道
	
	RadiocontrolIdle();

	return SUCCESS;
}

/*************************************************************************
*功能描述:射频控制进入空闲状态,CC1000、SPI进入接收状态
*参数说明:无
*返回值:  成功
**************************************************************************/
result_t RadiocontrolIdle()
{
	if (state == IDLE) 
		return SUCCESS;
	if (state == SYNC_START) {
		state = IDLE;
		return SUCCESS;
	}
	if (state == SLEEP) {								// 打开CC1000
		CC1000ControlStdControlStart();
	} else {
		* (volatile unsigned char *)(0x0D + 0x20) = 0x00;// 关SPI和SPI中断
	}
	CC1000ControlRxMode();								//CC1000设为接收模式
	// 配置SPI为输入
	OSH_MAKE_MISO_INPUT();
	OSH_MAKE_MOSI_INPUT();
	* (volatile unsigned char *)(0x0D + 0x20) = 0xc0;	// 开SPI和SPI中断

	state = IDLE;
	return SUCCESS;
}

/*************************************************************************
*功能描述:射频控制进入睡眠状态,CC1000、SPI进入关闭状态
*参数说明:无
*返回值:  成功
**************************************************************************/
result_t RadiocontrolSleep()
{
	if (state == SLEEP) 
		return SUCCESS;
	* (volatile unsigned char *)(0x0D + 0x20) = 0x00;	// 关SPI和SPI中断
	CC1000ControlStdControlStop();						// 关CC1000
	
	state = SLEEP;
	return SUCCESS;
}

/*************************************************************************
*功能描述:设置载波监听的比特数(实际监听为字节数,因为每次监听的ADC调用由一
*          次SPI中断调用引发,故一次监听为一个字节的RSSI),
*参数说明:要监听的位数
*返回值:  成功
**************************************************************************/
result_t RadiocontrolCarrierSenseStart(uint16_t numBits)
{
	if (state != IDLE)									// 只有空闲时才允许监听
		return FAIL;
	extFlag = 0;
	carrSenTime = numBits >> 3;							// 转化为字节数
	csVal1 = 0x180;
	return SUCCESS;
}

/*************************************************************************
*功能描述:ADC中断调用,表明RSSI数据到达,判断信道空闲与否
*参数说明:ADC采集到的数据
*返回值:  成功
**************************************************************************/
result_t RadiocontrolRSSIADCDataReady(uint16_t data)	// 判断信道是否空闲
{
	if (state == IDLE && carrSenTime > 0) {
		csValAve = (csVal1 + data) >> 1;				// 相邻两次监听的平均值;
		if (csValAve < BUSY_THRESHOLD) {				// 因为CC1000提供的是反电压值,所以值越小,信号越强;
            carrSenTime = 0;
			MACChannelBusy();
            //加入对上层函数的调用, 通知信道忙
		} else {
			MACChannelIdle();
		}
	} else if (state == SYNC_START || state == RECEIVE) {
	}
	return SUCCESS;
}

/*************************************************************************
*功能描述:启动发送数据包的流程,并准备要发送的导频字节,CC1000、SPI进入发送态
*参数说明:无
*返回值:  成功
**************************************************************************/
result_t RadiocontrolStartTx()
{
	char temp;
	* (volatile unsigned char *)(0x0D + 0x20) = 0x00;	// 关SPI中断
	if (state == SLEEP) {								// 如果睡眠则唤醒
		CC1000ControlStdControlStart();
	}
	nextByte = 0xaa;									// 缓存下一个要发送的字节
	txCount = 2;
	temp = * (volatile unsigned char *)(0x0E + 0x20);   // 清空SPSR寄存器
	* (volatile unsigned char *)(0x0F + 0x20) = 0xaa;;  //将要发送的第一个字节写入SPDR
	
	//进入发送模式
	CC1000ControlTxMode();						
	OSH_MAKE_MISO_OUTPUT();
	OSH_MAKE_MOSI_OUTPUT();
	* (volatile unsigned char *)(0x0D + 0x20) = 0xc0;    // 开SPI中断
	
	state = TRANSMIT;
	return SUCCESS;
}

/*************************************************************************
*功能描述:供上层调用,把下一个要发送的字节存入发送缓冲
*参数说明:要发送的字节
*返回值:  成功
**************************************************************************/
result_t RadiocontrolTxNextByte(char data)				// 准备下一个要发送的字节
{
	nextByte = data;
//	uartDebug_txByte(data);
	return SUCCESS;
}

/*************************************************************************
*功能描述:SPI中断服务程序,由CC1000的时钟信号引发,与CC1000同步,即数据率相同
*          根据本地状态进行相应的处理,为上层提供服务
*参数说明:无
*返回值:  成功
**************************************************************************/
void __attribute((signal))   __vector_17(void)
{
	uint8_t data;
	data = * (volatile unsigned char *)(0x0F + 0x20);		// 从SPDR读入字节
	if (bInvertRxData) data = ~data;
	
	if (state == TRANSMIT) {								// 发送状态
		* (volatile unsigned char *)(0x0F + 0x20) = nextByte;// 发送缓存中的字节
		if (txCount < PREAMBLE_LEN) {						// 继续发送导频
            nextByte = 0xaa;
            txCount++;
		} else if (txCount < PREAMBLE_LEN + sizeof(start)) {// 导频发送完毕
            nextByte = start[txCount - PREAMBLE_LEN];		// 发两个同步字节;
            txCount++;
		} else {
			PhysicalTxByteReady();
            //加入对上层函数的调用							// 通知上层发送数据包;
		}
	} else if (state == IDLE) {								// 空闲
		bManchesterBad = * (volatile unsigned char *)(0x1A + 0x20) & 0x40;// CHP_OUT位
		if ((!bManchesterBad) && (data == 0xaa || data == 0x55)) {
            PreambleCount++;
            if (PreambleCount > VALID_PRECURSOR) {			// 接收到足够的导频字节
				state = SYNC_START;
				if (carrSenTime > 0) {						// MAC层正在进行载波监听
					carrSenTime = 0;						// 停止监听
					MACChannelBusy();
				}
            }
		} else {
			PreambleCount = 0;								// 导频计数置0
		}
		if (carrSenTime > 0)								// 调用ADC采集监听数据
			ADCGetData(OS_ADC_CC_RSSI_PORT);				
	} else if (state == SYNC_START) {						// 接收同步字
		uint8_t i;
		if (data == 0xaa || data == 0x55) {
			SOFCount = 0;									// 再收到同步字节则丢弃
		} else {											// 进行同步
            uint8_t usTmp;
            SOFCount++;
            switch (SOFCount) {
            case 1:
				RxShiftBuf.MSB = data;
				break;
            case 2:
				RxShiftBuf.LSB = data;
				if (RxShiftBuf.W == SYNC_WORD) {
					state = RECEIVE;
					RxBitOffset = 0;						// 通知上层检测到起始符号且同步完成
					if (PhysicalStartSymDetected() == FAIL) {
						RadiocontrolIdle();
					}
				} 
				break;            
            case 3: 
				usTmp = data;
				for(i = 0; i < 8; i++) {
					RxShiftBuf.W <<= 1;
					if(usTmp & 0x80)
						RxShiftBuf.W |= 0x1;
					usTmp <<= 1;
					if (RxShiftBuf.W == SYNC_WORD) {
						state = RECEIVE;
						RxBitOffset = 7-i;
						RxShiftBuf.LSB = data;				// 通知上层检测到起始符号且同步完成
						if (PhysicalStartSymDetected() == FAIL) {
							RadiocontrolIdle();
						}
						break;
					}
				}
				break;
            default:
				RadiocontrolIdle();
				break;
            }
		}
	}else if (state == RECEIVE) {							// 根据偏移量接收数据
		char Byte;
		RxShiftBuf.W <<=8;									// 移去已经接收的字节
		RxShiftBuf.LSB = data;								// 存入刚刚收到的字节到低八位
		Byte = (RxShiftBuf.W >> RxBitOffset);				// 根据偏移量取出字节

		PhysicalRxByteDone(Byte);							// 通知上层处理接收到的字节
//		uartDebug_txByte(Byte);
	}		
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -