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

📄 m2.c

📁 用C51编写的现场总线多机通讯程序
💻 C
字号:
#include "reg51.h"
#include "absacc.h"

// uart 485
sbit RE_DE = P1^0;
#define TXD_485 1
#define RXD_485 0
// watch dog
sbit CLK = P1^1;
// double port SDRAM
#define DoublePort_W 0
#define DoublePort_R 1
sbit BUSY = P3^3;

#define COMMAND_SET 	'S'
#define COMMAND_FIND 	'T'
#define COMMEND_FIND 	't'
#define COMMAND_GET 	'G'
#define COMMAND_CLR	'C'

#define PC_SET	'V'
#define PC_GET	'G'
#define PC_FIND	'F'
#define PC_ERROR 'e'

#define ACK 	 'o'
#define SET_ACK	 's'
#define GET_ACK	 'g'
#define FIND_ACK 'f'

#define SET_OK	  1
#define SET_ERROR 0

#define FIND_LEN 7
#define SET_LEN  7
#define GET_LEN 18
sbit test=P1^2;
sbit test1=P1^3;

#define RAM_order 0
#define RAM_set_addr	10
#define RAM_find_addr	20
#define RAM_get_addr	30
#define RAM_clr_addr	40
#define RAM_para_addr	50
#define RAM_data_addr	2000

#define WAIT_for_set	0xffff
#define WAIT_for_find	0x7fff



#define TRY_set		0x7000
#define TRY_find	0x7000

void UART_TXD(unsigned char uartdata);
bit UART_RXD(unsigned char *rxd_data);
void initialize(void);
void wait(unsigned short int x);
void DoublePortRAM(	bit wr, // wr=0/1 -- write/read
			unsigned char length, // data length
			unsigned short int address, // RAM start address
			unsigned char *buf); // data buffer
void find(unsigned char s_addr);

