找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2853|回复: 2
打印 上一主题 下一主题
收起左侧

stc12单片机+gprs+433网关开发程序

[复制链接]
跳转到指定楼层
楼主
ID:359588 发表于 2020-1-31 22:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
stc12c5a60s2是一个双串口的单片机,一个串口连接433模块,一个串口连接gprs模块。从而做成一个将本地433通信通过gprs转发到网络的网关。
代码送上:


/*本程序经过测试完全正常, 不提供电话技术支持, 如不能理解, 请自行补充相关基础. */


/*************        本程序功能说明        **************

        测试方法:

        根据您的主时钟和波特率修改"用户定义参数"里的相关定义,编译后下载到MCU。

        通过串口助手向MCU发送数据,MCU收到后原样返回。
*/


/*************** 用户定义参数 *****************************/

#define MAIN_Fosc                22118400L        //define main clock

#define Baudrate1                9600                //define the baudrate, 如果使用BRT做波特率发生器,则波特率跟串口2一样
                                                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ

#define Baudrate2                19200                //define the baudrate2,
                                                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ

#define                BUF_LENTH        64                //定义串口接收缓冲长度

/**********************************************************/

#include        <reg51.h>
#include    <string.h>

//   unsigned char  u8;
//   unsigned int   u16;
//   unsigned long  u32;

sfr AUXR1 = 0xA2;
sfr        AUXR = 0x8E;
sfr S2CON = 0x9A;        //12C5A60S2双串口系列
sfr S2BUF = 0x9B;        //12C5A60S2双串口系列
sfr IE2   = 0xAF;        //STC12C5A60S2系列
sfr BRT   = 0x9C;

unsigned char         uart1_wr;                //写指针
unsigned char         uart1_rd;                //读指针
unsigned char         xdata RX1_Buffer[BUF_LENTH];
bit                B_TI;

unsigned char         uart2_wr;                //写指针
unsigned char         uart2_rd;                //读指针
unsigned char         xdata RX2_Buffer[BUF_LENTH];
unsigned char         xdata RX2_Buffer_Temp[BUF_LENTH];
bit                B_TI2;


/****************** 编译器自动生成,用户请勿修改 ************************************/

#define T1_TimerReload        (256 - MAIN_Fosc / 192 / Baudrate1)                        //Calculate the timer1 reload value        at 12T mode
#define BRT_Reload                (256 - MAIN_Fosc / 12 / 16 / Baudrate2)                //Calculate BRT reload value

#define        TimeOut1                (28800 / (unsigned long)Baudrate1 + 2)
#define        TimeOut2                (28800 / (unsigned long)Baudrate2 + 2)

#define        TI2                                (S2CON & 0x02) != 0
#define        RI2                                (S2CON & 0x01) != 0
#define        CLR_TI2()                S2CON &= ~0x02
#define        CLR_RI2()                S2CON &= ~0x01



/**********************************************************/
//串口1发送回车换行
#define UART1_SendLR() UART1_SendData(0X0D);\
                                                                                         UART1_SendData(0X0A)
//串口2发送回车换行
#define UART2_SendLR() UART2_SendData(0X0D);\
                                                                                         UART2_SendData(0X0A)

/*************        本地常量声明        **************/

const unsigned char *string = "AT+CIPSTART=\"TCP\",\"xxx\",19";        //IP登录服务器
//const unsigned char *string = "AT+CIPSTART=\"TCP\",\"xxx\",19";        //IP登录服务器

unsigned char Times=0,shijian=0;
unsigned int Heartbeat=0;
//u8 Time_count=0;
unsigned char count_20ms;
bdata unsigned char Flag;//定时器标志位
sbit Timer0_start =Flag^0;        //定时器0延时启动计数器
sbit Heart_beat          =Flag^1;        //发送心跳帧标志位
int Message_beat =1;
int Sound_beat=0;
int Sound_num=0;

//int uart2_reciveStart=0;//接收开始uart_startRecive
//int uart2_reciveEnd=0;//433接收完毕0、1
int mylength=0;
int failCount=0;//心跳包失败次数

sbit sound=P1^0;

/******************** 本地函数声明 ***************/
void        uart1_init(void);
void        uart2_init(void);
void        UART1_SendData(unsigned char dat);
void        UART2_SendData(unsigned char dat);
void        UART1_SendString(unsigned char code *puts);
void        UART2_SendString(unsigned char  *puts);
/*************        本地函数声明2        **************/
void Timer0Init(void);
void CLR_Buf1(void);
void CLR_Buf2(void);
void CLR_Buf2_TEMP(void);
unsigned char Find(unsigned char *a);
void Second_AT_Command(unsigned char *b,unsigned char *a,unsigned char wait_time);
void Second_AT_Command_2(unsigned char *b,unsigned char *a,unsigned char wait_time);
void Set_ATE0(void);
void Connect_Server(void);
void Rec_Server_Data(void);
void Wait_CREG(void);
void Send_OK(void);
void SendMsgNum(unsigned char *k);
void delay_ms(unsigned char ms);



void        main(void)
{
        Timer0Init();
        uart1_rd = 0;
        uart1_wr = 0;
        uart2_rd = 0;
        uart2_wr = 0;
        //uart2_reciveStart=0;
        //uart2_reciveEnd=0;

        AUXR |=  0x01;                //串口1使用独立波特率发生器, 波特率跟串口2一样
        AUXR1 |= (1<<4);        //将UART2从P1口切换到 RXD2--P1.2切换到P4.2   TXD2---P1.3切换到P4.3
        
        uart1_init();
        uart2_init();
        
        
        Wait_CREG();    //查询等待模块注册成功
        Set_ATE0();     //取消回显
        Connect_Server();//配置GPRS服务
        CLR_Buf1();
        CLR_Buf2();
        CLR_Buf2_TEMP();
        //UART2_SendString("start server");
        while(1)
        {
                 //if(uart2_reciveEnd==1){
                         Rec_Server_Data(); //接收服务器下发的数据,并处理
                //        uart2_reciveEnd=0;
                 //}
                 
                 if(Heart_beat&&Message_beat)     //发送心跳帧
                 {
                        Send_OK();
                        Heart_beat=0;
                        
                 }
                 if(Sound_beat)
                 {
                        Sound_beat=0;
                        sound=1;//无论如何结束求救警报
                 }
                /**if(uart1_rd != uart1_wr)        //串口0转发
                {
                        UART1_SendData(RX1_Buffer[uart1_rd]);
                        if(++uart1_rd >= BUF_LENTH)                uart1_rd = 0;
                }

                if(uart2_rd != uart2_wr)        //串口2转发
                {
                        UART2_SendData(RX2_Buffer[uart2_rd]);
                        if(++uart2_rd >= BUF_LENTH)                uart2_rd = 0;
                }**/
        }
}

void        UART1_SendData(unsigned char dat)
{
        
        B_TI = 0;
        SBUF = dat;
        while(!B_TI);
        B_TI = 0;
        
}

void        UART2_SendData(unsigned char dat)
{
    IE2=0;
        B_TI2 = 0;
        S2BUF = dat;
        while(!B_TI2);
        B_TI2 = 0;
        IE2=1;
}

void UART1_SendString(unsigned char code *puts)                //发送一串字符串
{
    //for (; *puts != 0x00;        puts++)  UART1_SendData(*puts);         //遇到停止符0结束
        while(*puts)//检测字符串结束符
        {
                UART1_SendData(*puts++);//发送当前字符
        }
}

void UART2_SendString(unsigned char  *puts)                //发送一串字符串
{
    //for (; *puts != 0x00;        puts++)  UART2_SendData(*puts);         //遇到停止符0结束
        while(*puts)//检测字符串结束符
        {
                UART2_SendData(*puts++);//发送当前字符
        }
}



void        uart1_init(void)
{
        PCON |= 0x80;                //UART0 Double Rate Enable
        SCON = 0x50;                //UART0 set as 10bit , UART0 RX enable
        TMOD &= ~(1<<6);                //Timer1 Set as Timer, 12T
        TMOD = (TMOD & ~0x30) | 0x20;        //Timer1 set as 8 bits auto relaod
        TH1 = T1_TimerReload;                //Load the timer
        TR1  = 1;
        ES  = 1;
        EA = 1;
}



