看百度文庫上這個文檔挺多的,可是我發現函數不全,好像不完整,有人編過430的MODBUS程序嗎,測試通過的,我看過這個程序了,
其中缺少函數,感覺這個不是完整的,有用這個程序試成功過的嗎,歡迎探討
#include "synth.h"
//------------------------------------------------------------------------------
bool CommState; // 通訊狀態
bool Request; // 允許接收
bool Response; // 允許發送
bool EnCommWrite; // 允許通訊寫
uchar UDRBuf; // 通訊接收寄存器緩存
uchar CommIndex; // 通訊索引
uchar CrcLow; // CRC低字節
uchar CrcHigh; // CRC高字節
uchar Interval; // 3.5字符時間間隔
uchar CommWrEntry; // 通訊寫入口
uchar CommBuf[BUF_SIZE]; // 通訊緩沖區
uint StartAddr; // 起始地址
uint RegNum; // 寄存器數量
int bAudBuf; // 通訊波特率緩存
int FormBuf; // 通訊數據格式緩存
extern const StrKeybd Keybd[];
//------------------------------------------------------------------------------
void ResetInterval(void) // 重置3.5字符時間間隔
{
switch(bAudBuf)
{
case 0: Interval = (uchar)(1000/( 1200/11.0)*3.5/TBASE); break;
case 1: Interval = (uchar)(1000/( 2400/11.0)*3.5/TBASE); break;
case 2: Interval = (uchar)(1000/( 4800/11.0)*3.5/TBASE); break;
default: Interval = (uchar)(1000/( 9600/11.0)*3.5/TBASE); break;
case 4: Interval = (uchar)(1000/(19200/11.0)*3.5/TBASE); break;
}
}
//******************************************************************************
void OpenComm(void) // 打開或關閉通訊
{
ResetInterval();
UCA0CTL1 |= (UCSSEL_2 + UCRXEIE);
switch(FormBuf)
{
default: UCA0CTL0 = UCSPB; break; // N-2
case 1: UCA0CTL0 = UCPEN; break; // O-1
case 2: UCA0CTL0 = UCPEN + UCPAR; break; // E-1
case 3: UCA0CTL0 = 0; break; // N-1
}
switch(bAudBuf)
{
case 0: UCA0BR1 = (uint)(BRCLK/1200) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/1200));
UCA0MCTL = (uint)((BRCLK/1200-(uint)(BRCLK/1200))*8)<<1;
break;
case 1: UCA0BR1 = (uint)(BRCLK/2400) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/2400));
UCA0MCTL = (uint)((BRCLK/2400-(uint)(BRCLK/2400))*8)<<1;
break;
case 2: UCA0BR1 = (uint)(BRCLK/4800) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/4800));
UCA0MCTL = (uint)((BRCLK/4800-(uint)(BRCLK/4800))*8)<<1;
break;
default: UCA0BR1 = (uint)(BRCLK/9600) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/9600));
UCA0MCTL = (uint)((BRCLK/9600-(uint)(BRCLK/9600))*8)<<1;
break;
case 4: UCA0BR1 = (uint)(BRCLK/19200) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/19200));
UCA0MCTL = (uint)((BRCLK/19200-(uint)(BRCLK/19200))*8)<<1;
break;
}
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0RXIE;
}
//******************************************************************************
void Communication(void) // 通訊
{
if((SMM.out1 == COMM) || (SMM.out2 == COMM) || (SMM.out3 == COMM))
{
if((bAudBuf != SMM.bAud) || (FormBuf != SMM.ForM) || (!CommState))
{
bAudBuf = SMM.bAud;
FormBuf = SMM.ForM;
UCA0CTL1 = UCSWRST;
OpenComm();
CommState = true;
}
}
else
{
UCA0CTL1 = UCSWRST;
CommState = false;
}
}
//******************************************************************************
void SingleCRC(uchar data) // 計算單字節CRC校驗碼
{
uchar c = CrcLow ^ data;
CrcLow = TabCRC[c] ^ CrcHigh;
CrcHigh = TabCRC[c + 0x100];
}
//******************************************************************************
__monitor void SilentInterval(void) // 檢測通訊3.5字符時間間隔
{
if(CommState)
{
if(Interval == 0)
{
ResetInterval();
CrcLow = 0xFF;
CrcHigh = 0xFF;
CommIndex = 0;
if(Response)
{
Response = false;
IE2 |= UCA0TXIE;
}
else
{
IE2 &= ~UCA0TXIE;
Request = true;
}
}
else
--Interval;
}
}
//******************************************************************************
bool CheckDataValid(void) // 檢測寫入數據的有效性
{
uchar c, index = StartAddr + OFFSET;
for(c = 0; c < RegNum; ++c, ++index)
{
uchar buf = c * 2;
int data = ((int)CommBuf[7 + buf] << 8) | CommBuf[8 + buf];
if((data < Keybd[index].LowerLimit) || (data > Keybd[index].HigherLimit))
return(false);
}
return(true);
}
//******************************************************************************
void GetDataToMenu(void) // 更新參數值
{
uchar c, *ta = &SB[(StartAddr + OFFSET) * 2], *src = &CommBuf[8];
for(c = RegNum; c; --c)
{ // 低字節
*ta = *src;
ta += 2; src += 2;
}
ta = &SB[(StartAddr + OFFSET) * 2 + 1], src = &CommBuf[7];
for(c = RegNum; c; --c)
{ // 高字節
*ta = *src;
ta += 2; src += 2;
}
}
//******************************************************************************
void GetDataToBuff(void) // 取參數值
{
uchar c, *ta = &CommBuf[4], *src = &SB[(StartAddr + OFFSET) * 2];
for(c = RegNum; c; --c)
{ // 低字節
*ta = *src;
ta += 2; src += 2;
}
ta = &CommBuf[3], src = &SB[(StartAddr + OFFSET) * 2 + 1];
for(c = RegNum; c; --c)
{ // 高字節
*ta = *src;
ta += 2; src += 2;
}
}
//******************************************************************************
void ManageWrite(void) // 寫指令
{
uchar c = REGNUM * 2 + 7; // 指向CRCL
if(CommIndex < c)
{
SingleCRC(UDRBuf);
CommBuf[CommIndex++] = UDRBuf;
}
else if(CommIndex == c)
{
if(CrcLow == UDRBuf)
{
StartAddr = STARTADDR;
RegNum = REGNUM;
++CommIndex;
}
else
Request = false;
}
else
{
Request = false;
if(CrcHigh == UDRBuf)
{
if((RegNum >= 1) && (RegNum <= 0x7B) && (CommBuf[6] == (RegNum * 2)))
{
if((StartAddr + RegNum) <= COMM_WL_WR)
{
if(!CheckDataValid())
{
CMD |= 0x80; CommBuf[2] = ERR_DATA; // 非法數據
}
else
{
GetDataToMenu();
if(StartAddr < (COMM_WL_WR - 2))
{
switch(StartAddr+RegNum)
{
case COMM_WL_WR : RegNum -= 2; break;
case (COMM_WL_WR-1): RegNum -= 1; break;
default : break;
}
CommWrEntry = ENTRY;
EnCommWrite = true;
}
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_ADDR; // 非法地址
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_NUM; // 非法數量
}
Response = true;
}
}
}
//******************************************************************************
void ManageRead(void) // 讀指令
{
if(CommIndex == 6)
{
if(CrcLow == UDRBuf)
{
StartAddr = STARTADDR;
RegNum = REGNUM;
CommBuf[2] = RegNum * 2;
++CommIndex;
}
else
Request = false;
}
else
{
Request = false;
if(CrcHigh == UDRBuf)
{
if((RegNum >= 1) && (RegNum <= 0x7D))
{
if((StartAddr + RegNum) <= COMM_WL_RD)
GetDataToBuff();
else
{
CMD |= 0x80; CommBuf[2] = ERR_ADDR; // 非法地址
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_NUM; // 非法數量
}
Response = true;
}
}
}
//******************************************************************************
#pragma vector = USCIAB0TX_VECTOR
__interrupt void UART_transmit(void) // 通訊發送
{
uchar c;
TACCTL0 &= ~CCIE;
IE2 &= ~UCA0TXIE;
__enable_interrupt();
ResetInterval();
if(CMD == READ) // 讀指令
c = CommBuf[2] + 3; // 指向CRCL
else if(CMD == WRITE) // 寫指令
c = 6;
else // 錯誤的指令
c = 3;
if(CommIndex <= (c + 1))
{
if(CommIndex < c)
{
c = CommBuf[CommIndex];
SingleCRC(c);
UCA0TXBUF = c;
}
else if(CommIndex == c)
UCA0TXBUF = CrcLow;
else
UCA0TXBUF = CrcHigh;
++CommIndex;
__disable_interrupt();
IE2 |= UCA0TXIE;
TACCTL0 |= CCIE;
}
else
{
__disable_interrupt();
TACCTL0 |= CCIE;
}
}
//******************************************************************************
#pragma vector = USCIAB0RX_VECTOR
__interrupt void UART_receive(void) // 通訊接收
{
UDRBuf = UCA0RXBUF;
TACCTL0 &= ~CCIE;
IE2 &= ~UCA0RXIE;
__enable_interrupt();
ResetInterval();
if(Request)
{
switch(CommIndex)
{
case 0: if(UDRBuf != SMM.Addr)
{
Request = false;
break;
}
case 1:
case 2:
case 3:
case 4:
case 5: SingleCRC(UDRBuf);
CommBuf[CommIndex++] = UDRBuf;
break;
default: if(CMD == READ) // 讀指令
ManageRead();
else if(CMD == WRITE) // 寫指令
ManageWrite();
else // 非法指令
{
Request = false;
CMD |= 0x80; CommBuf[2] = ERR_CMD;
Response = true;
}
break;
}
}
__disable_interrupt();
IE2 |= UCA0RXIE;
TACCTL0 |= CCIE;
|