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

📄 hdlc.c

📁 ADUC841的AD编程
💻 C
字号:

#pragma CODE DEBUG SYMBOLS OBJECTEXTEND
#include <aduc841.h>
#include <stdio.h>
#include <absacc.h>
#include <string.h>
#include <intrins.h>
#include "Const.h"
#include "Extern.h"

extern void receive();
void init_interface()			//释放发送缓冲池
{
	unsigned int *point_temp,temp_init;
	point_temp = 0;
	point_temp = &(interface_a.serial.head[0]);
	for(temp_init = 0;temp_init < sizeof(struct serial_define); temp_init++)
	{
		*(point_temp + temp_init) = 0x0;
	}
}
void init_st16c554 (void)							 /* 初始化ST16C554	*/
{
	DPP = ST16C554A;								 //对应16c554a地址		
	XBYTE[IER] =	0x01; 							 /* IER: enable receive, disable transmit */ 
	XBYTE[FCR] =	0x0f; 							 /* FCR: enable transmit and receive FIFO,	FIFO level is 8	*/
	XBYTE[LCR] =	0x80; 							 /* programe baud rate: 00c0 2400 0060	4800 0030 9600 */
	XBYTE[DLL] =	0x30;
	XBYTE[DLM] =	0x00;			 
	XBYTE[LCR] =	0x03;			 				 /* LCR: word length 8,stop bit 1,no parity */
	XBYTE[MCR] =	0x0b;							 /* MCR: 0x1b loopback,0x0b normal	*/
	DPP = 0;
}

void set_int(unsigned char value)									//使能或关闭发送中断
{
	unsigned char idata ifr;
	DPP = ST16C554A;
	ifr = XBYTE[IER];
	if(value == RIGHT)					//使能
	{
		XBYTE[IER] = ifr | BIT1;
	}
	else if(value == ERROR)				//关闭
	{
		XBYTE[IER] = ifr & 0xfd;
	} 						
	DPP = 0;
}

void set_send_flag (unsigned char type,unsigned char value)			//写入或清除非信息包发送标记
{
	unsigned char flag;
	flag = interface_a.flag ;										//取出原标记
	switch (type)													//非信息包类型
	{
		case HEART:													//心跳包
		{
			if(value == 1)											//写入标记
			{
				flag = flag | BIT0;									//bit0置1
				interface_a.flag = flag;
			}
			else													//清除标记
			{
				flag = flag & 0xfe;									//bit0置0
				interface_a.flag = flag;
			}
		}
		break;
		case STATE_R:												//正确回应包
		{
			if(value == 1)											//写入标记
			{
				flag = flag | BIT1;
				interface_a.flag = flag;							//bit1置1
			}
			else													//清除标记
			{
				flag = flag & 0xfd;									//bit1置0
				interface_a.flag = flag;
			}
		}
		break;
		case STATE_E:												//错误回应包
		{
			if(value == 1)											//写入标记
			{
				flag = flag |  BIT2;								//bit2置1
				interface_a.flag = flag;
			}
			else													//清除标记
			{
				flag = flag & 0xfb;								//bit2置0
				interface_a.flag = flag;
			}
		}
		break;
		default:
		break;
	}
}
void frame_send(unsigned char value)								//非信息包发送
{
	unsigned char idata serial_state,temp;
	temp = value;
	DPP = ST16C554A;
	serial_state = XBYTE[LSR];										//读发送fifo状态
	while((serial_state & BIT6) != BIT6)							//为空,写入,否则继续读
	{
		serial_state = XBYTE[LSR];
	}
	XBYTE[THR] = 0xee;
	XBYTE[THR] = 0xee;
	XBYTE[THR] = value;												//非信息包类型
	DPP = 0;
}

void n_inf_frame()													//发送非信息包,同时清除标记										
{
	if((interface_a.flag & BIT0) == BIT0)							//心跳包
	{
		frame_send(HEART);											//发送
		set_send_flag(HEART,0);										//清除标记
	}
	if((interface_a.flag & BIT1) == BIT1)							//正确回应包
	{
		frame_send(STATE_R);
		set_send_flag(STATE_R,0);
	}
	if((interface_a.flag & BIT2) == BIT2)							//错误回应包
	{
		frame_send(STATE_E);
		set_send_flag(STATE_E,0);
	}
	
}


