找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

基于12单片机通过双串口查询电表电量的问题,麻烦大家帮我看一下,感激不尽(DLT64...

查看数: 6869 | 评论数: 12 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2017-6-9 13:26

正文摘要:

   STC12系列单片机拥有双串口,所以我用串口一与电表通信,串口二与电脑通信,以单片机为枢纽,把串口一收到到数据再从串口二发送给电脑,同样电脑端发送查询数据,hex模式,通过串口二传递给串口一再发 ...

回复

ID:290231 发表于 2018-5-1 14:21
老哥,你解决了吗,我也碰到同样的问题,能讲下吗
ID:209219 发表于 2017-6-12 09:34
dzbj 发表于 2017-6-10 19:50
大致扫了一下你的程序 我觉得没什么问题 有个建议是  s1_send_char(uart_2[a]); 这种函数尽量不放在中断 ...

总之还是要谢谢您能在工作之余还能帮我分析问题,真的非常感谢,一个人的思路毕竟是有局限的,谢谢前辈的帮助,有机会再一起讨论
ID:209219 发表于 2017-6-12 09:31
dzbj 发表于 2017-6-10 19:50
大致扫了一下你的程序 我觉得没什么问题 有个建议是  s1_send_char(uart_2[a]); 这种函数尽量不放在中断 ...

通信规约上没应答之类,此类通讯应该是半双工通信,数据的发送和接收都有起始符,结束符,和校验码,我在发送和接收中加了判断起止结束位和校验码,奇偶校验位(以前没加,因为校验码都计算好了没有问题,所以本不想判断了),对比和参考了一下前人写的液晶显示的51与电表通信。最后通信成功,将返回数据处理后与电表电量一致。但问题真正原因还是没找到,不加判断起始结束就没法接收吗(例如,判断起始位68H,如果不判断是不是68H,来的数据我都接收也应该可以啊,又不是应答之类的),我觉得问题不是出在这里。
ID:47286 发表于 2017-6-10 19:50
宁采尘 发表于 2017-6-10 11:24
串口一接收不到反馈信息,我现在也不确定是电表没接收到数据,还是我的接收数据程序有问题。我可以确定的 ...

大致扫了一下你的程序 我觉得没什么问题 有个建议是  s1_send_char(uart_2[a]); 这种函数尽量不放在中断里 你这里这么用没问题 但是冲断的优先级都高于正常程序 以后写别的有可能有影响 养成个好习惯

你这段程序的意思是把串口2收到的东西用串口1转发出来是么 如果是 先不进行这个 还是我之前说的 你直接把上位机并在单片机和模块之间的通讯上 看它们之间聊的怎么样

昨天看你说那个协议的时候 也是匆匆一扫 它好象有什么对位或者应答之类的要求 你这程序里有么
ID:209219 发表于 2017-6-10 11:24
dzbj 发表于 2017-6-9 21:13
我大概看了一下你说的DLT645-1997 这是个通讯协议 从你说的情况感觉不是单片机串口的问题 是和DLT645-199 ...

串口一接收不到反馈信息,我现在也不确定是电表没接收到数据,还是我的接收数据程序有问题。我可以确定的是我再电脑端的串口助手能收到我发送的查询数据。而且这串查询数据我用抄表软件发送时没问题的,唯独放到我程序里没有回应。您看一下我的发送和接收有问题吗?
//发送函数,在主函数中,截取相关部分
         while(1)
        {
                  if(k==0)        //按键按下一次发送一次查询命令
                  {
                          delay(20);
                          if(k==0)
                          {
                                  flag=0;
                          }
                  }
                  if(flag==0)
                  {
                   for(m=0;m<15;m++)
                   {
                   s1_send_char(uart[m]);                 
                   }
                   flag=1;
                  }
       //           uchar code uart[]={0xFE,0x68,0x74,0x27,0x12,0x00,
       //          0x80,0x13,0x68,0x01,0x02,0x43,0xC3,0x19,0x16};
                                   //读正向有功总电能命令帧
     }

//接收函数,截取相关部分,已将串口1并连电脑和电表。
/*串口一发送程序*/
void s1_send_char(uchar dat)//?发送端(发送的是字符)
{
        SBUF=dat;       
        while(!TI);         
        TI=0;          //清零标志
}
void UART1() interrupt 4  //串口1中断函数          
{                                                                                                                                                          
    if(RI==1)
        {       
                uart_2[a]=SBUF;
                s1_send_char(uart_2[a]);
                a++;
                RI=0;
                if(a>14)
                {
                        a=0;
                //        flag=1;
                }
        }
}                        
ID:47286 发表于 2017-6-9 21:13
宁采尘 发表于 2017-6-9 17:22
我串口一波特率发生器用的T1,串口二用的独立的波特率发生器。因为DLT645-1997通信规约要求,与电表通信 ...

我大概看了一下你说的DLT645-1997 这是个通讯协议 从你说的情况感觉不是单片机串口的问题 是和DLT645-1997通讯没成功 你可以这样 先不用串口2 直接把上位机并联到串口1上 相当于三机互连 然后看单片机发送给电表和电表反馈的数据是什么 根据反馈修改程序 直到调通它们后 再考虑串口2转发的问题
ID:209219 发表于 2017-6-9 17:22
dzbj 发表于 2017-6-9 14:22
另 附上我用的串口1和2初始化 基本上是用STC-ISP生成的 你对比一下看看 也许有帮助

void Init_UART1();         ...

我串口一波特率发生器用的T1,串口二用的独立的波特率发生器。因为DLT645-1997通信规约要求,与电表通信波特率为1200bps,为方便,我两个都设了1200bps。发送数据,模块RXD指示灯会亮,但是TXD指示灯一直都不会亮,应该是通讯没有成功。我没有设奇偶校验,单纯的发送查询命令帧后等待串口一接收中断,好像一直没有触发。您有时间再帮我在看看吧,我也尝试其他方法。方便加QQ交流吗875576671
ID:209219 发表于 2017-6-9 17:02
lshhjx 发表于 2017-6-9 14:37
首先问一下楼主,你串口一能够正常和电表通讯吗?

串口一能正常通讯我确定,但是和电表通讯没有成功,我每次发送数据,模块的发送指示灯都会亮,但是接收指示灯一直没有亮,应该是通讯没有成功。
ID:59827 发表于 2017-6-9 14:37
首先问一下楼主,你串口一能够正常和电表通讯吗?
ID:47286 发表于 2017-6-9 14:22
另 附上我用的串口1和2初始化 基本上是用STC-ISP生成的 你对比一下看看 也许有帮助

void Init_UART1();                                                                //串口初始化 1T/定时器1作波特率发生器

void Init_UART1()        //串口初始化 1T/定时器1作波特率发生器
{
        PCON |= 0x80;                        //使能波特率倍速位SMOD
        SCON = 0x50;                        //8位数据,可变波特率
        AUXR |= 0x40;                        //定时器1时钟为Fosc,即1T
        AUXR &= 0xFE;                        //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                        //清除定时器1模式位
//        TMOD |= 0x21;                        //设定定时器1为8位自动重装方式
        TMOD |= 0x20;                        //设定定时器1为8位自动重装方式
        TL1=TH1=BAUD1;                        //设定定时初值
        ET1 = 0;                                //禁止定时器1中断
        TR1 = 1;                                //启动定时器1
        ES=1;                                        //开串口中断
}

void Init_UART2();                //串口2初始化 1T/独立波特率发生器(串口2只能使用独立波特率发生器)

void Init_Uart2()                //串口2初始化 115200bps@11.0592MHz@独立波特率发生器
{
       
        AUXR |= 0x08;                //使能波特率倍速位S2SMOD 0000 1000
        S2CON = 0x50;                //8位数据,可变波特率 0101 0000
        AUXR |= 0x04;                //独立波特率发生器时钟为Fosc,即1T 0000 0100
        BRT = BAUD2;                //设定独立波特率发生器重装值
        AUXR |= 0x10;                //启动独立波特率发生器 0001 0000
        IE2=0X01;                        //允许串口2中断
}
ID:209219 发表于 2017-6-9 14:14
请大家帮帮分析分析
ID:47286 发表于 2017-6-9 14:13
上班呢 程序没看 你说的应用我用过 没有任何问题 你坚信一定会成功吧

我用12c5a做显示屏 屏幕是串口屏 用uart2和屏通讯 uart1+485和其它模块通讯 和你的应用差不多

1. uart2可以用计时器做波特率发生器也可以用独立波特率发生器 如果用两个串口 尽量各自用一个波特率发生器 我是因为两个串口速率不一样 其它模块是57600 屏是115200

2. 485完全无需转其它方式 直接ttl到485就没问题 这个我用过很多很多很多 但485片子不同厂家有时候会出各种莫名其妙的不通讯问题 要注意485的电源滤波电容大小 按你买品牌的手册要求高 我遇到过要求1.5uf的我用0.1uf就不行

3. uart1和2的转发 你直接在内存开个缓冲区 如果第一位不是0或者ff或者你定义的什么东西 就直接发 实验的时候 你可以不断的用串口1往上位机发缓冲区内容 观察串口2是否正常工作了 这样有利于找到问题 我就是写了个双向直接转发的程序 连串口屏自动联机都可以

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表