久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6559|回復(fù): 12
打印 上一主題 下一主題
收起左側(cè)

基于12單片機(jī)通過雙串口查詢電表電量的問題,麻煩大家?guī)臀铱匆幌拢屑げ槐M(DLT64...

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
20黑幣
   STC12系列單片機(jī)擁有雙串口,所以我用串口一與電表通信,串口二與電腦通信,以單片機(jī)為樞紐,把串口一收到到數(shù)據(jù)再從串口二發(fā)送給電腦,同樣電腦端發(fā)送查詢數(shù)據(jù),hex模式,通過串口二傳遞給串口一再發(fā)送出去,具體請看我程序。問題就出在這,電腦發(fā)送的數(shù)據(jù)發(fā)送出去了,卻沒有收到電表回復(fù)的數(shù)據(jù)。
  我單獨(dú)測試過串口一二與電腦通信沒有問題,并將兩串口同時接到電腦,在電腦端打開兩個串口助手,也能完成通信。當(dāng)我把串口一摘下經(jīng)過TTL轉(zhuǎn)232模塊、232轉(zhuǎn)485模塊再接到電表測試時,收不到電表傳回的信息。
  一開始我是直接用的TTL轉(zhuǎn)485與電表通信的,也是沒有成功,在論壇看到有位前輩用TTL轉(zhuǎn)232再232轉(zhuǎn)485與電表通信成功了,他是用的51 ,單串口1602顯示的,然后按照他硬件電路試了一下還是沒有成功。我想問題應(yīng)該是出在我程序上了,麻煩各位前輩幫我看一看有什么問題,通信規(guī)約我已經(jīng)仔細(xì)看過了,程序要求不需要太復(fù)雜,只要求發(fā)送同一條指令(我已存到數(shù)組中),能接收到電表返回的數(shù)據(jù)信息就行,具體數(shù)據(jù)我再進(jìn)行處理就好,麻煩大家?guī)臀彝瓿蛇@一步,在下感激不盡,有地方我說的不明白的請?jiān)僭儐栁遥艺娴谋贿@個程序塊搞壞了。。。
  下面是我程序,麻煩大家?guī)臀曳治鲆幌隆?br />



/*要實(shí)現(xiàn)功能:通過單片機(jī)兩個串口,串口二連接在電腦端,
              串口一連接電表,完成查詢正向有功功率任務(wù)。
  目前進(jìn)度:  兩串口均測試可與電腦單獨(dú)通訊沒有問題,
              把串口一接入電表無法接收到返回信息
*/
#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發(fā)送中斷請求標(biāo)志位
#define S2RI 0x01      // 串口2接收中斷請求標(biāo)志位
sbit REDE=P1^4;

void delay(uint x)          //  延時子函數(shù)
{
        uint i,j;

        for(i=x;i>0;i--)
          for(j=110;j>0;j--);
}

void main()
{
    uchar m;
        UartInit_1();        //初始化串口一          //  為遵循DLT645-1997與電表通信規(guī)約
        UartInit_2();        //初始化串口二           //兩串口        波特率均設(shè)為1200bps
        while(1)
        {               
                  if(flag=0)
                  {
                   for(m=0;m<17;m++)                //上電先通過串口一發(fā)送讀正向有功總電能命令幀
                   {                                                //根據(jù)DLT645-1997規(guī)約編輯的命令幀,串口波特率1200bps
                      s1_send_char(uart[m]);                  
                   }
                   flag=1;          //標(biāo)志變?yōu)?,等待串口一接收數(shù)據(jù)后標(biāo)志再次變?yōu)?.
                              //重復(fù)查詢功能暫時不用,先用電腦手動再次發(fā)送
                  }
                   delay(1000);                                                                                
        }
          
}
void UartInit_1(void) //1200bps@12MHz
{
        TMOD=0x20;          //設(shè)置定時器1位工作方式2
        TH1=0xE8;          //方式2為8位自動重裝,
                       //初值查表可得1200波特率
        TL1=0xD0;
        TR1=1;         //打開定時器1
        SM0=0;         //設(shè)置串口工作方式1,10位固定
        SM1=1;
        REN=1;         //允許串口接收數(shù)據(jù)
        EA=1;         //打開總中斷
        ES=1;         //打開串口中斷
}

