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