前几天一直在生病,腹部感觉非常难受,经常感到恶心反胃。还胸闷气喘,走几步就累得不行,连坐着都觉得很费劲,只有在床上躺着才会舒服些。所以整整在床上躺了三天,几乎都没出宿舍门,米水也不沾,因为总感觉胃胀。直到昨天早晨起床时才觉得好点儿,至少能下床活动活动了。到今天又好了一些,上午还去上了课,午饭、晚饭也能正常饮食了。我想,这病应该算是熬过去了···
具体什么原因嘛,我也不清楚。可能是哪天夜里没盖好被子,着凉了,再加上前段时间不规律的作息方式,导致亏钱自己身体的债集中到一起爆发,要我还债了。养病的这几天也确实体会到了久违了的睡眠充足的快感,也跟自己的床铺好好亲密了一番。
但是,看看目前的情况,还是很不乐观呐!下周就有课程开始考试了,一直要考到7月1号,断断续续好几门课。别说复习要抓紧,有一些课程甚至从来都没预习过··· 还有更重要的是开发板的试用期也快结束了,我的项目基本上还处于研究学习阶段,还没开始正式进行自己的实验,而且soso姐都已经答应给我延长到7月了,我可千万不能辜负了她的好意!所以,这几天务必要全力以赴,抓紧时间把自己的项目做出来!
好了,闲话少说(老毛病了,呵呵 ),下面就来晒晒生病前后的一些学习成果。
首先,我上次解读的接收端demo_AP程序文件只有main()里面的内容,下面接着把文件剩下的部分解读完,也就是一些main()中调用的函数的定义:
/*------------------------------------------------------------------------------
*创建随机地址
------------------------------------------------------------------------------*/
void createRandomAddress()
{
unsigned int rand, rand2;
do
{
rand = TI_getRandomIntegerFromVLO();
}
while( (rand & 0xFF00)==0xFF00 || (rand & 0xFF00)==0x0000 );
rand2 = TI_getRandomIntegerFromVLO(); // 从VLO(片内超低功耗12KHz低频振荡器)获取整数数值,首字节不能为0x00或0xFF
BCSCTL1 = CALBC1_1MHZ; //#define BCSCTL1_ (0x0057u) /* 基础时钟模块控制寄存器1 */
// DEFC( BCSCTL1 , BCSCTL1_)
//#define CALBC1_1MHZ_ (0x10FFu) /* BCSCTL1分频因数数值*/
// READ_ONLY DEFC( CALBC1_1MHZ , CALBC1_1MHZ_)
DCOCTL = CALDCO_1MHZ; //这一句里的寄存器和参数和上面的类似,只不过是针对DCO(片内可数字控制振荡器)的
//这两句总的结果是设置DCO为1MHz,这样的语句在编程中也是经常用到的,应该熟练掌握
FCTL2 = FWKEY + FSSEL0 + FN1; // FCTL1、FCTL2、FCTL3是Flash控制寄存器
// #define FWKEY (0xA500) —口令码:写入为5AH
// #define FSSEL0 (0x0040u) —Flash 时钟选择为1 - MCLK
// #define FN1 (0x0002) —32*FN5 + 16*FN4 + 8*FN3 + 4*FN2 + 2*FN1 + FN0 + 1=2*1+1=3
// 这一句的效果是选择MCLK并3分频作为Flash时序发生器
FCTL3 = FWKEY + LOCKA; // 清楚锁定位,使Flash可读
FCTL1 = FWKEY + WRT; // 置位WRT使Flash可写
Flash_Addr[0]=(rand>>8) & 0xFF;
Flash_Addr[1]=rand & 0xFF;
Flash_Addr[2]=(rand2>>8) & 0xFF;
Flash_Addr[3]=rand2 & 0xFF; //这四句是设置Flash地址为上面产生的随机地址
FCTL1 = FWKEY; // 清除WRT
FCTL3 = FWKEY + LOCKA + LOCK; // 锁定FLash,这两句的作用应该是保护上面设置的Flash地址
}
/*发送数据函数,该函数在main中最后一段处理节点信号语句中被调用,现在来详细分析其实参、形参及功能:
1,形参addr对应实参i,是发来信号的节点序号,要求不大于sNumCurrentPeers参数(现有节点数量);
2,形参rssi对应实参sigInfo.sigInfo[0],sigInfo是一个ioctlRadioSiginfo_t形式的参数,定义在nwk_types.h文件中:
typedef struct
{
linkID_t lid; //指定的信号信息输入端口(一个字节)
uint8_t sigInfo[MRFI_RX_METRICS_SIZE]; //#define MRFI_RX_METRICS_SIZE __mrfi_RX_METRICS_SIZE__(mrfi.h);#define __mrfi_RX_METRICS_SIZE__ 2(mrfi_CC2500_defs.h)—信号长度为两个字节
} ioctlRadioSiginfo_t;
这里只用了sigInfo[]数组的第一个元素sigInfo[0],但接收到的信号总共有1+2=3字节
3,形参char msg[MESSAGE_LENGTH](#define MESSAGE_LENGTH 3)对应实参main中uint8_t msg[MAX_APP_PAYLOAD](main中343行)
这里问一下,万一MAX_APP_PAYLOAD≠MESSAGE_LENGTH怎么办?形参、实参数组长度就配不上了呀
但这个msg其实就是main中331~333行的温度和电压数据存储数组。
4,这个函数和下一个函数transmitDataString( addrString, rssiString, msg )还只是预处理传送数据,
只是改变了addr和rssi的数据格式,真正的传送函数是调用的TXString()函数来实现的*/
void transmitData(int addr, signed char rssi, char msg[MESSAGE_LENGTH] )
{
char addrString[4];
char rssiString[3];
volatile signed int rssi_int;
addrString[0] = '0'; //转换地址数据格式
addrString[1] = '0';
addrString[2] = '0'+(((addr+1)/10)%10);
addrString[3] = '0'+((addr+1)%10);
rssi_int = (signed int) rssi; //转换信号强度数据格式
rssi_int = rssi_int+128;
rssi_int = (rssi_int*100)/256;
rssiString[0] = '0'+(rssi_int%10);
rssiString[1] = '0'+((rssi_int/10)%10);
rssiString[2] = '0'+((rssi_int/100)%10);
transmitDataString( addrString, rssiString, msg ); //把修改好的数据传送给transmitDataString( )函数
}
/*------------------------------------------------------------------------------
*
------------------------------------------------------------------------------*/
void transmitDataString(char addr[4],char rssi[3], char msg[MESSAGE_LENGTH] )
{
char temp_string[] = {" XX.XC"}; //X代表待定数值,C代表设定好的字符,temp_string[4] = '.'
int temp = msg[0] + (msg[1]<<8);
if( !degCMode ) //非摄氏度格式,即为华氏温度格式
{
temp = (((float)temp)*1.8)+320; //转化为华氏温度数值,若是摄氏温度格式则不需要这一步,因为上面在求temp是默认的就是摄氏温度数据格式
temp_string[5] = 'F';
}
if( temp < 0 ) //温度为负值,显示'-'并改为正数数值
{
temp_string[0] = '-';
temp = temp * -1;
}
else if( ((temp/1000)%10) != 0 ) //下面显示的是摄氏温度格式
{
temp_string[0] = '0'+((temp/1000)%10); //提取百位数值
}
temp_string[4] = '0'+(temp%10); //提取小数位数值
temp_string[2] = '0'+((temp/10)%10); //提取个位数值
temp_string[1] = '0'+((temp/100)%10); //提取十位数值
if( verboseMode ) //上面已经定义了verboseMode=1,即选择串口模式,下面就发送串口模式下的数据格式
{
char output_verbose[] = {"\r\nNode:XXXX,Temp:-XX.XC,Battery:X.XV,Strength:XXX%,RE:no "};
output_verbose[46] = rssi[2]; //强度数据
output_verbose[47] = rssi[1];
output_verbose[48] = rssi[0];
output_verbose[17] = temp_string[0]; //温度数据
output_verbose[18] = temp_string[1];
output_verbose[19] = temp_string[2];
output_verbose[20] = temp_string[3];
output_verbose[21] = temp_string[4];
output_verbose[22] = temp_string[5];
output_verbose[32] = '0'+(msg[2]/10)%10; //电压数据
output_verbose[34] = '0'+(msg[2]%10);
output_verbose[7] = addr[0]; //地址数据
output_verbose[8] = addr[1];
output_verbose[9] = addr[2];
output_verbose[10] = addr[3];
TXString(output_verbose, sizeof output_verbose ); //该函数完成数据的发送任务
}
else //按照上面的格式对号入座,好像对不上呀,这里只有3个待定的X,但要传送的变量却有好多位呢!求解···
{
char output_short[] = {"\r\n$ADDR,-XX.XC,V.C,RSI,N#"};
output_short[19] = rssi[2];
output_short[20] = rssi[1];
output_short[21] = rssi[0];
output_short[8] = temp_string[0];
output_short[9] = temp_string[1];
output_short[10] = temp_string[2];
output_short[11] = temp_string[3];
output_short[12] = temp_string[4];
output_short[13] = temp_string[5];
output_short[15] = '0'+(msg[2]/10)%10;
output_short[17] = '0'+(msg[2]%10);
output_short[3] = addr[0];
output_short[4] = addr[1];
output_short[5] = addr[2];
output_short[6] = addr[3];
TXString(output_short, sizeof output_short );
}
}
/*------------------------------------------------------------------------------
*
------------------------------------------------------------------------------*/
void TXString( char* string, int length ) //如前所述,这个函数才真正完成了发送任务
{
int pointer;
for( pointer = 0; pointer < length; pointer++)
{
volatile int i; //这里定义这个变量起什么作用?
UCA0TXBUF = string[pointer];
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?IFG2:中断标志2;#define UCA0TXIFG (0x02)
}
}
/*------------------------------------------------------------------------------
*
------------------------------------------------------------------------------*/
void MCU_Init()
{
// Set DCO
BCSCTL1 = CALBC1_8MHZ; //#define CALBC1_8MHZ_ (0x10FDu) /* BCSCTL1 Calibration Data for 8MHz */
//READ_ONLY DEFC( CALBC1_8MHZ , CALBC1_8MHZ_)
DCOCTL = CALDCO_8MHZ; //#define CALDCO_8MHZ_ (0x10FCu) /* DCOCTL Calibration Data for 8MHz */
//READ_ONLY DEFC( CALDCO_8MHZ , CALDCO_8MHZ_)
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO(低频振荡器)
//#define BCSCTL3_ (0x0053u) /* Basic Clock System Control 3 */
//DEFC( BCSCTL3 , BCSCTL3_)
TACCTL0 = CCIE; // 捕获比较控制寄存器开启(#define CCIE (0x0010u))
TACCR0 = 12000; // TACCR0中断使能,延时1s
TACTL = TASSEL_1 + MC_1; // ACLK, upmode
P3SEL |= 0x30; // 定义P3.4,5为串口传输的USCI_A0 TXD/RXD端口
UCA0CTL1 = UCSSEL_2; // SMCLK
UCA0BR0 = 0x41; // 8Mhz分频为9600hz作为波特率
UCA0BR1 = 0x3;
UCA0MCTL = UCBRS_2;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // USCI_A0 RX中断使能
__enable_interrupt();
}
/*------------------------------------------------------------------------------
* 该程序运行在 ISR(中断服务例程)中. 读取帧则在应用程序中而不是在ISR中.
------------------------------------------------------------------------------*/
static uint8_t sCB(linkID_t lid)
{
if (lid)
{
sPeerFrameSem++;
}
else
{
sJoinSem++;
}
// 保留帧交给应用层读取
return 0;
}
/*------------------------------------------------------------------------------
* ADC10 interrupt service routine
------------------------------------------------------------------------------*/
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
__bic_SR_register_on_exit(CPUOFF); // 清除CPUOFF位
}
/*------------------------------------------------------------------------------
* 定时器A0中断服务程序
------------------------------------------------------------------------------*/
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
sSelfMeasureSem = 1;
}
/*------------------------------------------------------------------------------
* USCIA中断服务程序
------------------------------------------------------------------------------*/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
char rx = UCA0RXBUF;
if ( rx == 'V' || rx == 'v' )
{
verboseMode = 1;
}
else if ( rx == 'M' || rx == 'm' )
{
verboseMode = 0;
}
else if ( rx == 'F' || rx == 'f' )
{
degCMode = 0;
}
else if ( rx == 'C' || rx == 'c' )
{
degCMode = 1;
}
}
以上就是demo_AP文件中的函数定义,至此,接收端的处理过程算是全弄明白了。下面,再简单分析下节点的程序demo_ED:
#include "bsp.h"
#include "mrfi.h"
#include "nwk_types.h"
#include "nwk_api.h"
#include "bsp_leds.h"
#include "bsp_buttons.h"
#include "vlo_rand.h" //各种头文件
void linkTo(void);
void MCU_Init(void); //main()调用到的函数声明
__no_init volatile int tempOffset @ 0x10F4; // Temperature offset set at production
__no_init volatile char Flash_Addr[4] @ 0x10F0; // Flash address set randomly,这两个在AP程序中已经介绍过了
void createRandomAddress();
void main (void)
{
addr_t lAddr;
WDTCTL = WDTPW + WDTHOLD; // 关看门狗
{
volatile int i;
for(i = 0; i < 0xFFFF; i++){}
} //延时,等待晶体振荡器稳定
if( CALBC1_8MHZ == 0xFF ) // Do not run if cal values are erased,上次忘了问,这句话是何作用?
{
volatile int i;
P1DIR |= 0x03; //P1.0,P1.1方向为输出
BSP_TURN_ON_LED1();
BSP_TURN_OFF_LED2();
while(1)
{
for(i = 0; i < 0x5FFF; i++){}
BSP_TOGGLE_LED2();
BSP_TOGGLE_LED1();
}
}
// SimpliciTI协议也会改变端口引脚设置
P1DIR = 0xFF; //P1端口全为输出
P1OUT = 0x00;
P2DIR = 0x27; //P2端口的0、1、2、5为输出
P2OUT = 0x00;
P3DIR = 0xC0; //P3端口的6、7为输出
P3OUT = 0x00;
P4DIR = 0xFF; //P4端口全为输出
P4OUT = 0x00;
BSP_Init();
if( Flash_Addr[0] == 0xFF &&
Flash_Addr[1] == 0xFF &&
Flash_Addr[2] == 0xFF &&
Flash_Addr[3] == 0xFF )
{
createRandomAddress(); // set Random device address at initial startup
}
lAddr.addr[0]=Flash_Addr[0];
lAddr.addr[1]=Flash_Addr[1];
lAddr.addr[2]=Flash_Addr[2];
lAddr.addr[3]=Flash_Addr[3];
SMPL_Ioctl(IOCTL_OBJ_ADDR, IOCTL_ACT_SET, &lAddr);
BCSCTL1 = CALBC1_8MHZ; // Set DCO after random function
DCOCTL = CALDCO_8MHZ;
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
TACCTL0 = CCIE; // TACCR0 interrupt enabled
TACCR0 = 12000; // ~ 1 sec
TACTL = TASSEL_1 + MC_1; // ACLK, upmode
/*一直尝试连接直到成功。翻转LEDS 以显示连接未完成。LED3为红色但在实验板丝印层上标记为LED4。LED1为绿色.*/
while (SMPL_NO_JOIN == SMPL_Init((uint8_t (*)(linkID_t))0))
{
BSP_TOGGLE_LED1();
BSP_TOGGLE_LED2();;
__bis_SR_register(LPM3_bits + GIE); // LPM3 with interrupts enabled
}
// 无条件连接到AP。连接成功后AP一直处于监听状态。
linkTo();
}
[ 本帖最后由 wwh19910609 于 2011-6-12 22:25 编辑 ]
void createRandomAddress()
{
unsigned int rand, rand2;
do
{
rand = TI_getRandomIntegerFromVLO(); // first byte can not be 0x00 of 0xFF
}
while( (rand & 0xFF00)==0xFF00 || (rand & 0xFF00)==0x0000 );
rand2 = TI_getRandomIntegerFromVLO();
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz
DCOCTL = CALDCO_1MHZ;
FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator
FCTL3 = FWKEY + LOCKA; // Clear LOCK & LOCKA bits
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
Flash_Addr[0]=(rand>>8) & 0xFF;
Flash_Addr[1]=rand & 0xFF;
Flash_Addr[2]=(rand2>>8) & 0xFF;
Flash_Addr[3]=rand2 & 0xFF;
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCKA + LOCK; // Set LOCK & LOCKA bit
}
void linkTo()
{
linkID_t linkID1;
uint8_t msg[3];
// keep trying to link...
while (SMPL_SUCCESS != SMPL_Link(&linkID1))
/*SMPL_Link(&linkID1):这个函数的调用发送了一个广播连接脚本后等待应答,当收到一个应答时,
两个节点之间的连接已经确定,会分配以一个Link ID作为连接的语柄。这个函数可以多次调用
来建立多个逻辑连接,在同级节点中可能连接相同或不同的设备。
函数原型: smplStatus_t SMPL_Link(linkID_t *lid)
参数lid: 这个参数是一个指向Link ID指针,如果调用成功,指针指向的变量将有效,并将在
随后的具体节点应用程序接口中使用。
返回值:SMPL_SUCCESS 连接成功。
SMPL_NO_LINK 在等待其间没有连接应答。
SMPL_NOMEM 没有空间分配给当地的接收端口,没有更多的空间连接表,或没有在输出帧队列空间。
SMPL_TX_CCA_FAIL 无法发送链接帧。 */
{
__bis_SR_register(LPM3_bits + GIE); // 选择LPM3模式,开总中断
BSP_TOGGLE_LED1();
BSP_TOGGLE_LED2();
}
// Turn off all LEDs
if (BSP_LED1_IS_ON())
{
BSP_TOGGLE_LED1();
}
if (BSP_LED2_IS_ON())
{
BSP_TOGGLE_LED2();
}
while (1)
{
volatile long temp;
int degC, volt;
int results[2];
SMPL_Ioctl( IOCTL_OBJ_RADIO, IOCTL_ACT_RADIO_SLEEP, "" );
/*SMPL_Ioctl():
原型:smplStatus_t SMPL_Ioctl(ioctlObject_t obj, ioctlAction_t act, void *val)
obj 被请求的动作的对象.
act 指定对象应完成的动作.
val 参数信息指针.有动作决定输入输出. 若对象/动作组合不需要参数信息则可为空值*/
__bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled
results[0] = ADC10MEM; //提取温度数值
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_11; // 开启电压采集通道,AVcc/2
ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE + REF2_5V;
for( degC = 240; degC > 0; degC-- ); // delay to allow reference to settle
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
__bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled
results[1] = ADC10MEM; //提取电压数值
ADC10CTL0 &= ~ENC;
ADC10CTL0 &= ~(REFON + ADC10ON); // turn off A/D to save power
// oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
// the temperature is transmitted as an integer where 32.1 = 321
// hence 4230 instead of 423
temp = results[0];
degC = ((temp - 673) * 4230) / 1024;
if( tempOffset != 0xFFFF )
{
degC += tempOffset;
}
/*数据格式, UB = upper Byte, LB = lower Byte
-------------------------------
|degC LB | degC UB | volt LB |
-------------------------------
0 1 2
*/
temp = results[1];
volt = (temp*25)/512;
msg[0] = degC&0xFF;
msg[1] = (degC>>8)&0xFF;
msg[2] = volt;
if (SMPL_SUCCESS == SMPL_Send(linkID1, msg, sizeof(msg)))
{
BSP_TOGGLE_LED2();
}
else
{
BSP_TOGGLE_LED2();
BSP_TOGGLE_LED1();
}
}
}
/*------------------------------------------------------------------------------
* ADC10 interrupt service routine
------------------------------------------------------------------------------*/
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
}
/*------------------------------------------------------------------------------
* Timer A0 interrupt service routine
------------------------------------------------------------------------------*/
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
__bic_SR_register_on_exit(LPM3_bits); // Clear LPM3 bit from 0(SR)
}
if( CALBC1_8MHZ == 0xFF ) // Do not run if cal values are erased,上次忘了问,这句话是何作用?
在430内部有个信息段用于存储为何DCO可以配置到各种不同的频率的值的,这个值为空的时候就是ff了 你懂的不多说了
你好,我想问下AD采样点数应该怎么设定呢?
引用: qiwan 发表于 2014-4-2 22:34
您好,请问:void createRandomAddress()在哪里找到的?
我从bsp、mrfi、nwk、nwk _applications到Peer_ap ...