void UartInit_2(void) //1200bps@12MHz        0xE8
{
AUXR = 0x10; //波特率不倍速
S2CON = 0x50; //8位數(shù)據(jù),可變波特率
BRT = 0xE8; //設(shè)定獨(dú)立波特率發(fā)生器重裝值
IE2 |= 0x01;            //充許串口2中斷
//AUXR &= 0xfb; //獨(dú)立波特率發(fā)生器時鐘為Fosc/12,即12T
//AUXR = 0x10; //啟動獨(dú)立波特率發(fā)生器

}
/*串口一發(fā)送程序*/
void s1_send_char(uchar dat)//發(fā)送端(發(fā)送的是字符)
{
        SBUF=dat;       
        while(!TI);         
        TI=0;          //清零標(biāo)志
}

void s1_send_string(uchar *pt)         //發(fā)送字符串
{
        while(*pt != '\0')
        {
                s1_send_char(*pt++);
        }
}
/*串口二發(fā)送程序*/
void s2_send_char(uchar dat2)   // 發(fā)送端(發(fā)送的是字符)
{
        S2BUF = dat2;  
        while(!(S2CON&S2TI));
        S2CON &= ~S2TI;
}

void s2_send_string(uchar *pt2)           //發(fā)送字符串
{
        while(*pt2!='\0')
        {
                s2_send_char(*pt2++);
        }
}
                                                                                                                                 
void UART1() interrupt 4  //串口1中斷函數(shù)          
{                                                  //串口一收到電表數(shù)據(jù),存入uart2,再通過串口二發(fā)送到電腦                                                                                                          
    if(RI==1) //接收數(shù)據(jù)
        {       
                uart_2[a]=SBUF;                 
                s2_send_char(uart_2[a]);  //串口二發(fā)送到電腦
                a++;
                RI=0;
                if(a>=17)         //接收17位       
                {
                        a=0;
                //        flag=0;          //先不讓標(biāo)志位=0;想要再發(fā)送查詢正向有功功率可以在電腦端串口二發(fā)送
                }
        }                                                                                                       
//        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中斷函數(shù)                                          
{                                                 //如果串口二接收到電腦端發(fā)送的查詢命令幀數(shù)據(jù),
                         //先存入數(shù)組uart1,再通過串口一發(fā)送給電表                                                                                                                                             
        if(S2CON&S2RI)                                                                                         
        {                                                                                                                      
           uart_1[b]=S2BUF;
           S2CON&=~S2RI;
        }
        s1_send_char(uart_1[b]);        //讓串口一發(fā)送查詢命令幀數(shù)據(jù)
        b++;
         if(b>=17)            
         {
                 b=0;
         }
//         flag=1;
}

P70609-115726.jpg (3.39 MB, 下載次數(shù): 108)

雙串口均接到電腦測試沒問題

雙串口均接到電腦測試沒問題

P70609-115822.jpg (3.16 MB, 下載次數(shù): 105)

把串口一換到電表上

把串口一換到電表上

QQ截圖20170609115657.png (362.41 KB, 下載次數(shù): 129)

串口一二接到電腦時的測試

串口一二接到電腦時的測試

P70609-131914.jpg (2.83 MB, 下載次數(shù): 110)

電表138000122774

電表138000122774
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報

沙發(fā)
ID:47286 發(fā)表于 2017-6-9 14:13 | 只看該作者
上班呢 程序沒看 你說的應(yīng)用我用過 沒有任何問題 你堅(jiān)信一定會成功吧

我用12c5a做顯示屏 屏幕是串口屏 用uart2和屏通訊 uart1+485和其它模塊通訊 和你的應(yīng)用差不多

1. uart2可以用計(jì)時器做波特率發(fā)生器也可以用獨(dú)立波特率發(fā)生器 如果用兩個串口 盡量各自用一個波特率發(fā)生器 我是因?yàn)閮蓚串口速率不一樣 其它模塊是57600 屏是115200

