在了解modbus協議後就是基於該協議的設計了,下面先說一下基於航太電子htm52微控制器的從機設計。
設計思想如下:
modbus協議是以主從的方式通訊的,也就是上位機傳送指令,下位機應答機制,發起通訊的一直是上位機,下位機只要應答就好了。
modbus協議被設計出來是針對plc應用的,這裡我們可以簡單的模擬plc環境,可以在微控制器裡面設計一塊共享區,該區域是上位機和下位機共享的,均可以讀取或寫入該區域的值,所有的modbus協議都是針對該快區域的操作,下位機也是根據這塊區域的值做相應的操作。
這塊共享區我們用結構體來表示,這裡我們只用了兩個變數:
/*modbus 16位值的定義,起始位址0000h,每乙個值為16位 int型,佔兩個位元組 */
struct modbus_add;
struct modbus_add modbus_addt;//宣告乙個modbus結構體變數
struct modbus_add *modbusadd;//結構體指標,指向這個變數
在主函式中,只需要查詢這塊區域的值,作出相應的動作就好了:
void main()
/*end*/
//同步公共區資料到實際執行效果
/*start*/
switch(modbus_addt.led_ctrl)
/*end*/
}}
接下來看modbus協議具體怎麼實現的,可以看到在主函式中是沒有參與這個協議的,也就是相當於modbus協議的實現是在另外乙個執行緒中,主函式不需要關心實現的細節,這樣做的好處的是主函式可以近針對於自己的實現任務,二不用考慮任務的引數從哪來的
51微控制器與上位機通訊採用串列埠的方式,串列埠中斷負責接收和傳送資料,這裡我們還用到了乙個定時器,負責監控當前modbus的狀態,判斷這一幀資料是否完成,如果判斷為一幀資料接收完成,就解析該幀資料,並執行相應的指令。
注意一下rec_time_out這個變數,這個變數在定時器中斷裡面是不斷自加的,但在串列埠中斷裡面就清零了,這樣做的意義是判斷一幀資料是否接收完成,如果rec_time_out這個變數值大於某個值,說明在一段時間是沒有資料接收的,可以認為資料接收接收,當然上位機那邊必須滿足一幀資料是連續傳送的
串列埠中斷程式如下,這裡用到了串列埠中斷傳送資料幀,具體解析可以參考我的另一篇部落格
//串列埠中斷
void serisr() interrupt 4 using 2
else
break;
case pack_rec_ing: // 正常接收
modbus_recv_buf[rec_num++] = data_value;
break;
case pack_addr_err: // 位址不符合 等待超時 幀結束
break;
default : break;
} } if(ti == 1) //進入傳送完成中斷,檢測是否有需要傳送的資料並進行傳送
sbuf = send_buf.buf[send_buf.index];//繼續傳送下乙個
}}
定時器實現函式,注意超時檢測方法:
/* 定時器中斷 1ms*/
void time0isr() interrupt 1 using 1
}
/*超時幀檢測,在1ms定時器裡面執行,返回當前狀態*/
int time_out_check_modbus(void)
else if((rec_time_out == 4) && (rec_num > 4)) // 超時資料幀結束4ms
return rec_stat;
}
一幀資料接收成功後,執行方法就在函式 function_modbus中,如下,指令解析和發動都是嚴格按照modbus協議來的,這裡只是用到了協議的常用的幾個指令,大家可以自由擴充套件,
void function_modbus(unsigned char *rec_buff)
rec_stat = pack_start;//傳送之後使快取回到初始狀態
rec_num = 0;
}
/*
function:對應modbus功能號03,04 批量讀暫存器
input:rec_buf接收到的指令 send_data需要傳送的指令
*/void read_reg(unsigned char * rec_buff)
send_crc = comp_crc16(rec_buff, send_num-2);
rec_buff[send_num-2] = send_crc >> 8;
rec_buff[send_num -1] = send_crc;
send_count = send_num;
putnchar(rec_buff , send_count);}/*
function:對應modbus功能號06和16,單個和批量寫暫存器
input:rec_buf接收到的指令 send_data需要傳送的指令
*/void force_reg(unsigned char * rec_buf)
else if(fun_code == 16)//寫多個暫存器
}send_crc = comp_crc16(rec_buf, send_num-2);//crc校驗
rec_buf[send_num-2] = send_crc >> 8;
rec_buf[send_num -1] = send_crc;
send_count = send_num;
putnchar(rec_buf , send_count);
}
裡面有多個工程,但設計方法是一致的。
51微控制器
數碼管顯示幾乎是每次藍橋杯微控制器設計與開發組競賽的必考部分,相對於使用lcd1602作為顯示裝置,使用數碼管來顯示能夠更好的考察參賽選手的微控制器基本功,因為ct107d開發平台的設計使得數碼管的顯示不僅牽扯到數碼管顯示的 基本內容,還涉及到74hc573鎖存器,74hc02異或門,74hc138...
51微控制器
建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 1.供電電源 一般開發板上提供兩種供電方式,usb供電和專用電源供電。使用usb供電你只要用一根usb線將開發板usb電源介面與電腦的usb...
51微控制器
設計包含乙個矩陣式鍵盤電路和動態顯示電路的微控制器應用系統,通過根據按下不同的數字按鍵 0 9 在數碼管上顯示出自己學號的後8位。各位大神幫忙挑挑錯,或者問題太大了可以幫忙寫乙個新的麼!萬分感謝!好著急 a 8255 equ 7cffh a口 b 8255 equ 7dffh b口 c 8255 e...