找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1369|回复: 0
收起左侧

单片机采样送can格式数据的源程序

[复制链接]
ID:481548 发表于 2019-4-24 09:09 | 显示全部楼层 |阅读模式
单片机采样送can格式数据,后端通过232转can传输

单片机源程序如下:
  1. //////////////////////////////////////////////////////////////////////////////////////////////
  2.   //编制的地面电源软件。发生过数组超限的情况软件仿真调试完成时间2010805,          //
  3.   // 该单片机的定时器、AD转换器、串行口都与以前不同,需要特别注意。
  4.   //////////////////////////////////////////////////////////////////////////////////////////////
  5.   #include <STC15.H>
  6. //  #include <absacc.h>
  7. //  #include <math.h>
  8.   #define uchar unsigned char
  9.   #define uint unsigned int
  10.   #define ulong unsigned long

  11.   //buf[0]~buf[3]是报头,buf[4]、buf[5]是输出电压BCD码uf[6]、buf[7]是输出电流BCD码,buf[8]是输出状态标志1,
  12.   //buf[9]、buf[10]是温度的BCD码,buf[11]是输入状态标志2,buf[12]、buf[13]暂时未使用。

  13.   uchar idata buf[45]={1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2};
  14.   uint  idata bufint[40]={0x0001,0x0002,0x0004,0x0008,0x0016,0x0032,0x0064,0x0128,0x0256,0x0512,0x1024,0x2048,0x4096,0x8192};
  15.   uchar code zifu1[40]={111,104,7,4,5,6,7,8,9,8,53,111,104,3,4,5,6,7,8,9,8,53,111,104,2,1,8,9,8,6,5,7,53};
  16.   uchar code zifu2[20]={1,2,4,8,16,32,3,2,1,2,3,4,5,6,7};
  17. //  unsigned int idata gz_time[10]={0,0,0,0,0};

  18.   sbit ADC_1=P1^0;             //电压测量
  19.   sbit ADC_2=P1^1;             //电流测量
  20.   sbit ADC_3=P1^2;             //温度测量
  21.   sbit TS=P2^5;                               //调试开关
  22.   sbit DJ=P2^1;                               //开关KGUAN
  23.   sbit SJ=P2^0;                          //发收FS   
  24. //  sfr  ADC_CONTR=0xBC;         //ADC控制寄存器
  25. //  sfr  ADC_RES=0xBD;           //ADRJ=0时,ADC结果高8位;ADRJ=1时,B1B0位ADC结果的高两位ADC_RES9 ADC_ RES8      
  26. //  sfr  ADC_RESL=0xBE;          //ADRJ=0时,B1B0位ADC结果的低两位ADC_RES1 ADC_ RES0;ADRJ=1时,ADC结果低8位
  27. //  sfr  WDT_CONTR=0xC1;
  28. //  sfr  AUXR=0x8E;
  29. //  sfr  AUXR1=0xA2;
  30. //  sfr  P1ASF=0x9D;
  31. //  sfr  CLK_DIV=0x97;           //ADRJ控制ADC结果存放的位置
  32. //  sfr  T2H=0xD6;               //需要定义,TH2不定义则不写分频系数进0xD6,导致定时器2不工作,串行口不发送数据,TI始终为0,不置1,无数据输出。
  33. //  sfr  T2L=0xD7;               //需要定义,TL2不定义则不写分频系数进0xD7
  34. //  sfr  P3M1=0xb1;
  35. //  sfr  P3M0=0xb2;
  36. //  sfr  P2M1=0x95;
  37. //  sfr  P2M0=0x96;
  38. //  sfr  P1M1=0x91;
  39. //  sfr  P1M0=0x92;
  40.   #define ADC_POWER  0x80      //ADC电源控制位
  41.   #define ADC_FLAG   0x10      //ADC完成标志位
  42.   #define ADC_START  0x08      //ADC开始控制位


  43.   void timer0_ISR (  ) interrupt 1 using 2                //10毫秒@11.0592MHz时钟
  44.               {
  45.                buf[25]=buf[25]+1;                         //中断次数计数,也就是计时。buf[25]记录中断的次数,达到10次后清零
  46.                                }

  47.   void time0Init()                                        //定时器0初始化
  48.              {
  49.                     AUXR &= 0x7F;                                         //定时器时钟12T模式
  50.                     TMOD &= 0xF0;                                         //设置定时器0模式
  51.                TL0=0x00;                                  //10ms中断一次,(10ms)TH0TL0=65536-11059200/12/100=55536=0xdc00,(10ms)TH0TL0=65536-12000000/12/100=55536=0xd8f0,
  52.                TH0=0xdc;                                  //               TH0=0xdc;TL0=0x00.(50ms)H0TL0=65536-11059200/12/20=19456=0x4c00
  53.                               TF0=0;                                     //清除TF0标志
  54.                      TR0=1;                                               //定时器0开始计时
  55.                EA=1;
  56.                     ET0=1;
  57.                        }




  58.   void inituart()                                                                    //串行口、定时器0初始化函数
  59.    {
  60.      SCON=0x50;                                                                 //串行口工作在方式1。01010000
  61.      AUXR1=0x40;                                           //将串口定义到P3.6、P3.7,AUXR1=01000000,
  62.      AUXR |= 0x01;                                            //定时器0、2不分频,选择定时器2作为串口1的波特率发生器
  63.      T2H=0xff;                                                                   //设定波特率重装值TH2TL2=65536-11059200/4/11520/12=65516=0xffecTH2TL2=65536-12000000/4/9600/12=65510=0xffe6。
  64.      T2L=0xe8;                                             //9600bps@11.0592MHzTH2TL2=65536-11059200/4/9600/12=65512=0xffe8;TH2TL2=65536-11059200/4/1200/12=65344=0xff40
  65.      PCON=0x00;                                            //波特率不加倍
  66.      AUXR |= 0x10;                                          //TR2=1; //启动T/C2
  67.      P3M1=0x00;
  68.      P3M0=0x00;
  69.    }

  70. //void UartInit(void)                                                   //9600bps@11.0592MHz
  71. //{
  72. //        SCON = 0x50;                                                      //8位数据,可变波特率
  73. //        AUXR |= 0x01;                                                      //串口1选择定时器2为波特率发生器
  74. //        AUXR &= 0xFB;                                                      //定时器2时钟为Fosc/12,即12T
  75. //        T2L = 0xE8;                                                         //设定定时初值
  76. //        T2H = 0xFF;                                                         //设定定时初值
  77. //        AUXR |= 0x10;                                                      //启动定时器2
  78. //}



  79.   void delay(uchar delay_time)                //延时函数。
  80.    {uchar n;
  81.     uint  m;
  82.     for (n=0;n<delay_time;n++)
  83.      {
  84.      for (m=0;m<10;m++)
  85.        WDT_CONTR=0x3C;
  86.      }
  87.    }

  88.   void set_p1_adc_channel()
  89.    {
  90.    uchar n;
  91.    P1=0x00;
  92.    ADC_CONTR=0xE0;                             //开启AD电源 (11100000)
  93.    ADC_RES=0;                             //AD结果高位清0
  94.    ADC_RESL=0;                            //AD结果低2位清0
  95.    P1ASF=0x07;                            //P1^0、P1^1和P1^2设为AD口。
  96.    n=1;
  97.    delay(n);                                                  //稳定电源延时。
  98.    }



  99.   void adcyang(uchar  idata *d,q)             /*A/D变换q将数据放在不同的位置*/

  100.   {uchar i,j;
  101.    ADC_CONTR=ADC_CONTR&0xE0;                   //a/d的数据存放:buf[35]buf[36]电压、buf[37]buf[38]电流、buf[39]buf[40]温度。
  102.    i=0;
  103.    ADC_CONTR=ADC_CONTR|i;                           //选择P1^0进行A/D转换,采集电压值
  104.    i=8;
  105.    ADC_CONTR=ADC_CONTR|i;                           //启动A/D。
  106.    j=0;
  107.    while(j==0)
  108.    {
  109.   
  110.     j=ADC_CONTR&0x10;
  111.          if (buf[25]>0x05)                     // //调试用,防止不断循环
  112.          {j=0x01;}
  113.    }
  114.    i=0xEF;
  115.    ADC_CONTR=ADC_CONTR&i;                           //清A/D标志。
  116.    d[q]=ADC_RES;                                         //P1^0的A/D电压值结果高8位。
  117.    d[q+1]=ADC_RESL;                      //P1^0的A/D电压值结果低2位。

  118.    ADC_CONTR=ADC_CONTR&0xE0;                   //
  119.    i=1;
  120.    ADC_CONTR=ADC_CONTR|i;                           //选择P1^1进行A/D转换,采集电流值,
  121.    i=8;
  122.    ADC_CONTR=ADC_CONTR|i;                           //启动A/D。
  123.    j=0;
  124.   while(j==0)
  125.   {
  126.   j=ADC_CONTR&0x10;
  127.          if (buf[25]>0x05)                   //调试用,防止不断循环
  128.          {j=0x01;}
  129.   }
  130.   i=0xEF;
  131.   ADC_CONTR=ADC_CONTR&i;                           //清A/D标志。
  132.   d[q+2]=ADC_RES;                                         //P1^1的A/D电流值结果高8位。
  133.   d[q+3]=ADC_RESL;                       //P1^1的A/D电流值结果低2位。

  134.   ADC_CONTR=ADC_CONTR&0xE0;                  //A/D准备
  135.   i=2;
  136.   ADC_CONTR=ADC_CONTR|i;                          //选择P1^2进行A/D转换。
  137.   i=8;
  138.   ADC_CONTR=ADC_CONTR|i;                           //启动A/D。
  139.   j=0;
  140.   while(j==0)
  141.   {
  142.   j=ADC_CONTR&0x10;
  143.          if (buf[25]>0x05)                    //调试用,防止不断循环
  144.          {j=0x01;}
  145.   }
  146.   i=0xEF;
  147.   ADC_CONTR=ADC_CONTR&i;                          //清A/D标志。
  148.   d[q+4]=ADC_RES;                                         //P1^2的A/D温度值结果高8位。
  149.   d[q+5]=ADC_RESL;                                      //P1^2的A/D温度值结果低2位。
  150.   }
  151.   



  152.     void bcdzhuanhua(unsigned int m,uchar a)
  153.      {
  154.        uchar i,p,q,r;         
  155.             uint j,k,n,h,l,t;
  156.                    q=0;
  157.        r=0;   
  158.               n=0;
  159.                               
  160.                  for(i=0;i<=14;i++)                       //二进制位权存在,加上一个字分为4位的BCD码。共检查14位。15、16位没有这么大的数。
  161.                  {
  162.                                                 //m是要转换的值。
  163.           j=m;                              
  164.                          j>>=i;                                //从最低位开始考察m。
  165.           q=(uchar)j;                           //将j转换换为字节
  166.           q=0x01&q;
  167.                          if(q>0)                               //考察m的每一位。
  168.                           {                            
  169.                                   k=bufint[i];                      //bufint[i]是二进制i的位权。
  170.                                   h=0x000f;
  171.               for(p=0;p<=3;p++)                 //p是BCD码的位置
  172.                                     {
  173.                l=n;
  174.                                         t=(k&h);
  175.                                         if(t>0)
  176.                                           {
  177.                                        n=n+t;                    //k的每组四位值最大为9。n是十进制数同样。不用考虑k、与n的值超过9,但要考虑进位。
  178.                    t=h;
  179.                    t<<=4;
  180.                                             l=t&l;
  181.                                             t=t&n;                                          
  182.                    if(t>l)                      //考虑进位
  183.                      {
  184.                                                     l=0x6666&h;
  185.                       n=n+l;                     //有进位则加6
  186.                      }
  187.                    l=n&0x000f;
  188.                                        if(l>=0x000a)                    //还需要检查十分位是9的情况。
  189.                                                 {
  190.                                                n=n-0x000a+0x0010;              //减10向十位进位。
  191.                      }
  192.                                         l=n&0x00f0;
  193.                     if(l>=0x00a0)
  194.                                               {
  195.                                                n=n-0x00a0+0x0100;             //减100向佰位进位。
  196.                      }
  197.                                              l=n&0x0f00;
  198.                     if(l>=0x0a00)
  199.                                               {
  200.                                                n=n-0x0a00+0x1000;             //减1000向千位进位。
  201.                                               }
  202.                                              }
  203.                                      h<<=4;
  204.                                         }                                                                         
  205.                           }
  206.                  }
  207.       j=0x00ff;                                     //这里有错,拆成一个字8位
  208.                 j=n&j;
  209.                 buf[a+2]=(uchar)j;                           
  210.            j=0xff00;
  211.                 j=n&j;
  212.                 j>>=8;
  213.                 buf[a+1]=(uchar)j;
  214.      }


  215.    void test_v( uint m )
  216.          {
  217.           int f;
  218.      uchar i;
  219.      bufint[14]=m;                        //buf[14]是电压的16进制值。
  220.      buf[8]=buf[8]&0xfc;                  //电压正常,buf[8]是状态字,状态字的B0、B1置0.
  221.           f=m-5200;                             //5200是520V电压,f值小于5200V位是低压状态。
  222.           if(f<0)
  223.           {
  224.            DJ=1;                               //发光二极管亮报警。
  225.       SJ=1;                               //蜂鸣器报警
  226.       buf[8]=buf[8]+0x02;                 //状态字B1置1;
  227.           }
  228.           f=m-5800;                             //5800是580V电压f值大于580V位是高压状态。

  229.           if(f>0)
  230.           {
  231.       DJ=1;                               //发光二极管亮报警?
  232.       SJ=1;                               //蜂鸣器报警
  233.       buf[8]=buf[8]+0x01;                 //状态字B0置1
  234.           }


  235.      i=buf[8]&0x1f;
  236.           if(i==0)
  237.           {
  238.       DJ=0;                               //发光二极管停止报警
  239.       SJ=0;                               //蜂鸣器停止报警
  240.           }

  241.          }


  242.    void test_I( uint m )
  243.          {
  244.           int f;
  245.       uchar i;      
  246.           bufint[15]= bufint[16];              // bufint[15]~ bufint[19]是每100ms采样的电流值。
  247.           bufint[16]= bufint[17];
  248.           bufint[17]= bufint[18];
  249.           bufint[18]= bufint[19];
  250.      bufint[19]=m;
  251.      buf[8]=buf[8]&0xe7;                  //电流正常,buf[8]是状态字,状态字的B3置0.
  252.           f=bufint[15]-m;                     
  253.           if(f>768)                            //768是电流掉9A的值,768=9/12*1024,处理掉电流报警。
  254.             {
  255.               DJ=1;                               //发光二极管亮报警。
  256.          SJ=1;                               //蜂鸣器报警
  257.          buf[8]=buf[8]+0x10;                 //状态字B3置1;
  258.             }
  259.      f=m-853;                                 //853是电流10A的值,853=10/12*1024
  260.      if(f>=0)                                 //超出10A电流报警。
  261.      {
  262.               DJ=1;                               //发光二极管亮报警。
  263.          SJ=1;                               //蜂鸣器报警
  264.          buf[8]=buf[8]+0x08;                 //状态字B3置1;      
  265.      }  
  266.      i=buf[8]&0x1f;
  267.           if(i==0)
  268.           {
  269.       DJ=0;                               //发光二极管停止报警
  270.       SJ=0;                               //蜂鸣器停止报警
  271.           }
  272.    
  273.          }


  274.    void test_T( uint m )
  275.          {
  276.           int f;
  277.      uchar i;
  278.      bufint[20]=m;                        //bufint[20]是温度的16进制值。
  279.      buf[8]=buf[8]&0xfb;                  //温度正常,buf[8]是状态字,状态字的B2置0.
  280.           f=m-700;                             //700是70度温度f值大于70度是高温状态。
  281.           if(f>0)
  282.           {
  283.       DJ=1;                               //发光二极管亮报警。
  284.       SJ=1;                               //蜂鸣器报警。
  285.       buf[8]=buf[8]+0x04;                 //状态字B2置1。
  286.           }

  287.      i=buf[8]&0x1f;
  288.           if(i==0)
  289.           {
  290.       DJ=0;                               //发光二极管停止报警
  291.       SJ=0;                               //蜂鸣器停止报警
  292.           }
  293.          }


  294.   void dsp_data_v( )       
  295.     {
  296.    uchar i,a;
  297.    uint  k,m,j;
  298.         a=0;
  299.         j=0;
  300.         k=0;                                  //buf[35]、buf[36]是电压的采样值。                                   
  301.    i=buf[35];                            //采样电压高位值送i
  302.    k=(int)i;                        
  303.    k<<=2;                                //高位置送字的高8位
  304.    i=buf[36];                            //采样电压低二位采样值送i
  305.         i=i&0x03;
  306.         k=k+(int)i;                           //拼接为字
  307.    m=k*5.8594;                          //电压值乘以5.8594,600V电压对应5V直流取样电压1024个单位,显示放大10倍,默认最后一位为小数位。
  308.    test_v(m);
  309.         a=3;                                  //buf[4]、buf[5]是电压的BCD码
  310.    bcdzhuanhua(m,a);
  311.     }

  312.   void dsp_data_I( )       
  313.     {
  314.    uchar i,a;
  315.    uint  k,m,j;
  316.         a=0;
  317.         j=0;
  318.         k=0;                                 //buf[37]、buf[38]是电流的采样值?
  319.    i=buf[37];                           //采样电流高位值送i
  320.    k=(int)i;                        
  321.    k<<=2;                               //高位置送字的高8位
  322.    i=buf[38];                           //采样电流低二位采样值送i
  323.         i=i&0x03;
  324.         k=k+(int)i;                          //拼接为字
  325.    m=k*0.1171875;                       //电流值乘以0.1171875,12A电流对应5V直流取样电压,对应xxx.x的BCD4位码,显示放大10倍,默认最后一位为小数位。
  326.    test_I(k);
  327.         a=5;                                 //buf[6]、buf[7]是电流的BCD码
  328.    bcdzhuanhua(m,a);
  329.     }

  330.   void dsp_data_T( )       
  331.     {
  332.    uchar i,a;
  333.    uint  k,m,j;
  334.         a=0;
  335.         j=0;
  336.         k=0;                                 //buf[39]、buf[40]是温度的采样值。
  337.    i=buf[39];                           //采样电流高位值送i
  338.    k=(int)i;                        
  339.    k<<=2;                               //高位置送字的高8位
  340.    i=buf[40];                           //采样电流低二位采样值送i
  341.         i=i&0x03;
  342.         k=k+(int)i;                          //拼接为字
  343.    m=k*0.976525;                        //温度值乘以0.976525,100度温度对应5V直流取样电压,对应xxx.x的BCD4位码,如065.7度、105.6度。
  344.    test_T(m);
  345.         a=8;                                 //buf[9]、buf[10]是温度的BCD码。
  346.    bcdzhuanhua(m,a);
  347.     }

  348.   
  349. void send1(uchar idata *d,uchar n)          //发送函数
  350.      { uchar i;
  351.        REN=0;                                              //防止自发自收。

  352.        for (i=0;i<=n;i++)
  353.         {
  354.         TI=0;
  355.         SBUF=d[i];                                   //发一个现在的数据                                 
  356.         while (TI==0);
  357.         TI=0;                          //等待发送出去
  358.         if(i==11)
  359.           {      
  360.                          TS=!TS;
  361.            }                    //发送一次数据取反一次。
  362.         }
  363.        REN=1;
  364.      }
  365.   

  366.     void receive(uchar idata *d,uchar n)                 //接受函数接收14位身份加2位开关
  367.      {
  368.           uchar i;            
  369.      for(i=0;i<=n;i++)
  370.         {while (RI==0)
  371.                          {
  372.                                         if(buf[25]>=0x07)
  373.                                           {
  374.                                           i=12;                           //接收的数据不可用,SBUF的数据储存到d[24]中丢弃。
  375.                                      break;
  376.                                           }
  377.                                         }
  378.                           RI=0;                         //接收n个数据;一般为12个。
  379.                 d[i+12]=SBUF;                             //接收一个数据,放在 d[i+m]处
  380.              }
  381.      }
  382.    


  383.   void main()
  384.   
  385.   {
  386.     //buf[0]~buf[3]是报头,buf[4]、buf[5]是输出电压BCD码uf[6]、buf[7]是输出电流BCD码,buf[8]是输出状态标志1,
  387.     //buf[9]、buf[10]是温度BCD码,buf[11]是输入状态标志2,
  388.    buf[0]=0x1c;   buf[1]=0xff;   buf[2]=0x50;   buf[3]=0xe7;   buf[4]=0x00;                          
  389.    buf[5]=zifu1[5];   buf[6]=zifu1[6];   buf[7]=zifu1[7];   buf[8]=0x00;   buf[9]=zifu1[9];
  390.    buf[10]=zifu1[10]; buf[11]=0x00; buf[12]=0x00; buf[13]=zifu1[13]; buf[14]=zifu1[14];
  391.    buf[15]=zifu1[15]; buf[16]=zifu1[16]; buf[17]=zifu1[17]; buf[18]=zifu1[18]; buf[19]=zifu1[19];
  392.    buf[20]=zifu1[20]; buf[21]=zifu1[21]; buf[22]=zifu1[22]; buf[23]=zifu1[23];
  393.         bufint[23]=1222;
  394.    // buf[39]=zifu1[24];
  395.    //buf[25]=zifu1[25]; buf[26]=zifu1[26]; buf[27]=zifu1[27]; buf[28]=zifu1[28]; buf[29]=zifu1[29];
  396.    //buf[30]=zifu1[30]; buf[31]=zifu1[31]; buf[32]=zifu1[32];
  397.    time0Init();                       //定时器0初始化
  398.    inituart();                        //串行口初始化 定时器2初始化//
  399.    P1=0x00;
  400.         P2=0x00;
  401.         P3=0x80;
  402.    for(; ;)                           //主程序循环执行。
  403.    {
  404.    uchar n,k;
  405.    set_p1_adc_channel();              //AD采样初始化

  406.    if (buf[25]>0x09)                 //100ms时间值0x0a。              
  407.         {
  408.      buf[34]= buf[34]+1;              //记录100ms时间的次数
  409.      buf[25]=0;                       //buf[25]记录10ms一次的时间,100ms时间到清零。其值为:
  410.      n=35;                              //a/d的数据存放:buf[35]buf[36]电压、buf[37]buf[38]电流、buf[39]buf[40]温度。
  411.      adcyang(buf,n);                                        //A/D采样。
  412.      dsp_data_v( );                   //对电压值进行处理
  413.      dsp_data_I( );                   //对电流值进行处理
  414.      dsp_data_T( );                   //对温度值进行处理

  415.    }


  416.   if (buf[34]>0x04)                   //500ms时间到,发送一次数据。
  417.    {
  418.    buf[34]=0;                         //发送完数据清零buf[34],500ms清零。

  419.    k=11;                              //一共发送12个数据,从d[0]~d[11]。
  420.    send1(buf,k);
  421.         }


  422.    n=11;                              //接收数据一帧为12个数据                                     
  423.    receive(buf,n);

  424.    WDT_CONTR=0x34;
  425.     n=1;
  426.    delay(n);
  427.     }

  428.   }


  429. //2017年编制的电压电流温度测量软件,处理并发送数据。
复制代码

所有资料51hei提供下载:
备份.zip (8.27 KB, 下载次数: 9)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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