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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機如何添加定時上報繼電器狀態功能?

[復制鏈接]
跳轉到指定樓層
樓主
ID:137005 發表于 2021-2-4 17:50 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
100黑幣
各位好,附件想增加定時上報繼電器狀態功能,需要怎么添加?我自己添加了定時器3代碼打印一個狀態,但串口只出現AA,然后就死了。請各位指導,看怎么添加定時上報繼電器狀態功能,謝謝!
void Init_Timer3(void)                //1000微秒@11.0592MHz
{
        T4T3M |= 0x02;                //定時器時鐘1T模式
        T3L = 0xCD;                //設置定時初值
        T3H = 0xD4;                //設置定時初值
        T4T3M |= 0x08;                //定時器3開始計時
        IE2 = ET3;                                  //使能定時器中斷
        EA = 1;
}

void Timer3_isr(void) interrupt 19
{
  unsigned char buf[10];
  unsigned char len=0;
  static INT16U tmr500ms = 0;
  tmr500ms++;
        if(tmr500ms >= 10000)
                                        {
            tmr500ms = 0;
                                buf[0]=0xAA;
                                buf[1]=addr;
                                buf[2]=0xFF;
                                buf[3]=0xFF;
                                buf[4]=0xBB;
                                len=5;
                                UartWrite(buf, len);
                                T3L = 0xCD;                //設置定時初值
                                T3H = 0xD4;                //設置定時初值
                                        }
}
main也添加了        Init_Timer3();

GYJ-0314測試程序.rar

76.47 KB, 下載次數: 4

最佳答案

查看完整內容

由于此標志是放在串口接收中斷函數中等發送完成后置位 flagTxd = 1; 樓主在定時器3中斷函數中調用UartWrite(buf, len);是等不到 flagTxd = 1,所以只發送一個字節后就死在while (!flagTxd); 。 在不改變原代碼的情況下可以另寫一個串口發送函數供定時器3中斷函數中調用。不過開定時器3似乎多余,完全可以在定時器0里增加一個標志,在主循環中定時發送上報繼電器狀態。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:213173 發表于 2021-2-4 17:50 | 只看該作者
由于此標志是放在串口接收中斷函數中等發送完成后置位 flagTxd = 1;  樓主在定時器3中斷函數中調用UartWrite(buf, len);是等不到 flagTxd = 1,所以只發送一個字節后就死在while (!flagTxd); 。
在不改變原代碼的情況下可以另寫一個串口發送函數供定時器3中斷函數中調用。不過開定時器3似乎多余,完全可以在定時器0里增加一個標志,在主循環中定時發送上報繼電器狀態。
回復

使用道具 舉報

板凳
ID:390416 發表于 2021-2-5 08:47 | 只看該作者
串口打印  你必須使用我們這種框架式編程方式,千萬不能有死等。
http://www.zg4o1577.cn/bbs/dpj-201660-1.html
回復

使用道具 舉報

地板
ID:871393 發表于 2021-2-5 09:35 | 只看該作者
是不是串口發送沒有等待發送完成標志位呢
回復

使用道具 舉報

5#
ID:752974 發表于 2021-2-5 09:39 | 只看該作者
波特率是多少?1個毫秒內能發送完這些數據嗎!
回復

使用道具 舉報

6#
ID:752974 發表于 2021-2-5 10:14 | 只看該作者
波特率是多少?一個毫秒時間內能發送完這些數據嗎!設計程序時有一個問題要特別注意,就是中斷服務程序越精簡越好,不要在中斷服務程序中處理數據。對于定時器定時中斷,中斷時間內必須能完成中斷服務程序的執行。
回復

使用道具 舉報

7#
ID:811405 發表于 2021-2-6 11:03 | 只看該作者
繼電器狀態變化導致串口通訊出錯
回復

使用道具 舉報

8#
ID:137005 發表于 2021-2-6 15:13 | 只看該作者
wulin 發表于 2021-2-6 08:34
由于此標志是放在串口接收中斷函數中等發送完成后置位 flagTxd = 1;  樓主在定時器3中斷函數中調用UartWrit ...

應該是這樣的,我換成LED燈就可以,但換成串口就不行。能示例一下,在定時器0怎么添加實現上報繼電器功能嗎?
回復

使用道具 舉報

9#
ID:213173 發表于 2021-2-6 21:08 | 只看該作者
molo 發表于 2021-2-6 15:13
應該是這樣的,我換成LED燈就可以,但換成串口就不行。能示例一下,在定時器0怎么添加實現上報繼電器功能 ...

