找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2531|回复: 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.51hei.com/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 单片机教程网

快速回复 返回顶部 返回列表