找回密码
 立即注册

QQ登录

只需一步,快速开始

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

通过自制串口协议驱动输出RS485通信232通信单片机源程序

[复制链接]
跳转到指定楼层
楼主
ID:358910 发表于 2019-6-10 10:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用STC12C5A60S2开发96路信号输出,可接485 多层主机 ,自制串口通信协议
附件中有PDF版AD原理图,源代码 开发文档。
原创。

上位机对于这些信号机的控制就是基于这块--96路信号灯板。顾名思义,96路信号灯板可以同时实现对96个信号灯的控制,操作人员只需在上位机电脑端,发送通信协议,单片机做出应答,外接设备轨道信号机实现列车指示作用。
  • 上位机与96路信号灯板通信界面
左上角选定单片机型号,数据通信端口号;发送缓冲区发送通信协议,这块96路信号灯板的通信协议为AB 02 01 07(主机地址,可根据现场实际情况进行更改) 10(端口控制量,十六进制) FF FF FF FF FF FF FF FF FF FF FF FF(十二路控制端口控制96路灯) 00 00 00 00 02(最后一位为奇偶校验,可根据之前的数据进行更改) CD
二、96路信号灯板原理图及PCB图
              96路信号灯板所用的控制原理是:STC12C5A60S2单片机通过操作P0口的电平高低,控制SN74HC573芯片,进而控制四-十六译码器CD4514,然后译码器控制十二路信号灯的控制芯片SN74HC573和ULN2803,实现信号灯的亮灭。
              

