?? 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 + -