main()
{
	unsigned char i;
	unsigned char buffer[GET_LEN+1];
	unsigned short int ustemp;
	unsigned char address; // slave address
	
	
	// initialize 
	CLK=0;CLK=1; // WatchDog
	initialize();
	address=0; // slave address

	while(1)
	{
		for(i=0;i<GET_LEN+1;i++) buffer[i]=0; // clear buffer
		DoublePortRAM(DoublePort_R,1,RAM_order,&i); // check DoublePortSDRAM order unit
		CLK=0;CLK=1; // WatchDog
		
		switch(i)
		{
			case COMMAND_CLR: // clear slave_parameter
				DoublePortRAM(DoublePort_R,1,RAM_clr_addr,&buffer[0]); // get slave_address
				
				RE_DE = TXD_485; // enable txd to 485
				TB8=1; // ready to send slave_address
				UART_TXD(buffer[0]); // send slave_address
				RE_DE = RXD_485; // enable rxd from 485
				if( (UART_RXD(&i))&&(i==ACK) ) // receive slave_ack? & slave_ack is right??
				{ // have received slave_ack & slave_ack is right
					RE_DE = TXD_485; // send setting_value to slave
					TB8 = 0;
					UART_TXD(COMMAND_CLR); // send order
					for(i=1;i<SET_LEN;i++) // send slave setting_value
					{
						UART_TXD(0);
					}
					// del slave_old_parameter
					ustemp = buffer[0]; // get slave_old_address
					ustemp = ustemp*SET_LEN +1; // get the module_unit of slave_old_address 
					ustemp = ustemp + RAM_para_addr;
					i = 0x7f; // setting module_value of slave_old_address
					DoublePortRAM(DoublePort_W,1,ustemp,&i);
				}
				i = COMMEND_FIND; // finish find slave
				DoublePortRAM(DoublePort_W,1,RAM_order,&i);
				break;
			case COMMAND_SET: // setting slave parameter
				DoublePortRAM(DoublePort_R,SET_LEN,RAM_set_addr,buffer); // get setting_value from DoublePortSDRAM
			
				RE_DE = TXD_485; // enable txd to 485
				TB8=1; // ready to send slave_address
				UART_TXD(buffer[0]); // send slave_address
				RE_DE = RXD_485; // enable rxd from 485
				if( (UART_RXD(&i))&&(i==ACK) ) // receive slave_ack? & slave_ack is right??
				{ // have received slave_ack & slave_ack is right
					RE_DE = TXD_485; // send setting_value to slave
					TB8 = 0;
					UART_TXD(COMMAND_SET); // send order
					for(i=1;i<SET_LEN;i++) // send slave setting_value
					{
						UART_TXD(buffer[i]);
					}
				}
				RE_DE=TXD_485;
				i = COMMEND_FIND; // finish find slave
				DoublePortRAM(DoublePort_W,1,RAM_order,&i);
				
				break;
			case COMMAND_FIND: // find slave
			        test1=!test1;
				DoublePortRAM(DoublePort_R,1,RAM_find_addr,&buffer[1]); // get slave_address from DoublePortSDRAM
				
				find(buffer[1]); // find slave parameter
				
				i = COMMEND_FIND; // finish find slave
				DoublePortRAM(DoublePort_W,1,RAM_order,&i);
				
				
			default: // get slave_collect_data
			        
                                test =!test;
				ustemp = address;
				ustemp = ustemp*FIND_LEN+1;
				ustemp = ustemp+RAM_para_addr;
				DoublePortRAM(DoublePort_R,1,ustemp,&i);
				if(i&0x80) // slave enable
				{
					CLK=0;CLK=1; // WatchDog
					RE_DE = TXD_485;
					TB8 = 1;
					UART_TXD(address);
					RE_DE = RXD_485;
					if( UART_RXD(&i)&&(i==ACK) ) // build uart
					{
						RE_DE = TXD_485;
						TB8 = 0;
						UART_TXD( COMMAND_GET ); // command-string
						for(i=0;i<6;i++)
						{
							UART_TXD(0);
							wait(10);
						}
						RE_DE = RXD_485;
						for(i=0;i<GET_LEN+1;i++) UART_RXD(&buffer[i]); // collect slave data
						buffer[2] = buffer[2]&0x7f;// have slave module
						buffer[2] = buffer[2]+0x80;
					}
				}
				else // slave disable
					buffer[2] = 0;
				buffer[1] = address; // save data to SDRAM
				ustemp = address;
				ustemp = ustemp*GET_LEN;
				ustemp = ustemp+RAM_data_addr;
				DoublePortRAM(DoublePort_W,GET_LEN,ustemp,&buffer[1]);
				
				address++;
			        if(address>25) address=0; // test

				break;
				
		} // switch
		CLK=0;CLK=1; // WatchDog
	} // while

}

// ============================== function ===============================================
/*
向主机发送数据
参数:
	uartdata — 将要发送的串行数据:unsigned char
执行方法:
令TB8=0(避免引起其他从机进行响应),开485(允许485发送),发送串口数据,开485(允许485接收)
*/
void UART_TXD(unsigned char uartdata)
{
	EA=0; // close uart
	SBUF=uartdata; // send data to serial
	while(!TI) ;
	TI=0;
	EA=1; // open uart
}
bit UART_RXD(unsigned char *rxd_data)
{
  #if 1
	// can break loop
	unsigned short int i;
//unsigned long int i;
	
	for(i=0;i<0xa000;i++) 
		{
		if(RI) break; // 0xf42400 ~= 16s
		CLK=0;CLK=1;
		}
	if(i>=0xa000) return 0; // error
  #else
	// can't break loop
	while(!RI) ;
  #endif
	RI = 0;
	*rxd_data = SBUF;
	return 1; // ok
}
/*
初始化本从机,使其开始正常工作
参数:
	i,uctemp — 临时变量
执行:清双口RAM,清串口缓冲区,串口(9位,9,600波特/秒,开串口中断),清中断标志,清中断指针,发送初始化完成标志
*/
void initialize(void)
{
	unsigned char i;
	
	// WatchDog
	CLK=0;CLK=1;
	// wait for m1.c
	wait(0xffff);
	// initialize
	TMOD=0x20; // 9600 band
	TH1= 0xfd;
	TL1=0xfd;
	SCON=0xd0; //0xf0; // uart: format3, 9 bits
	PCON = 0; // PCON=0x00/0x80; -- 9,6kBand/19.2kBand
	TR1 = 1; // start to count time & offer 9,600 bit/s
	RI = 0;
	EA=0;
	RE_DE = TXD_485;
}
/*
延时
参数:
	x — 延时长度:unsigned short int
*/
void wait(unsigned short int x)
{
	while(x--) ;
	return;
}
/*
读写双口RAM
参数:
	wr 	— write/read flag(0/1-write/read):bit
	length	— data length:unsigned char
	address — SDRAM start address:unsigned short int
	buf 	— data buffer:unsigned char *
执行:
若wr=0,则向双口RAM的address单元依次写入length个数据;若wr=1,则从双口RAM的address单元依次读出length个数据
*/
void DoublePortRAM(	bit wr, // wr=0/1 -- write/read
			unsigned char length, // data length
			unsigned short int address, // RAM start address
			unsigned char *buf) // data buffer
{
	unsigned char i;
	unsigned uctemp;
	
	uctemp = (unsigned char) wr;
	if(uctemp) // read from DoublePortRam
	{
		for(i=0;i<length;i++)
		{
			while(!BUSY) {CLK=0;CLK=1;} // DoublePortSDRAM is busy
			buf[i]=XBYTE[address+i]; // read data from DoublePortSDRAM
		}
	}
	else // write to DoublePortRAM
	{
		for(i=0;i<length;i++)
		{
			while(!BUSY) {CLK=0;CLK=1;} // DoublePortSDRAM is busy
			XBYTE[address+i] = buf[i]; // write data to DoublePortSDRAM
		}
	}
}
/*
查找从机
参数:
	s_addr  — 被查找的从机地址
执行:
令TB8=1,表明为地址帧,发送该地址帧,收从机的应答信号。在预定的时间内若收到从机的应答信号,则要求从机返回从机参数;若未收到从机应答信号,则赋值未找到从机,并将查找结果写入双口RAM中,
*/
void find(unsigned char s_addr)
{
	unsigned char buf[FIND_LEN+1];
	unsigned char i;
	unsigned short int ustemp;
	
	for(i=0;i<FIND_LEN+1;i++) buf[i]=0; // initialize buf[]
	
	RE_DE = TXD_485;
	TB8=1;
	UART_TXD(s_addr);// send slave address
	RE_DE = RXD_485;
	if( UART_RXD(&i)&&(i==ACK) )  // build uart 
	{
		RE_DE = TXD_485;
		TB8 = 0; // uart slave data
		UART_TXD( COMMAND_FIND ); // command-string
		for(i=0;i<6;i++) 
			{ 
				UART_TXD(0);
		//		wait(10); 
			}
		RE_DE = RXD_485;
		
		CLK=0;CLK=1;
		
		for(i=0;i<FIND_LEN+1;i++) UART_RXD(&buf[i]); // collect slave data
		buf[2] = buf[2]&0x7f;// have slave module
		buf[2] = buf[2]+0x80;
	}
	else /* 无从机应答 */
		buf[2]=0x7f;
	buf[1] = s_addr; 
	/* 查找结果存入双口RAM */		
	ustemp = s_addr;
	ustemp = ustemp*FIND_LEN;
	ustemp = ustemp + RAM_para_addr;
	DoublePortRAM(DoublePort_W, FIND_LEN, ustemp , &buf[1]);

	CLK=0;CLK=1; // watch dog
	
	return ;
}

⌨️ 快捷键说明

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