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

📄 serialdemo.c

📁 用串口连接GSM手机发送和接收短消息
💻 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 + -