2. 485完全無需轉(zhuǎn)其它方式 直接ttl到485就沒問題 這個我用過很多很多很多 但485片子不同廠家有時候會出各種莫名其妙的不通訊問題 要注意485的電源濾波電容大小 按你買品牌的手冊要求高 我遇到過要求1.5uf的我用0.1uf就不行

3. uart1和2的轉(zhuǎn)發(fā) 你直接在內(nèi)存開個緩沖區(qū) 如果第一位不是0或者ff或者你定義的什么東西 就直接發(fā) 實(shí)驗(yàn)的時候 你可以不斷的用串口1往上位機(jī)發(fā)緩沖區(qū)內(nèi)容 觀察串口2是否正常工作了 這樣有利于找到問題 我就是寫了個雙向直接轉(zhuǎn)發(fā)的程序 連串口屏自動聯(lián)機(jī)都可以
回復(fù)

使用道具 舉報

板凳
ID:209219 發(fā)表于 2017-6-9 14:14 | 只看該作者
請大家?guī)蛶头治龇治?/td>
回復(fù)

使用道具 舉報

地板
ID:47286 發(fā)表于 2017-6-9 14:22 | 只看該作者
另 附上我用的串口1和2初始化 基本上是用STC-ISP生成的 你對比一下看看 也許有幫助

void Init_UART1();                                                                //串口初始化 1T/定時器1作波特率發(fā)生器

void Init_UART1()        //串口初始化 1T/定時器1作波特率發(fā)生器
{
        PCON |= 0x80;                        //使能波特率倍速位SMOD
        SCON = 0x50;                        //8位數(shù)據(jù),可變波特率
        AUXR |= 0x40;                        //定時器1時鐘為Fosc,即1T
        AUXR &= 0xFE;                        //串口1選擇定時器1為波特率發(fā)生器
        TMOD &= 0x0F;                        //清除定時器1模式位
//        TMOD |= 0x21;                        //設(shè)定定時器1為8位自動重裝方式
        TMOD |= 0x20;                        //設(shè)定定時器1為8位自動重裝方式
        TL1=TH1=BAUD1;                        //設(shè)定定時初值
        ET1 = 0;                                //禁止定時器1中斷
        TR1 = 1;                                //啟動定時器1
        ES=1;                                        //開串口中斷
}

void Init_UART2();                //串口2初始化 1T/獨(dú)立波特率發(fā)生器(串口2只能使用獨(dú)立波特率發(fā)生器)

void Init_Uart2()                //串口2初始化 115200bps@11.0592MHz@獨(dú)立波特率發(fā)生器
{
       
        AUXR |= 0x08;                //使能波特率倍速位S2SMOD 0000 1000
        S2CON = 0x50;                //8位數(shù)據(jù),可變波特率 0101 0000
        AUXR |= 0x04;                //獨(dú)立波特率發(fā)生器時鐘為Fosc,即1T 0000 0100
        BRT = BAUD2;                //設(shè)定獨(dú)立波特率發(fā)生器重裝值
        AUXR |= 0x10;                //啟動獨(dú)立波特率發(fā)生器 0001 0000
        IE2=0X01;                        //允許串口2中斷
}
回復(fù)

使用道具 舉報

5#
ID:59827 發(fā)表于 2017-6-9 14:37 來自手機(jī) | 只看該作者
首先問一下樓主,你串口一能夠正常和電表通訊嗎?
回復(fù)

使用道具 舉報

6#
ID:209219 發(fā)表于 2017-6-9 17:02 | 只看該作者
lshhjx 發(fā)表于 2017-6-9 14:37
首先問一下樓主,你串口一能夠正常和電表通訊嗎?

串口一能正常通訊我確定,但是和電表通訊沒有成功,我每次發(fā)送數(shù)據(jù),模塊的發(fā)送指示燈都會亮,但是接收指示燈一直沒有亮,應(yīng)該是通訊沒有成功。
回復(fù)

使用道具 舉報

