|
單片機(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ù)間隔時(shí)間不得超過1.5字符的靜止時(shí)間。
因此:
。1)、當(dāng)串口產(chǎn)生接收中斷后,立即重裝“超時(shí)定時(shí)器”的初始值。(注:超時(shí)定時(shí)器的初始值和波特率有關(guān))
問題如下:
。╝)、由于要求在串口接收中斷中重裝超時(shí)定時(shí)器初始值,那么,該超時(shí)定時(shí)器就只能采用“溢出模式”,而不能采用“CTC模式”
(b)、超時(shí)定時(shí)器必須在程序初始化時(shí)就一直開啟。
我的理解對嗎?
(2)兩幀之間的3.5字符的靜止時(shí)間該如何實(shí)現(xiàn)呢?
接收到每個(gè)字節(jié)的時(shí)候,初始化定時(shí)器就行,最后一個(gè)字節(jié)后,定時(shí)器就溢出了
利用單獨(dú)的軟件定時(shí)器,來判斷一幀接收報(bào)文結(jié)束,可以防止若報(bào)文接收不完整,該幀通信任務(wù)無法結(jié)束而影響下一幀的接收。
由于一幀報(bào)文中字節(jié)與字節(jié)之間的時(shí)間間隔和幀與幀之間的時(shí)間間隔相比要小得多,因此每當(dāng)接收一個(gè)新字節(jié),就啟動(dòng)軟件定時(shí)器開始計(jì)時(shí),定時(shí)器的時(shí)間設(shè)定為幀與幀的最小時(shí)間間隔。波特率不同,該時(shí)間間隔也不同。若不到預(yù)定的時(shí)間內(nèi)又接收到下一個(gè)字節(jié),則說明一幀報(bào)文未結(jié)束,定時(shí)器重新計(jì)時(shí);若定時(shí)器順利計(jì)數(shù)到預(yù)定時(shí)間,就會觸發(fā)相應(yīng)的中斷號,在該定時(shí)器中斷子程序中設(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ā)送幀。
上面就是解決以下兩個(gè)問題的方法
(1)、當(dāng)前幀兩個(gè)字節(jié)之間的1.5字符靜止時(shí)間
(2)、兩幀之間3.5字符的靜止時(shí)間
這里有個(gè)SPI串口擴(kuò)展芯片uCSU122P,內(nèi)置MODBUS引擎,DIP28,或許對你有用點(diǎn)擊此處下載 (原文件名:ucmu2_dat_v122.pdf)
其實(shí)這個(gè)時(shí)間不用這么準(zhǔn)確啦,因?yàn)槭菃柎鹗降膮f(xié)議,你可以以某個(gè)定時(shí)時(shí)間查詢串口緩沖區(qū)字符的長度,如果兩次讀入的長度一樣就認(rèn)為一幀結(jié)束了,這個(gè)查詢間隔根據(jù)波特率微調(diào),就是3.5個(gè)字符時(shí)間。
7樓的做法不嚴(yán)格,如果第一次定時(shí)查詢的時(shí)候正在收最后一個(gè)字節(jié),第二次查顯然收完了,第三次查數(shù)據(jù)不變,那么就導(dǎo)致了7個(gè)字符的間隔,如果對方在3.5~7字符之間又來了數(shù)據(jù),就麻煩了;
T1.5和T3.5最嚴(yán)格的方法還是開定時(shí)器,但是可以靈活一點(diǎn);低波特率(<19200)的時(shí)候嚴(yán)格定時(shí),和波特率相關(guān);高波特率(>19200)的時(shí)候就固定定時(shí)(T1.5=750us,T3.5=1750us),這樣降低了CPU中斷響應(yīng)的負(fù)擔(dān)。
給你這個(gè)程序片段應(yīng)該可以解決你的問題,我的程序經(jīng)過嚴(yán)格的測試,高掃描周期、波特率19200下連續(xù)運(yùn)行了一個(gè)星期,沒出一個(gè)錯(cuò)誤
#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
|
|