找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3784|回复: 4
收起左侧

用STC单片机做的7KW电动车充电桩源程序

  [复制链接]
ID:878048 发表于 2021-1-16 09:56 | 显示全部楼层 |阅读模式
用是STCD 15W404AS 做主控,片内资源用到了,可调PWM,ADC , 串口(用来读取计量模块的数据),具体功能,可按键调充电功率,1602显示实时电压,电流,功率,电能累计,
设计有1602显示,但是不知道时序写的还有些问题还是干扰问题,充电的时候就白屏了或者乱码了,,不充电有时候有时候是正常的,这里还需要调试,目前已经正常充电,电流30A

单片机源程序如下:
  1. #include <reg52.h>
  2. #include "intrins.h"
  3. sfr AUXR        =   0x8E;   //0000,0000 辅助寄存器
  4. sfr T2H         =   0xD6;   //0000,0000 T2高字节
  5. sfr T2L         =   0xD7;   //0000,0000 T2低字节

  6. sfr P0M1 = 0x93;
  7. sfr P0M0 = 0x94;
  8. sfr P1M1 = 0x91;
  9. sfr P1M0 = 0x92;
  10. sfr P2M1 = 0x95;
  11. sfr P2M0 = 0x96;
  12. sfr P3M1 = 0xb1;
  13. sfr P3M0 = 0xb2;
  14. sfr P4M1 = 0xb3;
  15. sfr P4M0 = 0xb4;
  16. sfr P5M1 = 0xC9;
  17. sfr P5M0 = 0xCA;
  18. sfr P6M1 = 0xCB;
  19. sfr P6M0 = 0xCC;
  20. sfr P7M1 = 0xE1;
  21. sfr P7M0 = 0xE2;
  22. /////////////////////////////////////////////////////////////////////////////////////////////
  23. //PWM模块寄存器定义
  24. sfr P_SW1  = 0xA2;             //外设功能切换寄存器1   针脚选择功能寄存器

  25. #define CCP_S0 0x10                 //P_SW1.4         选择针脚功能
  26. #define CCP_S1 0x20                 //P_SW1.5         选择针脚功能
  27. #define S1_S1 0x80                 //P_SW3.6         选择针脚功能
  28. #define S1_S0 0x40                 //P_SW3.7         选择针脚功能
  29. sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
  30. sfr ADC_RES     =   0xBD;           //ADC高8位结果
  31. sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
  32. sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器

  33. #define ADC_POWER   0x80            //ADC电源控制位
  34. #define ADC_FLAG    0x10            //ADC完成标志
  35. #define ADC_START   0x08            //ADC起始控制位
  36. #define ADC_SPEEDLL 0x00            //540个时钟
  37. #define ADC_SPEEDL  0x20            //360个时钟
  38. #define ADC_SPEEDH  0x40            //180个时钟
  39. #define ADC_SPEEDHH 0x60            //90个时钟
  40.                                                                                                                                                                                                                                                                             
  41. sfr CCON        =   0xD8;           //PCA控制寄存器
  42. sbit CCF0       =   CCON^0;         //PCA模块0中断标志
  43. sbit CCF1       =   CCON^1;         //PCA模块1中断标志
  44. sbit CR         =   CCON^6;         //PCA定时器运行控制位
  45. sbit CF         =   CCON^7;         //PCA定时器溢出标志
  46. sfr CMOD        =   0xD9;           //PCA模式寄存器
  47. sfr CL          =   0xE9;           //PCA定时器低字节
  48. sfr CH          =   0xF9;           //PCA定时器高字节
  49. sfr CCAPM0      =   0xDA;           //PCA模块0模式寄存器  
  50. sfr CCAP0L      =   0xEA;           //PCA模块0捕获寄存器 LOW
  51. sfr CCAP0H      =   0xFA;           //PCA模块0捕获寄存器 HIGH
  52. sfr CCAPM1      =   0xDB;           //PCA模块1模式寄存器
  53. sfr CCAP1L      =   0xEB;           //PCA模块1捕获寄存器 LOW
  54. sfr CCAP1H      =   0xFB;           //PCA模块1捕获寄存器 HIGH
  55. sfr CCAPM2      =   0xDC;           //PCA模块2模式寄存器
  56. sfr CCAP2L      =   0xEC;           //PCA模块2捕获寄存器 LOW
  57. sfr CCAP2H      =   0xFC;           //PCA模块2捕获寄存器 HIGH
  58. sfr PCA_PWM0    =   0xf2;           //PCA模块0的PWM寄存器
  59. sfr PCA_PWM1    =   0xf3;           //PCA模块1的PWM寄存器
  60. sfr PCA_PWM2    =   0xf4;           //PCA模块2的PWM寄存器
  61. ///////////////////////////////////////////////////////////函数列表、、、、、、、、、、、、、、、、、、、、、、、、、、、
  62. void UartInit();   //初始化串口
  63. void Timer0Init(); //初始化T0
  64. void UartWxd();         //发送数据查询实时信息
  65. void jiexibuf();         //解析接受到的数据
  66. void pwm();         //解析接受到的数据
  67. void InitADC(); //初始化ADC
  68. void GetADCResult();   //读取ADC的值存储在变量adc里面
  69. void Delay(unsigned int n);           //软件延时 1.6毫秒左右
  70. void chongdian();                        //          充电流程
  71. void  diannengjisuan();//J计算初始电能并计算已用电能
  72. void dianliuxuanze(); //按钮选项电流
  73. ///////////////////////////////////////////////////////////定义的一些变量、、、、、、、、、、、、、、、、、、、、、、、、、、、
  74. bit flagTxd = 0; //单字节发送完成标志,用来替代 TXD 中断标志位
  75. sbit s1 = P3^3;         //切换继电器
  76. sbit km = P3^2;         //功率继电器接触器
  77. sbit pwmdip = P1^1;
  78. sbit k1 = P3^0;                //按钮
  79. //sbit LED = P1^2;
  80. unsigned char cntRxd = 0; //接收字节计数器
  81. unsigned char pdata bufRxd[30]; //接收字节缓冲区
  82. unsigned char code bufWxd[8] ={0x01,0x03,0x00,0x48,0x00,0x0A,0x45,0xDB,};//发送的数据        增加了code关键字,此数组写在程序区减少使用内部内存128K
  83. unsigned long pdata cnt = 0; //毫秒计数
  84. unsigned long pdata sec; //秒计数
  85. //unsigned cha *but;// 发送指针
  86. unsigned int pdata vcc; // 电压
  87. unsigned int pdata vci; // 电流
  88. unsigned int pdata power; // 功率
  89. unsigned long pdata kwh=0; // 电能
  90. unsigned long pdata kwh1; // 初始电能
  91. unsigned char pw;         //设定的空占比%
  92. unsigned char cp; //充电桩PWM波形 cp电压采集信号        120
  93. ////            关于LCD 1602        /////////////////LCD的一些定义
  94. sfr P5   = 0xC8;
  95. unsigned char pdata lcd1[16];         //LCD第一行
  96. unsigned char pdata lcd2[16];         //LCD第二行
  97. sbit LCD1602_RS = P5^5;         //命令、数据选择 H\L
  98. sbit LCD1602_E = P5^4;         //使能
  99. unsigned char pdata ki;        //电流显示1表示16A   2表示32A

  100. #define LCD1602_DATAPINS P1    //定义P1口为数据端
  101. void LcdWriteCom(unsigned char com); /*LCD1602写入8位数据子函数*/       
  102. void LcdWriteData(unsigned char dat);        /*LCD1602写入8位数据子函数*/
  103. void LcdInit();                        /*LCD1602初始化子程序*/       
  104. void lcd1602();         //1602显示刷新
  105. void Lcd1602_Delay5ms();
  106. void Lcd1602_Delay1ms();

  107. void main(){
  108.     P0M0 = 0x00;
  109.     P0M1 = 0x00;
  110.     P1M0 = 0x00;
  111.     P1M1 = 0x00;
  112.     P2M0 = 0x00;
  113.     P2M1 = 0x00;
  114.     P3M0 = 0x00;
  115.     P3M1 = 0x00;
  116.     P4M0 = 0x00;
  117.     P4M1 = 0x00;
  118.     P5M0 = 0x00;
  119.     P5M1 = 0x00;
  120.     P6M0 = 0x00;
  121.     P6M1 = 0x00;
  122.     P7M0 = 0x00;
  123.     P7M1 = 0x00;
  124.         P_SW1=P_SW1|S1_S0;
  125.     EA = 1; //使能总中断
  126.         ES = 1;    //使能串口1中断
  127.            UartInit();         //初始化串口
  128.             pwm();         //初始化pwm模块设置
  129.         InitADC(); //初始化ADC
  130.        
  131.         Timer0Init(); //初始化T0
  132.                 LcdInit();//初始化lcd
  133.                   
  134.     while (1){
  135.         chongdian();  //充电流程
  136.         dianliuxuanze(); //电流选择函数
  137.        
  138.         if(TF0==1){                                   //t0溢出的次数
  139.                 cnt++;}
  140.       if(pwmdip==1){           //检测                  
  141.           GetADCResult(); //读取刷新ADC的值         cp就是读取的8位电压信号
  142.             
  143.            }
  144.         if(cnt>=20000){                  //大概1秒钟,还可以调整
  145.                         
  146.              cnt=0;
  147.                  sec++;
  148.                                                    
  149.                  UartWxd();          //发送电能模块读取命令                 
  150.                  jiexibuf();  //解析接受到的数据
  151.                  diannengjisuan(); //电能计算函数
  152.                  lcd1602();          //lcd显示          
  153.                           }

  154.           

  155.                                          }  }
  156.   void chongdian(){          //、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、充电流程

  157.            if(cp>111){      //当cp电压大于11.1时                          状态1
  158.                  s1=1;                        //小接触器不吸合 常闭点12V  s1
  159.                  km=1;
  160.                          }           //主接触器不吸合   
  161.            if(98>cp && cp>81){           //当cp电压大于8.1V小于9.8时          状态2                 与车辆已连接
  162.                  s1=0;                        //小接触器吸合         切换至PWM
  163.                  km=1;                        }           //主接触器不吸合
  164.            if(66>cp && cp>51){                  //当cp电压大于5.1小于6.6时          状态3         充电中
  165.                  s1=0;                   //小接触器吸合         切换至PWM
  166.                  km=0;                                    //主接触器吸合  开始充电
  167.                
  168.                          }
  169.                         }

  170.   void dianliuxuanze(){                         //电流选择初始值16A
  171.                  bit i=0;                //电流选择初始值16A
  172.                  if (i==1){            //不切换电流16A
  173.                            pw=33;
  174.                                    ki=1;}
  175.                   else{pw=60;
  176.                   ki=2;}         // 切换电流32A

  177.        if(k1==0)
  178.         {  Lcd1602_Delay5ms();
  179.                    Lcd1602_Delay5ms();
  180.                    if(k1==0){
  181.               i=!i;//k1按下置反i
  182.                              }
  183.       

  184. }
  185.         }

  186.   void pwm(){  //PWM程序、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

  187.    
  188.     ACC = P_SW1;                                        //累加器 等于外设寄存器
  189.     ACC &= ~(CCP_S0 | CCP_S1);      //CCP_S0=0 CCP_S1=0
  190.     P_SW1 = ACC;                    //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)         读取累加器的值写进外设寄存器
  191.     CCON = 0;                       //初始化PCA控制寄存器
  192.                                     //PCA定时器停止
  193.                                     //清除CF标志
  194.                                     //清除模块中断标志
  195.     CL = 0;                         //复位PCA寄存器
  196.     CH = 0;
  197.         CMOD = 0x04;
  198.    // CMOD = 0x04;                    //设置PCA时钟源        t0定时器
  199.                                     //禁止PCA定时器溢出中断
  200.     PCA_PWM0 = 0x00;                //PCA模块0工作于8位PWM
  201.     CCAP0H = CCAP0L =255-255*60/100;         //PWM0的占空比为87.5% ((100H-20H)/100H)         255-255*设定空占比        /100
  202.     CCAPM0 = 0x42;                  //00101010  PCA模块0允许比较功能        使用CCP0脚为可调脉冲输出         P1.1

  203.                                  }
  204. void Timer0Init()                //T0作为PWM频率基准发生
  205. {
  206.        
  207.         AUXR |= 0x80;                //定时器时钟1T模式
  208.         TMOD &= 0xF0;                //设置定时器模式
  209.         TL0 = 0xd5;        //设置定时初值                计算方法,65536-晶振/(256*需要频率)   
  210.         TH0 = 0xFf;                //设置定时初值       
  211.         TR0 = 1;                //定时器0开始计时
  212.           ET0 =0;                        // 禁止T0中断
  213.         TF0 = 0;                //清除TF0标志
  214. //        EA  =0;                        关闭总总中断
  215.     CR = 1; }                        //PCA定时器开始工作

  216. ///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. //        AUXR |= 0x80;                //定时器时钟1T模式
  218. //        TMOD &= 0xF0;                //设置定时器模式
  219. //        TL0 = 0xff;                //设置定时初值
  220. //        TH0 = 0xf6;                //设置定时初值
  221. //        TF0 = 0;                //清除TF0标志
  222. //        TR0 = 1;                //定时器0开始计时
  223. /*----------------------------
  224. 初始化ADC
  225. ----------------------------*/
  226. void InitADC() //初始化ADC
  227. {
  228.     P1ASF = 0x01;                   //设置P1.0口为AD口
  229.     ADC_RES = 0;                    //清除结果寄存器
  230.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
  231.     Delay(2);                       //ADC上电并延时
  232. }
  233. /*----------------------------
  234. 读取ADC结果
  235. ----------------------------*/
  236. void GetADCResult()
  237. {        unsigned long y;
  238.     ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 0 | ADC_START;         //ADC电源    540个时钟ADC_SPEEDHH    ADC_SPEEDLL  通道号           启动
  239.     _nop_();                        //等待4个NOP
  240.     _nop_();
  241.     _nop_();
  242.     _nop_();
  243.     while (!(ADC_CONTR & ADC_FLAG));//等待ADC转换完成
  244.     ADC_CONTR &= ~ADC_FLAG;         //Close ADC
  245.          
  246.          //实际滤波测得4.6V一下不予处理
  247.          if(ADC_RES>0x64){
  248.             y=12000000/256*(ADC_RES+1);                                                  //ADC结果转换 单位是最大12000毫伏          
  249.            cp=y/100000;                                                        //结果转换120v  放大10倍最大电压
  250.                                         }
  251. }

  252.    void jiexibuf()                 //解析接受到的数据
  253. {        unsigned long h;
  254.         unsigned long j;
  255.         unsigned long l;
  256.         unsigned long o;
  257.         vcc    = (bufRxd[3]<<8)| bufRxd[4];        //电压          int16位
  258.         vci    = (bufRxd[5]<<8)| bufRxd[6];        //电流          int16位
  259.         power  = (bufRxd[7]<<8)| bufRxd[8];        //功率          int16位
  260.          h     = (bufRxd[9]<<8)| bufRxd[10];//电能 32位数据高16位
  261.          j           = (bufRxd[11]<<8)|bufRxd[12];//电能 32位数据低16位
  262.          l     = h<<16;
  263.          o     = (l|j)*100;
  264.         kwh   =  o/3200;             
  265.                                 }
  266. void  diannengjisuan()        //计算电能显示函数
  267. {         unsigned long x;
  268.           static bit p=1;
  269.        
  270.          if(p==1){        //开始初始电能记录
  271.                      if(s1==0){  //刷新是否有电能数据
  272.                                     x=kwh1;                // 初始电能传给x
  273.                                     p=0;                //退出初始电能记录
  274.                                                           }       
  275.                        }
  276.      // kwh=kwh1-x;
  277.              }

  278. void UartInit()                //4800bps@11.0592MHz

  279. {
  280. //        P_SW1=P_SW1|S1_S0;
  281.         SCON = 0x50;                //8位数据,可变波特率
  282.         AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
  283.         AUXR |= 0x04;                //定时器2时钟为Fosc,即1T
  284.         T2L = 0xC0;                //设定定时初值
  285.         T2H = 0xFD;                //设定定时初值
  286.         AUXR |= 0x10;                //启动定时器2
  287. }
  288. void UartWxd(){       
  289.         unsigned char u; //数据位置         bufWxd[u]  
  290.          for(u=0;u<=7;u++)
  291.          {       
  292.         flagTxd=0;
  293.                 SBUF=bufWxd[u];                //          SBUF=bufWxd[u];
  294.                 while(!flagTxd);
  295.                                                
  296.         }
  297.                                         }

  298. /*----------------------------
  299. 软件延时
  300. ----------------------------*/
  301. void Delay(unsigned int n)
  302. {
  303.     unsigned int x;

  304.     while (n--)
  305.     {
  306.         x = 5000;
  307.         while (x--);
  308.     }
  309. }



  310. void InterruptUART() interrupt 4{
  311.     if (RI){ //接收到字节
  312.         RI = 0; //手动清零接收中断标志位
  313.         bufRxd[cntRxd++] = SBUF; //接收的数据存到接收缓冲区,数组
  314.            if(cntRxd==25){                  //接收24帧数据,然后复位接收计数器,下次从0开始接收
  315.                  cntRxd=0;
  316.                               }
  317.     }
  318.     if (TI){ //字节发送完毕
  319.        TI = 0; //手动清零发送中断标志位
  320.            flagTxd = 1; //设置字节发送完成标志
  321.     }
  322.         }
  323. //清中断标志/清中断标志
  324. //void PCA_isr() interrupt 7
  325. //{
  326. //    CCF0 = 0;                       //清中断标志
  327. //    CCAP0L = value;
  328. //    CCAP0H = value >> 8;            //更新比较值
  329. //    value += T100Hz;
  330. //    if (cnt-- == 0)
  331. //    {
  332. //        cnt = 100;                  //记数100次
  333. //       PCA_LED = !PCA_LED;         //每秒闪烁一次
  334. //    }
  335. //}
  336. ////            关于LCD 1602 LCD 1602 LCD 1602 LCD 1602 LCD 1602 LCD 1602 LCD 1602                            /////////////////LCD的一些定义

  337. void LcdWriteCom(unsigned char com)          //写入命令
  338. {
  339.         LCD1602_E = 0;         //使能清零
  340.         LCD1602_RS = 0;         //选择写入命令

  341.         LCD1602_DATAPINS = com >>2;        //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
  342.         Lcd1602_Delay1ms();

  343.         LCD1602_E = 1;         //写入时序
  344.         Lcd1602_Delay5ms();
  345.         LCD1602_E = 0;

  346.         LCD1602_DATAPINS = com << 2; //发送低四位       
  347.         Lcd1602_Delay1ms();

  348.         LCD1602_E = 1;         //写入时序
  349.         Lcd1602_Delay5ms();
  350.         LCD1602_E = 0;
  351.                                 }
  352. void LcdWriteData(unsigned char dat)                        //写入数据
  353. {
  354.         LCD1602_E = 0;          //使能清零
  355.         LCD1602_RS = 1;          //选择写入数据
  356. //        LCD1602_RW = 0;          //选择写入
  357.           
  358.              
  359.         LCD1602_DATAPINS = dat >>2;        //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
  360.         Lcd1602_Delay1ms();

  361.         LCD1602_E = 1;          //写入时序
  362.         Lcd1602_Delay5ms();
  363.         LCD1602_E = 0;

  364.         LCD1602_DATAPINS = dat << 2; //写入低四位
  365.         Lcd1602_Delay1ms();

  366.         LCD1602_E = 1;          //写入时序
  367.         Lcd1602_Delay5ms();
  368.         LCD1602_E = 0;
  369. }
  370. void LcdInit()                                                  //LCD初始化子程序
  371. {       
  372.         Delay(20);
  373.         LcdWriteCom(0x32);         //将8位总线转为4位总线
  374.         LcdWriteCom(0x28);         //在四位线下的初始化
  375.         LcdWriteCom(0x0c);  //开显示不显示光标
  376.         LcdWriteCom(0x06);  //写一个指针加1
  377.         LcdWriteCom(0x01);  //清屏
  378.         //LcdWriteCom(0x80);  //设置数据指针起点
  379. }
  380. void lcd1602()
  381. {        LcdWriteCom(0x80);  //设置数据指针起点
  382.         LcdWriteData('V');
  383.         LcdWriteData(':');
  384.         LcdWriteData('0'+vcc/10000%10);
  385.         LcdWriteData('0'+vcc/1000%10);
  386.         LcdWriteData('0'+vcc/100%10);
  387.         LcdWriteData('.');
  388.         LcdWriteData('0'+vcc/10%10);
  389.         LcdWriteData('0'+vcc%10);
  390.         LcdWriteData(' ');
  391. ……………………

  392. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
51hei截图20210116100025.png 51hei.png

所有程序51hei提供下载:
485 - 通讯程序加显示.zip (53.37 KB, 下载次数: 109)

评分

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

查看全部评分

回复

使用道具 举报

ID:864602 发表于 2021-1-20 21:15 | 显示全部楼层
学习利器,谢谢
回复

使用道具 举报

ID:507641 发表于 2022-9-22 10:14 | 显示全部楼层
原理图都没有,怎么分析??/
回复

使用道具 举报

ID:507641 发表于 2022-9-22 10:25 | 显示全部楼层
原理图与 pcb都可能,结合程序分析才能分析.下载看你的还要币???怎么的会有人帮分析老大???
回复

使用道具 举报

ID:1046301 发表于 2022-9-30 08:34 | 显示全部楼层
从事电源类开发的。加个好友一起学习一下。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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