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