MCU:MSP430F2618
RS485接口芯片:MAX3485
采用第三方开发板作为主机(MCU),从机为一个RS485协议的气体传感器模块
通信要求:通用 R S 4 8 5 总线,所有控制板连接在一条 R S 4 8 5 总线上;
通信方式:通用异步接收 /发送( UART),波特率为 9 60 0,数据位为 8 位, 1 位停止位,偶校验;
我写的的程序主要函数如下,完整程序在附件里,看不出问题出在哪里,就是不能成功实现RS485通信,主机发送指令后,从机返回的数据无法接收到,到底是主机发送格式的问题,还是从机返回数据主机没收到,我无法判断出来,请专家帮忙看看,谢了!
//*************************************************************************
// 系统时钟初始化
//*************************************************************************
void Clock_Init()
{
BCSCTL1 &= ~XT2OFF; //打开XT2振荡器
BCSCTL3 |= XT2S_2; // Mode 2 for XT2 : 3 – 16 MHz
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (uint i = 0xFF; i > 0; i–); // Time for flag to set
}
while (IFG1 & OFIFG); // OSCFault flag still set? IFG1 &= ~OFIFG; BCSCTL2 |= SELM_2+SELS; //MCLK为8MHZ,SMCLK为8MHZ
}
//***********************************************************************
// MSP430串口初始化
//*************************************************************************
void UART_Init()
{
UCA1CTL1 |= UCSWRST;
UCA1CTL0 |= UCPEN + UCPAR; //奇偶校验被启用,偶校验,8位数据模式
UCA1CTL1 |= UCSSEL_2; //SMCLK为串口时钟 + UCBRKIE
UCA1BR0 = 0x34; //波特率设置
UCA1BR1 = 0x00; //9600bps@8MHz
UCA1MCTL |= UCBRF_1+UCOS16; /*
UCA1CTL1 |= UCSSEL_1; // CLK = ACLK
UCA1BR0 = 0x03; // 32kHz/9600 = 3.41
UCA1BR1 = 0x00; //
UCA1MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3
*/
P3SEL|= BIT6 + BIT7; //设置IO口为第二功能模式,启用UART功能
P3DIR|= BIT6; //设置TXD1口方向为输出
UCA1CTL1 &= ~UCSWRST; UC1IE |= UCA1RXIE; //接收中断启用
}
//***********************************************************************
// CRC16 码直接计算法
//*pSendBuf:首字节指针//nEnd:数据校验长度
//*************************************************************************
unsigned int GetCheck(unsigned char *pSendBuf,unsigned char nEnd){ unsigned char i,j; unsigned int wCrc = (unsigned int)(0xffff); for(i = 0;i<nEnd;i++) { wCrc ^= (unsigned int)(pSendBuf[i]); for(j = 0;j<8;j++) { if(wCrc&0x01) { wCrc >>=1; wCrc ^= 0xA001; } else wCrc >>=1; } } return wCrc;}
//*************************************************************************
// 串口1发送数据函数
//*************************************************************************
void Send_Byte(uchar data)
{
while(!(UC1IFG & UCA1TXIFG)); //发送寄存器空的时候发送数据
UCA1TXBUF = data;
}
//*************************************************************************
// 串口1发送字符串函数
//*************************************************************************
void Send_CMD(uchar *s,uchar n)
{
uint crc16;
crc16 = GetCheck(s,n-2); //CRC16校验
s[n-2] = crc16 & 0xff; //校验低
s[n-1] = (crc16>>8) & 0xff; //校验高
RS485_CTR1; //切换到发送状态
// delay_us(100);
for(uchar i=0;i<n;i++)
{
Send_Byte(s[i]);
}
while(!(UC1IFG & UCA1TXIFG));// delay_us(200);
RS485_CTR0; //切换到接收状态}
bing shen1:
我用示波器观察了MAX3485的RS485信号输出,与我程序中设定的一样,问题可能是出现在发送与接收模式的切换上,我发现发完数据后切换到接收模式,接收数据线上存在中间电平状态,就是基于高低电平信号之间,很奇怪,估计通信错误就是这个产生的,但这到底是什么原因造成的?
b h:
回复 bing shen1:
我也遇到和你相似的问题,我是利用STM32做了其他几块功能板卡,STM32板卡之间利用485通信正常,一旦我把利用430做的功能板卡插入设备中整个485总线通信就无法被识别了(利用示波器能观测到波形),我不存在收发电平转换(我利用了两个MAX485芯片:一收一发)。希望可以交流一下。
yezi:
回复 bing shen1:
您好,请问您的问题解决了吗?这个收发模式到底怎么切换,我的485通讯也是用的max3485,现在通信也有点问题,希望能交流下。谢谢!
灰小子:
回复 yezi:
这类通讯类的问题,没有太好的办法,建议用逻辑分析仪观察一下时序
YL CHAN:
我最近也遇到这个问题了,特点是MSP430发送的最后一个字符串恒为FF。
问题就出在把RS485芯片切换为接受状态的时机。
判断的是IFGX寄存器的UCA0TXIFG 位是否被置位,然而该位被置位只是表示UCAXTXBUF 为空,可以发送下一位,实际上这时数据仍然在移位寄存器中发送,这时把RS485切换为中断就会导致最后一个字符接受错误。
应该改为判断UCAxSTAT寄存器(状态寄存器)的UCBUSY位,该位是指示USCI是否正在发送或者接受,这样就可以了。
我也是翻了用户指南才了解的。