|
20黑幣
STC12系列單片機擁有雙串口,所以我用串口一與電表通信,串口二與電腦通信,以單片機為樞紐,把串口一收到到數據再從串口二發送給電腦,同樣電腦端發送查詢數據,hex模式,通過串口二傳遞給串口一再發送出去,具體請看我程序。問題就出在這,電腦發送的數據發送出去了,卻沒有收到電表回復的數據。
我單獨測試過串口一二與電腦通信沒有問題,并將兩串口同時接到電腦,在電腦端打開兩個串口助手,也能完成通信。當我把串口一摘下經過TTL轉232模塊、232轉485模塊再接到電表測試時,收不到電表傳回的信息。
一開始我是直接用的TTL轉485與電表通信的,也是沒有成功,在論壇看到有位前輩用TTL轉232再232轉485與電表通信成功了,他是用的51 ,單串口1602顯示的,然后按照他硬件電路試了一下還是沒有成功。我想問題應該是出在我程序上了,麻煩各位前輩幫我看一看有什么問題,通信規約我已經仔細看過了,程序要求不需要太復雜,只要求發送同一條指令(我已存到數組中),能接收到電表返回的數據信息就行,具體數據我再進行處理就好,麻煩大家幫我完成這一步,在下感激不盡,有地方我說的不明白的請再詢問我,我真的被這個程序塊搞壞了。。。
下面是我程序,麻煩大家幫我分析一下。
/*要實現功能:通過單片機兩個串口,串口二連接在電腦端,
串口一連接電表,完成查詢正向有功功率任務。
目前進度: 兩串口均測試可與電腦單獨通訊沒有問題,
把串口一接入電表無法接收到返回信息
*/
#include <stc12c5a60s2.h>
#include "intrins.h"
#include "uart.h"
uchar flag=0,dat,a=0,b=0;
uchar code uart[]={0xFE,0xFE,0xFE,0x68,0x74,0x27,0x12,0x00,
0x80,0x13,0x68,0x01,0x02,0x43,0xC3,0x19,0x16};
//讀正向有功總電能命令幀,電表
uchar data uart_1[36];
uchar data uart_2[36];
#define S2TI 0x02 // 串口2發送中斷請求標志位
#define S2RI 0x01 // 串口2接收中斷請求標志位
sbit REDE=P1^4;
void delay(uint x) // 延時子函數
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void main()
{
uchar m;
UartInit_1(); //初始化串口一 // 為遵循DLT645-1997與電表通信規約
UartInit_2(); //初始化串口二 //兩串口 波特率均設為1200bps
while(1)
{
if(flag=0)
{
for(m=0;m<17;m++) //上電先通過串口一發送讀正向有功總電能命令幀
{ //根據DLT645-1997規約編輯的命令幀,串口波特率1200bps
s1_send_char(uart[m]);
}
flag=1; //標志變為1,等待串口一接收數據后標志再次變為0.
//重復查詢功能暫時不用,先用電腦手動再次發送
}
delay(1000);
}
}
void UartInit_1(void) //1200bps@12MHz
{
TMOD=0x20; //設置定時器1位工作方式2
TH1=0xE8; //方式2為8位自動重裝,
//初值查表可得1200波特率
TL1=0xD0;
TR1=1; //打開定時器1
SM0=0; //設置串口工作方式1,10位固定
SM1=1;
REN=1; //允許串口接收數據
EA=1; //打開總中斷
ES=1; //打開串口中斷
}
void UartInit_2(void) //1200bps@12MHz 0xE8
{
AUXR = 0x10; //波特率不倍速
S2CON = 0x50; //8位數據,可變波特率
BRT = 0xE8; //設定獨立波特率發生器重裝值
IE2 |= 0x01; //充許串口2中斷
//AUXR &= 0xfb; //獨立波特率發生器時鐘為Fosc/12,即12T
//AUXR = 0x10; //啟動獨立波特率發生器
}
/*串口一發送程序*/
void s1_send_char(uchar dat)//發送端(發送的是字符)
{
SBUF=dat;
while(!TI);
TI=0; //清零標志
}
void s1_send_string(uchar *pt) //發送字符串
{
while(*pt != '\0')
{
s1_send_char(*pt++);
}
}
/*串口二發送程序*/
void s2_send_char(uchar dat2) // 發送端(發送的是字符)
{
S2BUF = dat2;
while(!(S2CON&S2TI));
S2CON &= ~S2TI;
}
void s2_send_string(uchar *pt2) //發送字符串
{
while(*pt2!='\0')
{
s2_send_char(*pt2++);
}
}
void UART1() interrupt 4 //串口1中斷函數
{ //串口一收到電表數據,存入uart2,再通過串口二發送到電腦
if(RI==1) //接收數據
{
uart_2[a]=SBUF;
s2_send_char(uart_2[a]); //串口二發送到電腦
a++;
RI=0;
if(a>=17) //接收17位
{
a=0;
// flag=0; //先不讓標志位=0;想要再發送查詢正向有功功率可以在電腦端串口二發送
}
}
// if(RI==1)
// {
// if(a==0&&0x68==SBUF)
// {
// uart_2[0]=SBUF;
// s2_send_char(uart_2[a]);
// }
//
// if(a>0&&uart_2[0]==0x68)
// {
// uart_2[a]=SBUF;
// s2_send_char(uart_2[a]);
//
// }
// a++;
// RI=0;
// }
//
// if(a>=36)
// {
// a=0;
// }
// flag=1;
}
void UART2() interrupt 8 //串口2中斷函數
{ //如果串口二接收到電腦端發送的查詢命令幀數據,
//先存入數組uart1,再通過串口一發送給電表
if(S2CON&S2RI)
{
uart_1[b]=S2BUF;
S2CON&=~S2RI;
}
s1_send_char(uart_1[b]); //讓串口一發送查詢命令幀數據
b++;
if(b>=17)
{
b=0;
}
// flag=1;
}
|
|