找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 5535|回復(fù): 6
打印 上一主題 下一主題
收起左側(cè)

STC8單片機(jī)串口1中斷收發(fā)-MODBUS協(xié)議源程序 帶詳細(xì)注釋

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1011490 發(fā)表于 2022-3-25 11:19 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
#define MAIN_Fosc                11059200L        //定義主時(shí)鐘 //

//#include        "..\..\STC8Gxxx.h"
#include        <reg52.h>

/*************        功能說明        **************

串口1按MODBUS-RTU協(xié)議通信. 本例為從機(jī)程序, 主機(jī)一般是電腦端.

本例程只支持多寄存器讀和多寄存器寫, 寄存器長(zhǎng)度為64個(gè), 別的命令用戶可以根據(jù)需要按MODBUS-RTU協(xié)議自行添加.

本例子數(shù)據(jù)使用大端模式(與C51一致), CRC16使用小端模式(與PC一致).
默認(rèn)參數(shù):
串口1設(shè)置均為 1位起始位, 8位數(shù)據(jù)位, 1位停止位, 無校驗(yàn).
串口1(P3.0 P3.1): 9600bps.

定時(shí)器0用于超時(shí)計(jì)時(shí). 串口每收到一個(gè)字節(jié)都會(huì)重置超時(shí)計(jì)數(shù), 當(dāng)串口空閑超過35bit時(shí)間時(shí)(9600bps對(duì)應(yīng)3.6ms)則接收完成.
用戶修改波特率時(shí)注意要修改這個(gè)超時(shí)時(shí)間.
定義了64個(gè)寄存器, 訪問地址為0x1000~0x103f.
命令例子:
寫入4個(gè)寄存器(8個(gè)字節(jié)):
10 10 1000 0004 08 1234 5678 90AB CDEF 4930
返回:
10 10 10 00 00 04 4B C6
讀出4個(gè)寄存器:
10 03 1000 0004 4388
返回:
10 03 08 12 34 56 78 90 AB CD EF 3D D5

******************************************/


typedef         unsigned char        u8;
typedef         unsigned int        u16;
typedef         unsigned long        u32;

sfr P1M1  = 0x91;        //P1M1.n,P1M0.n         =00--->Standard,        01--->push-pull                實(shí)際上1T的都一樣
sfr P1M0  = 0x92;        //                                        =10--->pure input,        11--->open drain
sfr P3M1  = 0xB1;        //P3M1.n,P3M0.n         =00--->Standard,        01--->push-pull
sfr P3M0  = 0xB2;        //                                        =10--->pure input,        11--->open drain
sfr P4M1  = 0xB3;        //P4M1.n,P4M0.n         =00--->Standard,        01--->push-pull
sfr P4M0  = 0xB4;        //                                        =10--->pure input,        11--->open drain
sfr P_SW1 = 0xA2;
sfr        AUXR  = 0x8E;
sfr IE2   = 0xAF;        //中斷允許寄存器2

sfr S2CON = 0x9A; //S2 Control  S2SM0  S2SM1  S2SM2  S2REN  S2TB8  S2RB8  S2TI  S2RI      00000000B
sfr S2BUF = 0x9B; //S2 Serial Buffer                                                      xxxx,xxxx
sfr BRT = 0x9C; //S2 Baud-Rate Timer                                                    0000,0000
/*************        本地常量聲明        **************/
#define        RX1_Length        128                /* 接收緩沖長(zhǎng)度 */
#define        TX1_Length        128                /* 發(fā)送緩沖長(zhǎng)度 */


/*************        本地變量聲明        **************/
u8        xdata        RX1_Buffer[RX1_Length];        //接收緩沖
u8        xdata        TX1_Buffer[TX1_Length];        //發(fā)送緩沖

u8        RX1_cnt;                //接收字節(jié)計(jì)數(shù).
u8        TX1_cnt;                //發(fā)送字節(jié)計(jì)數(shù)
u8        TX1_number;                //要發(fā)送的字節(jié)數(shù)
u8        RX1_TimeOut;        //接收超時(shí)計(jì)時(shí)器

bit        B_RX1_OK;                // 接收數(shù)據(jù)標(biāo)志
bit        B_TX1_Busy;                // 發(fā)送忙標(biāo)志
sbit P12=P1^2;

/*************        本地函數(shù)聲明        **************/
void        UART1_config(u32 brt, u8 timer, u8 io);        // brt: 通信波特率,  timer=2: 波特率使用定時(shí)器2, 其它值: 使用Timer1做波特率. io=0: 串口1切換到P3.0 P3.1,  =1: 切換到P3.6 P3.7, =2: 切換到P1.6 P1.7,  =3: 切換到P4.3 P4.4.
u8                Timer0_Config(u8 t, u32 reload);        //t=0: reload值是主時(shí)鐘周期數(shù),  t=1: reload值是時(shí)間(單位us), 返回0正確, 返回1裝載值過大錯(cuò)誤.
u16                MODBUS_CRC16(u8 *p, u8 n);
u8                MODBUS_RTU(void);



#define        SL_ADDR                0x10        /* 本從機(jī)站號(hào)地址 */
#define        REG_ADDRESS        0x1000        /* 寄存器首地址   */
#define        REG_LENGTH        64                /* 寄存器長(zhǎng)度     */
u16                xdata modbus_reg[REG_LENGTH];        /* 寄存器地址 */

//========================================================================
// 函數(shù): void main(void)
// 描述: 主函數(shù)
// 參數(shù): none.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 備注:
//========================================================================
void main(void)
{
        u8        i;
        u16        crc;
        
        Timer0_Config(0, MAIN_Fosc / 10000);        //t=0: reload值是主時(shí)鐘周期數(shù),  (中斷頻率, 20000次/秒)
        UART1_config(9600UL, 1, 0);        // brt: 通信波特率,  timer=2: 波特率使用定時(shí)器2, 其它值: 使用Timer1做波特率. io=0: 串口1切換到P3.0 P3.1,  =1: 切換到P3.6 P3.7, =2: 切換到P1.6 P1.7,  =3: 切換到P4.3 P4.4.

        EA = 1;
        P12= 0;
        while (1)
        {
                if(B_RX1_OK && !B_TX1_Busy)        //收到數(shù)據(jù), 進(jìn)行MODBUS-RTU協(xié)議解析
                {
                        if(MODBUS_CRC16(RX1_Buffer, RX1_cnt) == 0)        //首先判斷CRC16是否正確, 不正確則忽略, 不處理也不返回信息
                        {
                                if((RX1_Buffer[0] == 0x00) || (RX1_Buffer[0] == SL_ADDR))        //然后判斷站號(hào)地址是否正確, 或者是否廣播地址(不返回信息)
                                {
                                        if(RX1_cnt > 2) RX1_cnt -= 2;        //去掉CRC16校驗(yàn)字節(jié)
                                        i = MODBUS_RTU();        //MODBUS-RTU協(xié)議解析
                                        if(i != 0)        //錯(cuò)誤處理
                                        {
                                                TX1_Buffer[0] = SL_ADDR;        //站號(hào)地址
                                                TX1_Buffer[1] = i;                        //錯(cuò)誤代碼
                                                crc = MODBUS_CRC16(TX1_Buffer, 2);
                                                TX1_Buffer[2] = (u8)(crc>>8);        //CRC是小端模式
                                                TX1_Buffer[3] = (u8)crc;
                                                B_TX1_Busy = 1;                //標(biāo)志發(fā)送忙
                                                TX1_cnt    = 0;                //發(fā)送字節(jié)計(jì)數(shù)
                                                TX1_number = 4;                //要發(fā)送的字節(jié)數(shù)
                                                TI = 1;                                //啟動(dòng)發(fā)送
                                        }
                                }
                        }
                        
                }
        }
}

求改正: UART2程序.7z (16.5 KB, 下載次數(shù): 172)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂 踩1
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:915491 發(fā)表于 2022-4-1 17:16 | 只看該作者
學(xué)習(xí)學(xué)習(xí)先,感謝樓主分享
回復(fù)

使用道具 舉報(bào)

板凳
ID:65369 發(fā)表于 2022-4-3 08:53 | 只看該作者
先學(xué)習(xí)一下MODBUS,這個(gè)應(yīng)用挺廣的,多謝分享
回復(fù)

使用道具 舉報(bào)

地板
ID:915491 發(fā)表于 2022-4-10 18:18 | 只看該作者
這個(gè)應(yīng)用挺廣的多謝分享
回復(fù)

使用道具 舉報(bào)

5#
ID:162733 發(fā)表于 2022-5-9 10:16 | 只看該作者
這個(gè)樓主不地道,給的不是完整程序
回復(fù)

使用道具 舉報(bào)

6#
ID:233291 發(fā)表于 2022-5-18 00:00 | 只看該作者
發(fā)的貨不對(duì)版,需要的看這個(gè)鏈接
http://www.torrancerestoration.com/bbs/dpj-220222-1.html
stc32單片機(jī)modbus-rtu通訊源程序
回復(fù)

使用道具 舉報(bào)

7#
ID:1091922 發(fā)表于 2023-10-28 00:14 | 只看該作者
沒有看下面回復(fù),浪費(fèi)了5個(gè)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表