MSP430单片机多机通信总结

1、硬件条件:MSP430F149;

2、编译环境:IAR5.3;

3、过程中所发现的问题

(1)串口配置所存在的问题

 主机的程序也需要设定为多机模式,并且主机也需要有地址 !

a)、主机串口配置程序

void usart1_init(void)
{
  U1CTL |=SWRST;  //SWRST复位,USART允许
  U1CTL=CHAR+MM;  //8位数据位,1位停止位,地址位模式,0x01
//  U1CTL=CHAR;
//  U1BR0=0X03;     //0x03位9600,0x06时为4800
//  U1BR1=0X00;
//  U1MCTL=0X4A;    //使用32KHZ晶振时,波特率为9600bps时为0x4A,波特率为4800bps时为0x6f
//  UTCTL1=0X10;
  //11520
  U1BR0=0X45;
  U1BR1=0X00;
  U1MCTL=0X00;
  U1TCTL|= SSEL1;
  
  U1CTL &= ~SWRST;//  设置完成
  
  U1RCTL |= URXWIE;//只有地址字符使URXIFG置位
  
  ME2 |= UTXE1 + URXE1;//允许串口接收与发送
  P3SEL |=0XC0;   //P3.6、P3.7由USART1发送模块占用
  P3DIR |=0X40;   //P3.6输出,P3.7输入
  IE2 |=URXIE1;   //接收中断
  _EINT();        //不要忘了开中断
}

b)、主机发送数据过程

先发送地址,再发送数据。主机向从机发送数据的程序如下:

//**************************************************//
//address表示从机地址
//*pBuffer表示要发送数据的指针
//n_byteb表示数据长度
//**************************************************//
void USART1_Send(uchar addr,uchar *pBuffer,uchar n_byte)
{
  unsigned int i;
  
  UTCTL1 |=TXWAKE;
  TXBUF1=addr;
  while((UTCTL1&0X01)==0); //查询等待一次发送完毕 
  UTCTL1&=~TXWAKE;
  for(i=0;i<n_byte;i++)
  {
    while((UTCTL1&0X01)==0);
    TXBUF1=*pBuffer;
    pBuffer++;        
  }
}

c)、主机串口接收中断

先把接收到的第一个数据与本机的地址进行对比,如果地址一致,说明数据是发给本机的,通过设置U1RCTL&=~URXWIE;,后面接收的为数据;如果不死本机的地址,则仍然处于接收地址状态,后面从机发送的数据将不会触发本接收中断。程序如下:

//接收中断服务函数

#pragma vector=UART1RX_VECTOR 
__interrupt void USART1_RXIRQ (void) 
{
  Data1[NRxBuff++]=RXBUF1;
  if(URCTL1&URXWIE) //接收为地址方式时,等待正确地址出现,URXWIE,RXWAKE
  {
    if(RXBUF1==ADDRESS) //地址正确,改变接收为数据方式,准备接受
    {
      U1RCTL&=~URXWIE;
      flag=1;
    }
    else
    {
      U1RCTL |= URXWIE;   //不是本机地址,则以后接收到数据不产生中断
    }
  }
  if((flag==1)&&(!(URCTL1&URXWIE)))
  {
      num++;
      if(num>1)//避免把地址作为第一位数据  
        Data1[NRxBuff++]=RXBUF1; //数据存入Data数组中
      if(NRxBuff==N_XY_BAO)
      {
        USART0_SendUint(RXBUF1);
        NRxBuff=0;
        flag_send=1;
        flag=0;
        num=0;    
        URCTL1|=URXWIE; //改变接收为地址方式,URXWIE        
        for(j1=0;j1<N_XY_BAO;j1++)
          aRxBuff[j1]=Data1[j1]; //复制字符串
        memset(Data1,0,36);//数组清零
      }
    }
  
    else
    {
      URCTL1|=URXWIE; //改变接收为地址方式,URXWIE
      memset(Data1,0,36);//数组清零
      NRxBuff=0;
    }

}


d)、从机串口配置程序

void usart1_init(void)
{
  P3SEL |=0XC0;   //P3.6、P3.7由USART1发送模块占用
  P3DIR |=0X40;   //P3.6输出,P3.7输入
  UCTL1 |=CHAR+MM+SWRST;   //8位数据位,1位停止位,地址位模式,0x01,
//  UCTL1 |=CHAR+SWRST;
//  U1BR0=0X03;     //0x03位9600,0x06时为4800
//  U1BR1=0X00;
//  U1MCTL=0X4A;    //使用32KHZ晶振时,波特率为9600bps时为0x4A,波特率为4800bps时为0x6f
//  U1TCTL=0x10;    //选定ACLK(32KHZ晶振)为时钟源,0x1 
  //115200
  U1BR0=0X45;
  U1BR1=0X00;
  U1MCTL=0X00;
  U1TCTL|= SSEL1;  
  
  U1RCTL|=URXWIE; //改变接收为地址方式
  U1CTL &= ~SWRST;
  ME2 |= UTXE1 + URXE1;//允许串口接收与发送  
  IE2 |=URXIE1;   //接收中断
  //_EINT();      //开总中断  ,工程中其他的程序已经打开了总中断
}

从机的数据发送与串口接收中断的程序基本一致,在此就不再赘述。

2)多个从机接在一块,通讯仍不正常

通过测试发现是从机串口的TxD造成的,在不发数据的状态下,TxD为高电平,造成整个总线上的电平不准确,所以从机需要在发送完数据后把串口的TxD设置为普通IO口,并且设置为输入状态!

3)当主机程序存在多个中断时,通讯有可能不能正常进行

最近在做一个项目,主机用到了3个中断:timeB定时溢出中断、usart0和usart1的串口接收中断。这样串口就很有可能不能接收到正确和完整的数据。解决办法有:

a)、在串口接收到本机地址后关闭其他中断,待数据接收完后立即打开其他中断;

b)、如果其他中断比较重要,不能随便的关闭,这是就需要对串口接收的数据做好容错处理,要去判断接收数据是否完成,接收过程中是否被打断过,等等。

 

 

 

 

          

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章