|
#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)
2022-4-16 17:13 上傳
點(diǎn)擊文件名下載附件
STC12
|
|