📄 hdlc.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 + -