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);
}
|