在定時器0里增加一個10秒標志flag,在主循環中添加Report()函數,定時發送上報繼電器狀態。
  1. #include <STC8F2K08S2.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char//宏定義無符號字符型
  4. #define uint unsigned int  //宏定義無符號整型

  5. typedef unsigned char  INT8U;
  6. typedef unsigned int   INT16U;
  7. #define ENABLE_ISP 0x82 //系統工作時鐘<20MHz 時,對IAP_CONTR 寄存器設置此值
  8. #define WD1        0x5a        //使用STC11xx系列單片機時,先寫入0x5a,然寫入0xa5
  9. #define WD2        0xa5
  10. char IAPAddr=0;

  11. unsigned char T0RH = 0;  //T0重載值的高字節
  12. unsigned char T0RL = 0;  //T0重載值的低字節
  13. bit flagFrame = 0;  //幀接收完成標志,即接收到一幀新數據
  14. bit flagTxd = 0;    //單字節發送完成標志,用來替代TXD中斷標志位
  15. unsigned char cntRxd = 0;   //接收字節計數器
  16. unsigned char pdata bufRxd[50];  //接收字節緩沖區
  17. void UartDriver();//串口驅動函數,監測數據幀的接收,調度功能函數,需在主循環中調用
  18. void UartAction(unsigned char *buf, unsigned char len);//在接收到的數據幀后添加換車換行符后發回
  19. void UartWrite(unsigned char *buf, unsigned char len);//串口數據寫入,即串口發送函數,buf-待發送數據的指針,len-指定的發送長度
  20. unsigned char UartRead(unsigned char *buf, unsigned char len);//串口數據讀取函數,buf-接收指針,len-指定的讀取長度,返回值-實際讀到的長度
  21. void UartRxMonitor(unsigned char ms);//串口接收監控,由空閑時間判定幀結束,需在定時中斷中調用,ms-定時間隔

  22. bit flagFrame2 = 0;  //幀接收完成標志,即接收到一幀新數據
  23. bit flagTxd2 = 0;    //單字節發送完成標志,用來替代TXD中斷標志位
  24. unsigned char cnt2Rxd = 0;   //接收字節計數器
  25. unsigned char pdata buf2Rxd[50];  //接收字節緩沖區
  26. void Uart2Driver();//串口驅動函數,監測數據幀的接收,調度功能函數,需在主循環中調用
  27. void Uart2Action(unsigned char *buf2, unsigned char len2);//在接收到的數據幀后添加換車換行符后發回
  28. void Uart2Write(unsigned char *buf2, unsigned char len2);//串口數據寫入,即串口發送函數,buf-待發送數據的指針,len-指定的發送長度
  29. unsigned char UartRead(unsigned char *buf2, unsigned char len2);//串口數據讀取函數,buf-接收指針,len-指定的讀取長度,返回值-實際讀到的長度

  30. void ConfigUART(unsigned int baud);//串口配置函數,baud-通信波特率
  31. void ConfigTimer0(unsigned int ms);//配置并啟動T0,ms-T0定時時間
  32. void Report(void);

  33. sbit IN_1  = P3^7;
  34. sbit IN_2  = P3^6;
  35. sbit IN_3  = P3^3;
  36. sbit IN_4  = P3^2;
  37. sbit out1  = P5^5;
  38. sbit out2  = P5^4;
  39. sbit out3  = P1^7;
  40. sbit out4  = P1^6;

  41. bit bz1=0,bz2=0,bz3=0,bz4=0;
  42. bit k=0,k1=0,bk1=0,ks=0,bzw=0;
  43. bit flag=0;
  44. uchar addr=0x00,xx_1=0,xx_2=0,xx_3=0,xx_4=0,zz=0x00;
  45. uchar y_1=0,y_2=0,y_3=0,y_4=0,zy=0x00,zt=0x00;
  46. uint js=0;
  47. /********************************************************************
  48.                             E2P函數
  49. *********************************************************************/
  50. union union_temp16
  51. {
  52.     INT16U un_temp16;
  53.     INT8U  un_temp8[2];
  54. }my_unTemp16;

  55. INT8U Byte_Read(INT16U add);              //讀一字節,調用前需打開IAP 功能
  56. void Byte_Program(INT16U add, INT8U ch);  //字節編程,調用前需打開IAP 功能
  57. void Sector_Erase(INT16U add);            //擦除扇區
  58. void IAP_Disable();                       //關閉IAP 功能

  59. void UartAction(unsigned char *buf, unsigned char len){//接收  
  60.            if((buf[0] == 0xAA)&&(buf[1] == addr)&&(buf[2] == 0x01)&&(buf[4] == 0xBB)&&(len==5)) //更改板子地址
  61.                  {
  62.                           addr=buf[3];k=1;
  63.                           buf[0] = 0xAA;
  64.                     buf[1] = addr;
  65.                     buf[2] = 0x01;
  66.                                 buf[3] = 0x01;
  67.                           buf[4] = 0x00;
  68.                                 buf[5] = 0xBB;
  69.                     len = 6;
  70.                     UartWrite(buf,len);
  71.                  }
  72.            if ((buf[0] == 0xAA)&&(buf[1] == addr)&&(buf[2] == 0x02)&&(buf[4] == 0xBB)&&(len==5))  //打開對應輸出
  73.         {
  74.                                   switch(buf[3])
  75.                                         {
  76.                                                 case 1:out1=0;break;
  77.                                                 case 2:out2=0;break;
  78.                                                 case 3:out3=0;break;
  79.                                                 case 4:out4=0;break;
  80.                                                 default:break;
  81.                                         }
  82.                 buf[0] = 0xAA;
  83.                      buf[1] = addr;
  84.                      buf[2] = 0x02;
  85.                                  buf[3] = buf[3];
  86.                                  buf[4] = 0xFF;
  87.                                  buf[5] = 0xBB;
  88.                      len = 6;
  89.                      UartWrite(buf,len);
  90.         }
  91.                  if ((buf[0] == 0xAA)&&(buf[1] == addr)&&(buf[2] == 0x03)&&(buf[4] == 0xBB)&&(len==5))  //關閉對應輸出
  92.         {                                         
  93.                                         switch(buf[3])
  94.                                         {
  95.                                                 case 1:out1=1;break;
  96.                                                 case 2:out2=1;break;
  97.                                                 case 3:out3=1;break;
  98.                                                 case 4:out4=1;break;
  99.                                                 default:break;
  100.                                         }
  101.                                  
  102.                 buf[0] = 0xAA;
  103.                      buf[1] = addr;
  104.                      buf[2] = 0x03;
  105.                                  buf[3] = buf[3];
  106.                                  buf[4] = 0x00;
  107.                                  buf[5] = 0xBB;
  108.                      len = 6;
  109.                      UartWrite(buf,len);
  110.         }
  111.                                
  112.                         if ((buf[0] == 0xAA)&&(buf[1] == addr)&&(buf[2] == 0x04)&&(buf[3] == 0x04)&&(buf[4] == 0xBB)&&(len==5))  //查詢輸入狀態
  113.         {                                         
  114.                             if(IN_1==0){xx_1=0x01;}else{xx_1=0x00;}
  115.                                         if(IN_2==0){xx_2=0x02;}else{xx_2=0x00;}
  116.                                         if(IN_3==0){xx_3=0x04;}else{xx_3=0x00;}
  117.                                         if(IN_4==0){xx_4=0x08;}else{xx_4=0x00;}
  118.                                  zz = ((xx_1)|(xx_2)|(xx_3)|(xx_4));
  119.                 buf[0] = 0xAA;
  120.                      buf[1] = addr;
  121.                      buf[2] = 0x04;                       
  122.                                  buf[3] = 0x04;
  123.                                  buf[4] = zz;
  124.                                  buf[5] = 0xBB;
  125.                      len = 6;
  126.                      UartWrite(buf,len);
  127.         }
  128.                                
  129.                         if ((buf[0] == 0xAA)&&(buf[1] == addr)&&(buf[2] == 0x05)&&(buf[3] == 0x04)&&(buf[4] == 0xBB)&&(len==5))  //查詢輸出狀態
  130.         {                                         
  131.                             if(out1==0){y_1=0x01;}else{y_1=0x00;}
  132.                                         if(out2==0){y_2=0x02;}else{y_2=0x00;}
  133.                                         if(out3==0){y_3=0x04;}else{y_3=0x00;}
  134.                                         if(out4==0){y_4=0x08;}else{y_4=0x00;}
  135.                                  zy = ((y_1)|(y_2)|(y_3)|(y_4));
  136.                 buf[0] = 0xAA;
  137.                      buf[1] = addr;
  138.                      buf[2] = 0x05;                       
  139.                                  buf[3] = 0x04;
  140.                                  buf[4] = zy;
  141.                                  buf[5] = 0xBB;
  142.                      len = 6;
  143.                      UartWrite(buf,len);
  144.         }
  145.                                
  146.                  if ((buf[0] == 0xAA)&&(buf[1] == 0x00)&&(buf[2] == 0x07)&&(buf[4] == 0xBB)&&(len==5))  //廣播控制輸出狀態
  147.         {               
  148.                                         zt=buf[3];
  149.           if((zt&0x01)==0x01){out1=0;}else{out1=1;}
  150.                                         if((zt&0x02)==0x02){out2=0;}else{out2=1;}
  151.                                         if((zt&0x04)==0x04){out3=0;}else{out3=1;}
  152.                                         if((zt&0x08)==0x08){out4=0;}else{out4=1;}
  153.                 buf[0] = 0xAA;
  154.                      buf[1] = addr;
  155.                      buf[2] = 0x07;                       
  156.                                  buf[3] = 0x04;
  157.                                  buf[4] = zt;
  158.                                  buf[5] = 0xBB;
  159.                      len = 6;
  160.                      UartWrite(buf,len);
  161.         }
  162.                                
  163.                                 if ((buf[0] == 0xAA)&&(buf[1] == 0x00)&&(buf[2] == 0x00)&&(buf[3] == 0x00)&&(buf[4] == 0xBB)&&(len==5))  //查詢板子地址
  164.                                 {
  165.                                  buf[0] = 0xAA;
  166.                      buf[1] = addr;
  167.                      buf[2] = 0x00;
  168.                                  buf[3] = 0x01;
  169.                                  buf[4] = 0x00;
  170.                                  buf[5] = 0xBB;
  171.                      len = 6;
  172.                      UartWrite(buf,len);
  173.                                 }
  174. }

  175. void Uart2Action(unsigned char *buf2, unsigned char len2)//接收
  176. {
  177.         if ((buf2[0] == 0xAA)&&(buf2[1] == addr)&&(buf2[2] == 0x02)&&(buf2[4] == 0xBB)&&(len2==5))  //打開
  178.         {
  179.                 switch(buf2[3])
  180.                 {
  181.                         case 1:out1=0;break;
  182.                         case 2:out2=0;break;
  183.                         case 3:out3=0;break;
  184.                         case 4:out4=0;break;
  185.                         default:break;
  186.                 }
  187.                 buf2[0] = 0xAA;
  188.                 buf2[1] = addr;
  189.                 buf2[2] = 0x02;
  190.                 buf2[3] = buf2[3];
  191.                 buf2[4] = 0xFF;
  192.                 buf2[5] = 0xBB;
  193.                 len2 = 6;
  194.                 Uart2Write(buf2,len2);
  195.         }
  196.         if ((buf2[0] == 0xAA)&&(buf2[1] == addr)&&(buf2[2] == 0x03)&&(buf2[4] == 0xBB)&&(len2==5))  //關閉
  197.         {                                         
  198.                 switch(buf2[3])
  199.                 {
  200.                         case 1:out1=1;break;
  201.                         case 2:out2=1;break;
  202.                         case 3:out3=1;break;
  203.                         case 4:out4=1;break;
  204.                         default:break;
  205.                 }                                 
  206.                 buf2[0] = 0xAA;
  207.                 buf2[1] = addr;
  208.                 buf2[2] = 0x03;
  209.                 buf2[3] = buf2[3];
  210.                 buf2[4] = 0xFF;
  211.                 buf2[5] = 0xBB;
  212.                 len2 = 6;
  213.                 Uart2Write(buf2,len2);
  214.         }
  215. }

  216. void ConfigTimer0(unsigned int ms)//配置并啟動T0,ms-T0定時時間
  217. {
  218.   unsigned long tmp;  //臨時變量   
  219.     tmp = 11059200 / 12;      //定時器計數頻率
  220.     tmp = (tmp * ms) / 1000;  //計算所需的計數值
  221.     tmp = 65536 - tmp;        //計算定時器重載值
  222.     tmp = tmp + 33;           //補償中斷響應延時造成的誤差
  223.     T0RH = (unsigned char)(tmp>>8);  //定時器重載值拆分為高低字節
  224.     T0RL = (unsigned char)tmp;
  225.     TMOD &= 0xF0;   //清零T0的控制位
  226.     TMOD |= 0x01;   //配置T0為模式1
  227.     TH0 = T0RH;     //加載T0重載值
  228.     TL0 = T0RL;
  229.     ET0 = 1;        //使能T0中斷
  230.     TR0 = 1;        //啟動T0
  231. }

  232. void ConfigUART(unsigned int baud)//串口配置函數,baud-通信波特率                                 
  233. {
  234.     SCON  = 0x50;  //配置串口為模式1
  235.     TMOD &= 0x0F;  //清零T1的控制位
  236.     TMOD |= 0x20;  //配置T1為模式2
  237.     TH1 = 256 - (11059200/12/32)/baud;  //計算T1重載值
  238.     TL1 = TH1;     //初值等于重載值
  239.     ET1 = 0;       //禁止T1中斷         
  240.     TR1 = 1;       //啟動T1
  241.        
  242. }
  243. void Config2UART()         //串口2配置
  244. {
  245.         S2CON = 0x50;
  246.         AUXR |= 0x04;
  247.         T2L = 0xE0;                                 //65536-11059200/115200/4=0FFE8H
  248.         T2H = 0xFE;
  249.         AUXR |= 0x10;                                //啟動定時器
  250.         IE2 = 0x01;
  251. }
  252. void senddate()//發送輸入狀態
  253. {
  254.                 unsigned char  buf[10];
  255.    unsigned char len=0;
  256.         if((k1==1)&&(bk1==0))
  257.         {
  258.                 bk1=1;
  259.          if(IN_1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;}//查詢輸入狀態打開為1,關閉為0
  260.          if(IN_2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}//查詢輸入狀態打開為1,關閉為0
  261.          if(IN_3 == 0){xx_3 = 0x04;}else{xx_3 = 0x00;}//查詢輸入狀態打開為1,關閉為0
  262.          if(IN_4 == 0){xx_4 = 0x08;}else{xx_4 = 0x00;}//查詢輸入狀態打開為1,關閉為0
  263.          zz = ((xx_1)|(xx_2)|(xx_3)|(xx_4));
  264.          buf[0]=0xAA;
  265.          buf[1]=addr;
  266.          buf[2]=0x06;
  267.          buf[3]=0x04;
  268.          buf[4]=zz;
  269.          buf[5]=0xBB;
  270.          len=6;
  271.          UartWrite(buf, len);
  272.          Uart2Write(buf, len);
  273.          k1=0;
  274.          ks=1;
  275.         }
  276.         if(bzw==1){bzw=0;bk1=0;}//消抖延時后清零
  277. }
  278. void main()
  279. {
  280.         P1M0 = 0xC0;   //
  281.         P1M1 = 0x00;
  282.         P5M0 = 0xFF;   //
  283.         P5M1 = 0x00;
  284.         EA = 1;ES  = 1;     //開總中斷
  285.         ConfigTimer0(1);   //配置T0定時1ms
  286.         ConfigUART(9600);  //配置波特率為9600
  287.         Config2UART();
  288.         out3=1;out4=1;out1=1;out2=1;//
  289.         if(Byte_Read(0X0001)==0xff){addr=0;}//首次讀取,如果讀到0xFF說明沒有存過數據,直接付給00值
  290.         else
  291.         {
  292.                 addr=Byte_Read(0X0001);
  293.         }
  294.         while(1)
  295.         {
  296.                 if((IN_1==0)&&(bz1==0)){bz1=1;k1=1;out1=0;}//點動
  297.                 if((IN_1==1)&&(bz1==1)){bz1=0;k1=1;out1=1;}
  298.                
  299.                 if((IN_2==0)&&(bz2==0)){bz2=1;k1=1;out2=0;}//點動
  300.                 if((IN_2==1)&&(bz2==1)){bz2=0;k1=1;out2=1;}
  301.                
  302.                 if((IN_3==0)&&(bz3==0)){bz3=1;k1=1;out3=0;}//點動
  303.                 if((IN_3==1)&&(bz3==1)){bz3=0;k1=1;out3=1;}
  304.                
  305.                 if((IN_4==0)&&(bz4==0)){bz4=1;k1=1;out4=0;}//點動
  306.                 if((IN_4==1)&&(bz4==1)){bz4=0;k1=1;out4=1;}
  307.                
  308.                 senddate();//發送輸入狀態
  309.                 UartDriver();  //調用串口驅動
  310.                 Uart2Driver();
  311.                 Report();               
  312.                 if(k==1)        //E2P
  313.                 {
  314.                         Sector_Erase(0);
  315.                         Byte_Program(0x0001,addr);  //寫入扇區
  316.                         k=0;
  317.                 }

  318.         }
  319. }
  320. void InterruptTimer0() interrupt 1//T0中斷服務函數,執行串口接收監控
  321. {
  322.         static unsigned int Cnt_1ms;
  323.         TH0 = T0RH;  //重新加載重載值
  324.         TL0 = T0RL;
  325.         UartRxMonitor(1);  //串口接收監
  326.         if(ks==1){js++;if(js==320){js=0;bzw=1;ks=0;}}       
  327.         Cnt_1ms++;
  328.         if(Cnt_1ms >= 10000)//10秒
  329.         {
  330.                 Cnt_1ms = 0;               
  331.                 flag=1;
  332.         }
  333. }
  334. void InterruptUART() interrupt 4{//串口中斷服務函數
  335.     if (RI) { //接收到新字節
  336.         RI = 0;  //清零接收中斷標志位
  337.         if (cntRxd < sizeof(bufRxd)) {//接收緩沖區尚未用完時,保存接收字節,并遞增計數器
  338.             bufRxd[cntRxd++] = SBUF;        // cntRxd++這個很重要,一開始 cntRxd < sizeof(bufRxd)當進入函數的次數增加,cntRxd慢慢變大,當傳入的數據不滿的時候就        用時間檢測,判斷是否是傳輸完成
  339.         }
  340.     }
  341.     if (TI) { //字節發送完畢
  342.         TI = 0;   //清零發送中斷標志位
  343.         flagTxd = 1;  //設置字節發送完成標志
  344.     }
  345. }

  346. /********************************************************************
  347.                          串口二(485) 發送接收中斷函數
  348. *********************************************************************/
  349. void uart2_isr()  interrupt 8
  350. {
  351.         if( S2CON & 0x01 )
  352.         {
  353.                 S2CON &= ~0x01;
  354.            if (cnt2Rxd < sizeof(buf2Rxd)) {//接收緩沖區尚未用完時,保存接收字節,并遞增計數器
  355.             buf2Rxd[cnt2Rxd++] = S2BUF;        // cntRxd++這個很重要,一開始 cntRxd < sizeof(bufRxd)當進入函數的次數增加,cntRxd慢慢變大,當傳入的數據不滿的時候就        用時間檢測,判斷是否是傳輸完成
  356.         }
  357.         }
  358.         if( S2CON & 0x02 )
  359.         {
  360.                 S2CON &= ~0x02;
  361.                 flagTxd2 = 1;  //設置字節發送完成標志
  362.         }
  363. }

  364. void UartWrite(unsigned char *buf, unsigned char len)//串口數據寫入,即串口發送函數,buf-待發送數據的指針,len-指定的發送長度
  365. {
  366.         while (len--)   //循環發送所有字節
  367.         {
  368.                 flagTxd = 0;      //清零發送標志
  369.                 SBUF = *buf;    //發送一個字節數據
  370.                 buf++;
  371.                 while (!flagTxd); //等待該字節發送完成
  372.         }
  373. }

  374. void Uart2Write(unsigned char *buf2, unsigned char len2){//串口數據寫入,即串口發送函數,buf-待發送數據的指針,len-指定的發送長度
  375.     while (len2--){   //循環發送所有字節
  376.         flagTxd2 = 0;      //清零發送標志
  377.         S2BUF = *buf2;    //發送一個字節數據
  378.                 buf2++;
  379.         while (!flagTxd2); //等待該字節發送完成
  380.     }
  381. }

  382. unsigned char UartRead(unsigned char *buf, unsigned char len){//串口數據讀取函數,buf-接收指針,len-指定的讀取長度,返回值-實際讀到的長度
  383.     unsigned char i;
  384.     if (len > cntRxd){  //指定讀取長度大于實際接收到的數據長度時,讀取長度設置為實際接收到的數據長度
  385.         len = cntRxd;
  386.     }

  387.     for (i=0; i<len; i++){  //拷貝接收到的數據到接收指針上
  388.         *buf++ = bufRxd[i];
  389.     }

  390.     cntRxd = 0;  //接收計數器清零
  391.     return len;  //返回實際讀取長度
  392. }

  393. unsigned char Uart2Read(unsigned char *buf2, unsigned char len2){//串口數據讀取函數,buf-接收指針,len-指定的讀取長度,返回值-實際讀到的長度
  394.     unsigned char i;
  395.     if (len2 > cnt2Rxd){  //指定讀取長度大于實際接收到的數據長度時,讀取長度設置為實際接收到的數據長度
  396.         len2 = cnt2Rxd;
  397.     }

  398.     for (i=0; i<len2; i++){  //拷貝接收到的數據到接收指針上
  399.         *buf2++ = buf2Rxd[i];
  400.     }

  401.     cnt2Rxd = 0;  //接收計數器清零
  402.     return len2;  //返回實際讀取長度
  403. }

  404. void UartDriver(){//串口驅動函數,監測數據幀的接收,調度功能函數,需在主循環中調用
  405.     unsigned char len;
  406.     unsigned char pdata buf[50];
  407.     if (flagFrame){ //有命令到達時,讀取處理該命令
  408.         flagFrame = 0;
  409.         len = UartRead(buf, sizeof(buf)-2); //將接收到的命令讀取到緩沖區中
  410.         UartAction(buf, len);  //傳遞數據幀,調用動作執行函數
  411.     }
  412. }

  413. void Uart2Driver(){//串口驅動函數,監測數據幀的接收,調度功能函數,需在主循環中調用
  414.     unsigned char len2;
  415.     unsigned char pdata buf2[50];
  416.     if (flagFrame2){ //有命令到達時,讀取處理該命令
  417.         flagFrame2 = 0;
  418.         len2 = Uart2Read(buf2, sizeof(buf2)-2); //將接收到的命令讀取到緩沖區中
  419.         Uart2Action(buf2, len2);  //傳遞數據幀,調用動作執行函數
  420.     }
  421. }

  422. void UartRxMonitor(unsigned char ms){//串口接收監控,由空閑時間判定幀結束,需在定時中斷中調用,ms-定時間隔
  423.     static unsigned char cntbkp = 0;
  424.     static unsigned char idletmr = 0;
  425.     if (cntRxd > 0){  //接收計數器大于零時,監控總線空閑時間
  426.         if (cntbkp != cntRxd){  //接收計數器改變,即剛接收到數據時,清零空閑計時
  427.             cntbkp = cntRxd;
  428.             idletmr = 0;
  429.         }else{                   //接收計數器未改變,即總線空閑時,累積空閑時間
  430.             if (idletmr < 30){  //空閑計時小于30ms時,持續累加
  431.                 idletmr += ms;
  432.                 if (idletmr >= 30){  //空閑時間達到30ms時,即判定為一幀接收完畢
  433.                     flagFrame = 1;  //設置幀接收完成標志
  434.                 }
  435.             }
  436.         }
  437.     }else if(cnt2Rxd > 0){
  438.         if (cntbkp != cnt2Rxd){
  439.             cntbkp = cnt2Rxd;
  440.             idletmr = 0;
  441.         }else{
  442.             if (idletmr < 30){
  443.                 idletmr += ms;
  444.                 if (idletmr >= 30){  
  445.                     flagFrame2 = 1; }}
  446.         }               
  447.         }
  448.         else{
  449.         cntbkp = 0;
  450.     }
  451. }
  452. //讀一字節,調用前需打開IAP 功能,入口:DPTR = 字節地址,返回:A = 讀出字節
  453. INT8U Byte_Read(INT16U add)
  454. {
  455.     IAP_DATA = 0x00;
  456.     IAP_CONTR = ENABLE_ISP;         //打開IAP 功能, 設置Flash 操作等待時間
  457.     IAP_CMD = 0x01;                 //IAP/ISP/EEPROM 字節讀命令

  458.     my_unTemp16.un_temp16 = add;
  459.     IAP_ADDRH = my_unTemp16.un_temp8[0];    //設置目標單元地址的高8 位地址
  460.     IAP_ADDRL = my_unTemp16.un_temp8[1];    //設置目標單元地址的低8 位地址

  461.     //EA = 0;
  462.     IAP_TRIG = WD1;   //先送 WD1,再送WD2 到ISP/IAP 觸發寄存器,每次都需如此
  463.     IAP_TRIG = WD2;   //送完WD2 后,ISP/IAP 命令立即被觸發起動
  464.     _nop_();
  465.     //EA = 1;
  466.     IAP_Disable();  //關閉IAP 功能, 清相關的特殊功能寄存器,使CPU 處于安全狀態,
  467.                     //一次連續的IAP 操作完成之后建議關閉IAP 功能,不需要每次都關
  468.     return (IAP_DATA);
  469. }
  470. /*********************************************************************************************/
  471. //字節編程,調用前需打開IAP 功能,入口:DPTR = 字節地址, A= 須編程字節的數據
  472. void Byte_Program(INT16U add, INT8U ch)
  473. {
  474.     IAP_CONTR = ENABLE_ISP;         //打開 IAP 功能, 設置Flash 操作等待時間
  475.     IAP_CMD = 0x02;                 //IAP/ISP/EEPROM 字節編程命令

  476.     my_unTemp16.un_temp16 = add;
  477.     IAP_ADDRH = my_unTemp16.un_temp8[0];    //設置目標單元地址的高8 位地址
  478.     IAP_ADDRL = my_unTemp16.un_temp8[1];    //設置目標單元地址的低8 位地址

  479.     IAP_DATA = ch;                  //要編程的數據先送進IAP_DATA 寄存器
  480.     //EA = 0;
  481.     IAP_TRIG = WD1;   //先送 WD1,再送WD2 到ISP/IAP 觸發寄存器,每次都需如此
  482.     IAP_TRIG = WD2;   //送完WD2 后,ISP/IAP 命令立即被觸發起動
  483.     _nop_();
  484.     //EA = 1;
  485.     IAP_Disable();  //關閉IAP 功能, 清相關的特殊功能寄存器,使CPU 處于安全狀態,
  486.                     //一次連續的IAP 操作完成之后建議關閉IAP 功能,不需要每次都關
  487. }
  488. /*********************************************************************************************
  489. //擦除扇區, 入口:DPTR = 扇區地址 */
  490. void Sector_Erase(uint addr)
  491. {
  492.     IAP_CONTR = ENABLE_ISP;         //打開IAP 功能, 設置Flash 操作等待時間
  493.     IAP_CMD = 3;                 //IAP/ISP/EEPROM 扇區擦除命令

  494. //    my_unTemp16.un_temp16 = add;
  495.     IAP_ADDRH = addr>>8;    //設置目標單元地址的高8 位地址
  496.     IAP_ADDRL = addr;    //設置目標單元地址的低8 位地址

  497.     IAP_TRIG = 0x5a;   //先送 WD1,再送WD2 到ISP/IAP 觸發寄存器,每次都需如此
  498.     IAP_TRIG = 0xa5;   //送完WD2 后,ISP/IAP 命令立即被觸發起動
  499.     _nop_();
  500.     //EA = 1;
  501.     IAP_Disable();  //關閉IAP 功能, 清相關的特殊功能寄存器,使CPU 處于安全狀態,
  502.                     //一次連續的IAP 操作完成之后建議關閉IAP 功能,不需要每次都關
  503. }
  504. /*********************************************************************************************/
  505. void IAP_Disable()
  506. {
  507.     //關閉IAP 功能, 清相關的特殊功能寄存器,使CPU 處于安全狀態,
  508.     //一次連續的IAP 操作完成之后建議關閉IAP 功能,不需要每次都關
  509.     IAP_CONTR = 0;      //關閉IAP 功能
  510.     IAP_CMD   = 0;      //清命令寄存器,使命令寄存器無命令,此句可不用
  511.     IAP_TRIG  = 0;      //清命令觸發寄存器,使命令觸發寄存器無觸發,此句可不用
  512.     IAP_ADDRH = 0x80;
  513.     IAP_ADDRL = 0;
  514. }
  515. /*********************************************************************************************/

  516. void Report(void)
  517. {
  518.         unsigned char buf[5];
  519.         unsigned char i;
  520.         if(flag==1)
  521.         {
  522.                 flag=0;
  523.                 buf[0]=0xAA;
  524.                 buf[1]=addr;
  525.                 buf[2]=0xFF;
  526.                 buf[3]=0xFF;
  527.                 buf[4]=0xBB;
  528.                 ES=0;                //關串口中斷
  529.                 for(i=0;i<5;i++)
  530.                 {
  531.                         SBUF=buf[i];//發送數據
  532.                         while(!TI);        //等待發送中斷請求標志位為1
  533.                         TI=0;                //發送中斷請求標志位清0
  534.                 }
  535.                 ES=1;                //開串口中斷
  536.         }
  537. }
