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

📄 m1.c

📁 用C51开发的单片机多机通讯程序
💻 C
字号:
#include "reg51.h"
#include "absacc.h"

// double port SDRAM
#define DoublePort_W 0
#define DoublePort_R 1
sbit BUSY = P3^3; // DoublePortSDRAM busy signal

#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_ADD  'D'
#define PC_CLEAR 'C'
#define PC_ERROR 'e'
#define PC_ALL 	'A'

#define SET_ACK	 's'
#define GET_ACK	 'g'
#define FIND_ACK 'f'
#define ADD_ACK  'd'
#define CLEAR_ACK 'c'
#define ALL_ACK  'a'

#define SET_OK	  1
#define SET_ERROR 0

#define FIND_LEN 7
#define SET_LEN  7
#define GET_LEN 18

#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); // send data to serial
void initialize(void); // initialize slave
void wait(unsigned short int x); // wait for time
// write or read DoublePortSDRAM
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

// parameter
bit uart_flag; // interrupt flag
unsigned char pointer;// interrupt pointer
#define COUNT 8
unsigned char pc[COUNT]; // interrupt buffer

/*
串行中断服务程序:接收串口的数据,并将其存入中断缓冲区,供主程序调用
参数:
	buffer[8]  — 中断缓冲区:unsigned char
	pointer    — 中断缓冲区指针,用于指示中断缓冲区是否已满:unsigned char
	uart_flag  — 中断标志,供主机查询用:bit
执行方法:
直接接收PC机发送的数据桢(8个字节);收满后置位相应的标志位
*/
void uart(void) interrupt 4
{
	RI = 0;
	pc[pointer]=SBUF; // save data to interrupt buffer
	pointer++; // adjust interrupt_pointer
	if(pointer>=COUNT) // data_string end
	{
		pointer=0; // adjust interrupt_pointer to 0
		uart_flag=1; // adjust uart_flag to 1
	}
	RI=0; // clear RI
}

/*
main1: 与PC机通讯,接收PC机命令(采用串口中断)并完成相应的处理过程

程序流程:
初始化:清除双口RAM单元内容,清串口缓冲区SBUF,初始化串口(9位,9,600波特/秒),开串行中断,开总中断,清除中断标志,清中断指针,发初始化完成标志'o'。
loop: 检查中断标志uart_flag(0/1-no/have),看是否有中断产生。若有,则取中断命令字pc[0],并根据该命令字执行相应的程序代码;若无,则进入下一轮循环。

命令处理程序:根据命令字pc[0]的内容进行相应的处理
	{
	pc[0]=PC_CLEAR:
		取从机地址
		将从机地址存入双口RAM的清除地址单元
		向双口RAM的order单元写入'COMMAND_CLR',通知main2清除该从机参数
	pc[0]=PC_ADD:
		取从机地址
		向双口RAM的相应单元添加从机
		向主机发送添加应答信号'ADD_ACK'
	pc[0]=PC_SET:
		取设置值
		将设置值存入双口RAM的设置单元
		向双口RAM的order单元写入'COMMAND_SET',通知main2设置从机
		延时,等待main2设置从机
		向主机发送设置应答信号'SET_ACK'
	pc[0]=PC_FIND:
		取从机地址
		将从机地址存入双口RAM的查找地址单元
		向双口RAM的order单元写入'COMMAND_FIND',通知main2查找该从机
		延时,等待main2查找从机
		检查main2是否完成查找从机的命令(共试TRY_find次)
		向主机发送查找应答信号'FIND_ACK'
		向主机发送添加地址应答信号
	pc[0]=PC_GET:
		取从机地址
		计算该从机的测量值在双口RAM中的存放地址
		从双口RAM的相应地址中取出该从机的测量值
		向主机发送取值应答信号'GET_ACK'
		向主机发送从机的测量结果
	pc[0]=其他值:
		向主机发送报错应答信号'PC_ERROR'
	}
	清中断指针
	清中断标志
	清双口RAM的order单元
	清数据缓冲区
*/
main()
{
	unsigned char i;
	unsigned short int ustemp;
	unsigned char length;
	unsigned char buffer[GET_LEN];
	
	// initialize 
	initialize();
	
	while(1)
	{
		i = (unsigned char) uart_flag;
		if(!i) continue;
		switch( pc[0] )
		{
			case PC_CLEAR: // clear slave_parameter
				i=pc[1];
				DoublePortRAM(DoublePort_W, 1, RAM_clr_addr , &i);
				i = COMMAND_CLR; // ask MCS51_main2 to clear slave_parameter
				DoublePortRAM(DoublePort_W,1,RAM_order,&i);
				break;
			case PC_ADD: // set slave_enable_flag
				for(i=1;i<8;i++) buffer[i]=pc[i]; // save pc_buffer
				for(i=1;i<8;i++) // save slave_enable_flag
				{
					ustemp=0;
					ustemp=(unsigned short int) buffer[i];
					ustemp=ustemp*FIND_LEN;
					ustemp = ustemp+RAM_para_addr;
					length=0x80;
					DoublePortRAM(DoublePort_W, 1, ustemp , &buffer[i]); // save slave_address to DoublePortRAM
					DoublePortRAM(DoublePort_W, 1, ustemp+1 , &length); // save slave_enable_flag to DoublePortRAM
				}
				UART_TXD(ADD_ACK); // send set_ack
				break;
			case PC_SET:
				for(i=0;i<COUNT;i++) buffer[i] = pc[i]; // save setting_value
				
				DoublePortRAM(DoublePort_W,SET_LEN,RAM_set_addr,&buffer[1]); // save setting_value to double_port_SDRAM
				
				i = COMMAND_SET; // ask MCS51_main2 to set slave
				DoublePortRAM(DoublePort_W,1,RAM_order,&i);
				
				wait(WAIT_for_set); // wait for setting slave
			wait(WAIT_for_set);	
				UART_TXD(SET_ACK); // send set_ack
				break;
			case PC_FIND:
				length=pc[1]; // save slave address
				
				DoublePortRAM(DoublePort_W,1,RAM_find_addr,&length); // ask MCS51_main2 to find slave
				i = COMMAND_FIND;
				DoublePortRAM(DoublePort_W,1,RAM_order,&i);
				
				wait(WAIT_for_find); // wait for finding slave
				
				for(ustemp=0;ustemp<TRY_find;ustemp++) // check: slave_setting finished? -- try 0xf000 times
				{
					DoublePortRAM(DoublePort_R,1,RAM_order,&i);
					if(i==COMMEND_FIND) break;
					wait(10);
				}
	//		UART_TXD((unsigned char) (ustemp>>8)); // test
	//		UART_TXD( (unsigned char) ustemp); // test
				if(ustemp<TRY_find) // find slave
				{ // get slave_parameter_value
					ustemp = length;
					ustemp = ustemp*FIND_LEN;
					ustemp = ustemp + RAM_para_addr;
					
	//		UART_TXD((unsigned char) (ustemp>>8)); // test
	//		UART_TXD( (unsigned char) ustemp); // test
					
					DoublePortRAM(DoublePort_R, FIND_LEN, ustemp , buffer);
				}
				// send the result of finding_slave to PC
				UART_TXD(FIND_ACK);
				for(i=0;i<FIND_LEN;i++)
				{
					UART_TXD( buffer[i] );
				}
				break;
			case PC_GET:
				ustemp = pc[1]; // get slave collect data
				ustemp = ustemp*GET_LEN;
				ustemp = ustemp+RAM_data_addr;
				DoublePortRAM(DoublePort_R,GET_LEN,ustemp,buffer);
				// send the result of getting_slave_data to PC
				UART_TXD(GET_ACK);
				for(i=0;i<GET_LEN;i++)
				{
					UART_TXD(buffer[i]);
				}
				break;
			default:
				UART_TXD(PC_ERROR); // error command of PC
				break;
		}
		pointer=0; // clear interrupt pointer
		uart_flag=0; // clear uart flag
		i = 0xff; // ask MCS51_main2 to set slave
		DoublePortRAM(DoublePort_W,1,RAM_order,&i);
		for(i=0;i<GET_LEN;i++) buffer[i]=0; // clear buffer
	}

}

