📄 serialdemo.c
字号:
#include <intrins.h>
#include <ctype.h>
#include <absacc.h>
#include <reg52.h>
#include <stdio.h>
#include <defreg.h>
#include <stdlib.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar data comrxdread=0; //串口接收读指针
uchar data comtxdread=0; //串口发送读指针
uchar data comrxdwrite=0; //串口接收写指针
uchar data comtxdwrite=0; //串口发送写指针
uchar data com_timeout_count; //串口超时计数器
bit comtxdbufempty=1; //串口的发送缓冲区空的标志
bit comrxdtimeout=0; //串口接收超时
#define com_rxd_buffer_size 26 //缓冲区长度
#define com_txd_buffer_size 40
uchar idata comrxdbuf[com_rxd_buffer_size]; //串口的接收缓冲区
uchar idata comtxdbuf[com_txd_buffer_size]; //串口的发送缓冲区
uchar data combuf[com_rxd_buffer_size]; //串口数据处理缓冲区
#define combuf_header combuf[0]
#define combuf_addr combuf[1]
#define combuf_cmd combuf[2]
#define combuf_length combuf[3]
#define combuf_para combuf[4]
uchar data serialmsg;
uchar data node_addr; //本机站点号:0-254
main()
{
init_sys_reg();
comtxdbufempty=1;
timer1_interrupt_enable;//ET1=1
interrupt_enable;
while(1)
{
if((msec == 0 )||(msec==25)) reset_watchdog();
if(comrxdtimeout) //接收超时
{
process_command();//处理用户从串口输入的命令
}
}
}
void service_timer1() interrupt 3 //10ms定时中断,方式1,16位定时器,常数0xdc00
{
interrupt_disable;
TH1 = 0xdc;
TL1 = 0x00;
com_timeout_count++;
if(com_timeout_count > COM_TIMEOUT) comrxdtimeout = 1;
interrupt_enable;
}
void service_serial() interrupt 4 using 3
{
interrupt_disable;
if(TI )
{
TI = 0;
if(comtxdread!=comtxdwrite)
{
SBUF=comtxdbuf[comtxdread];
comtxdread++;
if(comtxdread==com_txd_buffer_size) comtxdread=0;
comtxdbufempty=0;
}else
{
comtxdbufempty=1;
}
}
if (RI )
{
RI = 0;
comrxdbuf[comrxdwrite]=SBUF ;
comrxdwrite++;
if(comrxdwrite==com_rxd_buffer_size) comrxdwrite=0;
com_timeout_count = 0; //用于控制串口接收超时,单位是10ms
}
interrupt_enable;
}
void init_sys_reg(void) //初始化,设置内部寄存器
{
//设置中断
interrupt_disable;
int0_mode_hightolow; //IT0 = 1 外中断边沿触发
int0_interrupt_enable;
int1_mode_hightolow;
int1_interrupt_enable;
PX1 = 1;
//设置定时器0
//设置定时器1
timer1_mode_16bit; //TMOD=TMOD&0xf0;TMOD=TMOD|0x01
timer1_priority_low; //PT1=0
timer1_speed0; //th1,tl1=0xdc00
timer1_run; //TR1=1
//设置定时器2,用作波特率发生器
timer2_interrupt_disable;
//设置串行口
serial_uart_8; //sm0=0; sm1=1; sm2=0
serial_baud_9600_timer2; //t2con=0x34;RCAP2H=0xff;rcap2l=0xdc;tr2=1
serial_receive_enable; //允许接收REN=1
TB8 = 0; //9位UART时发送的第九位
TI = 0; //中断标志,手工清零
serial_interrupt_enable; //ES=1
}
uchar get_char() //从串口缓冲区读取字符
{
uchar temp;
temp=comrxdbuf[comrxdread];
comrxdread++;
if(comrxdread==com_rxd_buffer_size){comrxdread=0;}
return(temp);
}
void send_char(uchar ascii) //往串口发送一个字符
{
serial_interrupt_disable;
comtxdbuf[comtxdwrite++]=ascii;
if(comtxdwrite==com_txd_buffer_size) comtxdwrite=0;
if(comtxdbufempty) { TI=1; }
serial_interrupt_enable;
}
//通信子程序
void process_command(void) //命令处理子程序,返回命令处理结果serialmsg
{
//起始标志:01111110
//目的地址:1字节,为0xff表示广播访问模式,其他表示单机访问模式
//通信命令:1字节
//信息长度:1字节,为0时表示信息内容为空,本通信帧为控制帧
//信息内容:可变长度
//校验:字节纵向奇偶校验,包括前面起始标志、目的地址等所有字节的校验
//结束标志:01111110
//通信协议返回信息格式,最短6字节
//起始标志:01111110
//目的地址:1字节
//执行情况:1字节
//信息长度:1字节,为0时表示信息内容为空
//信息内容:可变长度
//校验:字节纵向奇偶校验,包括前面起始标志、目的地址等所有字节的校验
//结束标志:01111110
uchar i,temp;
uchar bytecrc;
uchar xdata * ptr;
i = 0;
bytecrc = 0;
serialmsg=0;
comrxdtimeout = 0;
if(comrxdread != comrxdwrite) //串口数据的缓冲区中有数据,进入命令处理
{
while(comrxdread != comrxdwrite)
{
combuf[i] = get_char();
bytecrc ^= combuf[i];
i++;
}
if( (combuf_addr != BROADCAST_ADDR) && (combuf_addr != node_addr) )//节点地址错误
{
serialmsg = SERIAL_NODE_ERROR;
}else
if(bytecrc != END_FLAG) //校验错误
{
serialmsg = SERIAL_CRC_ERROR;
}else //开始处理命令
{
serialmsg = combuf_cmd;
switch(serialmsg)
{
case CMD_SET_NODEADDR://范例
if(combuf_length < 2) {serialmsg=SERIAL_PARA_ERROR;break;}
if(set_nodeaddr(combuf_length,&combuf_para)) {serialmsg=SERIAL_EXE_ERROR;break;}//设置站点地址站名
break;
case CMD_QUERY_CHANNEL://范例
combuf_length = 8;//设定信息长度
ptr = BASE_ADDRESS+1;
for (i=0;i<8;i++)
{
combuf[4+i] = *ptr;
ptr++;
ptr++;
}
break;
default:
serialmsg = SERIAL_CMD_ERROR;
break;
}//end of switch 返回数据准备完成,已经存入combuf
}//end of bytecrc 校验正确
if(serialmsg) //以下处理返回的数据从串行口发送出去
{
if((serialmsg>0x80)||(serialmsg<0x10))
{
reply_cmd_message(); //通过串行口返回命令处理正确或错误信息
}else
{
reply_query_para(); //通过串行口返回查询命令信息
}
}//end of serialmsg
}//end of comrxdread
}
void reply_cmd_message(void) //返回命令处理正确或错误信息
{
uchar temp;
send_char(HEADER_FLAG);
send_char(combuf_addr);
send_char(serialmsg);
send_char(0); //length
temp = HEADER_FLAG ^ combuf_addr ^ serialmsg;
send_char(temp);
send_char(END_FLAG);
}
void reply_query_para(void) //返回查询参数
{
uchar i;
uchar temp;
combuf_cmd = serialmsg;
temp = 0;
for(i=0;i<combuf_length+4;i++)
{
temp ^= combuf[i];
send_char(combuf[i]);
}
send_char(temp);
send_char(END_FLAG);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -