⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f340_modbus.c

📁 单片机Modebus主站程序 MCU:C8051F340
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// F340_modbus.c			Modbus Master
//-----------------------------------------------------------------------------
//
// Program Description:
//
// 完成Modbus协议的部分功能:
// 功能码	功能描述				可用数量
//-------------------------------------------
// 01		读取线圈状态(多位)		
// 02		读取输入状态(多位)		共128
//-------------------------------------------
// 03		读取保持寄存器(多字)
// 04		读取输入寄存器(多字)	共16
//-------------------------------------------
// 05		强置单线圈,支持广播方式
// 06		预置单寄存器,支持广播方式
//-------------------------------------------
// 08		回送诊断(原帧回传)
//-------------------------------------------
// 15		强置多线圈				共128
// 16		预置多寄存器			共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 发送接收控制
bit  bMB_idle;							//=0:Modbus空闲;=1:Modbus占用

U8	xdata sendBuf[64],receBuf[64]; 		//发送接收缓冲区
U8	checkoutError;						// ==2 偶校验错  
U8	receTimeOut;						//接收超时:开始接收后规定时间内未收到数据,已收数据无效
U8  MB_BroadTimer;						//广播计时器:广播发送数据后,产生固定延时,再回到空闲
U16 MB_TimeOut;							//Modbus超时:发送数据后规定时间内无响应,产生94号错误
U8  MB_ErrorCode;						//错误代码:01:功能码错;02:地址错;03:数据个数错;
										//         92:CRC错;93:响应格式错;94:无响应.
U8  MB_TestEcho;						//诊断结果回应
U8  MB_c15done;							//code15功能 =S:发送指令,=15:完成发送,=0:功能完成
bit bMB_setup;							//MB设置:0:工作状态,1:设置状态;由通讯设置采单改变
U8  MB_SendNum;							//发送指令序号:工作状态使用的指令序号,完成发送后+1
extern U8 menu_comm0_addr[6];			//通讯地址定义
extern U8 menu_comm0_test;				//通讯测试地址
extern U8 menu_brChange;				//波特率改变寄存器:0-5
extern U8 SignalSet;					//信号设置:高4位:清零;低4位:极性 		FRAM 11

U8	localAddr ;							//本机地址
U8	sendCount;							//发送字节个数
U8	receCount;	    					//接收到的字节个数
U8	sendPosi;	    					//发送位置
extern U8 menu_alarm_set[4];			//报警设置  数组									FRAM 284-287(4)
extern U8 FM_alarming[5];				//报警状态:0x00:无报警,0x0f:警告,0xff:报警
										//         0:重量,1:幅度,2:高度,3:角度,4:力矩
U8 MB_SetAlarm;							//从机报警设置
//-----------------------------------------------------------------------------
// 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;    			//发送完后将485置于接收状态
			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个字节
	}
}
//-----------------------------------------------------------------------------
// 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主控设备设置,主机必须同时改变波特率
//-----------------------------------------------------------------------------
void BaudRateChange (void)
{
	static U16 NoChange;
	if (SetReg0 != NoChange  && bMB_idle == 0)//只在SetReg[0]改变与空闲时执行				
	{										
		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 字节初始化  
	U8 uchCRCLo = 0xFF ; 								//低CRC 字节初始化
	U32 uIndex ; 										//CRC循环中的索引 
	while (usDataLen--) 								//传输消息缓冲区 
	{ 
		uIndex = uchCRCHi ^ *puchMsg++ ; 				//计算CRC 
		uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; 
		uchCRCLo = auchCRCLo[uIndex] ; 
	} 
	return (uchCRCHi << 8 | uchCRCLo) ; 
}
//-----------------------------------------------------------------------------
// MB_DataProc_step								数据处理
//-----------------------------------------------------------------------------
void MB_DataProc_step(void)
{
	if(MB_c15done==15){SignalSet=(char)SetReg[0][11];MB_c15done=0;}	//信号设置完成	
	
}
//-----------------------------------------------------------------------------
// Modbus_CommandSend
//
// Modbus
//
// Parameters   :addr地址:00广播,01采样,02行走,03变幅,04回转,05起升
//				 func功能码:01读取多线圈,03读取多寄存器,06设置单寄存器,08诊断
//				 num :func 01,03:元件个数 func06,08:数据内容
// 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;		//元件个数
	crcData.U16 = crc16(sendBuf,6);		//CRC
	sendBuf[6]=crcData.U8[MSB];			//CRC高字节
	sendBuf[7]=crcData.U8[LSB];			//CRC低字节
	sendCount = 8;						//发送字节数
	beginSend();						//开始发送
}
//-----------------------------------------------------------------------------
// Modbus_DataSend
//
// Modbus
//
// Parameters   :addr地址:00广播,01采样
//				 func功能码:15设置多线圈(16),16设置多寄存器(1word)
//				 Saddr:数据起始地址(word)
//				 dat  :数据内容(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;					//元件个数
	sendBuf[6]=2;								//字节个数

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -