stc12c5a60s2是一個雙串口的單片機,一個串口連接433模塊,一個串口連接gprs模塊。從而做成一個將本地433通信通過gprs轉發(fā)到網絡的網關。
代碼送上:
/*本程序經過測試完全正常, 不提供電話技術支持, 如不能理解, 請自行補充相關基礎. */
/************* 本程序功能說明 **************
測試方法:
根據您的主時鐘和波特率修改"用戶定義參數"里的相關定義,編譯后下載到MCU。
通過串口助手向MCU發(fā)送數據,MCU收到后原樣返回。
*/
/*************** 用戶定義參數 *****************************/
#define MAIN_Fosc 22118400L //define main clock
#define Baudrate1 9600 //define the baudrate, 如果使用BRT做波特率發(fā)生器,則波特率跟串口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發(fā)送回車換行
#define UART1_SendLR() UART1_SendData(0X0D);\
UART1_SendData(0X0A)
//串口2發(fā)送回車換行
#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; //發(fā)送心跳幀標志位
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使用獨立波特率發(fā)生器, 波特率跟串口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(); //接收服務器下發(fā)的數據,并處理
// uart2_reciveEnd=0;
//}
if(Heart_beat&&Message_beat) //發(fā)送心跳幀
{
Send_OK();
Heart_beat=0;
}
if(Sound_beat)
{
Sound_beat=0;
sound=1;//無論如何結束求救警報
}
/**if(uart1_rd != uart1_wr) //串口0轉發(fā)
{
UART1_SendData(RX1_Buffer[uart1_rd]);
if(++uart1_rd >= BUF_LENTH) uart1_rd = 0;
}
if(uart2_rd != uart2_wr) //串口2轉發(fā)
{
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) //發(fā)送一串字符串
{
//for (; *puts != 0x00; puts++) UART1_SendData(*puts); //遇到停止符0結束
while(*puts)//檢測字符串結束符
{
UART1_SendData(*puts++);//發(fā)送當前字符
}
}
void UART2_SendString(unsigned char *puts) //發(fā)送一串字符串
{
//for (; *puts != 0x00; puts++) UART2_SendData(*puts); //遇到停止符0結束
while(*puts)//檢測字符串結束符
{
UART2_SendData(*puts++);//發(fā)送當前字符
}
}
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秒發(fā)送心跳幀
{
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
* 描述 : 發(fā)送AT指令函數
* 輸入 : 發(fā)送數據的指針、發(fā)送等待時間(單位: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上下文,互聯網接協(xié)議,接入點等信息
Second_AT_Command("AT+CGATT=1","OK",2);//附著GPRS業(yè)務
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轉發(fā)
{
//如果消息長度小于15收了;
if(strlen(RX2_Buffer)<=20){
Message_beat=0;//發(fā)送消息狀態(tài),此時停止發(fā)送心跳包
//
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();
}
}
//直接發(fā)送消息包就好
/**
char *mymsg = RX2_Buffer;
Message_beat=0;//發(fā)送消息狀態(tài),此時停止發(fā)送心跳包
SendMsgNum(mymsg);
CLR_Buf2();
Message_beat=1;
Heart_beat=0;
**/
}
/*******************************************************************************
* 函數名 : Send_OK
* 描述 : 發(fā)送數據應答服務器的指令,該函數在有兩功能
1:接收到服務器的數據后,應答服務器
2:服務器無下發(fā)數據時,每隔10秒發(fā)送一幀心跳,保持與服務器連接
* 輸入 :
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
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);
}
|