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

標題: 基于12單片機通過雙串口查詢電表電量的問題,麻煩大家幫我看一下,感激不盡(DLT64... [打印本頁]

作者: 寧采塵    時間: 2017-6-9 13:26
標題: 基于12單片機通過雙串口查詢電表電量的問題,麻煩大家幫我看一下,感激不盡(DLT64...
   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;
}

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

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

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

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

把串口一換到電表上

把串口一換到電表上

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

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

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

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

電表138000122774

電表138000122774

作者: dzbj    時間: 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是否正常工作了 這樣有利于找到問題 我就是寫了個雙向直接轉發的程序 連串口屏自動聯機都可以
作者: 寧采塵    時間: 2017-6-9 14:14
請大家幫幫分析分析
作者: dzbj    時間: 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中斷
}

作者: lshhjx    時間: 2017-6-9 14:37
首先問一下樓主,你串口一能夠正常和電表通訊嗎?
作者: 寧采塵    時間: 2017-6-9 17:02
lshhjx 發表于 2017-6-9 14:37
首先問一下樓主,你串口一能夠正常和電表通訊嗎?

串口一能正常通訊我確定,但是和電表通訊沒有成功,我每次發送數據,模塊的發送指示燈都會亮,但是接收指示燈一直沒有亮,應該是通訊沒有成功。
作者: 寧采塵    時間: 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
作者: dzbj    時間: 2017-6-9 21:13
寧采塵 發表于 2017-6-9 17:22
我串口一波特率發生器用的T1,串口二用的獨立的波特率發生器。因為DLT645-1997通信規約要求,與電表通信 ...

我大概看了一下你說的DLT645-1997 這是個通訊協議 從你說的情況感覺不是單片機串口的問題 是和DLT645-1997通訊沒成功 你可以這樣 先不用串口2 直接把上位機并聯到串口1上 相當于三機互連 然后看單片機發送給電表和電表反饋的數據是什么 根據反饋修改程序 直到調通它們后 再考慮串口2轉發的問題
作者: 寧采塵    時間: 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;
                }
        }
}                        
作者: dzbj    時間: 2017-6-10 19:50
寧采塵 發表于 2017-6-10 11:24
串口一接收不到反饋信息,我現在也不確定是電表沒接收到數據,還是我的接收數據程序有問題。我可以確定的 ...

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

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

昨天看你說那個協議的時候 也是匆匆一掃 它好象有什么對位或者應答之類的要求 你這程序里有么
作者: 寧采塵    時間: 2017-6-12 09:31
dzbj 發表于 2017-6-10 19:50
大致掃了一下你的程序 我覺得沒什么問題 有個建議是  s1_send_char(uart_2[a]); 這種函數盡量不放在中斷 ...

通信規約上沒應答之類,此類通訊應該是半雙工通信,數據的發送和接收都有起始符,結束符,和校驗碼,我在發送和接收中加了判斷起止結束位和校驗碼,奇偶校驗位(以前沒加,因為校驗碼都計算好了沒有問題,所以本不想判斷了),對比和參考了一下前人寫的液晶顯示的51與電表通信。最后通信成功,將返回數據處理后與電表電量一致。但問題真正原因還是沒找到,不加判斷起始結束就沒法接收嗎(例如,判斷起始位68H,如果不判斷是不是68H,來的數據我都接收也應該可以啊,又不是應答之類的),我覺得問題不是出在這里。
作者: 寧采塵    時間: 2017-6-12 09:34
dzbj 發表于 2017-6-10 19:50
大致掃了一下你的程序 我覺得沒什么問題 有個建議是  s1_send_char(uart_2[a]); 這種函數盡量不放在中斷 ...

總之還是要謝謝您能在工作之余還能幫我分析問題,真的非常感謝,一個人的思路畢竟是有局限的,謝謝前輩的幫助,有機會再一起討論
作者: nephty    時間: 2018-5-1 14:21
老哥,你解決了嗎,我也碰到同樣的問題,能講下嗎




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 91在线视频播放 | 欧美综合一区二区 | 精产国产伦理一二三区 | 国产原创视频 | av在线免费网站 | 国产精品一区二区在线 | 51ⅴ精品国产91久久久久久 | av国产精品 | 精品国产乱码一区二区三区a | 国产午夜av片 | 99精品在线观看 | 韩国主播午夜大尺度福利 | 亚洲欧美日韩精品久久亚洲区 | 国产精品久久久久久久久动漫 | 中文字幕免费 | 亚洲免费人成在线视频观看 | 国产成人精品久久二区二区 | 精品一区电影 | 九九热在线观看视频 | 在线一级片 | 在线国产一区二区 | 紧缚调教一区二区三区视频 | 精品美女| 日韩在线国产 | 爱爱无遮挡 | 欧美精品欧美精品系列 | 日韩精品一区二区三区中文在线 | h视频免费在线观看 | 一级大黄色片 | 99精品网站| 日韩影院一区 | 精品国产乱码久久久 | 欧美日韩不卡合集视频 | 欧美一级免费看 | 91视频久久 | 中日韩欧美一级片 | 在线只有精品 | 在线观看免费毛片 | 国产极品粉嫩美女呻吟在线看人 | 亚洲综合大片69999 | 成人亚洲视频 |