?? f340_modbus.c
字號:
//-----------------------------------------------------------------------------
// F340_modbus.c Modbus Master
//-----------------------------------------------------------------------------
//
// Program Description:
//
// 完成Modbus協(xié)議的部分功能:
// 功能碼 功能描述 可用數(shù)量
//-------------------------------------------
// 01 讀取線圈狀態(tài)(多位)
// 02 讀取輸入狀態(tài)(多位) 共128
//-------------------------------------------
// 03 讀取保持寄存器(多字)
// 04 讀取輸入寄存器(多字) 共16
//-------------------------------------------
// 05 強置單線圈,支持廣播方式
// 06 預(yù)置單寄存器,支持廣播方式
//-------------------------------------------
// 08 回送診斷(原幀回傳)
//-------------------------------------------
// 15 強置多線圈 共128
// 16 預(yù)置多寄存器 共16
//-------------------------------------------
// Target: C8051F340
// Tool chain: Keil C51 7.10
// Command Line: None
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f340.h> // SFR declarations
#include <compiler_defs.h>
#include <modbus.h>
#include <crc.h>
//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------
#define SYSCLK 48000000 // Internal oscillator frequency in Hz
U8 xdata SetCoil[5][4]; //位地址5*32
U16 xdata SetReg[5][16]; //字地址5*16
U16 xdata SetReg0;
extern U8 menu_brChange; //波特率改變寄存器:0-5
sbit b485Send = P3^2; //485 發(fā)送接收控制
bit bMB_idle; //=0:Modbus空閑;=1:Modbus占用
U8 xdata sendBuf[64],receBuf[64]; //發(fā)送接收緩沖區(qū)
U8 checkoutError; // ==2 偶校驗錯
U8 receTimeOut; //接收超時:開始接收后規(guī)定時間內(nèi)未收到數(shù)據(jù),已收數(shù)據(jù)無效
U8 MB_BroadTimer; //廣播計時器:廣播發(fā)送數(shù)據(jù)后,產(chǎn)生固定延時,再回到空閑
U16 MB_TimeOut; //Modbus超時:發(fā)送數(shù)據(jù)后規(guī)定時間內(nèi)無響應(yīng),產(chǎn)生94號錯誤
U8 MB_ErrorCode; //錯誤代碼:01:功能碼錯;02:地址錯;03:數(shù)據(jù)個數(shù)錯;
// 92:CRC錯;93:響應(yīng)格式錯;94:無響應(yīng).
U8 MB_TestEcho; //診斷結(jié)果回應(yīng)
U8 MB_c15done; //code15功能 =S:發(fā)送指令,=15:完成發(fā)送,=0:功能完成
bit bMB_setup; //MB設(shè)置:0:工作狀態(tài),1:設(shè)置狀態(tài);由通訊設(shè)置采單改變
U8 MB_SendNum; //發(fā)送指令序號:工作狀態(tài)使用的指令序號,完成發(fā)送后+1
extern U8 menu_comm0_addr[6]; //通訊地址定義
extern U8 menu_comm0_test; //通訊測試地址
extern U8 menu_brChange; //波特率改變寄存器:0-5
extern U8 SignalSet; //信號設(shè)置:高4位:清零;低4位:極性 FRAM 11
U8 localAddr ; //本機地址
U8 sendCount; //發(fā)送字節(jié)個數(shù)
U8 receCount; //接收到的字節(jié)個數(shù)
U8 sendPosi; //發(fā)送位置
extern U8 menu_alarm_set[4]; //報警設(shè)置 數(shù)組 FRAM 284-287(4)
extern U8 FM_alarming[5]; //報警狀態(tài):0x00:無報警,0x0f:警告,0xff:報警
// 0:重量,1:幅度,2:高度,3:角度,4:力矩
U8 MB_SetAlarm; //從機報警設(shè)置
//-----------------------------------------------------------------------------
// UART0_ISR
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// 串行中斷程序:8-O-1
//
//-----------------------------------------------------------------------------
void UART0_ISR(void) interrupt 4
{
if(TI0)
{
TI0 = 0;
if(sendPosi < sendCount)
{
sendPosi++;
ACC = sendBuf[sendPosi];
TB80 = P; //加上校驗位
SBUF0 = sendBuf[sendPosi];
}
else
{
b485Send = 0; //發(fā)送完后將485置于接收狀態(tài)
receCount = 0; //清接收地址偏移寄存器
checkoutError = 0; //偶校驗清零
if(sendBuf[0]==0) MB_BroadTimer=120; //廣播計時
else MB_TimeOut=1000; //Modbus超時計時
}
}
else if(RI0)
{
RI0 = 0;
receTimeOut =0x40; //通訊超時值
receBuf[receCount] = SBUF0;
ACC = receBuf[receCount];
if(P != RB80)checkoutError = 2; //偶校驗出錯
receCount++; //接收地址偏移寄存器加1
receCount &= 0x3f; //最多一次只能接收64個字節(jié)
}
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for 9600 and 偶校驗.
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0xd0; // SCON0: 9-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits 偶校驗
// clear RI0 and TI0 bits
TH1 = -(SYSCLK/9600/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
ES0 = 1; // Enable UART0 interrupts
SetReg0=0; // SetReg0:0:9600;
menu_brChange=0;
}
//-----------------------------------------------------------------------------
// BaudRateChange
//
// Return Value : None
// Parameters : None
//
// 運行中改變波特率
//
// SetReg[0]:0:9600;1:4800;2:14400;3:19200;4:115200;5:230400
// SetReg[0]由Modbus主控設(shè)備設(shè)置,主機必須同時改變波特率
//-----------------------------------------------------------------------------
void BaudRateChange (void)
{
static U16 NoChange;
if (SetReg0 != NoChange && bMB_idle == 0)//只在SetReg[0]改變與空閑時執(zhí)行
{
switch(SetReg0)
{
case 0: CKCON &= ~0x0b; CKCON |= 0x02;TH1 = -(SYSCLK/9600/2/48);break; //9600
case 1: CKCON &= ~0x0b; CKCON |= 0x02;TH1 = -(SYSCLK/4800/2/48);break; //4800
case 2: CKCON &= ~0x0b; TH1 = -139; break; //-(SYSCLK/14400/2/12); //14400
case 3: CKCON &= ~0x0b; TH1 = -(SYSCLK/19200/2/12); break; //19200
case 4: CKCON |= 0x08; TH1 = -(SYSCLK/115200/2); break; //115200
case 5: CKCON |= 0x08; TH1 = -(SYSCLK/230400/2); break; //230400
default:break;
}
NoChange = SetReg0;
}
}
//-----------------------------------------------------------------------------
// CRC16
//-----------------------------------------------------------------------------
U16 crc16(U8 *puchMsg, U16 usDataLen)
{
U8 uchCRCHi = 0xFF ; //高CRC 字節(jié)初始化
U8 uchCRCLo = 0xFF ; //低CRC 字節(jié)初始化
U32 uIndex ; //CRC循環(huán)中的索引
while (usDataLen--) //傳輸消息緩沖區(qū)
{
uIndex = uchCRCHi ^ *puchMsg++ ; //計算CRC
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
//-----------------------------------------------------------------------------
// MB_DataProc_step 數(shù)據(jù)處理
//-----------------------------------------------------------------------------
void MB_DataProc_step(void)
{
if(MB_c15done==15){SignalSet=(char)SetReg[0][11];MB_c15done=0;} //信號設(shè)置完成
}
//-----------------------------------------------------------------------------
// Modbus_CommandSend
//
// Modbus
//
// Parameters :addr地址:00廣播,01采樣,02行走,03變幅,04回轉(zhuǎn),05起升
// func功能碼:01讀取多線圈,03讀取多寄存器,06設(shè)置單寄存器,08診斷
// num :func 01,03:元件個數(shù) func06,08:數(shù)據(jù)內(nèi)容
// Return Value :none
//
//-----------------------------------------------------------------------------
void Modbus_CommandSend(unsigned char addr,func,num)
{
UU16 crcData;
sendBuf[0]=addr; //從機地址
sendBuf[1]=func; //功能碼:
sendBuf[2]=0;sendBuf[3]=0; //起始地址
sendBuf[4]=0;sendBuf[5]=num; //元件個數(shù)
crcData.U16 = crc16(sendBuf,6); //CRC
sendBuf[6]=crcData.U8[MSB]; //CRC高字節(jié)
sendBuf[7]=crcData.U8[LSB]; //CRC低字節(jié)
sendCount = 8; //發(fā)送字節(jié)數(shù)
beginSend(); //開始發(fā)送
}
//-----------------------------------------------------------------------------
// Modbus_DataSend
//
// Modbus
//
// Parameters :addr地址:00廣播,01采樣
// func功能碼:15設(shè)置多線圈(16),16設(shè)置多寄存器(1word)
// Saddr:數(shù)據(jù)起始地址(word)
// dat :數(shù)據(jù)內(nèi)容(word)
// Return Value :none
//
//-----------------------------------------------------------------------------
void Modbus_DataSend(unsigned char addr,func,unsigned int Saddr,dat)
{
UU16 crcData;
sendBuf[0]=addr; //從機地址
sendBuf[1]=func; //功能碼:
sendBuf[2]=Saddr>>8;sendBuf[3]=(char)Saddr; //起始地址
sendBuf[4]=0;sendBuf[5]=16; //元件個數(shù)
sendBuf[6]=2; //字節(jié)個數(shù)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -