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

📄 rs485.c

📁 SPI FLASH,SL811HST驱动
💻 C
字号:
/********************************************************************************
*
*
*名称:master.c
*功能:RS485主机收发程序
*说明:主机向整个网络发送地址信息,等待接收从机数据包
*程序设计:
*设计时间:
*
*
通信规则: 
1:时钟4MHZ/波特率9600bps 
2:通讯连接采用硬件MAX485,双向半双工
3:采用一主多从的多机通信方式 
4:主机数据包格式,帧头+从机地址 + CRC8校验位
5:从机数据包格式,帧头+主机地址 + 从机地址 + 数据长度 + 数据块 + CRC8校验位
6:主机向整个网络发送数据包,等待从机的反应
7:所有从机处于接收状态,当接收到的数据包中的地址信息与本机匹配,立即给主机发送数据
  否则从机继续处于接收状态
8:当主机接收到从机信息判断是否是要访问的从机,是则保存相应的温度数据,并发送下一个
  从机地址信息,否则主机再次发送该从机地址信息访问该从机
9:发送数据包采用查询方式,接收数据包采用中断方式 
10:0为无效地址,主机地址是1,从机地址是2.3.4......
*
*
*********************************************************************************/

#include <pic18.h>
#include "rs485.h"

unsigned char h;
unsigned char i;

typedef struct{						//结构体定义每个箱子的温度数据
	 unsigned char box_num;					//箱子号
	 unsigned char tempeture[NumOfChannel];	//六路温度数据
}wendu;

wendu box[NumOfBox];			//定义3个探测箱数据结构	

const unsigned char SlaveAddr[] = {2,3,4,5,6,7,8,9,10,11};		//3个从机地址

unsigned char SendBuf[LenOfSend];		//发送数据缓冲区
unsigned char RecBuf[LenOfRec];			//接收数据缓冲区

unsigned char REC_BUF[60];
//static unsigned char Start;						//接收数据起始位
//定时时间到,则设置开始发送数据包
//static unsigned char start_send_flag = 0;			//开始发送数据标志

unsigned char flag_me;	//本机数据标志	 				
unsigned char rec_count = 0;					//接收计数

static unsigned char j;

extern void ClearLcd( void );
/*
********************************
*
*名称:
*功能:
*说明:
*参数:
*
********************************
*/
void  Timer1Init( void )
{
	GIE = 0;		//关全局中断
	TMR1IF = 0;
	TMR1H = 0XC3;
	TMR1L = 0XB0; 	//4M外部晶振,定时器赋初值50000,0.1s定时
	
	T1CON = 0x10; 	//开启定时器1,定时模式8分频,指令周期2us
	TMR1IE = 1;  	//开启定时器1中断
	PEIE = 1; 		//开启外围中断
	TMR1ON = 1;		//开启定时器Timer1	
	GIE = 1;		//全局中断允许

}

//Usart串口初始化函数
void UsartInit( void )
{

	GIE = 0;		//关闭全局中断
	TRISC7 = 1;		//RX(RC7引脚)为输入
	TRISC6 = 0;		//TX(RC6引脚)为输出
	TRISC2 = 0;		//RC2作为MAX485控制位,输出
	RC2 = 0;		//单片机上电主机处于接收状态
	
	CSRC = 0;		//选择外部时钟
	SPBRG = 25;		//外部晶振4MHZ,波特率设定9600bps
//	SPBRG = 103;	//外部晶振4MHZ,波特率设定2400bps
	BRGH = 1;		//高速模式
	SYNC = 0;		//异步通信
	SPEN = 1;		//打开串行通信口
	
	TX9 = 0;		//选择8位数据发送
	RX9 = 0;		//选择8位接收

	TXIF = 0;		//不受软件控制
	TXEN = 1;		//发送使能
	
	RCIE = 1;		//接收中断使能
	RCIF = 0;		//不受软件控制
	CREN = 1;		//允许连续接收
	
	PEIE = 1;		//外部中断使能
	GIE = 1;		//开全局中断	
}


/********************************
*名称:
*功能:1us延时函数
*说明:
*参数:
*返回值:
*********************************/
void delay_1us( void )                 
{
	asm( "nop" );
}

/********************************
*名称:
*功能:N us延时函数
*说明:
*参数:
*返回值:
*********************************/

void delay_nus( unsigned int n )       
{
	unsigned int i=0;
	for( i = 0; i < n; i++ )
		delay_1us();
}

/********************************
*名称:
*功能:
*说明:
*参数:
*返回值:
*********************************/ 

void delay_1ms()
{
	unsigned int i;
	for( i = 0; i < 1140; i++ )
		;
}

/********************************
*名称:
*功能:
*说明:
*参数:
*返回值:
*********************************/  

void delay_nms( unsigned int n )       //N ms延时函数
{
	unsigned int i = 0;
	for (i = 0; i < n; i++ )
		delay_1ms();
}