unsigned char inf_frame()									//信息包
{
	unsigned char temp_inf,check
	check = 0;
	interface_a.serial.head[0] = 0xee;						//收到字头1 0xee
	interface_a.serial.head[1] = 0xee;						//收到字头2 0xee
	interface_a.serial.type    = INF;						//信息包类型
	total_length = 0;
	command_length = interface_a.transmit_buf[interface_a.transmit_buf_bottom];//命令字长度
	while((interface_a.transmit_buf_bottom != interface_a.transmit_buf_top) && ((total_length + command_length) < SERIAL_VALUE_LENGTH))//缓冲区有数,发送池容量够大
	{
		if((command_length < SERIAL_MAX_L_COMMAND) && (command_length > SERIAL_MIX_L_COMMAND))//命令字长度和标
		{
			for(temp_inf = 0;temp_inf < command_length;temp_inf++)
			{
				interface_a.serial.buf[total_length + temp_inf] = interface_a.transmit_buf[interface_a.transmit_buf_bottom];//将该命令字写入发送池
				if(temp_inf == (command_length - 1))//笑颜和
				{
					check = (check + (interface_a.transmit_buf[interface_a.transmit_buf_bottom] << 1));  //总效验和 = 各效验命令子效验和相加 * 2;
				}
				interface_a.transmit_buf_bottom = (interface_a.transmit_buf_bottom + 1) % BUF_MAX_LENGTH; 
			}
			total_length = total_length + command_length;			//计算总长度
			command_length = interface_a.transmit_buf[interface_a.transmit_buf_bottom];//命令字长度<ol><li></li></ol>
		}
		else													//命令字长度不和标,清除缓冲区
		{
			interface_a.transmit_buf_bottom = 0;
			interface_a.transmit_buf_top    = 0;
			return (ERROR);
		}
	}
	interface_a.serial.buf[total_length] = check;			//写效验和
	interface_a.serial.length    = total_length + 5;		//写总长度
	return (RIGHT);
}

void transmit_receive()																//中断方式接收发送命令字
{
	unsigned char idata serial_state,temp;
	unsigned char xdata temp_transmit,*send_point;
	DPP = ST16C554A;
	serial_state = ((XBYTE[ISR] & 0x0e) >> 1) ;										//读isr寄存器
	if(((serial_state & 0x06) == 0x02) ||((serial_state & 0x06) == 0x06))			//接收中断
	{
		while((XBYTE[LSR] & 0x01) == 0x01)											//接收fifo中有数
		{
			temp = XBYTE[RHR];														//读出	
			DPP = 0;
			receive_serial(temp);													//串口数据接收处理		
			DPP = ST16C554A;
		}
	}
	else if(((serial_state & 0x06) == 0x01)
	{
		DPP = ST16C554A;
		serial_state = XBYTE[LSR];					//读发送fifo状态
		DPP = 0;
		while((serial_state & BIT6) != BIT6)		//为空,写入,否则继续读
		{
			DPP = ST16C554A;
			serial_state = XBYTE[LSR];
			DPP = 0;
		}
		if(interface_a.serial.serial_point == interface_a.serial.length)		//发完
		{
			set_int(ERROR);														//关闭发送中断使能
			interface_a.serial.serial_point = 0;								//发送指针清0
			interface_a.serial.send_time = 1;									//发送计时开始
		}
		temp_transmit = 0;
		while((interface_a.serial.serial_point < interface_a.serial.length) ||(temp_transmit < 16))//依次写入16个
		{
			DPP = 0;
			send_point = &(interface_a.serial.head[0]);		//去发送池首地址
			temp = *(send_point + interface_a.serial.serial_point);		//按指针依次取出池中的数
			interface_a.serial.serial_point = (interface_a.serial.serial_point + 1) //指针加1
			DPP = ST16C554A;
			XBYTE[THR] = temp;														//数据写入发送fifo
			DPP = 0;
			temp_transmit = temp_transmit + 1;
		}
	}	
}

void receive_serial(unsigned char serial_data)															//串口数据接收处理	
{
	switch (serial_state)
	{
		case 0:
		{
			if(serial_data == 0xee)																		//收到字头1 0xee
			{
				serial_state = 1;
			}		
		}
		break
		case 1:
		{
			if(serial_data == 0xee)																		//收到字头2 0xee
			{
				serial_state = 2;
				interface_a.time = 1;																	//开始接收计时(300ms没收完则回状态0)
			}
			else																
			{
				serial_state = 0;																		//收错则回状态0
			}
		}
		break;
		case 2:
		{
			if(serial_data == INF)																		//收到信息包
			{
				serial_state = 3;
				interface_a.receive_buf_point = interface_a.receive_buf_top;							//接收寄存指针== 接收缓冲区头指针
				interface_a.check = 0;																	//效验和清0
			}
			else if(serial_data == HEART)																//收到心跳包
			{
				serial_state = 0;																		//一次完成回状态0
				set_send_flag(HEART,1);																	//写发心跳包标记
				interface_a.time = 0;																	//接收计时结束
			}
			else if(serial_data == STATE_R)																//收到正确回应包
			{
				serial_state = 0;																		//一次完成回状态0
				init_interface();																		//释放发送缓冲池
				interface_a.time = 0;																	//接收计时结束
			}
			else if(serial_data == STATE_E)																//收到错误回应包
			{
				serial_state = 0;																		//一次完成回状态0
				interface_a.time = 0;																	//接收计时结束
				interface_a.serial.flag = interface_a.serial.flag | RESEND;								//写重发标记
				interface_a.serial.send_time = 0;														//发送计时清0
			}
			else
			{
				serial_state = 0;																		//收错则回状态0
				interface_a.time = 0;																	//接收计时结束
			}	
		}
		break;	
		case 3:
		{
			if(serial_data < SERIAL_MAX_LENGTH)															//长度和标
			{
				interface_a.receive_length = serial_data;												//记录长度
				serial_state = 4;
				interface_a.receive_num = 4;															//已收长度
			}
			else
			{
				serial_state = 0;																		//收错则回状态0
				interface_a.time = 0;																	//接收计时结束
			}	
		}
		break;
		case 4:
		{
			interface_a.receive_num++;																	//记录长度++
			if(interface_a.receive_num == interface_a.receive_length) 									//数已收完
			{
				if(interface_a.check == serial_data)													//效验和正确
				{
					interface_a.receive_buf_top = interface_a.receive_buf_point;						//接收缓冲区头指针 == 接收寄存指针
					interface_a.receive_buf_point = 0;													//接收寄存指针清0
					serial_state = 0;																	//一次完成回状态0
					interface_a.time = 0;																//接收计时结束
					interface_a.check = 0;																//校验和清0
					set_send_flag(STATE_R,1);															//写发正确回应报包标记
				}
				else
				{
					serial_state = 0;																	//一次完成回状态0
					interface_a.check = 0;																//校验和清0
					interface_a.time = 0;																//接收计时结束
					set_send_flag(STATE_E,1);	
				}																						//写发错误回应报包标记
			}
			else																						//数没收完
			{
				interface_a.receive_buf[interface_a.receive_buf_point] = serial_data;					//写入接受寄存器
				interface_a.receive_buf_point = (interface_a.receive_buf_point + 1) % BUF_MAX_LENGTH;	//寄存器指针加加
				interface_a.check = (interface_a.check + serial_data) & PAGE;							//计算效验和
			}
		}
		break;
		default:
			serial_state = 0;
			interface_a.time = 0;
		break;
	}
}

unsigned char check_count(unsigned char buf[SERIAL_MAX_L_COMMAND],unsigned char length)//计算效验和
{
	unsigned char temp_check,check;
	check = 0;
	for(temp_check = 0; temp_check < (length-1); temp_check++)
	{
		check = (check + buf[temp_check]) & PAGE;
	}
	if(check == buf[length - 1])
	{
		return (RIGHT);
	}
	return (ERROR);
}

void extract_serial	(void)																				/*提取接收到的的命令字*/
{
	unsigned char xdata serial_length,temp_serial;
	unsigned char xdata serial_buf[SERIAL_MAX_L_COMMAND]
	while(interface_a.receive_buf_top != interface_a.receive_buf_bottom)								//接收缓冲区有数
	{
		serial_length = interface_a.receive_buf[interface_a.receive_buf_bottom]							//取命令字长度
		if((serial_length > SERIAL_MIX_L_COMMAND)&&(serial_length <= SERIAL_MAX_L_COMMAND))				//长度合标
		{
			for(temp_serial = 0; temp_serial < serial_length; temp_serial++)
			{
				serial_buf[temp_serial] = interface_a.receive_buf[interface_a.receive_buf_bottom + temp_serial];	//取出命令字内容
			}
			if(check_count(serial_buf,serial_length))																//效验和合标
			{
				receive(serial_buf,serial_length);																	//处理
				interface_a.receive_buf_bottom = (interface_a.receive_buf_bottom + serial_length) & PAGE;			//尾指针增加
			}
			else																									//效验和不合标,清空缓冲区
			{
				interface_a.receive_buf_bottom = 0;
				interface_a.receive_buf_top    = 0;
			}
		}
	}
}

void resend(void)//重新发送
{
	unsigned char resend_count;
	if(interface_a.serial.send_time >= 1)	//发送计时已开始
	{
		interface_a.serial.send_time = interface_a.serial.send_time + 1;			//发送计时++
		if(interface_a.serial.send_time >= FLAG_1S)									//计时到一秒
		{
			interface_a.serial.flag = interface_a.serial.flag | RESEND;				//置重发标记
			interface_a.serial.send_time = 0;										//发送计时清0
		}
	}
	if((interface_a.serial.flag & RESEND) == RESEND)								//需要重发
	{
		resend_count = interface_a.serial.flag & BIT0_1;							//读重发次数
		resend_count++
		if(resend_count >= 3)														//重发次数大于3
		{
			init_interface();														//释放发送缓冲池
		}
		else
		{
			set_int(RIGHT);															//重发
			interface_a.serial.flag = interface_a.serial.flag & 0xfc;				//技术次数清0;
			interface_a.serial.flag = interface_a.serial.flag + resend_count;		//写重发次数
			interface_a.serial.flag = interface_a.serial.flag & 0xf7;				//重发标记清0;
		}
	}
}




unsigned char send_buf(void)												//成信息包发送	
{
	if(interface_a.transmit_buf_top != interface_a.transmit_buf_bottom)		//发送缓冲区中有数
	{
		interface_a.serial.flag = 0;
		interface_a.serial.flag = interface_a.serial.flag | OCCUPY;			//占用
		inf_frame();														//成信息包
		set_int(RIGHT);														//使能发送中断
		return (RIGHT);
	}
	return (ERROR);
}

⌨️ 快捷键说明

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