在线情况
楼主
  • 头像
  • 级别
    • 积分8
    • 经验414
    • 文章10
    • 注册2009-08-10
    求助:基于MSP430F149的NRF905的无线透明传输问题?
    MSP430的RS232--NRF905无线透明传输,发送问题!具体程序见第9楼,我又重新发了一份!
    [ 此贴最后由qianzhou518在2010-11-23 14:57:04编辑过 ]
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
    • 门派
    • 职务总版主
    • 声望+9
    • 财富5
    • 积分3065
    • 经验390701
    • 文章6744
    • 注册2006-03-07
    建议一:
    尝试将SPI速度降低到几十K试试,这样可以保证低速下时减少一些走线或器件的对时序影响。
    其二:
    你问题在59与60两者有驱别,这个会不会一个单简问题呢;比如C语言计数时公式你一时搞错了。检查一下...。
    [COLOR=#0000ff]欢迎发贴分享设计心得、开源DIY...[/COLOR]
    在线情况
    3
    • 头像
    • 级别
      • 积分8
      • 经验414
      • 文章10
      • 注册2009-08-10
      谢谢DC了!
        这两天我又弄了一下,SPI速度降低也没有效果。我总觉得我的程序有问题,并且认为是发送端的问题,就是不知道出在哪儿。
        我的程序思路是:430从PC接收长短不一的字符串,接收数据先暂存,再通过NRF905无线发送出去,NRF905每次最多只发送31字节,其中0字节为本次发送的字长。430用中断接收,定时器用来判断PC端所有数据接收完毕,每次接收中断,定时器清0并重新计数,定时间隔为两字符接收时间间隔。定时器中断说明PC端数据接收完毕。NRF905发送完后进入无线接收模式等待接收数据。
        现在的问题是:发送接收59以下字节,都能正常,当PC发送60字节时,返回的是前30字节,后30没了;当PC发送60多字节时,返回的是前30字加上未尾的不满30的尾数字节,中间的30以上字节没有了。从表面上看,好像是NRF905前一次还没发送完,后面的一帧就又要开始发送了。NRF905无线速率是50-100K,而串口才9.6K,NRF905应该还比较空闲呀。还有就是定时器间隔应该2000uS就足了(9.6K串口),但调试时有些长度的尾数字节返回不了(如61,62;而68,69等又可以)。间隔时间要40000uS不同长度的尾数字节才都可以返回,我是真的搞不懂了!呵呵。
        本人是新手,所以这个问题折腾几天了无果。希望做过NRF905的大师们能再指点一下为盼!
      微控网感谢您的参与
      在线情况
      4
      • 头像
      • 级别
        • 积分14
        • 经验2823
        • 文章55
        • 注册2007-04-09
        如果PC机发送的数据比较多,你程序中接满31个字节就发送数据,当你在用905发送数据的时候串口数据可能会丢。建议先把串口数据都接收完之后,再用905打包发送,有几包数据就发送几包。
        微控网感谢您的参与
        在线情况
        5
        • 头像
        • 级别
          • 积分8
          • 经验414
          • 文章10
          • 注册2009-08-10
          如果PC机发送的数据比较多,你程序中接满31个字节就发送数据,当你在用905发送数据的时候串口数据可能会丢。建议先把串口数据都接收完之后,再用905打包发送,有几包数据就发送几包。
            串口是中断接收的,串口这里好像不会丢包的吧。我又折腾了一下,发现NRF905发送一包数据需500MS以上的时间,也就是说,NRF905从MCU把TRX_CE置高到NRF905的DR置高要花500MS以上的时间。不知道是怎么回事?
            我也试着先串口全部接收完再NRF905转发,结果还是一样的,只能收到一第一包数据。嗨,人都搞昏了,不知道是不是NRF905不适合做透传?请朋友们赐教啊!
          微控网感谢您的参与
          在线情况
          6
          • 头像
          • 级别
            • 积分14
            • 经验2823
            • 文章55
            • 注册2007-04-09
            串口数据都接收完成,905转发只能收到第一包数据?
            先要确定是否串口数据都已经正确接收,如果串口接收正常,那就调试905发射。
            固定数据包,59个字节以上,看是否能正常发射和接收。
            微控网感谢您的参与
            在线情况
            7
            • 头像
            • 级别
              • 积分8
              • 经验414
              • 文章10
              • 注册2009-08-10
              谢谢boyyuboy  !我试过了串口接收的情况,应该是没问题。我把串口接收下来的数据第一包先不发,直接发送第二包,第二包接收也正常,但是也只能收到一包, 我想这个应该能说明串口接收没啥问题。
                 我又发现一个奇怪的现象了,真是邪乎了,在发送数据包程序中我把while(!DR);TRX_CE_0;(即启动发射后等待数据发射完成DR置高),换成delay_us(20);TRX_CE_0; 完了,这下一包都收不到了,加大延时也是一样,又是不可思议!资料上说TRX_CE有10US以上的脉冲就可以保证数据发射完毕的。于是我又开始怀疑905芯片了,准备换一片905,很不幸,905的焊盘脱了一个,又要折腾了!
              微控网感谢您的参与
              在线情况
              8
              • 头像
              • 级别
                • 积分14
                • 经验2823
                • 文章55
                • 注册2007-04-09
                void delay_us(uint x)
                {
                   for(uint i=0;x>i;i--);  
                }
                函数写错了吧,你加大多少,程序都执行一次,i--后i=65535,跳出循环……
                905的电源不过压,不反接,一般坏不了
                微控网感谢您的参与
                在线情况
                9
                • 头像
                • 级别
                  • 积分8
                  • 经验414
                  • 文章10
                  • 注册2009-08-10
                  基于MSP430的NRF905无线透传问题
                  先谢谢“boyyuboy  ”,不好意思,我重发一份。情况是PC只能收到第一包。如果屏蔽第一包则只能收到第二包。如果PC重新发别的字符(长度任意`),每次返回来的还是改变发送字符之前的字符,好像PC第一次发送时,程序一直卡在发送第二个包上,所以串口接收计数一直都没清0
                  [CODE]
                  #include <msp430x14x.h>
                  //=================================================================
                  #define  uchar   unsigned char
                  #define  uint    unsigned int

                  //==================TXEN,TRX_CE,PWR_0 为收发模式控制端口==========
                  #define  TXEN_0     P6OUT &=~BIT2          // TX_EN输出0
                  #define  TXEN_1     P6OUT |= BIT2          // TX_EN输出1
                  //=================================================================
                  #define  TRX_CE_0   P6OUT &=~BIT1
                  #define  TRX_CE_1   P6OUT |= BIT1
                  //==============================================================
                  #define  PWR_0      P6OUT &=~BIT0
                  #define  PWR_1      P6OUT |= BIT0

                  //================SPI使能端口======================
                  #define  CSN_0      P5OUT &=~BIT0
                  #define  CSN_1      P5OUT |= BIT0
                  //===下为状态端口========================================
                  //===============AM  地址匹配================
                  #define  AM         P2IN & BIT6       
                  //===============DR 数据接收状态=================
                  #define  DR         P2IN & BIT7
                  //=============CD 载波侦听状态========
                  #define  CD         P2IN & BIT5
                  //================================================

                  //=============NRF905:SPI指令=========
                  #define WC            0x00        // 写配置寄存器命令
                  #define RC            0x10        // 读配置寄存器命令
                  #define WTP          0x20        // 写TX有效数据命令
                  #define RTP      0x21        // 读TX有效数据命令
                  #define WTA      0x22        // 写TX地址命令
                  #define RTA      0x23        // 读TX地址命令
                  #define RRP      0x24        // 读接收有效数据命令
                     
                  uchar TxBuf[96];                    // 缓存里32个等发送的字
                  uchar RxBuf[32];                    // 缓存里32个待接收的字                               
                  uchar TxAddress[4]={0xE7,0xE7,0xE7,0xE7}; // 4个字节的发送地址
                  uchar DATA_BUF;                       // 本字符变量作暂存用
                  uchar k=0;

                  //============NRF905:10寄存器配置=================
                  unsigned char  RFConf[11]=
                  {
                    WC,                         //SPI写操作命令
                    0x4c,                       //CH_NO,配置频段在430MHZ
                    0x0C,                       //输出功率为10db,不重发,节电为正常模式
                    0x44,                       //地址宽度设置,为4字节
                    0x20,0x20,                  //接收发送有效数据长度为32字节
                    0xE7,0xE7,0xE7,0xE7,       //接收地址
                    0x5F             //CRC充许,8位CRC校验,外部时钟信号输出500K,16M晶振
                  };
                  /********************************************************************
                  系统初始化
                  *********************************************************************/
                  void InitSys()
                  {
                     uint i;
                     BCSCTL1 &=~XT2OFF;              //启用XT2振荡器
                     do
                        {
                          IFG1 &= ~OFIF;            // 清除振荡器失效标志
                          for (i = 0xFF; i > 0; i--);     // 延时,等待XT2起振
                        }
                     while ((IFG1 & OFIFG) != 0);    // 判断XT2是否起振            
                     BCSCTL2 =SELM1+SELS;                // MCLK,SMCLK时钟为XT2
                    //----LED测试用-----
                     P4DIR |= BIT6;
                     P4OUT |= BIT6;
                    //----串口0设置RS232------
                    P3SEL |= BIT4+BIT5;                   //UART0 TX,RX
                    P3DIR |= BIT4;
                    ME1 |= UTXE0+URXE0;
                    U0CTL |= CHAR+SWRST;                  // 数据位为8位
                    U0TCTL = SSEL1;                       //波特率时钟源为SMCLK
                    UBR0_0 = 0x41;     //8M/9.6K
                    UBR1_0 = 0x03;     //
                    UMCTL_0= 0x49;
                    //UBR0_0 = 0x82;     //8M/4.8K
                    //UBR1_0 = 0x06;     //
                    //UMCTL_0= 0xAD;
                    IFG1 &= ~UTXIFG0;
                    U0CTL &= ~SWRST;
                    IE1   |= URXIE0;             // 使能接收中断
                  //------串口1设置SPI--------
                    P5SEL |= BIT3+BIT2+BIT1;// P5.0--STE1 CSN P5.1--SIMO1  P5.2--SOMI1 P5.3--CLK1
                    P5SEL &= ~BIT0;          // P5.0CSN作普通IO
                    P5DIR |= BIT3+BIT1+BIT0;     // 都作输出
                    P5OUT |= BIT3+BIT1+BIT0;     // 都输出高电平
                    UCTL1 |= SWRST;
                    UCTL1 |= CHAR+SYNC+MM;       // 数据8位,SPI模式,单片主机模式
                    UTCTL1 &= ~(CKPH|CKPL);  // SPI时钟设置
                    UTCTL1 |= SSEL1+STC;         // 时钟源为SMCLK 3线模式
                    ME2    |= USPIE1;            // 使能SPI模块
                    UBR0_1 = 0x02;               // 8M/4M=8   SPI 4M速率
                    UBR1_1 = 0x00;               //
                    UMCTL_1= 0x00;
                    U1CTL &= ~SWRST;
                    //IE2   |= URXIE1+UTXIE1;  
                  }
                  //=========初始化nRF905===================
                  void nRF905_IO_set(void)
                  {
                     //P5DIR |= BIT0+BIT1+BIT3;// P5.0-CSN,P5.1-MOSI,P5.3-SCK都为输出 P5.2-MISO
                     P6DIR |= BIT0+BIT1+BIT2;     // P6.0-PWR_UP,P6.1-TRX_CE,P6.2-TXEN都为输出
                     P2DIR &= ~(BIT5+BIT6+BIT7);  // P2.5-CD,P2.6-AM,P2.7-DR 都为输入    
                     P2IE |= BIT7;                // 使能P2.7 中断并且上升沿触发
                          
                     CSN_1;                   // Spi disable
                     PWR_1;                   // nRF905上电
                     TRX_CE_0;               // nRF905进入待机模式
                     TXEN_0;                   // 进入接收模式
                  }

                  //===========10uS延时 (8M主时钟)====================
                  void delay_10us(uint x)
                  {
                    uchar q;
                    for(uchar i=0;i<x;i++)
                       {
                         for(q=17;q>0;q--);
                       }
                  }

                  //===============NRF905 SPI读函数==================
                  uchar SpiRead(void)
                  {
                    U1TXBUF=0;
                    while(!(U1TCTL&TXEPT));
                    return U1RXBUF;
                  }
                  //==============NRF905 SPI读写函数==================
                  void SpiWrite(uchar send)
                  {  
                    U1TXBUF=send;
                    while(!(U1TCTL&TXEPT)); //等待发送器为空
                  }

                  //==============初始化NRF905========================
                  void Config905(void)
                  {
                    uchar i;
                    CSN_0;                      // 使能SPI
                    for (i=0;i<11;i++)           // 写配置字,共要写完配置寄存器里的10个字配置字
                       {
                        SpiWrite(RFConf[I]);       
                       }
                   // while(!(IFG2&UTXIFG1));
                    CSN_1;                        //关闭SPI
                  }
                  //--------定时器A初始化-------------
                  void Timer_A_init()
                  {
                   CCTL0=CCIE;                       // CCR0中断允许
                   TACTL=TASSEL_2+TACLR+MC_1+ID1+ID0;//定时器A时钟源为SMCLK并且8分频,计数器清0,增计数模式
                  }

                  //===============接收模式===============
                  void SetRxMode(void)
                  {
                    TXEN_0;
                    TRX_CE_1;
                    delay_10us(70);            // delay for mode change(>=650us)
                  }

                  void SetTxMode(void)
                  {
                    TXEN_1;
                    TRX_CE_0;
                    delay_10us(70);            // delay for mode change(>=650us)
                  }

                  //=========NRF905装载地址+数据打包+数据发送=============
                  void TxPacket(uchar a,uchar b)
                  {
                    uchar i;  
                    CSN_0;                    // 使能SPI
                    SpiWrite(WTA);             // 写入地址命令
                    for (i=0;i<4;i++)             // 4字节地址
                       {
                        SpiWrite(TxAddress[I]);
                       }
                    CSN_1;                 // 写完后关闭SPI
                    delay_10us(1);                  
                    CSN_0;                    // 再打开SPI
                    SpiWrite(WTP);         // 写装载TX有效数据命令
                     for (i=a;i<b;i++)    // 写TX有效数据     {
                         SpiWrite(TxBuf[I]);
                         //TxBuf[I]=0;
                       }
                    CSN_1;              // 再关闭SPI
                    TRX_CE_1;            // 开始发射
                    //delay_10us(2);  //10us的脉冲以确保数据发送完。《如果用本句PC只能收一次数据》
                    while(!(DR));     //若DR为低则一直等待 。??本句等待时间很长,不知为啥??
                    TRX_CE_0;         //905待机
                    //TXEN_0;                 
                  }     

                  //==========数据接收==================
                  void RxPacket(void)                                    
                  {
                      uchar i;
                      TRX_CE_0;
                      CSN_0;                       // SPI使能  
                      SpiWrite(RRP);              // SPI读接收有效数据命令
                      for (i = 0 ;i < 32;i++)    
                        {  
                         RxBuf[I]=SpiRead();      // 从NRF905读数据至数组
                        }  
                      //while(DR||AM);            //等待数DR或AM变低即据接收完毕
                      CSN_1;                              
                      delay_10us(1);
                      for (i = 0 ;i <32;i++)
                         {  
                           if(RxBuf[I]!=0)
                           {
                             while(!(IFG1&UTXIFG0)); // 等待发送器为空
                             TXBUF0 = RxBuf[I];   // 将接收的数据通过串口发送至PC或其它设备
                             //RxBuf[I]=0;
                             // while(!(U0TCTL&TXEPT)); // 等待发送器为空
                           }
                         }
                      delay_10us(1);
                      TRX_CE_1;
                      delay_10us(70);               //切换进入接收状态
                      P4OUT |= BIT6;
                  }


                  //===========主函数================
                  void main(void)
                  {
                     WDTCTL = WDTPW + WDTHOLD;         // 禁止看门狗
                     InitSys();                        // 系统初始化
                     nRF905_IO_set();                  // NRF905初始化
                     Config905();                      // 配置NRF905的配置寄存器  
                     Timer_A_init();                   //定时器初始化
                     SetRxMode();                      //接收模式
                     _EINT();                          // 开总中断
                     while(1)
                       {
                        // LPM1;    
                       }  
                  }    

                  #pragma vector = UART0RX_VECTOR
                  __interrupt void usart0_rx()
                  {
                   // LPM1_EXIT;
                    TACTL &= ~(MC1+MC0);       //停止计数器
                    TACTL |= TACLR+MC0;        // 清除计数器内容重新计数                         
                    CCR0=1500;                 // 重新启动增计数模式
                    TxBuf[k]=RXBUF0;           // 接收数据先暂存
                    k++;
                  }
                   
                  #pragma vector = PORT2_VECTOR //905中断接收
                  __interrupt void PORT2_rx()
                  {
                   // LPM1_EXIT;
                    P2IFG &= ~BIT7;     // 清除标志
                    if((DR)&&(AM))      // 若接收的地址与数据 正确  
                      RxPacket();       // 接收数据包并发送至PC或其它设备    
                  }

                  #pragma vector = TIMERA0_VECTOR//本中断程序的启动表示本次所有数据串口接收完毕
                  __interrupt void Timer_A()
                  {
                   //LPM1_EXIT;
                    TACTL &= ~(MC1+MC0);    //接收转发完了 停止计数器
                    if((k>0)&&(k<=32))
                      {
                       SetTxMode();
                       TxPacket(0,32);          // 发送数据包
                       k=0;
                      }
                   else if((k>32)&&(k<=64))
                      {
                       SetTxMode();
                       TxPacket(0,32);         // 发送数第1包据包
                       //delay_10us(1000);
                       TxPacket(32,64);        // 发送数第2包据包
                       k=0;
                      }
                   else if((k>64)&&(k<=96))
                     {
                      SetTxMode();
                      TxPacket(0,32);          // 发送数第1包据包
                     // delay_10us(1000);
                      TxPacket(32,64);         // 发送数第2包据包
                     // delay_10us(1000);
                      TxPacket(64,96);        // 发送数第3包据包
                      k=0;
                     }
                   else if((k>96)&&(k<=128))
                     {
                      SetTxMode();
                      TxPacket(0,32);          // 发送数据包
                      TxPacket(32,64);  
                      TxPacket(64,96);
                      TxPacket(96,128);
                      k=0;
                     }
                    else if((k>128)&&(k<=160))
                     {
                      SetTxMode();
                      TxPacket(0,32);          // 发送数据包
                      TxPacket(32,64);  
                      TxPacket(64,96);
                      TxPacket(96,128);
                      TxPacket(128,160);
                      k=0;
                     }
                   else if((k>160)&&(k<=192)) //暂时就这样
                     {
                      SetTxMode();
                      TxPacket(0,32);          // 发送数据包
                      TxPacket(32,64);  
                      TxPacket(64,96);
                      TxPacket(96,128);
                      TxPacket(128,160);
                      TxPacket(160,192);
                      k=0;
                     }
                    SetRxMode();           // 发送完毕NRF905接收模式
                  }[/CODE]
                  [ 此贴最后由DC在2010-11-23 19:51:38编辑过 ]
                  微控网感谢您的参与
                  在线情况
                  10
                  • 头像
                  • 级别
                    • 积分14
                    • 经验2823
                    • 文章55
                    • 注册2007-04-09
                    在905接收中断里面加串口数据发送?
                    再开一个缓冲区,接收到的数据放在放在新缓冲区中,把串口数据发送放在在主函数中试下。
                    先确定905是否已将两包或更多数据正常接收,如果905都没有接收完整,PC机肯定收到的完整数据包
                    微控网感谢您的参与
                    在线情况
                    11
                    • 头像
                    • 级别
                      • 积分8
                      • 经验414
                      • 文章10
                      • 注册2009-08-10
                      问题解决了,但是NRF905在MCU9.6K串口速率下(SPI为4M),发送一包的时间很长,好像不像是资料上说的50K的曼码速率。串口测试软件测试时,PC一帧数据最多只能250字以下,否则程序会出错,也就是NRF905在以上条件时转发一帧频PC数据最多只有250字节,这个好像有点太少了。不知道有没有用过NRF905做数据传输的朋友,是如何实现数据传输的?
                      微控网感谢您的参与
                      在线情况
                      12
                      • 头像
                      • 级别
                        • 积分6
                        • 经验182
                        • 文章6
                        • 注册2009-09-23
                        楼主 您好  为什么我的spi调试不通呢 是不是spi需要高频晶振呢
                        微控网感谢您的参与
                        Powered by LeadBBS 9.2 .
                        Page created in 0.2676 seconds with 5 queries.