// ============================== function ===============================================
/*
向主机发送数据
参数:
	uartdata — 将要发送的串行数据:unsigned char
执行方法:
令TB8=0(避免引起其他从机进行响应),开485(允许485发送),发送串口数据,开485(允许485接收)
*/
void UART_TXD(unsigned char uartdata)
{
	TB8=0; /* 避免引起其他从机进行响应 */
	SBUF=uartdata; // send data to serial
	while(!TI) ;
	TI=0; // clear TI
}
/*
初始化本从机,使其开始正常工作
参数:
	i,uctemp — 临时变量
执行:清双口RAM,清串口缓冲区,串口(9位,9,600波特/秒,开串口中断),清中断标志,清中断指针,发送初始化完成标志
*/
void initialize(void)
{
	unsigned char i;
	unsigned char uctemp;
	unsigned short int ustemp;
	
	// clear DoublePortSDRAM 0~8000 unit
	for(i=0,ustemp=0;ustemp<8000;ustemp++) DoublePortRAM(DoublePort_W,1,ustemp,&i); 
	// clear uart_rxd_buffer
	for(i=0;i<5;i++) uctemp = SBUF; 
	
	// initialize uart
	TMOD=0x20; // 9600 band
	TH1= 0xfd;
	TL1=0xfd;
	SCON=0xd0; //0xf0; // uart: format3, 9 bits
	PCON = 0x80; // PCON=0x00/0x80; -- 9,6kBand/19.2kBand
	TR1 = 1; // start to count time & offer 9,600 bit/s
	RI = 0;
	ES = 1; // open serial interrupt
	EA = 1; // open interrupt
	
	uart_flag=0; // clear uart flag
	pointer=0; // clear interrupt pointer
	
	UART_TXD('o'); // m1 finished initialize
}
/*
延时
参数:
	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); // DoublePortSDRAM is busy
			buf[i]=XBYTE[address+i]; // read data from DoublePortSDRAM
		}
	}
	else // write to DoublePortRAM
	{
		for(i=0;i<length;i++)
		{
			while(!BUSY) ; // DoublePortSDRAM is busy
			XBYTE[address+i] = buf[i]; // write data to DoublePortSDRAM
		}
	}
}

⌨️ 快捷键说明

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