7#
ID:209219 發(fā)表于 2017-6-9 17:22 | 只看該作者
dzbj 發(fā)表于 2017-6-9 14:22
另 附上我用的串口1和2初始化 基本上是用STC-ISP生成的 你對比一下看看 也許有幫助

void Init_UART1();         ...

我串口一波特率發(fā)生器用的T1,串口二用的獨(dú)立的波特率發(fā)生器。因?yàn)镈LT645-1997通信規(guī)約要求,與電表通信波特率為1200bps,為方便,我兩個都設(shè)了1200bps。發(fā)送數(shù)據(jù),模塊RXD指示燈會亮,但是TXD指示燈一直都不會亮,應(yīng)該是通訊沒有成功。我沒有設(shè)奇偶校驗(yàn),單純的發(fā)送查詢命令幀后等待串口一接收中斷,好像一直沒有觸發(fā)。您有時間再幫我在看看吧,我也嘗試其他方法。方便加QQ交流嗎875576671
回復(fù)

使用道具 舉報

8#
ID:47286 發(fā)表于 2017-6-9 21:13 | 只看該作者
寧采塵 發(fā)表于 2017-6-9 17:22
我串口一波特率發(fā)生器用的T1,串口二用的獨(dú)立的波特率發(fā)生器。因?yàn)镈LT645-1997通信規(guī)約要求,與電表通信 ...

我大概看了一下你說的DLT645-1997 這是個通訊協(xié)議 從你說的情況感覺不是單片機(jī)串口的問題 是和DLT645-1997通訊沒成功 你可以這樣 先不用串口2 直接把上位機(jī)并聯(lián)到串口1上 相當(dāng)于三機(jī)互連 然后看單片機(jī)發(fā)送給電表和電表反饋的數(shù)據(jù)是什么 根據(jù)反饋修改程序 直到調(diào)通它們后 再考慮串口2轉(zhuǎn)發(fā)的問題
回復(fù)

使用道具 舉報

9#
ID:209219 發(fā)表于 2017-6-10 11:24 | 只看該作者
dzbj 發(fā)表于 2017-6-9 21:13
我大概看了一下你說的DLT645-1997 這是個通訊協(xié)議 從你說的情況感覺不是單片機(jī)串口的問題 是和DLT645-199 ...

串口一接收不到反饋信息,我現(xiàn)在也不確定是電表沒接收到數(shù)據(jù),還是我的接收數(shù)據(jù)程序有問題。我可以確定的是我再電腦端的串口助手能收到我發(fā)送的查詢數(shù)據(jù)。而且這串查詢數(shù)據(jù)我用抄表軟件發(fā)送時沒問題的,唯獨(dú)放到我程序里沒有回應(yīng)。您看一下我的發(fā)送和接收有問題嗎?
//發(fā)送函數(shù),在主函數(shù)中,截取相關(guān)部分
         while(1)
        {
                  if(k==0)        //按鍵按下一次發(fā)送一次查詢命令
                  {
                          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};
                                   //讀正向有功總電能命令幀
     }

//接收函數(shù),截取相關(guān)部分,已將串口1并連電腦和電表。
/*串口一發(fā)送程序*/
void s1_send_char(uchar dat)//?發(fā)送端(發(fā)送的是字符)
{
        SBUF=dat;       
        while(!TI);         
        TI=0;          //清零標(biāo)志
}
void UART1() interrupt 4  //串口1中斷函數(shù)          
{                                                                                                                                                          
    if(RI==1)
        {       
                uart_2[a]=SBUF;
                s1_send_char(uart_2[a]);
                a++;
                RI=0;
                if(a>14)
                {
                        a=0;
                //        flag=1;
                }
        }
}                        
回復(fù)

使用道具 舉報

10#
ID:47286 發(fā)表于 2017-6-10 19:50 | 只看該作者
寧采塵 發(fā)表于 2017-6-10 11:24
串口一接收不到反饋信息,我現(xiàn)在也不確定是電表沒接收到數(shù)據(jù),還是我的接收數(shù)據(jù)程序有問題。我可以確定的 ...

