|
單片機(jī)RS485通訊的程序,工作中的成熟應(yīng)用案例。分享給大家。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
0.png (29.27 KB, 下載次數(shù): 122)
下載附件
2018-2-11 18:04 上傳
0.png (52.98 KB, 下載次數(shù): 89)
下載附件
2018-2-11 18:17 上傳
由于MODBUS-RTU 要求每幀信息中的數(shù)據(jù)間隔時間不得超過1.5字符的靜止時間。
因此:
。1)、當(dāng)串口產(chǎn)生接收中斷后,立即重裝“超時定時器”的初始值。(注:超時定時器的初始值和波特率有關(guān))
問題如下:
(a)、由于要求在串口接收中斷中重裝超時定時器初始值,那么,該超時定時器就只能采用“溢出模式”,而不能采用“CTC模式”
。╞)、超時定時器必須在程序初始化時就一直開啟。
我的理解對嗎?
(2)兩幀之間的3.5字符的靜止時間該如何實(shí)現(xiàn)呢?
接收到每個字節(jié)的時候,初始化定時器就行,最后一個字節(jié)后,定時器就溢出了
利用單獨(dú)的軟件定時器,來判斷一幀接收報(bào)文結(jié)束,可以防止若報(bào)文接收不完整,該幀通信任務(wù)無法結(jié)束而影響下一幀的接收。
由于一幀報(bào)文中字節(jié)與字節(jié)之間的時間間隔和幀與幀之間的時間間隔相比要小得多,因此每當(dāng)接收一個新字節(jié),就啟動軟件定時器開始計(jì)時,定時器的時間設(shè)定為幀與幀的最小時間間隔。波特率不同,該時間間隔也不同。若不到預(yù)定的時間內(nèi)又接收到下一個字節(jié),則說明一幀報(bào)文未結(jié)束,定時器重新計(jì)時;若定時器順利計(jì)數(shù)到預(yù)定時間,就會觸發(fā)相應(yīng)的中斷號,在該定時器中斷子程序中設(shè)定幀結(jié)束標(biāo)志字節(jié),表明一幀報(bào)文接收完畢。當(dāng)主程序內(nèi)檢測到一幀報(bào)文接收完畢后,會通過核查從方地址及循環(huán)冗余校驗(yàn)字節(jié)是否正確來判斷該幀的有效性。若確定接收到的是一幀發(fā)送給已方的正確報(bào)文,則會根據(jù)報(bào)文內(nèi)的功能碼對該幀命令進(jìn)行相應(yīng)的處理,并準(zhǔn)備發(fā)送幀。
上面就是解決以下兩個問題的方法
。1)、當(dāng)前幀兩個字節(jié)之間的1.5字符靜止時間
。2)、兩幀之間3.5字符的靜止時間
這里有個SPI串口擴(kuò)展芯片uCSU122P,內(nèi)置MODBUS引擎,DIP28,或許對你有用點(diǎn)擊此處下載 (原文件名:ucmu2_dat_v122.pdf)
其實(shí)這個時間不用這么準(zhǔn)確啦,因?yàn)槭菃柎鹗降膮f(xié)議,你可以以某個定時時間查詢串口緩沖區(qū)字符的長度,如果兩次讀入的長度一樣就認(rèn)為一幀結(jié)束了,這個查詢間隔根據(jù)波特率微調(diào),就是3.5個字符時間。
7樓的做法不嚴(yán)格,如果第一次定時查詢的時候正在收最后一個字節(jié),第二次查顯然收完了,第三次查數(shù)據(jù)不變,那么就導(dǎo)致了7個字符的間隔,如果對方在3.5~7字符之間又來了數(shù)據(jù),就麻煩了;
T1.5和T3.5最嚴(yán)格的方法還是開定時器,但是可以靈活一點(diǎn);低波特率(<19200)的時候嚴(yán)格定時,和波特率相關(guān);高波特率(>19200)的時候就固定定時(T1.5=750us,T3.5=1750us),這樣降低了CPU中斷響應(yīng)的負(fù)擔(dān)。
給你這個程序片段應(yīng)該可以解決你的問題,我的程序經(jīng)過嚴(yán)格的測試,高掃描周期、波特率19200下連續(xù)運(yùn)行了一個星期,沒出一個錯誤
#pragma interrupt_handler Timer1:iv_TIMER1_OVF
void Timer1(void)
{
unsigned short CRC;
TCNT1=65525-51*11;//65535-(11*(ubbr+1)) 波特率9600
if(CNT<8)
{
CNT++;
if(CNT==4)
{
ModBusQueryDataLong=IsrCount;
IsrCount=0;
}
else if(CNT==8)
{
if(ModBusQueryDataLong>2)
{
CRC=CRC16((unsigned char *)&ModbusFunctionUnion,ModBusQueryDataLong-2);
if((ModbusFunctionUnion.Data[ModBusQueryDataLong-2]==MSB(CRC))&&
(ModbusFunctionUnion.Data[ModBusQueryDataLong-1]==LSB(CRC)))
{
FrameStatu=1;
}
}
}
}
}
#pragma interrupt_handler UART_isr:iv_USART0_RX
void UART_isr(void)
{
CNT=0;
while(!(UCSR0A&(1<<RXC0)));
ModbusFunctionUnion.Data[IsrCount++]=UDR0;
}
單片機(jī)源程序如下:
所有資料51hei提供下載:
01.02.26通訊.rar
(77.34 KB, 下載次數(shù): 479)
2018-2-11 17:01 上傳
點(diǎn)擊文件名下載附件
485通訊 下載積分: 黑幣 -5
|
|