老哥,你解决了吗,我也碰到同样的问题,能讲下吗 |
dzbj 发表于 2017-6-10 19:50 总之还是要谢谢您能在工作之余还能帮我分析问题,真的非常感谢,一个人的思路毕竟是有局限的,谢谢前辈的帮助,有机会再一起讨论 ![]() |
dzbj 发表于 2017-6-10 19:50 通信规约上没应答之类,此类通讯应该是半双工通信,数据的发送和接收都有起始符,结束符,和校验码,我在发送和接收中加了判断起止结束位和校验码,奇偶校验位(以前没加,因为校验码都计算好了没有问题,所以本不想判断了),对比和参考了一下前人写的液晶显示的51与电表通信。最后通信成功,将返回数据处理后与电表电量一致。但问题真正原因还是没找到,不加判断起始结束就没法接收吗(例如,判断起始位68H,如果不判断是不是68H,来的数据我都接收也应该可以啊,又不是应答之类的),我觉得问题不是出在这里。 |
宁采尘 发表于 2017-6-10 11:24 大致扫了一下你的程序 我觉得没什么问题 有个建议是 s1_send_char(uart_2[a]); 这种函数尽量不放在中断里 你这里这么用没问题 但是冲断的优先级都高于正常程序 以后写别的有可能有影响 养成个好习惯 你这段程序的意思是把串口2收到的东西用串口1转发出来是么 如果是 先不进行这个 还是我之前说的 你直接把上位机并在单片机和模块之间的通讯上 看它们之间聊的怎么样 昨天看你说那个协议的时候 也是匆匆一扫 它好象有什么对位或者应答之类的要求 你这程序里有么 |
dzbj 发表于 2017-6-9 21:13 串口一接收不到反馈信息,我现在也不确定是电表没接收到数据,还是我的接收数据程序有问题。我可以确定的是我再电脑端的串口助手能收到我发送的查询数据。而且这串查询数据我用抄表软件发送时没问题的,唯独放到我程序里没有回应。您看一下我的发送和接收有问题吗? //发送函数,在主函数中,截取相关部分 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; } } } |
宁采尘 发表于 2017-6-9 17:22 我大概看了一下你说的DLT645-1997 这是个通讯协议 从你说的情况感觉不是单片机串口的问题 是和DLT645-1997通讯没成功 你可以这样 先不用串口2 直接把上位机并联到串口1上 相当于三机互连 然后看单片机发送给电表和电表反馈的数据是什么 根据反馈修改程序 直到调通它们后 再考虑串口2转发的问题 |
dzbj 发表于 2017-6-9 14:22 我串口一波特率发生器用的T1,串口二用的独立的波特率发生器。因为DLT645-1997通信规约要求,与电表通信波特率为1200bps,为方便,我两个都设了1200bps。发送数据,模块RXD指示灯会亮,但是TXD指示灯一直都不会亮,应该是通讯没有成功。我没有设奇偶校验,单纯的发送查询命令帧后等待串口一接收中断,好像一直没有触发。您有时间再帮我在看看吧,我也尝试其他方法。方便加QQ交流吗875576671 |
lshhjx 发表于 2017-6-9 14:37 串口一能正常通讯我确定,但是和电表通讯没有成功,我每次发送数据,模块的发送指示灯都会亮,但是接收指示灯一直没有亮,应该是通讯没有成功。 |
首先问一下楼主,你串口一能够正常和电表通讯吗? |
另 附上我用的串口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中断 } |
请大家帮帮分析分析 |
上班呢 程序没看 你说的应用我用过 没有任何问题 你坚信一定会成功吧 我用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是否正常工作了 这样有利于找到问题 我就是写了个双向直接转发的程序 连串口屏自动联机都可以 |