單片機串口發送接收程序,下面是關于GPS_CHECKTIAMER,局部應用程序
#define UART_R_LEN 60
#define UART_T_LEN 34
uchar idata trdata[UART_T_LEN]; //定義串口發送緩沖區
uchar idata gpsdata[UART_R_LEN]; //定義GPS數據串口接收緩沖區
uchar *inlast_t = trdata; //最后放進發送緩沖區的
uchar *outlast_t = trdata; //最后從發送緩沖區出去的
uchar *inlast_r = gpsdata; //最后進入接收緩沖區的
uchar *outlast_r = gpsdata; //最后從接收緩沖區取走的
bit t_empty,t_full,r_empty,r_full; //緩沖區的狀態標志位
bit new_time,t_finish; //接收完標志和發送完標志
void serail(void) interrupt 4
{
if(TI) //如果發送中斷置位
{
TI = 0;
if(!t_empty) //如果發送緩沖區數據沒有發完
{
SBUF = *outlast_t; //最后從發送緩沖區出去的字符送SBUF
outlast_t++; //最后發送字符指針地址增1
t_full = 0; //發送區狀態為未滿
if(outlast_t >= (trdata + UART_T_LEN)) //如果最后發送字符的地址超出
outlast_t = trdata; //地址到頂部回到底部
if(outlast_t == inlast_t) //如果最后發送字符的地址為最后進入發送的字符地址
t_empty = 1;
}
else t_finish = 1;
}
if(RI) //如果接收中斷置位
{
RI = 0;
if(~r_full) //如果接收緩沖區未滿
{
*inlast_r = SBUF; //最后進入接收緩沖區的字符送SBUF
inlast_r++; //最后進入接收緩沖區的字符地址增1
r_empty = 0; //接收緩沖區為非空
if(inlast_r >= (gpsdata + UART_R_LEN)) //如果最后接收字符的地址超出
inlast_r = gpsdata; //地址到頂部回到底部
if(inlast_r == outlast_r) //如果最后接收字符的地址等于最后從接收區取走的字符地址
r_full = 1; //則接收區滿
}
}
}
void loadmsg(uchar *msg, int num) //把字符串放入發送緩沖區準備發送
{
int i;
for(i=0; i< num; i++)
{
*inlast_t = *msg; //字符裝入最后進入發送發送緩沖區的內容
msg++; //字符串和緩沖地址同時增1
inlast_t++;
t_empty = 0; //未發送完
if(inlast_t >= (trdata+UART_T_LEN))
inlast_t = trdata; //地址到頂部回到底部
if(inlast_t == outlast_t)
t_full = 1; //發送緩沖區滿
}
if(t_finish)
{
TI = 1;
t_finish = 0;
}
}
uchar getbyte_r(void) //從接收緩沖區取一個字節
{
uchar c;
while(r_empty); //當接收緩沖區等待接收
ES = 0; //禁止串行中斷
c = *outlast_r; //最后從接收緩沖區取走的數據賦值給C
r_full = 0; //接收未滿
outlast_r++; //最后由接收緩沖區取走的數據地址增1
if(outlast_r >= (gpsdata + UART_R_LEN)) //如果地址超出
outlast_r = gpsdata; //地址回原處
if(outlast_r == inlast_r) //如果最后接收字符的地址等于最后從接收區取走的字符地址
r_empty = 1; //接收緩沖區為空
ES = 1; //恢復串行中斷
return c;
}
uchar r_state = 0;
uchar r_byte = 0;
uchar gps_chksum= 0;
void r_string(void) // 接收字符串
{
uint *ptr;
uchar temp;
uchar tp[7]; //定義時標接收區,所存儲的時標數據為接收緩沖區未作轉換的時標,用來作全局時標的中轉存儲
while(!r_empty && !new_time) //若接收緩沖區非空,且接收未完成
{
temp = getbyte_r(); //每次while循環依次取入一個字節的接收數據
switch(r_state) //如果依次取入的數據符合表頭“@@Hb”,r_state位置4,進入取時標及GPS狀態字節
{
case 0:
if(temp == 0x40) //@
r_state = 1;
break;
case 1:
if(temp == 0x40) //@
{
r_state = 2;
gps_chksum = 0;
}
else r_state = 0;
break;
case 2:
if(temp == 0x48) //H
{
r_state = 3;
gps_chksum = gps_chksum^temp;
}
else r_state = 0;
break;
case 3:
if(temp == 0x62) //b
{
r_state = 4;
r_byte = 0;
gps_chksum = gps_chksum^temp;
}
else r_state = 0;
break;
case 4:
if(r_byte == 47)
{ if(gps_chksum == temp) //在完成有用數據采集后,經過數據轉換,將標準字符存入全局時標緩沖中
{
ptr = (uint*)(tp+2);
//經轉換數據送時標緩沖區
gps_dt[0] = (*ptr)%100; //年
gps_dt[1] = tp[0]; //月
gps_dt[2] = tp[1]; //日
gps_dt[3] = tp[4]; //時
gps_dt[4] = tp[5]; //分
gps_dt[5] = tp[6]; //秒
new_time = 1;
}
r_state = 0; //用于判斷的數據歸零,以便下一次取數據
}
else
{
gps_chksum = gps_chksum^temp;
if(r_byte <7)
tp[r_byte] = temp;
else if(r_byte == 38)
gps_state = temp;
r_byte++;
}
break;
default:
break;
}
}
}