/**********************************************/
void UART0_RCV (void) interrupt 4
{
        if(RI)
        {
                RI = 0;
                RX1_Buffer[uart1_wr] = SBUF;
                if(++uart1_wr >= BUF_LENTH)        uart1_wr = 0;
        }

        if(TI)
        {
                TI = 0;
                B_TI = 1;
        }
}


/**********************************************/
void        uart2_init(void)
{
        AUXR |=  (1 << 3);                //串口2波特率加倍
        S2CON  = (S2CON & 0x3f) | (1<<6);        //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率
        S2CON |= 1 << 4;                //允许串2接收

        AUXR |=  1 << 4;        //baudrate use BRT
        BRT = BRT_Reload;

        IE2 |=  1;                        //允许串口2中断
}

/**********************************************/
void UART2_RCV (void) interrupt 8
{
        if(RI2)
        {        
                char mymsg = S2BUF;
                CLR_RI2();
                RX2_Buffer[uart2_wr] = mymsg;
                if(++uart2_wr >= BUF_LENTH)        uart2_wr = 0;
        }

        if(TI2)
        {
                CLR_TI2();
                B_TI2 = 1;
        }
}

/*******************************************************************************
* 函数名 : Timer0_ISR
* 描述   : 定时器0中断服务入口函数,20ms中断一次
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Timer0_ISR() interrupt 1
{
        static unsigned char Time_count=0;
        TR0=0;//关定时器
        TL0 = 0x00;                //重设定时器初值
        TH0 = 0xB8;                //重设定时器初值
        Time_count++;
        if(Time_count>=50)//1秒运行指示灯闪烁
        {
                Time_count = 0;
                //RUNING_LED =~RUNING_LED;
        }
        if(count_20ms) //20ms延时计数器
                count_20ms--;
        Heartbeat++;
        if(Heartbeat>500)//每10秒发送心跳帧
        {
                Heartbeat=0;
                Heart_beat=1;
        }
        Sound_num++;
        if(Sound_num>1000)
        {
           Sound_num=0;
           Sound_beat=1;
        }
        if(Timer0_start)
        Times++;
        if(Times > (50*shijian))
        {
                Timer0_start = 0;
                Times = 0;
        }
        TR0=1;//开定时器
}
/*******************************************************************************
* 函数名 : Timer0Init
* 描述   : 定时器0初始化,20ms定时
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Timer0Init(void)                //20毫秒@11.0592MHz
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //
        TMOD |= 0x01;                //设置定时器模式,16位定时器
        TL0 = 0x00;                  //设置定时器初值
        TH0 = 0xB8;                  //设置定时器初值
        TF0 = 0;                    //清TF0标志
        TR0 = 1;                    //定时器0开始计时
        ET0 = 1;              //使能定时器0中断
}

/*******************************************************************************
* 函数名 : Wait_CREG
* 描述   : 等待模块注册成功
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Wait_CREG(void)
{
        unsigned char i;
        unsigned char k;
        i = 0;
        CLR_Buf1();
    while(i == 0)                                
        {
                CLR_Buf1();        
                UART1_SendString("AT+CREG?");
                UART1_SendLR();
                delay_ms(250);                                                  
            for(k=0;k<BUF_LENTH;k++)                              
            {
                        if(RX1_Buffer[k] == ':')
                        {
                                if((RX1_Buffer[k+4] == '1')||(RX1_Buffer[k+4] == '5'))
                                {
                                        i = 1;
                                    break;
                                }
                        }
                }
        }
}

/*******************************************************************************
* 函数名 : Find
* 描述   : 判断缓存中是否含有指定的字符串
* 输入   :
* 输出   :
* 返回   : unsigned char:1 找到指定字符,0 未找到指定字符
* 注意   :
*******************************************************************************/

