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)、如果其他中斷比較重要,不能隨便的關閉,這是就需要對串口接收的數據做好容錯處理,要去判斷接收數據是否完成,接收過程中是否被打斷過,等等。