復制代碼
回復

使用道具 舉報

10#
ID:137005 發表于 2021-2-8 08:17 | 只看該作者
wulin 發表于 2021-2-6 21:08
在定時器0里增加一個10秒標志flag,在主循環中添加Report()函數,定時發送上報繼電器狀態。

非常好,這個就是我想要的功能,再次感謝!謝謝!
回復

使用道具 舉報

11#
ID:213173 發表于 2021-3-12 14:58 | 只看該作者
molo 發表于 2021-2-8 08:17
非常好,這個就是我想要的功能,再次感謝!謝謝!

視頻.zip (3.91 MB, 下載次數: 5)
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产日韩欧美一区 | 国产精品久久久久久一区二区三区 | 中文字幕 在线观看 | 蜜桃综合在线 | 亚洲国产精品一区二区第一页 | 日韩精品一区二区三区在线播放 | 国产精品视频综合 | 免费视频二区 | 91av免费观看 | 成人在线不卡 | 伊人狼人影院 | 久久国内| 免费国产一区 | 国产午夜精品久久久 | 国产美女黄色片 | 国产精品一区在线观看 | 久久国产视频播放 | 成人精品视频 | 日日摸夜夜添夜夜添特色大片 | 欧美日韩亚洲一区 | 日韩视频在线一区 | 欧美日韩专区 | 久国产精品 | 免费看91| 国产免费自拍 | 欧美日韩黄色一级片 | 久久精品久久久 | 精品国产99| 天天干天天爱天天 | 在线视频成人 | 97偷拍视频 | 欧美一区2区三区3区公司 | 国产精品久久一区二区三区 | 日韩欧美成人精品 | 亚洲精品在 | 久在线精品视频 | 国产玖玖| 久久一日本道色综合久久 | 亚洲aⅴ | 亚洲网站在线观看 | www.婷婷|