unsigned char Find(unsigned char *a)
{
  if(strstr(RX1_Buffer,a)!=NULL)
            return 1;
        else
                        return 0;
}

/*******************************************************************************
* 函数名 : Second_AT_Command
* 描述   : 发送AT指令函数
* 输入   : 发送数据的指针、发送等待时间(单位:S)
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/

void Second_AT_Command(unsigned char *b,unsigned char *a,unsigned char wait_time)         
{
        unsigned char i;
        unsigned char *c;
        c = b;                                                                                //保存字符串地址到c
        CLR_Buf1();
    i = 0;
        while(i == 0)                    
        {
                if(!Find(a))
                {
                        
                        if(Timer0_start == 0)
                        {
                                b = c;                                                        //将字符串地址给b
                                for (b; *b!='\0';b++)
                                {
                                        UART1_SendData(*b);
                                }
                                UART1_SendLR();        
                                Times = 0;
                                shijian = wait_time;
                                Timer0_start = 1;
                   }

      }
           else
          {
                        i = 1;
                        Timer0_start = 0;
                        
          }
        }
        CLR_Buf1();
}

void Second_AT_Command_2(unsigned char *b,unsigned char *a,unsigned char wait_time)         
{
        unsigned char i;
        unsigned char *c;
        failCount=0;
        c = b;                                                                                //保存字符串地址到c
        CLR_Buf1();
    i = 0;
        while(i == 0)                    
        {
                if(!Find(a))
                {
                        if(Timer0_start == 0&&failCount<10)
                        {
                                b = c;                                                        //将字符串地址给b
                                for (b; *b!='\0';b++)
                                {
                                        UART1_SendData(*b);
                                }
                                UART1_SendLR();        
                                Times = 0;
                                shijian = wait_time;
                                Timer0_start = 1;
                                failCount++;
                   }
                   else if(Timer0_start == 0&&failCount>=10)
                   {
                                Connect_Server();//断线重连
                                CLR_Buf1();
                                CLR_Buf2();
                                CLR_Buf2_TEMP();

                                Times = 0;
                                shijian = wait_time;
                                Timer0_start = 1;
                                failCount=0;
                                i=1;

                                Second_AT_Command_2("AT+CIPSEND",">",2);
                   }
                        
      }
           else
                {
                        i = 1;
                        Timer0_start = 0;
                        failCount=0;
                }
        }
        CLR_Buf1();
}
/*******************************************************************************
* 函数名 : Set_ATE0
* 描述   : 取消回显
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Set_ATE0(void)
{
        Second_AT_Command("ATE0","OK",3);                                                                //取消回显               
}
/*******************************************************************************
* 函数名 : Connect_Server
* 描述   : GPRS连接服务器函数
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Connect_Server(void)
{
        UART1_SendString("AT+CIPCLOSE=1");        //关闭连接
        delay_ms(5);
        Second_AT_Command("AT+CIPSHUT","SHUT OK",2);                //关闭移动场景
        Second_AT_Command("AT+CGCLASS=\"B\"","OK",2);//设置GPRS移动台类别为B,支持包交换和数据交换
        Second_AT_Command("AT+CGDCONT=1,\"IP\",\"CMNET\"","OK",2);//设置PDP上下文,互联网接协议,接入点等信息
        Second_AT_Command("AT+CGATT=1","OK",2);//附着GPRS业务
        Second_AT_Command("AT+CIPCSGP=1,\"CMNET\"","OK",2);//设置为GPRS连接模式
        Second_AT_Command("AT+CIPHEAD=1","OK",2);//设置接收数据显示IP头(方便判断数据来源,仅在单路连接有效)
        Second_AT_Command(string,"OK",5);        
        delay_ms(5);
        CLR_Buf1();
}
/*******************************************************************************
* 函数名 : Rec_Server_Data
* 描述   : 接收服务器数据函数
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Rec_Server_Data(void)
{

        if(strstr(RX2_Buffer,"sos")){
           sound=0;                //开启警报
           Sound_num=0;
        }
        if(strstr(RX2_Buffer,"#")&&strstr(RX2_Buffer,"$")&&strstr(RX2_Buffer,"aw"))        //串口2转发
        {
               
                //如果消息长度小于15收了;
                if(strlen(RX2_Buffer)<=20){
                        Message_beat=0;//发送消息状态,此时停止发送心跳包
                        //
                         while(uart2_rd < BUF_LENTH){
                                //UART1_TxByte(RX2_Buffer[uart2_rd]);
                                RX2_Buffer_Temp[uart2_rd] = RX2_Buffer[uart2_rd];
                                if(RX2_Buffer[uart2_rd]=="$")         break;
                                uart2_rd++;
                        }
                        
                        //uart2_rd=0;
                        //while(uart2_rd < BUF_LENTH){
                        //        UART1_SendData(RX2_Buffer_Temp[uart2_rd]);
                        //        uart2_rd++;
                        //}
                        uart2_rd = 0;
                        uart2_wr = 0 ;
                        SendMsgNum(RX2_Buffer_Temp);
                        CLR_Buf2();
                        //
                        Message_beat=1;
                        Heart_beat=0;
                        Heartbeat=0;
                }else{
                        //丢弃
                        uart2_rd = 0;
                        uart2_wr = 0 ;
                        CLR_Buf2();
                }

                        
        }        
        
        //直接发送消息包就好
        /**
        char *mymsg = RX2_Buffer;
        Message_beat=0;//发送消息状态,此时停止发送心跳包
        SendMsgNum(mymsg);
        CLR_Buf2();
        Message_beat=1;
        Heart_beat=0;
    **/   

}
/*******************************************************************************
* 函数名 : Send_OK
* 描述   : 发送数据应答服务器的指令,该函数在有两功能
                                        1:接收到服务器的数据后,应答服务器
                                        2:服务器无下发数据时,每隔10秒发送一帧心跳,保持与服务器连接
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void Send_OK(void)
{
        Second_AT_Command_2("AT+CIPSEND",">",2);
        Second_AT_Command_2("A2\n\32\0","SEND OK",8);                        //回复OK
        delay_ms(10);
        CLR_Buf1();
}
void SendMsgNum(unsigned char *k)
{
        unsigned char str[40];
    strcpy (str,k);
    strcat (str,"\n\32\0");
        Second_AT_Command_2("AT+CIPSEND",">",2);
        Second_AT_Command_2(str,"SEND OK",8);
    //Second_AT_Command_2(str,"SEND OK",8);
        delay_ms(10);
        CLR_Buf1();
}

/*******************************************************************************
* 函数名 : CLR_Buf1
* 描述   : 清除串口1缓存数据
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void CLR_Buf1(void)
{
        unsigned int k;
        for(k=0;k<BUF_LENTH;k++)      //将缓存内容清零
        {
                RX1_Buffer[k] = 0x00;
        }
    uart1_wr = 0;             //接收字符串的起始存储位置
}
/*******************************************************************************
* 函数名 : CLR_Buf2
* 描述   : 清除串口2缓存数据
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void CLR_Buf2(void)
{
        unsigned int k;
        for(k=0;k<BUF_LENTH;k++)      //将缓存内容清零
        {
                RX2_Buffer[k] = 0x00;
        }
    uart2_wr = 0;             //接收字符串的起始存储位置
}
/*******************************************************************************
* 函数名 : CLR_Buf2_TEMO
* 描述   : 清除串口2缓存数据
* 输入   :
* 输出   :
* 返回   :
* 注意   :
*******************************************************************************/
void CLR_Buf2_TEMP(void)
{
        unsigned int k;
        for(k=0;k<BUF_LENTH;k++)      //将缓存内容清零
        {
                RX2_Buffer_Temp[k] = 0x00;
        }
}
//========================================================================
// 函数: void  delay_ms
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持20*256ms.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(unsigned char ms)
{
         count_20ms=ms;
         while(count_20ms);
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:328014 发表于 2020-2-1 01:41 | 只看该作者
能分享下原理图吗?
回复

使用道具 举报

板凳
ID:764660 发表于 2022-10-31 09:31 | 只看该作者
能分享下原理图吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表