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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6491|回復: 12
打印 上一主題 下一主題
收起左側

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

[復制鏈接]
跳轉到指定樓層
樓主
20黑幣
   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
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
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是否正常工作了 這樣有利于找到問題 我就是寫了個雙向直接轉發的程序 連串口屏自動聯機都可以
回復

使用道具 舉報

板凳
ID:209219 發表于 2017-6-9 14:14 | 只看該作者
請大家幫幫分析分析
回復

使用道具 舉報

地板
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中斷
}
回復

使用道具 舉報

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

使用道具 舉報

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

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

使用道具 舉報

7#
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
回復

使用道具 舉報

8#
ID:47286 發表于 2017-6-9 21:13 | 只看該作者
寧采塵 發表于 2017-6-9 17:22
我串口一波特率發生器用的T1,串口二用的獨立的波特率發生器。因為DLT645-1997通信規約要求,與電表通信 ...

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

使用道具 舉報

9#
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;
                }
        }
}                        
回復

使用道具 舉報

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

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

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

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

使用道具 舉報

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

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

使用道具 舉報

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

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

使用道具 舉報

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一区视频在线 | 亚洲 欧美 另类 综合 偷拍 | 中文字幕高清一区 | 日韩久久久久久久久久久 | 日韩中文字幕在线免费 | av在线播放网站 | 日韩在线不卡视频 | 久久久久久久国产 | 日韩影音| 成人网av| 免费a v网站 | 在线中文字幕av | 日韩视频免费 | 欧洲一区二区视频 | 日韩中文视频 | 久久99精品久久久久蜜桃tv | 日韩有码一区 | 人操人免费视频 | 午夜激情免费视频 | 性色av一区二区三区 | 国产精品三级 | 久久久久久久综合色一本 | 国产一级片一区二区三区 | 国产东北一级毛片 | 中文字幕 在线观看 | 国产成人免费网站 | 欧美a区| 久久久久久久久国产精品 | 久草在线青青草 | 在线观看免费av网 | 色播久久久 | 国产一在线观看 | 国产成人精品免费视频大全最热 | 日韩欧美电影在线 | 亚洲资源在线 | 精品三区| 日韩精品在线播放 | 日本成人在线网址 | 久久国产一区 | 国产欧美日韩综合精品一区二区 | 国产性网 |