找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2068|回复: 2
打印 上一主题 下一主题
收起左侧

C51单片机接收到一个开关量之后,通过串口RS485发送一个指令出来

[复制链接]
跳转到指定楼层
楼主
ID:115923 发表于 2020-12-17 22:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. *********************************************************************/
  2. #include "main.h"
  3. #include "init.h"

  4. #define ENABLE_IAP 0x83 //系统工作时钟<12MHz 时,对IAP_CONTR 寄存器设置此值
  5. #define CMD_IDLE 0
  6. #define CMD_READ 1
  7. #define CMD_PROGRAM 2
  8. #define CMD_ERASE 3
  9. #define ENABLE_IAP 0x83//SYSCLK<12MH
  10. #define IAP_ADDRESS 0x0000        //存储地址


  11. uint8 add;    //掉电保持485的地址
  12. uint8 j=0;
  13. uint8 dat=0X00;   
  14. bit flag_zx=0;
  15.         bit bz1=0;
  16.         bit bz2=0;
  17.         bit bz3=0;
  18.         bit bz4=0;
  19.         bit bz5=0;
  20.         bit bz6=0;
  21.         bit bz7=0;
  22.         bit bz8=0;
  23. uint8 sendPosi=0;     //发送缓冲区指针
  24. uint8 receCount=0;    //接收缓冲区指针
  25. uint8 sendCount=0;    //需要发送数据个数
  26. uint8 receTimeOut=0;  //通讯超时值
  27. uint8 byteCount=5;    //发送个数

  28. uint8 sendBuf[10];          //发送缓冲区
  29. uint8 receBuf[10];    //接收缓冲区

  30. /********************************************************************
  31.                            定义数据类型
  32. *********************************************************************/
  33. uint8 TBUF,RBUF;
  34. uint8 TDAT,RDAT;
  35. uint8 TCNT,RCNT;
  36. uint8 TBIT,RBIT;
  37. bit TING,RING;
  38. bit TEND,REND;

  39. uint8 t,r,ii;                  //定义数据类型
  40. uint8 but[16];          //数据存储数组
  41. /********************************************************************
  42.                             定义 ISP/IAP/EEPROM 命令
  43. *********************************************************************/

  44. void IapIdle();//禁用 ISP/IAP/EEPROM functionmake 单片机 在 一 安全 状态
  45. uint8 IapReadByte(uint16 addr);//读数据
  46. void IapProgramByte(uint16 addr, uint8 dat);//写数据
  47. void IapEraseSector(uint16 addr);//擦除数据


  48. void delay()//延时程序
  49. {
  50.         uint8 m,n,s;
  51.         for(m=10;m>0;m--)
  52.         for(n=20;n>0;n--)
  53.         for(s=248;s>0;s--);
  54. }




  55. /****************发送函数*********************/
  56. void senduart2()
  57. {            RS485_DIR=1;
  58.         for(ii=0;ii<5;ii++)
  59.                 {
  60.                     if(TEND)          //允许发送
  61.                         {
  62.                                  TEND=0;
  63.                                  TBUF=sendBuf[t++&0x0F];
  64.                                  TING=1;
  65.                         }
  66.                         while(!TEND);
  67.                 }
  68.                 t=0;
  69.                 RS485_DIR=0;
  70. }
  71. /*****************清空发送缓冲区*************************/
  72. void clear_receBuf()
  73. {
  74.     uint8 i;
  75.         for(i=0;i<5;i++)
  76.         {
  77.             receBuf[i]=0;
  78.         }
  79. }
  80. void main()
  81. {
  82.            delay();
  83.     clear_receBuf();
  84.     add= IapReadByte(0x01);//读取存储的值
  85.           if(add==0xff)
  86.           add=0x00;
  87.     ConfigUART1();
  88.           TR0=1;
  89.           EA=1;
  90.     while(1)
  91.         {  
  92.            if(REND)  //如果有接收
  93.            {
  94.              REND=0; //接收标志清零
  95.              receBuf[r++&0x0F]=RBUF;     //把接受的数据存储到BUT数组中
  96.                          if(receBuf[0]!=0xaa){r=0;}
  97.                  if(r>=5)
  98.                  {        r=0;

  99.                     flag_zx=1;
  100.                  }
  101.            }
  102.            if(flag_zx==1)
  103.            {                     

  104.                 flag_zx=0;
  105.                     //0         1       2       3        4               
  106.                         //起始位   地址位  功能位   数据位  结束位
  107.                         if((receBuf[0]==0xaa)&&(receBuf[4]==0xbb)&&(receBuf[1]==add))          //如果开始位和结束位,还有地址都正确,进行下一步判断
  108.                         {
  109.                            if(receBuf[2]==0x01)  //修改板子地址
  110.                            {
  111.                               add=receBuf[3];
  112.                                     IapEraseSector(0);  //擦除扇区
  113.             IapProgramByte(0x01,add);//写入新的地址                           
  114.                            }
  115.                            else if(receBuf[2]==0x02)  //打开单路继电器
  116.                            {
  117.                                        switch(receBuf[3])
  118.                                         {
  119.                                           case 0x01: COM1=0; break;
  120.                                                 case 0x02: COM2=0; break;
  121.                                                 case 0x03: COM3=0; break;
  122.                                                 case 0x04: COM4=0; break;
  123.                                                 default:break;
  124.                                         }
  125.                            }
  126.                            else if(receBuf[2]==0x03)  //关闭单路继电器
  127.                            {
  128.                                        switch(receBuf[3])
  129.                                         {
  130.                                           case 0x01: COM1=1; break;
  131.                                                 case 0x02: COM2=1; break;
  132.                                                 case 0x03: COM3=1; break;
  133.                                                 case 0x04: COM4=1; break;
  134.                                                 default:break;
  135.                                         }                       
  136.                            }
  137.                            else if(receBuf[2]==0x04)  //打开全部继电器
  138.                            {
  139.                                 if(receBuf[3]==0xff)
  140.                                 {
  141.                                             COM1=0; COM2=0; COM3=0;COM4=0;
  142.                                         }  
  143.                            }
  144.                            else if(receBuf[2]==0x05)  //关闭全部继电器
  145.                            {
  146.                                 if(receBuf[3]==0x00)
  147.                                 {
  148.                                             COM1=1; COM2=1; COM3=1; COM4=1;
  149.                                         }                       
  150.                            }
  151.                            else if(receBuf[2]==0x06)  //查询继电器
  152.                            {
  153.                                         sendBuf[0]=0xaa;
  154.                                         sendBuf[1]=add;
  155.                                         sendBuf[2]=0x07;
  156.                                         //sendBuf[3]=0xfe;
  157.                                         sendBuf[4]=0xbb;        
  158.                                switch(receBuf[3])
  159.                                    {
  160.                                      case 0x01: if(COM1==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  161.                                            case 0x02: if(COM2==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  162.                                            case 0x03: if(COM3==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  163.                                            case 0x04: if(COM4==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  164.                                            default:break;
  165.                                    }  
  166.                                    senduart2();
  167.                            }
  168.                            else if(receBuf[2]==0x08)  //查询输入状态
  169.                            {
  170.                                         sendBuf[0]=0xaa;
  171.                                         sendBuf[1]=add;
  172.                                         sendBuf[2]=0x09;
  173.                                         //sendBuf[3]=0xfe;
  174.                                         sendBuf[4]=0xbb;
  175.                                 
  176.                                switch(receBuf[3])
  177.                                    {
  178.                                      case 0x01: if(IN1==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  179.                                            case 0x02: if(IN2==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  180.                                            case 0x03: if(IN3==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  181.                                            case 0x04: if(IN4==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  182.                                            case 0x05: if(IN5==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  183.                                            case 0x06: if(IN6==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  184.                                            case 0x07: if(IN5==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  185.                                            case 0x08: if(IN6==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  186.                                            default:break;
  187.                                    }  
  188.                                         senduart2();
  189.                            }                          
  190.                         }
  191.                         if((receBuf[0]==0xaa)&&(receBuf[1]==0x00)&&(receBuf[2]==0x00)&&(receBuf[3]==0x00)&&(receBuf[4]==0xbb))
  192.                         {
  193.                               add=0x00;
  194.                                     IapEraseSector(0);  //擦除扇区
  195.             IapProgramByte(0x01,0x00);//写入新的地址
  196.           sendBuf[0]=0xaa;
  197.                                         sendBuf[1]=add;
  198.                                         sendBuf[2]=0x00;
  199.                                         sendBuf[3]=0x00;
  200.                                         sendBuf[4]=0xbb;                                
  201.                                   senduart2();
  202.                         }
  203.                         clear_receBuf();
  204.                 }
  205. if((IN1==0)&&(bz1==0)){delay();if(IN1==0){bz1=1;if(TEND){TEND=0;TBUF='A';TING=1;}while(!TEND);}}
  206. if((IN1==1)&&(bz1==1)){delay();if(IN1==1){bz1=0;}}        
  207.         
  208. if((IN2==0)&&(bz2==0)){delay();if(IN2==0){bz2=1;if(TEND){TEND=0;TBUF='B';TING=1;}while(!TEND);}}
  209. if((IN2==1)&&(bz2==1)){delay();if(IN2==1){bz2=0;}}               

  210. if((IN3==0)&&(bz3==0)){delay();if(IN3==0){bz3=1;if(TEND){TEND=0;TBUF='C';TING=1;}while(!TEND);}}
  211. if((IN3==1)&&(bz3==1)){delay();if(IN3==1){bz3=0;}}        
  212.         
  213. if((IN4==0)&&(bz4==0)){delay();if(IN4==0){bz4=1;if(TEND){TEND=0;TBUF='D';TING=1;}while(!TEND);}}
  214. if((IN4==1)&&(bz4==1)){delay();if(IN4==1){bz4=0;}}        


  215. }
  216. }


  217. // /**********************************************************
  218. //放在主函数,定时0溢出中断函数,
  219. //*********************/
  220. void tm0()interrupt 1 using 1
  221. {
  222. if(RING)
  223.   {
  224.    if(--RCNT==0)
  225.     {
  226.          RCNT=3;
  227.          if(--RBIT==0)
  228.         {
  229.                  RBUF=RDAT;
  230.                  RING=0;
  231.          REND=1;
  232.                 }
  233.                 else
  234.                 {
  235.                  RDAT>>=1;
  236.                  if(RXB)RDAT|=0X80;
  237.                 }

  238.     }
  239.   }
  240.     else if(!RXB)
  241.         {
  242.          RING=1;
  243.          RCNT=4;
  244.          RBIT=9;
  245.         }
  246.     if(--TCNT==0)
  247.         {
  248.         TCNT=3;


  249.         if(TING)
  250.         {
  251.           if(TBIT==0)
  252.           {
  253.           TXB=0;
  254.           TDAT=TBUF;
  255.           TBIT=9;
  256.           }
  257.           else
  258.           {
  259.           TDAT>>=1;
  260.           if(--TBIT==0)
  261.           {
  262.            TXB=1;
  263.            TING=0;
  264.            TEND=1;
  265.           }
  266.           else
  267.           {
  268.           TXB=CY;
  269.           }
  270.           }
  271.         }
  272.         }
  273. }
  274. void IapIdle(){//禁用 ISP/IAP/EEPROM functionmake 单片机 在 一 安全 状态
  275.     IAP_CONTR = 0;           //
  276.         IAP_CMD = 0;           //
  277.         IAP_TRIG = 0;           //
  278.         IAP_ADDRH = 0x80;  //
  279.         IAP_ADDRL = 0;           //
  280. }
  281. uint8 IapReadByte(uint16 addr){//读数据
  282.    uint8 dat;
  283.    IAP_CONTR = ENABLE_IAP;
  284.    IAP_CMD = CMD_READ;
  285.    IAP_ADDRL = addr;
  286.    IAP_ADDRH = addr >> 8;
  287.    IAP_TRIG = 0x5A;
  288.    IAP_TRIG = 0xA5;
  289.    _nop_();
  290.    dat = IAP_DATA;
  291.    IapIdle();
  292.    return dat;
  293. }
  294. void IapProgramByte(uint16 addr, uint8 dat){//写数据
  295.    IAP_CONTR = ENABLE_IAP;
  296.    IAP_CMD = CMD_PROGRAM;
  297.    IAP_ADDRL = addr;
  298.    IAP_ADDRH = addr >> 8;
  299.    IAP_DATA = dat;
  300.    IAP_TRIG = 0x5A;
  301.    IAP_TRIG = 0xA5;
  302.    _nop_();
  303.    IapIdle();
  304. }
  305. void IapEraseSector(uint16 addr){//擦除数据
  306.    IAP_CONTR = ENABLE_IAP;
  307.    IAP_CMD = CMD_ERASE;
  308.    IAP_ADDRL = addr;
  309.    IAP_ADDRH = addr >> 8;
  310.    IAP_TRIG = 0x5A;
  311.    IAP_TRIG = 0xA5;
  312.    _nop_();
  313.    IapIdle();
  314. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:115923 发表于 2020-12-17 22:05 | 只看该作者
带 控制,  带保存功能. EPROM 读/写/擦 功能.
回复

使用道具 举报

板凳
ID:328014 发表于 2020-12-20 04:21 | 只看该作者
好东东 楼主能上传一下工程包吗 原理图
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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