大致掃了一下你的程序 我覺得沒什么問題 有個建議是  s1_send_char(uart_2[a]); 這種函數(shù)盡量不放在中斷里 你這里這么用沒問題 但是沖斷的優(yōu)先級都高于正常程序 以后寫別的有可能有影響 養(yǎng)成個好習(xí)慣

你這段程序的意思是把串口2收到的東西用串口1轉(zhuǎn)發(fā)出來是么 如果是 先不進(jìn)行這個 還是我之前說的 你直接把上位機(jī)并在單片機(jī)和模塊之間的通訊上 看它們之間聊的怎么樣

昨天看你說那個協(xié)議的時候 也是匆匆一掃 它好象有什么對位或者應(yīng)答之類的要求 你這程序里有么
回復(fù)

使用道具 舉報

11#
ID:209219 發(fā)表于 2017-6-12 09:31 | 只看該作者
dzbj 發(fā)表于 2017-6-10 19:50
大致掃了一下你的程序 我覺得沒什么問題 有個建議是  s1_send_char(uart_2[a]); 這種函數(shù)盡量不放在中斷 ...

通信規(guī)約上沒應(yīng)答之類,此類通訊應(yīng)該是半雙工通信,數(shù)據(jù)的發(fā)送和接收都有起始符,結(jié)束符,和校驗(yàn)碼,我在發(fā)送和接收中加了判斷起止結(jié)束位和校驗(yàn)碼,奇偶校驗(yàn)位(以前沒加,因?yàn)樾r?yàn)碼都計(jì)算好了沒有問題,所以本不想判斷了),對比和參考了一下前人寫的液晶顯示的51與電表通信。最后通信成功,將返回?cái)?shù)據(jù)處理后與電表電量一致。但問題真正原因還是沒找到,不加判斷起始結(jié)束就沒法接收嗎(例如,判斷起始位68H,如果不判斷是不是68H,來的數(shù)據(jù)我都接收也應(yīng)該可以啊,又不是應(yīng)答之類的),我覺得問題不是出在這里。
回復(fù)

使用道具 舉報

12#
ID:209219 發(fā)表于 2017-6-12 09:34 | 只看該作者
dzbj 發(fā)表于 2017-6-10 19:50
大致掃了一下你的程序 我覺得沒什么問題 有個建議是  s1_send_char(uart_2[a]); 這種函數(shù)盡量不放在中斷 ...

總之還是要謝謝您能在工作之余還能幫我分析問題,真的非常感謝,一個人的思路畢竟是有局限的,謝謝前輩的幫助,有機(jī)會再一起討論
回復(fù)

使用道具 舉報

13#
ID:290231 發(fā)表于 2018-5-1 14:21 來自手機(jī) | 只看該作者
老哥,你解決了嗎,我也碰到同樣的問題,能講下嗎
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产精品乱码一区二区三区 | 婷婷综合色 | 国产在线精品免费 | 天天曰夜夜 | 91 视频网站 | 亚洲资源站 | 黄色国产视频 | 精品国产不卡一区二区三区 | 中文字幕一区二区三区在线观看 | 国产在线一区二区 | 涩涩视频网站在线观看 | 伊人网综合在线观看 | 精品久久久久一区二区国产 | 欧美 日韩 在线播放 | 羞羞的视频在线 | www.亚洲区| 亚洲一区在线免费观看 | 午夜无码国产理论在线 | 亚洲国产精品一区二区三区 | 成人欧美日韩一区二区三区 | 亚洲三区在线观看 | 免费网站国产 | 久久久久久亚洲欧洲 | 亚洲视频免费在线看 | 国内自拍偷拍 | 久久久久亚洲精品国产 | 盗摄精品av一区二区三区 | 欧美xxxx色视频在线观看免费 | 日韩视频在线观看中文字幕 | 国产精品亚洲精品日韩已方 | 国产精品美女在线观看 | h视频免费在线观看 | 成人免费视频网站在线看 | 伦理二区 | 黄色精品 | 精品国产不卡一区二区三区 | 中文字幕人成人 | 日韩精品一区二区三区视频播放 | 国产精品久久二区 | 91精品国产欧美一区二区成人 | 国产精品一区久久久久 |