在线情况
楼主
  • 头像
  • 级别
    • 积分8
    • 经验414
    • 文章10
    • 注册2009-08-10
    求助:基于MSP430F149的NRF905的无线透明传输问题?
    MSP430的RS232--NRF905无线透明传输,发送问题!具体程序见第9楼,我又重新发了一份!
    [ 此贴最后由qianzhou518在2010-11-23 14:57:04编辑过 ]
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
      • 积分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的大师们能再指点一下为盼!
      微控网感谢您的参与
      在线情况
      3
      • 头像
      • 级别
        • 积分8
        • 经验414
        • 文章10
        • 注册2009-08-10
        如果PC机发送的数据比较多,你程序中接满31个字节就发送数据,当你在用905发送数据的时候串口数据可能会丢。建议先把串口数据都接收完之后,再用905打包发送,有几包数据就发送几包。
          串口是中断接收的,串口这里好像不会丢包的吧。我又折腾了一下,发现NRF905发送一包数据需500MS以上的时间,也就是说,NRF905从MCU把TRX_CE置高到NRF905的DR置高要花500MS以上的时间。不知道是怎么回事?
          我也试着先串口全部接收完再NRF905转发,结果还是一样的,只能收到一第一包数据。嗨,人都搞昏了,不知道是不是NRF905不适合做透传?请朋友们赐教啊!
        微控网感谢您的参与
        在线情况
        4
        • 头像
        • 级别
          • 积分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的焊盘脱了一个,又要折腾了!
          微控网感谢您的参与
          在线情况
          5
          • 头像
          • 级别
            • 积分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编辑过 ]
            微控网感谢您的参与
            在线情况
            6
            • 头像
            • 级别
              • 积分8
              • 经验414
              • 文章10
              • 注册2009-08-10
              问题解决了,但是NRF905在MCU9.6K串口速率下(SPI为4M),发送一包的时间很长,好像不像是资料上说的50K的曼码速率。串口测试软件测试时,PC一帧数据最多只能250字以下,否则程序会出错,也就是NRF905在以上条件时转发一帧频PC数据最多只有250字节,这个好像有点太少了。不知道有没有用过NRF905做数据传输的朋友,是如何实现数据传输的?
              微控网感谢您的参与
              在线情况
              7
              • 头像
              • 级别
                • 积分8
                • 经验414
                • 文章10
                • 注册2009-08-10
                看看是不是SPI设置问题,还有读写函数。我的也是自从上次调通后,一直再没弄过了。
                微控网感谢您的参与
                Powered by LeadBBS 9.2 .
                Page created in 0.0938 seconds with 6 queries.