单片机源程序如下:
  1. /*-----------------------------------------------
  2.   名称:串口通信
  3.   日期:2019.6.10
  4.   内容: 多机通信,第一层机,485通信     本机为输出功能从机    YN防485信号接收冲突     
  5. ------------------------------------------------*/
  6. #include<stc12c5a60s2.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
  7. #include<intrins.h>
  8.                         
  9. void datapro();                //总数据处理函数
  10. unsigned char  a[20],c[25],b[25],ca[25];     //a[20]暂存数据包,一些计算在这个数组里面完成   c[25],ca[25]串口接收缓冲数据包   

  11. sbit DE=P1^1;                //485通信方向控制              
  12. sbit W=P3^7;                   //    锁存的地址输出控制
  13. sbit LE=P3^6;                    //地址信号锁存到573

  14. sbit XZ=P1^0;                 //信号控制线

  15. unsigned char flag=1,i=0,m=0,flag_1=0,flag_2=0;      //地址信号锁存  flag=1 串口发送完标志,i=0,m=0,全局变量 为串口接收数组小标,flag_1=0,flag_2=0串口接收数据接收完标志
  16. unsigned char address_1;             //本机地址

  17. unsigned char  YN=0,k=1;          // k 接收数据时 转义用 ;YN 串口接收状态值
  18. unsigned char ZY_1=0,ZY_2=0;
  19. /*------------------------------------------------
  20.          uS延时函数
  21. ------------------------------------------------*/
  22. void DelayUs2x(unsigned short int t)
  23. {   
  24. while(--t);
  25. }
  26. /*------------------------------------------------
  27.          mS延时函数
  28. ------------------------------------------------*/
  29. void DelayMs(unsigned short int t)
  30. {   
  31. while(t--)
  32. {
  33.      //大致延时1mS
  34.      DelayUs2x(245);
  35.      DelayUs2x(245);
  36. }
  37. }
  38. /*------------------------------------------------
  39.        串口和心跳定时器初始化
  40. ------------------------------------------------*/
  41. void InitUART(void)
  42. {
  43.     SCON  = 0x50;                // SCON: 模式 1, 8-bit UART, 使能接收  
  44.     TMOD  = 0x21;               // TMOD: timer 1, mode 2, 8-bit 重装
  45.     PCON=0X80;
  46.     TH1   = 0xFD;               // TH1: 重装值 253   波特率19200 晶振 11.0592MHz

  47.     TH0   = 0x4b ;                 // TH0,TL0:  重装值 15536  定时约50ms
  48.     TL0   = 0xfd ;

  49.     WDT_CONTR=0x3f;                  //看门狗

  50.     IP    =0x10;                //串口优先 ,心跳信息次之
  51.     TR1   = 1;                 // TR1:  timer 1 打开
  52.     TR0   = 1;                  // TR0:  timer 0 打开
  53.    
  54.     DE=0;                        //485通信默认状态为接收
  55.       
  56.     EA    =1;                    //总中断开
  57.     ET0   = 1;                  //定时中断开
  58.    
  59.    
  60.                         
  61. }                                                                                                                                                                                                                                                                                                                                                                                   


  62. /*------------------------------------------------
  63.              校验情况函数
  64. ------------------------------------------------*/
  65. void check(unsigned char x)
  66. {       unsigned char j;                                 //函数功能  告诉上位机奇偶校验的结果     暂时未用
  67.        unsigned char d=0;

  68.                  a[1]=0x01;                                    //ab 01 01 ad_1 x R cd
  69.                  a[2]=0x01;                                       
  70.                    a[3]=address_1;
  71.                  a[4]=x;

  72.                  
  73.                   d=a[1]+a[2]+a[3]+a[4];
  74.                     
  75.                  if(d%2==0)  a[5]=0x02;
  76.                  if(d%2==1)  a[5]=0x01;                               //计算奇偶   奇数 01   偶数 02
  77.                
  78.                  DE=1;          //使485芯片处于发送状态
  79.                  DelayMs(1);

  80.                     flag=1 ;SBUF=0xab; while(flag==1);            //发送报文头

  81.                  for(j=1;j<6;j++)
  82.                  {
  83.                  if(a[j]==0xfe||a[j]==0xab||a[j]==0xcd) {  flag=1 ;SBUF=0xfe; while(flag==1);   flag=1 ; SBUF=a[j]; while(flag==1); }
  84.                  else { flag=1 ;SBUF=a[j];  while(flag==1); }
  85.                  }
  86.                  flag=1;SBUF=0xcd;while(flag==1);                  //发送报文尾

  87.                     DE=0; //使485芯片回到接收状态
  88. }
  89. /*------------------------------------------------
  90.               控制输出函数
  91. ------------------------------------------------*/
  92. void control_out(void)
  93. {
  94. unsigned char A,j;                               //函数功能      开关量的输出
  95. A=b[4];                           //数据帧,,要输出的字节数

  96. for(j=0;j<A;j++)
  97. {
  98. P0=j;                                //4-16译码地址
  99. LE=1;                                   //573 使能引脚
  100. DelayMs(10);
  101. LE=0;        //地址锁存到地址存储573芯片

  102. P0=b[j+5];           //要输出的数据
  103. W=0;
  104. DelayMs(10);
  105. W=1;      //已经锁存的地址信号输出

  106. }

  107. }



  108. /*------------------------------------------------
  109.              接收数据处理程序
  110. ------------------------------------------------*/
  111. void datapro()
  112. {
  113.   unsigned char d=0;
  114.   unsigned char j,t;

  115. if((c[0]==0xab&&c[i-1]==0xcd)||(ca[0]==0xab&&ca[m-1]==0xcd))                 //     数据报文头报文尾确认
  116.       {   
  117.         
  118.        if(flag_1==1) {for(j=0;j<25;j++) { b[j]=c[j];c[j]=0;} t=i;i=0;flag_1=0;}                           //数据存储区转移
  119.         else  if(flag_2==1) { for(j=0;j<25;j++) { b[j]=ca[j];ca[j]=0;} t=m;m=0;flag_2=0;}               //      数据存储区转移
  120.          
  121.       
  122.       
  123.       for(j=1;j<(t-2);j++)
  124.              {
  125.                 d=d+b[j] ;
  126.                }
  127.             if(d%2==0x00) d=0x02;
  128.                 else  d=0x01;         //               奇偶计算
  129.             
  130.          if(b[t-2]==d)           //计算的奇偶与上位机发送过来的数据的奇偶校验字节相比较
  131.           {         
  132.                    if(b[1]==0x02&&b[2]==0x01&&b[3]==address_1)  {/*check(0x01); */ control_out(); for(j=0;j<25;j++) {b[j]=0;} ;t=0; }      
  133.                           //上位机发送过来的命令     本机发送给上位机校验情况,再控制输出
  134.                         else if(b[1]==0x04)  { for(j=0;j<25;j++) {b[j]=0;} ;t=0; }
  135.                                //上位机发送过来的命令   本机为输出功能从机,不作反应
  136.                           else   if(b[1]==0x05||b[1]==0x03){ for(j=0;j<25;j++) {b[j]=0;} ;t=0; }
  137.                                     //上位机发送过来的多余数据     此为广播方式进行多级 多机通信弊端  
  138.                                  else   if(b[1]==0x01)  { for(j=0;j<25;j++) {b[j]=0;} ;t=0;}
  139.                                        //上位机发送过来的上位机校验情况命令  ,本机为输出功能机,该命令是另外功能机的命令,所以不作反应,是广播通信弊端
  140.                                 
  141.            }                                   
  142.           else {  if(b[1]==0x02) {check(0x02); }      //上位机发送过来的命令  校验失败
  143.                   for(j=0;j<25;j++) {b[j]=0;} ;t=0;   
  144.                }
  145.        }
  146.    
  147. }
  148. /*------------------------------------------------
  149.              单片机心跳信息函数
  150. ------------------------------------------------*/
  151. void heartb()
  152. {
  153. unsigned char d=0;

  154. if(YN==0)
  155. {
  156. DE=1;
  157. DelayMs(1);                          // ab 05  ad1 R cd

  158. flag=1 ;
  159. SBUF=0xab;
  160. while(flag==1);

  161. flag=1 ;
  162. a[1]=0x05;
  163. SBUF=a[1];
  164. while(flag==1);

  165. flag=1 ;
  166. a[2]=0x01;
  167. SBUF=a[2];
  168. while(flag==1);

  169. flag=1;
  170. a[3]=address_1;

  171. if(a[3]==0xfe||a[3]==0xab||a[3]==0xcd)    {SBUF=0xfe;while(flag==1);}    ;

  172. flag=1 ;
  173. SBUF=a[3];
  174. while(flag==1);

  175. d=a[1]+a[2]+a[3];
  176. if(d%2==0x00) d=0x02;
  177. else d=0x01;

  178. flag=1;
  179. a[4]=d;
  180. SBUF=a[4];
  181. while(flag==1);

  182. flag=1 ;
  183. SBUF=0xcd;
  184. while(flag==1);

  185. DE=0;

  186. }
  187. }



  188. /*------------------------------------------------
  189.                  主函数
  190. ------------------------------------------------*/
  191. void main (void)
  192. {
  193. unsigned char j;

  194. unsigned char x;
  195.     x=5;

  196. P0M1=0X00;
  197. P0M0=0XFF;


  198. address_1=0x04;         //本机地址

  199. for(j=0;j<25;j++)
  200. {
  201. a[j]=0;b[j]=0;c[j]=0; ca[j]=0;        //数组初始化
  202. };

  203. InitUART();
  204. ES=1;


  205. b[4]=0x10;            //数据长度 16个字节

  206. b[5]=0x00;
  207. b[6]=0x00;
  208. b[7]=0x00;
  209. b[8]=0x00;

  210. b[9]=0x00;
  211. b[10]=0x00;
  212. b[11]=0x00;
  213. b[12]=0x00;

  214. b[13]=0x00;
  215. b[14]=0x00;
  216. b[15]=0x00;
  217. b[16]=0x00;

  218. b[17]=0x00;
  219. b[18]=0x00;
  220. b[19]=0x00;
  221. b[20]=0x00;

  222. control_out();        //使所有信号输出为0
  223. x=(x-1);
  224.   XZ=1;
  225. while(1)
  226. {  
  227.      
  228.     DelayMs(10);
  229.     datapro();
  230.    
  231. }  



  232. }


  233. /*------------------------------------------------
  234.                串口中断程序
  235. ------------------------------------------------*/
  236. void UART_SER (void) interrupt 4 //串行中断服务程序
  237. {
  238.    unsigned char Temp;          //定义临时变量

  239. if(RI)                        //判断是接收中断产生
  240.      {
  241.       
  242.       RI=0;                      //标志位清零
  243.       Temp=SBUF;
  244.       
  245.       if(flag_1==0)         //     flag_1==1 表示按照协议接收到了一串完整的数据
  246.         {
  247.          YN=1;               //YN=1表示串口处于接收状态
  248.          if(i==0&&Temp!=0xab){ YN=0;}     //如果 接收到的第一个字节不是报文头0xab,则放弃接收该字节
  249.          else{   
  250.                 if(Temp==0xfe)
  251.                   {   if(k==1) {k++;ZY_1=0XFE;}
  252.                       else  { k=1;  ZY_1=0;   c[i]=Temp;i++; }  //转义  处理
  253.                   }
  254.                  
  255.                 else {c[i]=Temp;   
  256.                         if(c[i]==0xcd&&ZY_1!=0xfe)   {flag_1=1; k=1;YN=0;}       ;  //判断是否处于报文尾
  257.                       if(ZY_1==0xfe)if(c[i]==0xcd||c[i]==0xab){k=1; ZY_1=0;};   
  258.                        i++;
  259.                      };
  260.          
  261.               
  262.                                 
  263.             }
  264.          }
  265.       else if(flag_2==0)
  266.           {     
  267.           YN=1;
  268.           if(m==0&&Temp!=0xab){ YN=0;}
  269.           else{  
  270.                if(Temp==0xfe)
  271.                {   if(k==1) {k++;ZY_2=0XFE;}
  272.                    else  { k=1;ZY_2=0;ca[m]=Temp;m++; }  //转义
  273.                }

  274.               else { ca[m]=Temp;  

  275.                     if(ca[m]==0xcd&&ZY_2!=0xfe)   {flag_2=1; k=1; YN=0;}
  276.                     if(ZY_2==0xfe){  if(ca[m]==0xcd||ca[m]==0xab){k=1;ZY_2=0;};     }
  277.                        m++;
  278.                     }
  279.                        
  280.                } ;

  281.             
  282.           }
  283.     }
  284.      

  285.       
  286.          
  287. if(TI){flag=0; TI=0;}         
  288. }
  289. /*------------------------------------------------
  290.                      心跳中断程序
  291. ------------------------------------------------*/
  292. void timer0(void) interrupt 1  
  293. {  static unsigned char  n=0 ;
  294.      n++;
  295.      if(n==110) {WDT_CONTR=0x3f;/* heartb(); n=0;*/    }                   // 6秒 喂看门狗,发送心跳信息
  296.      if(n==220)    {WDT_CONTR=0x3f;  heartb(); n=0;    }
  297.          
  298. ……………………

  299. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

全部资料51hei下载地址:
96路信号灯开发源程序.7z (25.97 KB, 下载次数: 28)
96路信号灯原理图PDF版.pdf (1.87 MB, 下载次数: 18)
96路信号灯开发文档.docx (224.07 KB, 下载次数: 18)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:617456 发表于 2019-11-30 15:55 | 只看该作者
学习学习大神的作品
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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