/********************************
*名称:
*功能:CRC8校验
*说明:
*参数:
*返回值:
*********************************/  
unsigned char crc8(unsigned char *ptr, unsigned char len) 
{ 
	unsigned char i; 
	unsigned char crc = 0; 
	while( ( len-- ) != 0 ) 
	{ 
		for( i = 1; i != 0; i *= 2 ) 
		{ 
			if( ( crc & 1 ) != 0 ) 
			{ 
				crc /= 2; 
				crc ^= 0x8C;
			} 
			else 
				crc /= 2; 
			if( ( *ptr & i ) != 0 ) 
				crc ^= 0x8C; 
		} 
		ptr++; 
	} 
	return( crc ); 
} 

/********************************
*名称:
*功能:发送len个字节
*说明:
*参数:
*返回值:
*********************************/
void SendData( unsigned char *data, unsigned char len)
{
	unsigned char i = 0;
	UsartConBit = 1;		//Usart口处于发送状态
	while( i < len )
	{
		TXREG = data[i];

		while( TXIF == 0 );	//等待发送完成,TXREG为空时TXIF=1
		i++;				//发送次数统计

		delay_nms(10);		//每次发送数据之间有间隔
	}
	
	UsartConBit = 0;		//数据发送完后处于接收状态
}

/********************************
*名称:
*功能:
*说明:
*参数:
*返回值:
*********************************/
void Rs485SendPkg( unsigned char address )
{
	RCIE = 0;		//关闭接收中断
	TXEN = 1;		//允许发送
	
	//将待发送的数据加载到发送缓冲区
	
	SendBuf[0] = 0x55;		//帧头
	SendBuf[1] = address;	//从机地址信息
	SendBuf[LenOfSend - 1] = crc8( SendBuf,LenOfSend - 1 );		//校验位
	//Print( SendBuf );
	SendData( SendBuf,LenOfSend );	//发送数据
	delay_nms(10);	

	//主机发送完数据后
	RCIE = 1;		//打开接收中断
	CREN = 1;		//允许连续接收			
}


/********************************
*名称:
*功能:
*说明:
*参数:
*返回值:
*********************************/
void Rs485_master( unsigned char j )
{
	unsigned char crc8_check;
	unsigned char h;
	unsigned char i;
//	for( j = 0; j < ( sizeof(SlaveAddr) / sizeof(unsigned char) ); j++)
	{
		Rs485SendPkg( SlaveAddr[j] );	//发送数据包

		UsartConBit = 0;
		RCIE = 1;
		CREN = 1; 
		delay_nms(50);

		//收发状态转换之间间隔不能太长
		while(1)
		{
			//等待中断
			if( flag_me == 1 )
			{
				flag_me = 0;	//标志位清零
			
			//	Print("hello");
				//Print( RecBuf );
				if( RecBuf[2] == SlaveAddr[j] )
				{
					//Print("hello");
					crc8_check = crc8( RecBuf, LenOfRec - 1 );
					
					if( crc8_check == RecBuf[LenOfRec - 1] )
					{
						//接收到的数据校验正确
						rec_count = 0;		//接收计数清零
						for( h = 0; h < NumOfChannel; h++ )
						{
							box[j].tempeture[h] = RecBuf[h+4];	//存储温度数据到相应箱子结构体中
							REC_BUF[h+j*6] = box[j].tempeture[h];
							//TRISD = 0x00;
							//PORTD = box[j].tempeture[h];
							//delay_nms(10);
						}
					//	Print("microchip");
					//	GotoXY(2,8);
					//	ClearLcd();			//清屏
					//	GotoXY(1,0);
					//	Print( j+1 );
					//	GotoXY(2,0);
					//	Print( box[j].tempeture );	//显示接收到的数据
						break;		//接收成功,跳出while死循环,访问下一个从机
					}
					else
					{
					//	Print("hello");
						//接收数据错误
						rec_count = 0;		//接收计数清零
						//Rs485SendPkg( SlaveAddr[j] );	//重新访问该从机
						//break;
						//while()//发送次数计数
					}	
				}
			}
			else
			{
				//Print("hello");
				rec_count = 0;
				break;
			}
			
		}
		//Print("world");
	//	break;	
	}
}




////////////////////////////////////////////////

/*if( ten_minute == set_ten_minute )
{
	ten_minute = 0;
	flash_falg = 1;

}
*/
////////////////////////////////////////////////
/*
/////////////////////////////////////////////
//////////////  主函数   ////////////////////
/////////////////////////////////////////////
void main( void )
{
	UsartInit();		//初始化
	Timer1Init();		//Timer1初始化
	InitLcd();			//LCD初始化			

	while(1)		
	{  
		if( ten_minute > set_ten_minute )
		{  
			ten_minute = 0;		//十分钟计数清零  
			
			//到了定时时间,set_ten_minute个十分钟
	
 			Rs485_master();		//开始收发数据
 		}
	}
}
*/

⌨️ 快捷键说明

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