wwwxxx国产_337p日本欧洲亚洲大胆张筱雨_免费在线看成人av_日本黄色不卡视频_国产精品成熟老女人_99视频一区_亚洲精品97久久中文字幕_免费精品视频在线_亚洲色图欧美视频_欧美一区二三区

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

基于51單片機的電表抄讀(DLT645-1997規約)

  [復制鏈接]
跳轉到指定樓層
樓主
硬件設計:AT89S52單片機通過MAX232實現電平轉換與串口連接。由于電能表采用RS485通信,因此串口與電能表之間必須使用RS232/RS485轉換器UT-2216進行連接。
軟件設計:實時時間的顯示和通信程序設計。要實現實時顯示就需要對DS1302時鐘芯片和液晶LCD1602進行編程,將DS1302的數據讀出來顯示在LCD1602第一行上,LCD1602也要顯示電能表數據。通信方式為主從站方式通信,單片機為主站,主站需要發送讀數據命令幀和接收電能表應答回復的數據,因此,就需要設計單片機發送命令和接收數據的程序。將接收到的數據儲存在單片機存儲器中,在程序中將其存于數組中。最后把數組中的數據取出來寫入液晶LCD1602中,顯示在液晶上。

源代碼如下:
  1. # include<reg52.h>
  2. # include<intrins.h>   //包含_nop_()函數定義的頭文件
  3. # define uchar unsigned char
  4. # define uint  unsigned int
  5. sbit SCLK=P1^0;   //位定義1302芯片的接口,時鐘輸出端口定義在P1.0引腳
  6. sbit DATA=P1^1;   //位定義1302芯片的接口,數據輸出端定義在P1.1引腳
  7. sbit RST=P1^2;    //位定義1302芯片的接口,復位端口定義在P1.2引腳
  8. sbit RS=P2^0;           //寄存器選擇位,將RS位定義為P2.0引腳
  9. sbit RW=P2^1;           //讀寫選擇位,將RW位定義為P2.1引腳
  10. sbit E=P2^2;            //使能信號位,將E位定義為P2.2引腳
  11. sbit BF=P0^7;           //忙碌標志位,,將BF位定義為P0.7引腳
  12. uchar RecNum=0;   
  13. uint  cs;//存放校驗碼
  14. uchar con;//存放控制碼
  15. uchar add[6];
  16. uchar idata rdata[6];
  17. uchar code string[ ]= {"Welcome to use"};
  18. uchar code string1[ ]= {"kWh"};
  19. uchar code digit[10]={"0123456789"};   //定義字符數組顯示數字
  20. unsigned char code key_code[]={ 0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77}; //鍵盤編碼
  21. uchar  add1[6]={0x53,0x50,0x00,0x00,0x00,0x00};//  存放1#電能表地址碼,(地址碼已經確定,通過電能表測試軟件確定)
  22. uchar  add2[6];//  存放2#電能表地址碼
  23. uchar  tdata[2]={0x10,0x90};// 存放要發送的數據
  24. uchar  tdata1[2]={0x20,0x90};
  25. uchar  tdata2[2]={0x10,0x94};
  26. uchar  tdata3[2]={0x20,0x94};
  27. /***************************特殊字符定義************************/
  28. # define PRECURSOR_CHAR 0xfe;//定義前導字符
  29. # define START_CHAR 0x68;//定義幀起始符
  30. # define END_CHAR 0x16;//定義幀結束符
  31. /***************************接收狀態定義************************/
  32. # define RS_WAIT  0;//等待狀態
  33. # define RS_AWAKEN 1;//喚醒狀態
  34. # define RS_ADD 2;//接收地址域狀態
  35. # define RS_HEADER 3;//接收幀頭狀態
  36. # define RS_CON 4;//接收控制碼狀態
  37. # define RS_DATALEN 5;//接收數據域長度狀態
  38. # define RS_DATA 6;//接收數據域狀態
  39. # define RS_CHECK 7;//接收校驗碼狀態
  40. # define RS_END 8;//接收結束符狀態
  41. /********************************延時若干毫秒 ****************************/
  42. void delaynms(uchar n)
  43. {
  44.    uchar i,j;
  45.    while(n--)
  46.    {
  47. for(i=0;i<10;i++)
  48.    for(j=0;j<33;j++);
  49.     }
  50. }[/color][/size][/align][size=3][color=#000000][font=宋體][align=left]
  51. /*****************************延時若干微秒******************************/
  52. void delaynus(uchar n)
  53. {
  54. uchar i;
  55. for(i=0;i<n;i++);
  56. }
  57.   
  58. /************矩陣鍵盤程序***********************/[/align][align=left]uchar  keyscan()
  59. {
  60.    uchar  scan1,scan2,keycode;[/align][align=left]   P1=0xf0;
  61.    scan1=P1;
  62.    if((scan1&0xf0)!=0xf0)           //判鍵是否按下
  63.    {
  64.      delaynms(20);                   //延時20ms
  65.      scan1=P1;
  66.      if((scan1&0xf0)!=0xf0)         //二次判鍵是否按下
  67.      {
  68.         P1=0x0f;  //線反轉法的核心
  69.         scan2=P1;
  70.         keycode=scan1|scan2;         //組合成鍵編碼
  71.   }
  72.       
  73.     return(keycode);
  74.     }
  75.      
  76. }
  77. /**********************判斷液晶模塊的忙碌狀態***********************/
  78. bit BusyTest(void)
  79.   {
  80.         bit result;
  81.      RS=0;       //根據規定,RS為低電平,RW為高電平時,可以讀狀態
  82.      RW=1;
  83.      E=1;        //E=1,才允許讀寫
  84.      _nop_();   //空操作
  85.      _nop_();
  86.      _nop_();
  87.      _nop_();   //空操作四個機器周期,給硬件反應時間
  88.      result=BF;  //將忙碌標志電平賦給result
  89.     E=0;         //將E恢復低電平
  90.     return result;
  91.   }
  92. /********************將模式設置指令或顯示地址寫入液晶模塊************************/
  93. void WriteInstruction (uchar dictate)
  94. {   
  95.     while(BusyTest()==1);   //如果忙就等待
  96.   RS=0;                  //根據規定,RS和R/W同時為低電平時,可以寫入指令
  97.   RW=0;   
  98.   E=0;                   //E置低電平(根據表8-6,寫指令時,E為高脈沖,
  99.                            // 就是讓E從0到1發生正跳變,所以應先置"0"
  100.   _nop_();
  101.   _nop_();               //空操作兩個機器周期,給硬件反應時間
  102.   P0=dictate;            //將數據送入P0口,即寫入指令或地址
  103.   _nop_();
  104.   _nop_();
  105.   _nop_();
  106.   _nop_();               //空操作四個機器周期,給硬件反應時間
  107.   E=1;                   //E置高電平
  108.   _nop_();
  109.   _nop_();
  110.   _nop_();
  111.   _nop_();               //空操作四個機器周期,給硬件反應時間
  112.    E=0;                  //當E由高電平跳變成低電平時,液晶模塊開始執行命令
  113. }
  114. /*****************指定字符顯示的實際地址*********************/
  115. void WriteAddress(uchar x)
  116. {
  117.      WriteInstruction(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"
  118. }
  119. /*********************將數據(字符的標準ASCII碼)寫入液晶模塊**************************/
  120. void WriteData(uchar y)
  121. {
  122.     while(BusyTest()==1);  
  123.    RS=1;           //RS為高電平,RW為低電平時,可以寫入數據
  124.    RW=0;
  125.    E=0;            //E置低電平(根據表8-6,寫指令時,E為高脈沖,
  126.                      // 就是讓E從0到1發生正跳變,所以應先置"0"
  127.    P0=y;           //將數據送入P0口,即將數據寫入液晶模塊
  128.    _nop_();
  129.    _nop_();
  130.     _nop_();
  131.      _nop_();       //空操作四個機器周期,給硬件反應時間
  132.    E=1;           //E置高電平
  133.    _nop_();
  134.    _nop_();
  135.    _nop_();
  136.   _nop_();        //空操作四個機器周期,給硬件反應時間
  137.   E=0;            //當E由高電平跳變成低電平時,液晶模塊開始執行命令
  138. }[/align][align=left]/*********************向1302寫一個字節數據******************************/
  139. void Write1302(uchar dat)
  140. {
  141.   uchar i;
  142.   SCLK=0;            //拉低SCLK,為脈沖上升沿寫入數據做好準備
  143.   delaynus(2);       //稍微等待,使硬件做好準備
  144.   for(i=0;i<8;i++)      //連續寫8個二進制位數據
  145.     {
  146.       DATA=dat&0x01;    //取出dat的第0位數據寫入1302  低位在前,高位在后
  147.    delaynus(2);       //稍微等待,使硬件做好準備
  148.    SCLK=1;           //上升沿寫入數據
  149.    delaynus(2);      //稍微等待,使硬件做好準備
  150.    SCLK=0;           //重新拉低SCLK,形成脈沖
  151.    dat>>=1;          //將dat的各數據位右移1位,準備寫入下一個數據位
  152.      }
  153. }
  154. /********************根據命令字,向1302寫一個字節數據 Cmd,儲存命令字;dat,儲存待寫的數據***************/
  155. void WriteSet1302(uchar Cmd,uchar dat)
  156. {   
  157.         RST=0;           //禁止數據傳遞
  158.         SCLK=0;          //確保寫數居前SCLK被拉低
  159.      RST=1;           //啟動數據傳輸
  160.      delaynus(2);     //稍微等待,使硬件做好準備
  161.      Write1302(Cmd);  //寫入命令字
  162.      Write1302(dat);  //寫數據
  163.      SCLK=1;          //將時鐘電平置于高電平狀態
  164.      RST=0;           //禁止數據傳遞
  165. }
  166. /************************從1302讀一個字節數據***************************/
  167. uchar Read1302(void)
  168. {
  169.     uchar i,dat;
  170. delaynus(2);       //稍微等待,使硬件做好準備
  171. for(i=0;i<8;i++)   //連續讀8個二進制位數據
  172.   {  dat>>=1;
  173.    if(DATA==1)    //如果讀出的數據是1
  174.    dat|=0x80;    //將1取出,寫在dat的最高位
  175.    SCLK=1;       //將SCLK置于高電平,為下降沿讀出
  176.    delaynus(2);  //稍微等待
  177.    SCLK=0;       //拉低SCLK,形成脈沖下降沿
  178.    delaynus(2);  //稍微等待
  179.    }  
  180.   return dat;        //將讀出的數據返回
  181. }  
  182. /*****************從1302讀取一個字節數據**********************/
  183. uchar  ReadSet1302(uchar Cmd)
  184. {
  185.   uchar dat;
  186.   RST=0;                 //拉低RST
  187.   SCLK=0;                //確保寫數居前SCLK被拉低
  188.   RST=1;                 //啟動數據傳輸
  189.   Write1302(Cmd);       //寫入命令字
  190.   dat=Read1302();       //讀出數據
  191.   SCLK=1;              //將時鐘電平置于已知狀態
  192.   RST=0;               //禁止數據傳遞
  193.   return dat;          //將讀出的數據返回
  194. }
  195. /************************顯示秒***********************/
  196. void DisplaySecond(uchar x)
  197. {
  198. uchar i,j;     //j,k分別儲存十位和個位
  199. i=x/10;//取十位
  200. j=x%10;//取個位     
  201. WriteAddress(0x0e);    //寫顯示地址,將在第1行第15列開始顯示
  202. WriteData(digit[i]);    //將百位數字的字符常量寫入LCD
  203. WriteData(digit[j]);    //將十位數字的字符常量寫入LCD
  204. delaynms(50);         //延時1ms給硬件一點反應時間   
  205. }[/i][/align][align=left][i]/*************************顯示分鐘*********************/
  206. void DisplayMinute(uchar x)
  207. {
  208. unsigned char i,j;     //j,k十位和個位
  209. i=x/10;//取十位
  210. j=x%10;//取個位     
  211. WriteAddress(0x0b);    //寫顯示地址,將在第1行第12列開始顯示
  212. WriteData(digit[i]);    //將百位數字的字符常量寫入LCD
  213. WriteData(digit[j]);    //將十位數字的字符常量寫入LCD
  214. delaynms(50);         //延時1ms給硬件一點反應時間   
  215. }
  216. /*************************顯示小時********************/
  217. void DisplayHour(uchar x)
  218. {
  219. uchar i,j;     //j,k十位和個位
  220. i=x/10;//取十位
  221. j=x%10;//取個位     
  222. WriteAddress(0x08);    //寫顯示地址,將在第1行第9列開始顯示
  223. WriteData(digit[i]);    //將百位數字的字符常量寫入LCD
  224. WriteData(digit[j]);    //將十位數字的字符常量寫入LCD
  225. delaynms(50);         //延時1ms給硬件一點反應時間   
  226. }
  227. /*******************顯示日*********************/
  228. void DisplayDay(uchar x)
  229. {
  230.   uchar i,j;     //j,k十位和個位
  231. i=x/10;//取十位
  232. j=x%10;//取個位     
  233. WriteAddress(0x06);    //寫顯示地址,將在第1行第7列開始顯示
  234. WriteData(digit[i]);    //將十位數字的字符常量寫入LCD
  235. WriteData(digit[j]);    //將個位數字的字符常量寫入LCD
  236. delaynms(50);         //延時1ms給硬件一點反應時間   
  237. }
  238. /************************顯示月**************/
  239. void DisplayMonth(uchar x)
  240. {
  241. uchar i,j;     //j,k分別儲存十位和個位
  242. i=x/10;//取十位
  243. j=x%10;//取個位     
  244. WriteAddress(0x03);    //寫顯示地址,將在第1行第4列開始顯示
  245. WriteData(digit[i]);    //將十位位數字的字符常量寫入LCD
  246. WriteData(digit[j]);    //將個位數字的字符常量寫入LCD
  247. delaynms(50);         //延時1ms給硬件一點反應時間   
  248. }
  249. /*************************顯示年**************/
  250. void DisplayYear(uchar x)
  251. {
  252.     uchar i,j;     //j,k分別儲存十位和個位
  253. i=x/10;//取十位
  254. j=x%10;//取個位     
  255. WriteAddress(0x00);    //寫顯示地址,將在第1行第1列開始顯示
  256. WriteData(digit[i]);    //將十位位數字的字符常量寫入LCD
  257. WriteData(digit[j]);    //將個位數字的字符常量寫入LCD
  258. delaynms(50);         //延時1ms給硬件一點反應時間   
  259. }[/i][/i][/i][/i][/i][/i][/align][align=left][i][i][i] /********************時間顯示********************/
  260. void display_time(void)
  261. {
  262.      
  263.    uchar second,minute,hour,day,month,year;      //分別儲存秒、分、小時,日,月,年
  264.       uchar ReadValue;   //儲存從1302讀取的數據
  265.    WriteAddress(0x02);  //寫年月分隔符的顯示地址, 顯示在第1行第3列
  266.       WriteData('-');      //將字符常量寫入LCD
  267.       WriteAddress(0x05);  //寫月日分隔符的顯示地址, 顯示在第1行第12列
  268.       WriteData('-');      //將字符常量寫入LCD
  269.       WriteAddress(0x0a);  //寫小時與分鐘分隔符的顯示地址, 顯示在第1行第6列
  270.       WriteData(':');      //將字符常量寫入LCD
  271.       WriteAddress(0x0d);  //寫分鐘與秒分隔符的顯示地址, 顯示在第1行第14列
  272.       WriteData(':');      //將字符常量寫入LCD
  273.    ReadValue = ReadSet1302(0x81);   //從秒寄存器讀數據
  274.       second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//將讀出數據轉化
  275.    DisplaySecond(second);          //顯示秒
  276.    ReadValue = ReadSet1302(0x83);  //從分寄存器讀
  277.       minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
  278.    DisplayMinute(minute);        //顯示分
  279.       ReadValue = ReadSet1302(0x85);  //從分寄存器讀
  280.       hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
  281.    DisplayHour(hour);              //顯示小時
  282.       ReadValue = ReadSet1302(0x87);  //從分寄存器讀
  283.       day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
  284.    DisplayDay(day);                //顯示日
  285.    ReadValue = ReadSet1302(0x89);  //從分寄存器讀
  286.       month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
  287.    DisplayMonth(month);            //顯示月
  288.    ReadValue = ReadSet1302(0x8d);  //從分寄存器讀
  289.       year=((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
  290.    DisplayYear(year);             //顯示年[/i][/i][/i][/align][align=left][i][i][i]
  291. }
  292. /*****************數據解析*********************/
  293. void message_proc()
  294. {
  295.     uchar mm,m,n,i;[/i][/i][/i][/align][align=left][i][i][i] WriteAddress(0x42);  // 設置顯示位置
  296. for(i=5;i>=3;i--)
  297.     {
  298.     mm=((rdata[i]&0x70)>>4)*10 + (rdata[i]&0x0F);
  299.     m=mm/10;
  300. n=mm%10;
  301. WriteData(digit[m]);
  302. WriteData(digit[n]);
  303. delaynms(100);
  304. }
  305. WriteData('.');
  306. delaynms(100);
  307.     mm=((rdata[2]&0x70)>>4)*10 + (rdata[2]&0x0f);//將BCD碼轉化成字符
  308.     m=mm/10; //取十位
  309. n=mm%10; //取個位
  310. WriteData(digit[m]);
  311. WriteData(digit[n]); //顯示在LCD1602上
  312. delaynms(100);
  313.     for(i=0;i<3;i++)   
  314. WriteData(string1[i]);
  315. delaynms(100);
  316. }
  317. /***************************1302初始化********************/
  318. void Init_DS1302(void)
  319. {[/i][/i][/i][/i][/i][/i][/align][align=left][i][i][i]   /*--------------------這是每次都初始化的語句-----------------*/
  320.   
  321.    /*  
  322.   
  323.    WriteSet1302(0x8E,0x00);                 //根據寫狀態寄存器命令字,寫入不保護指令
  324.    WriteSet1302(0x80,((20/10)<<4|(20%10)));   //根據寫秒寄存器命令字,寫入秒的初始值[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x82,((28/10)<<4|(28%10)));   //根據寫分寄存器命令字,寫入分的初始值[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x84,((10/10)<<4|(10%10))); //根據寫小時寄存器命令字,寫入小時的初始值[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x86,((10/10)<<4|(10%10))); //根據寫日寄存器命令字,寫入日的初始值[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x88,((5/10)<<4|(5%10))); //根據寫月寄存器命令字,寫入月的初始值[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x8c,((13/10)<<4|(13%10)));   //根據寫年寄存器命令字,寫入年的初始值[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x90,0xa5);                //打開充電功能 選擇2K電阻充電方式[/i][/i][/i][/align][align=left][i][i][i] WriteSet1302(0x8E,0x80);              //根據寫狀態寄存器命令字,寫入保護指令
  325. */
  326.     uchar flag;
  327.    
  328.     flag= ReadSet1302(0x81);
  329. if(flag&0x80)
  330. {      //判斷時鐘芯片是否關閉
  331.     WriteSet1302(0x8E,0x00);                 //根據寫狀態寄存器命令字,寫入不保護指令
  332.     WriteSet1302(0x80,((10/10)<<4|(10%10)));   //根據寫秒寄存器命令字,寫入秒的初始值
  333. WriteSet1302(0x82,((28/10)<<4|(28%10)));   //根據寫分寄存器命令字,寫入分的初始值
  334. WriteSet1302(0x84,((10/10)<<4|(10%10))); //根據寫小時寄存器命令字,寫入小時的初始值
  335. WriteSet1302(0x86,((10/10)<<4|(10%10))); //根據寫日寄存器命令字,寫入日的初始值
  336. WriteSet1302(0x88,((5/10)<<4|(5%10))); //根據寫月寄存器命令字,寫入月的初始值
  337. WriteSet1302(0x8c,((13/10)<<4|(13%10)));  //根據寫年寄存器命令字,寫入年的初始值
  338. WriteSet1302(0x90,0xa5);                //打開充電功能 選擇2K電阻充電方式
  339. WriteSet1302(0x8E,0x80);      //根據寫狀態寄存器命令字,寫入保護指令
  340.   }
  341.       

  342.      //如果不想每次都初始化時間,也就是掉電后還想讓時鐘繼續走時的話 就用上面的語句   [/i][/i][/i][/align][align=left][i][i][i]  }
  343. /***************串口初始化*********************/
  344. void initial_serial(void)
  345. {[/i][/i][/i][/align][align=left][i][i][i]  TMOD=0x20;   // 定時器1工作于8位自動重載模式(工作方式2), 用于產生波特率
  346.   TH1=TL1=0xe8;   // 波特率為1200bps
  347.   TF1=0;    // 計數未滿
  348.   TR1=1;          //啟動定時器1
  349.   SCON=0xd0;   // 設定串行口工作方式3(11位異步收發方式) ,允許接收數據
  350.   PCON=0x00;            //波特率不加倍                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 //波特率不加倍(SMOD=0)
  351.   ES=1;     //開串行口中斷
  352.   EA=1;                 //開總中斷[/i][/i][/i][/align][align=left][i][i][i]}
  353. /*************************LCD初始化**************************/
  354. void LcdInitiate(void)
  355. {
  356.     delaynms(15);               //延時15ms,首次寫指令時應給LCD一段較長的反應時間
  357.     WriteInstruction(0x38);     //顯示模式設置:16×2顯示,5×7點陣,8位數據接口
  358. delaynms(5);                //延時5ms ,給硬件一點反應時間
  359.     WriteInstruction(0x38);
  360. delaynms(5);               //延時5ms ,給硬件一點反應時間
  361. WriteInstruction(0x38);     //連續三次,確保初始化成功
  362. delaynms(5);               //延時5ms ,給硬件一點反應時間
  363. WriteInstruction(0x0c);     //顯示模式設置:顯示開,無光標,光標不閃爍
  364. delaynms(5);               //延時5ms ,給硬件一點反應時間
  365. WriteInstruction(0x06);     //顯示模式設置:光標右移,字符不移
  366. delaynms(5);                //延時5ms ,給硬件一點反應時間
  367. WriteInstruction(0x01);     //清屏幕指令,將以前的顯示內容清除
  368. delaynms(5);             //延時5ms ,給硬件一點反應時間[/i][/i][/i][/align][align=left][i][i][i] }
  369. /***************單片機(主站)發送函數********************/
  370. void send(uchar * add,uchar con1,uchar DataLen1,uchar *tdata)
  371. {
  372.   uchar  sh,j,m,ecc=0;  //定義變量
  373.   TI=0;// 發送中斷標志復位
  374.   sh=START_CHAR;//發送幀起始符0x68;
  375.   ACC=sh;
  376.   TB8=P;
  377.   SBUF=sh;
  378.   ecc=ecc+sh;//計算校驗和 (校驗和指從幀起始符到檢驗碼之前所有各字節二進制和)
  379.   while(!TI);
  380.   TI=0;
  381.   for(j=0;j<6;j++)
  382.   {
  383.     sh=*(add+j);//發送地址
  384.     ACC=sh;
  385.     TB8=P;
  386.     SBUF=sh;
  387.     ecc=ecc+sh;//再一次計算校驗和
  388.     while(!TI);
  389.     TI=0;
  390.    }
  391.   sh=START_CHAR;//發送幀起始符0x68;
  392.   ACC=sh;
  393.   TB8=P;
  394.   SBUF=sh;
  395.   ecc=ecc+sh;//計算校驗和 (校驗和指從幀起始符到檢驗碼之前所有各字節二進制和)
  396.   while(!TI);
  397.   TI=0;
  398.   sh=con1;//發送控制碼
  399.   ACC=sh;
  400.   TB8=P;
  401.   SBUF=sh;
  402.   ecc=ecc+sh;//計算校驗和
  403.   while(!TI);
  404.   TI=0;
  405.   sh=DataLen1; //發送數據長度
  406.   ACC=sh;
  407.   TB8=P;
  408.   SBUF=sh;
  409.   ecc=ecc+sh;//計算校驗和
  410.   while(!TI);
  411.   TI=0;
  412.   for(m=0;m<DataLen1;m++)
  413.   {
  414.    sh=(*(tdata+m)+0x33);// 發送數據標識DI0 DI1,傳輸時發送方按字節進行加33H 處理
  415.    ACC=sh;
  416.    TB8=P;
  417.    SBUF=sh;
  418.    ecc=ecc+sh;//計算校驗和
  419.    while(!TI);
  420.    TI=0;
  421.    }
  422.    sh=ecc;
  423.    ACC=sh;
  424.    TB8=P;
  425.    SBUF=sh;
  426.    while(!TI);
  427.    TI=0;
  428.    ecc=0;//校驗和清0
  429.    sh=END_CHAR; //發送幀結束符0x16
  430.    ACC=sh;
  431.    TB8=P;
  432.    SBUF=sh;
  433.    while(!TI);
  434.    TI=0;
  435.   [/i][/i][/i][/align][align=left][i][i][i]}                    

  436. /********************主函數********************/
  437. void main(void)
  438. {
  439.   uchar tt,i;
  440.   LcdInitiate();      //液晶初始化
  441.   initial_serial();  //串口初始化
  442.   Init_DS1302();    //DS1302初始化
  443.   WriteAddress(0x01);  // 設置顯示位置為第一行的第1個字
  444.   i = 0;
  445.   while(string[i] != '\0')    //'\0'是數組結束標志
  446. {     
  447. WriteData(string[i]);
  448. i++;
  449. delaynms(20);

  450. }

  451.   WriteAddress(0x42);  // 設置顯示位置為第二行的第5個字
  452.   for(i=0;i<12;i++)
  453.   WriteData('-'); //顯示在LCD1602上
  454.   while(1)
  455.   {
  456.      P1=0xf0;
  457.   if((P1&0xf0)!=0xf0)
  458. {
  459.        tt=keyscan();
  460.     switch (tt)
  461.     {
  462.      case 0xe7:  send(&add1,0x01,0x02,&tdata);display_time();break;//發送讀正向有功總電能命令幀
  463.      case 0xd7:  send(&add1,0x01,0x02,&tdata1);display_time();break; //讀反向有功總電能
  464.   case 0xb7: send(&add1,0x01,0x02,&tdata2);display_time();break;  //讀上月正向有功總電能
  465.   case 0x77:  send(&add1,0x01,0x02,&tdata3);display_time();break; //讀上月反向有功總電能
  466.     }
  467. }
  468. message_proc();
  469. [/i][/i][/i][/i][/i][/align][align=left][i][i][i]  }

  470. }[/i][/i][/i][/align][/font][/color][/size][align=left][size=3][color=#000000][font=宋體][i][i][i]/********************單片機(主站接收)串行口中斷函數********************/
  471. void serial() interrupt 4
  472. {
  473.    uchar ch;//存放當前接收的字符
  474.    static uchar ecc,flag=0;
  475.    static uchar AddCount;//地址域計數器
  476.    static uchar DataCount;//數據域計數器
  477.    static uchar DataLen;//數據域長度
  478.    static uchar RecState=RS_WAIT;//串口初始接收狀態為等待
  479.    if(RI) //接收中斷
  480.    {
  481.      RI=0;//中斷標志復位
  482.   ch=SBUF;// 將接收的字符存入ch
  483.   ACC=ch;
  484.   if(RB8==P) //判斷偶校驗
  485.   {
  486.    if(flag==1)
  487.    ecc=ecc+ch;//計算校驗和
  488.   }
  489. else
  490.     RecState=RS_WAIT;//如果偶校驗錯誤,返回等待狀態
  491. if(RecNum!=0) return;//如果主程序正在處理接收緩沖區內容,返回
  492. switch(RecState)  //根據當前狀態和接收字節判斷接收狀態
  493. {
  494.    case 0://等待狀態
  495.    if(ch==0xfe) //前導字符
  496.    {
  497.      RecState++;
  498.   flag=1;//從下一個狀態開始計算校驗和
  499.   
  500.    }
  501.    break;
  502.    case 1:    //喚醒狀態
  503.    if(ch==0x68)   //如果接收幀起始符68H
  504.    {
  505.     RecState++;        //進入接收地址域狀態
  506.         AddCount=0;
  507.    }
  508.    else
  509.    {
  510.     flag=0;
  511.     ecc=0;
  512.     RecState=RS_WAIT;//返回等待狀態
  513.    }
  514.    break;
  515.    case 2: //接收地址域狀態
  516.    *(add+AddCount)=ch;
  517.    AddCount++;
  518.    if(AddCount==6)//如果接受完地址域6個字節
  519.    {
  520.      AddCount=0;// 地址域計數器復位
  521.   RecState++;
  522.     }
  523.       break;
  524.    case 3:  //接收幀頭狀態
  525.    if(ch==0x68)
  526.    RecState++;
  527.    break;
  528.    case 4:  //接收控制碼狀態
  529.    con=ch;//保存控制碼
  530.    RecState++;
  531.    break;
  532.    case 5: //接收數據域長度狀態
  533.    DataLen=ch;//取出數據域長度
  534.    if(DataLen==0)
  535.    RecState=RecState+2;//如果數據域長度為0,直接進入校驗和狀態
  536.    else
  537.    {
  538.     RecState++;
  539.     DataCount=0; //賦初值
  540.    }
  541.    break;
  542.    case 6:   //接收數據狀態
  543.    *(rdata+DataCount)=ch-0x33; //保存數據在rdata[10]數組中
  544.    DataCount++;
  545.    if(DataCount==DataLen) //接收完DataLen個數據
  546.    {
  547.     RecState++;
  548.     DataCount=0;//數據域計數器復位,準備接收下一幀數據
  549.     flag=0; //下一個狀態停止計算檢驗和
  550.    }
  551.    break;
  552.    case  7:
  553.    cs=ch;//保存校驗和
  554.    ecc=ecc^cs;
  555.    if(ecc==0)//校驗和正確
  556.    {
  557.     RecState++;
  558.     ecc=0;
  559.    }
  560.    else
  561.    RecState=RS_WAIT;  //如果校驗和錯誤,返回等待狀態
  562.    break;
  563.    case  8: //接收結束符
  564.    if(ch==0x16) //如果接收幀結束符,表明這一幀接收正確
  565.    {
  566.     RecNum=DataLen;//取出字節數
  567.   DataLen=0;

  568.    }
  569.    RecState=RS_WAIT;// 返回等待狀態
  570.    break;
  571.     }
  572.   }
  573. }
復制代碼

基于 單片機開發板讀表系統仿真電路.PDF

31.83 KB, 下載次數: 131, 下載積分: 黑幣 -5

評分

參與人數 3黑幣 +110 收起 理由
海水千山 + 5 贊一個!
寧采塵 + 5 很給力!
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏14 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:209219 發表于 2017-6-8 15:48 | 只看該作者
樓主方便加下QQ嗎,有些問題想請教,875576671謝謝!
回復

使用道具 舉報

板凳
ID:214844 發表于 2017-6-26 17:00 | 只看該作者
新手很多不懂
回復

使用道具 舉報

地板
ID:217617 發表于 2017-7-7 13:36 | 只看該作者
很實用的作品
回復

使用道具 舉報

5#
ID:157057 發表于 2017-7-7 23:05 | 只看該作者
感謝分享,51黑有你更精彩!!!
回復

使用道具 舉報

6#
ID:249957 發表于 2017-11-16 10:21 | 只看該作者
多謝分享!感覺這個51論壇還是有很多好文章呢。
回復

使用道具 舉報

7#
ID:301327 發表于 2018-4-3 10:17 | 只看該作者
樓主,方便說一下用的哪一種電能表嗎
回復

使用道具 舉報

8#
ID:51443 發表于 2018-4-6 13:55 | 只看該作者
菩提樹下 發表于 2018-4-3 10:17
樓主,方便說一下用的哪一種電能表嗎

通用(DLT645-1997規約),但無用,表不讓讀。
回復

使用道具 舉報

9#
ID:311865 發表于 2018-4-21 16:44 | 只看該作者
電量采集裝置有什么推薦的嗎?直接用一塊電表?
回復

使用道具 舉報

10#
ID:313732 發表于 2018-4-23 13:30 | 只看該作者
怎么回事

錯誤.PNG (103.22 KB, 下載次數: 189)

錯誤.PNG
回復

使用道具 舉報

11#
ID:69408 發表于 2019-12-24 10:16 | 只看該作者
感謝分享,51黑有你更精彩!!!
回復

使用道具 舉報

12#
ID:29579 發表于 2021-10-3 17:19 | 只看該作者
感謝分享,51黑有你更精彩!!!
回復

使用道具 舉報

13#
無效樓層,該帖已經被刪除
14#
ID:137736 發表于 2022-11-2 10:30 | 只看該作者
貼的程序中間亂碼有點多
回復

使用道具 舉報

15#
ID:137736 發表于 2022-11-2 10:31 | 只看該作者

程序中間亂碼需要刪除
回復

使用道具 舉報

16#
ID:195496 發表于 2022-11-3 13:16 | 只看該作者
電度表的地址怎么確定的?
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
91精品国产丝袜白色高跟鞋| 亚洲国产成人精品电影| 黄色欧美视频| 亚洲av综合色区无码一二三区 | 国产乱码精品1区2区3区| 成人欧美在线| 精品日韩在线播放| 日韩一区二区三区在线| 先锋亚洲精品| 成人av福利| 国内精品久久久久久久久久| caoporn超碰97| 欧美成人精品一区| 欧美国产一区二区| 日本在线中文字幕一区| 免费免费啪视频在线观看| 国产一级特黄a高潮片| 亚洲国产精品一区在线观看不卡| 日韩精品中文字幕在线一区| 日本网站在线观看一区二区三区| 欧美被日视频| 亚洲美女综合网| 91精品视频国产| 国产精品伦子伦免费视频| 色综合天天视频在线观看| 欧美成人国产| 尤物yw193can在线观看| 久热视线观看免费视频| 精品少妇人妻一区二区黑料社区| 成人av网站观看| 欧美高清www午色夜在线视频| 日本午夜精品一区二区三区电影| 中文av在线全新| 色偷偷网站视频| 国精品无码一区二区三区| 亚洲欧洲国产日韩精品| 日韩在线视频二区| 亚洲免费视频中文字幕| 精品成人免费| 欧美gay视频| 国产羞羞视频在线观看| 天天综合久久综合| 日本网站在线看| 黑人巨大精品欧美一区二区小视频| 欧美va亚洲va香蕉在线| 91在线精品秘密一区二区| 国产a久久精品一区二区三区| 欧美孕妇孕交xxⅹ孕妇交| 青青草视频在线免费播放| 色吧影院999| 久久女同性恋中文字幕| 91综合久久一区二区| 免费不卡av| 午夜男人天堂| 精品自拍偷拍视频| 日本不卡在线观看视频| 97视频热人人精品| 日韩精品极品视频| 亚洲精品国产a久久久久久| 国产精品视频久久一区| 麻豆精品一区| 国产免费av高清在线| 欧美另类在线视频| 欧美性猛交bbbbb精品| wwwxxx色| 久久久久福利视频| 国产一区欧美二区三区| 一本大道久久加勒比香蕉 | 91精品国产乱码久久久久久蜜臀 | 欧美成人免费在线| 欧美精品videosex牲欧美| 欧美午夜片在线看| 久久九九久久九九| 免费在线观看污视频| 2018亚洲男人天堂| 日韩av在线电影| 黑人玩弄人妻一区二区三区| 在线视频不卡一区二区三区| 国产精品久久久久久久久久久不卡 | 欧美成人a在线| 国产精品麻豆久久久| 久久亚洲欧美| 日韩理论电影| 超碰aⅴ人人做人人爽欧美| 亚洲综合图片| 毛片女人与拘交视频| 成人久久久精品国产乱码一区二区 | 国产精品视频不卡| 一区二区欧美日韩视频| 欧美在线免费观看亚洲| 中文字幕一区二区三区四区不卡 | 国产色视频在线播放| 色一情一区二区三区四区| 国产成人激情小视频| 一二美女精品欧洲| 日韩欧美你懂的| 舔着乳尖日韩一区| www久久久久| 另类中文字幕网| 欧美va天堂在线| 日韩欧美美女在线观看| 三上悠亚亚洲一区| 国产网站在线免费观看| 久久久亚洲精华液精华液精华液 | 日韩电影免费观看在线观看| 天天影视涩香欲综合网| 欧美激情中文字幕| 国产精品影视在线观看| 一区二区三区导航| 日韩精品一区二区三区免费观看| а√天堂中文资源在线bt| 爱久久·www| 开心丁香婷婷深爱五月 | 日韩高清欧美高清| 欧美电影在线免费观看| 亚洲国产综合在线| 国产精品福利一区| av激情亚洲男人天堂| 蜜臀久久久久久久| 性一交一乱一区二区洋洋av| 91亚洲国产成人久久精品| 欧美三级午夜理伦三级小说| 国产麻豆精品| 婷婷激情成人| 久久久加勒比| gay欧美网站| 国产免费拔擦拔擦8x在线播放| 五月婷婷在线观看| 久久天堂电影| 欧美日韩影视| 欧美女子与性| 男女污污视频在线观看| 在线播放av片| 在线国产视频观看| 亚洲图区欧美| 青草久久伊人| 第三区美女视频在线| 日产精品久久久久久久性色| 激情视频免费观看在线| 日本搞黄视频| 在线一二三区| 四虎精品在线| 国产高清视频免费最新在线| 在线看的av网站| 黄页视频在线播放| 免费网站看v片在线a| 超碰在线电影| 中文字幕理伦片免费看| 在线小视频网址| 香蕉av一区| 波多野结衣一区二区| av电影在线播放高清免费观看| 奇米影视888狠狠狠777不卡| 国内精品在线视频| 成人直播在线| 小h片在线观看| 日本在线中文字幕一区二区三区| 久久亚洲人体| 99ri日韩精品视频| 国产精品一国产精品| 久久一本综合| 国产精品草草| 天堂av在线一区| 国产一区亚洲一区| av在线不卡免费看| 国产精品美女久久福利网站| 一区二区三区资源| 欧洲av一区二区嗯嗯嗯啊| 欧美一级高清片在线观看| 日韩国产高清视频在线| www日韩中文字幕在线看| 久久久最新网址| 国产在线观看一区二区三区| 精品九九九九| 亚洲黄色网址在线观看| 欧美视频第一区| 免费啪视频在线观看| 日韩欧美视频免费观看| 黄色片网站在线免费观看| 亚洲精品久久久久久无码色欲四季 | 免费看又黄又无码的网站| 可以在线看的av网站| avtt中文字幕| 欧美黑吊大战白妞| 亚洲乱色熟女一区二区三区| 三级全黄视频| 中文字幕在线影院| 激情国产在线| 国产精品嫩模av在线| 久久av一区| 国产欧美一区二区精品性| 91黄色在线观看| 中文字幕精品一区久久久久| 国产精品成人国产乱一区| 日韩免费一区二区三区| 日韩欧美xxxx| 国产精品久久久久久久av| 91午夜精品亚洲一区二区三区| 爱福利一区二区| 黑巨人与欧美精品一区| 1区2区3区在线视频| 久久99国产精品久久99大师| 蜜桃久久av| 日韩一区在线看| 亚洲精品成人久久电影| 国产精品久久久久久久久久ktv| 午夜老司机精品| 久久黄色一级视频| 99热在线观看免费精品| 欧美性受xxxx黑人xxxx| 免费高清在线| 51一区二区三区| 欧美一区二区三区久久精品| 国产精品综合一区二区| 亚洲欧洲在线观看av| 日韩欧美极品在线观看| 久久视频在线播放| 成人午夜两性视频| 亚洲国产一二三精品无码| 亚洲精品mv在线观看| eeuss中文字幕| 国产精品人人妻人人爽| 天堂在线国产| 18成人免费观看视频漫画| 激情视频在线观看| 久久69av| 99视频精品| jiyouzz国产精品久久| 欧美猛男超大videosgay| 中文字幕在线国产精品| 成人av色在线观看| 97超碰在线人人| 男生裸体视频网站| 六月丁香色婷婷| 99热在线免费| 影院在线观看全集免费观看| 最新亚洲精品| 精品亚洲国产成人av制服丝袜| 亚洲日穴在线视频| 亚洲国产精品美女| 国产欧美一区二区三区四区| 国产亚洲黄色片| 国产精品一区二区亚洲| 亚洲乱色熟女一区二区三区| 日韩专区一区二区| 四虎精品一区二区免费| 一区二区黄色| 一区二区在线观看不卡| 亚洲欧洲一区二区三区久久| 麻豆一区区三区四区产品精品蜜桃| 久久国产精品国产精品| 日韩欧美一区二区一幕| 免费国产h视频在线观看86| 毛片在线播放网址| 欧美videos粗暴| 美女免费视频一区二区| 亚洲一区二区三区在线看| zzjj国产精品一区二区| 青青影院一区二区三区四区| youjizz.com国产| 男人先锋资源| 九色视频在线播放| 欧美极品在线观看| 99久久久国产精品| 欧洲一区二区三区免费视频| 国产一区二区三区在线视频| 亚洲xxxx视频| 五月天视频在线观看| 久久久久久久久黄色| h网站免费看| 日韩亚洲国产免费| 老色鬼精品视频在线观看播放| 在线免费观看日韩欧美| 国产精品久久一区主播| 日韩网址在线观看| 国产乱淫片视频| 深夜爽爽视频| 国内精品国产成人国产三级粉色| 成人午夜在线视频| 日韩hd视频在线观看| 先锋影音男人资源| 久久久久久国产精品免费播放| 曰皮视频在线播放免费的| 日韩影院在线| 欧美精选一区| 欧美日韩不卡在线| 国产欧美日韩免费看aⅴ视频| 亚洲综合色在线观看| 成人黄色片在线观看| 4虎在线播放1区| 精品美女久久| 国产精品网站在线观看| xvideos成人免费中文版| 狠狠精品干练久久久无码中文字幕| 劲爆欧美第一页| 成人免费观看在线网址| 91成人在线精品视频| 97se狠狠狠综合亚洲狠狠| 精品国产一区二区三区久久久蜜月| 日韩一区二区三区资源| 免费高清在线观看电视| 成年网站视频| 91国内精品白嫩初高生| 91首页免费视频| 操91在线视频| 欧美激情成人网| 中文字幕第2页| 成人福利影视| 韩国毛片一区二区三区| 亚洲理论在线a中文字幕| 一区二区三区四区免费视频| 无码人妻一区二区三区线| 四虎影视精品成人| 亚洲精品免费观看| 欧美精品国产精品| 日本一区二区三区精品视频| 日韩av女优在线观看| 轻轻色免费在线视频| 欧美伊人影院| 日韩激情片免费| 久久久国内精品| 亚洲无码精品国产| 1769免费视频在线观看| 国产精品99久久久久久久vr| 中文字幕精品久久| 自拍偷拍 国产| 最新亚洲精品国自产在线观看| 免费观看亚洲天堂| 综合av第一页| 91精品在线播放| 色哟哟一一国产精品| 三级在线观看| 天堂蜜桃91精品| 国产性猛交xxxx免费看久久| av网站在线观看不卡| 性一交一乱一伧老太| 欧美日韩免费电影| 国产精品久久久久久久浪潮网站| 日韩免费中文字幕| 好吊视频在线观看| 樱桃视频免费看| 精品动漫一区| 亚洲乱码国产乱码精品精| 欧美a在线视频| 日本高清色图| 精品国产不卡| 欧美麻豆精品久久久久久| 亚洲一区二区三区四区中文| 亚洲 美腿 欧美 偷拍| avtt久久| 亚洲va欧美va人人爽午夜| 久久99精品久久久水蜜桃| 国产精品一二三四五区| 神马久久资源| 亚洲女同一区二区| 亚洲影院污污.| 亚洲高清毛片一区二区| 电影亚洲精品噜噜在线观看| 亚洲欧美一区二区三区久本道91| 国产日韩久久| 91精品国产高清一区二区三密臀| 日产福利视频在线观看| 亚洲国产精品国自产拍av| 91视频在线免费观看| 国产suv精品一区二区33| 视频91a欧美| 欧美小视频在线| 狠狠噜天天噜日日噜| 亚洲综合欧美色图| 欧美福利电影在线观看| 亚洲性猛交xxxxwww| 91传媒理伦片在线观看| 在线免费观看你懂的| 国产成人免费视频网站| 成人h片在线播放免费网站| 国产精品久免费的黄网站| aa在线视频| 欧美日韩午夜视频在线观看| 国内自拍中文字幕| 国产精品乱码一区二区三区视频| 午夜久久免费观看| 在线视频欧美日韩精品| 亚洲精品中文字幕在线播放| 巨骚激情综合| 亚洲理论在线观看| 欧洲精品视频在线| 一本加勒比hezyo黑人| 狠狠久久婷婷| 国产精品国语对白| 国产精品尤物视频| 亚洲五码在线| 欧美色精品天天在线观看视频| 日日噜噜夜夜狠狠| 香港日本韩国三级| 福利一区二区在线| 极品尤物一区二区三区| 欧美一区二区三区激情| 成人3d精品动漫精品一二三| 亚洲欧美日韩国产精品| 欧美黑人猛猛猛|