找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+CS5463单相用电器分析监测装置程序+电路设计与制作

  [复制链接]
跳转到指定楼层
楼主
ID:602704 发表于 2019-8-28 15:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好:

          这是我第二天在51黑电子论坛的知识海洋里与各位共师兄习和探讨,做了一个单相用电器分析监测装置,希望哪里有需要完善的地方请各位多多赐教。
          话不多说上图


1,实物照片



2,测试数据照片




3,原理图及PCB文件







4,CS5463  单相双向功率/电能IC *****************************

    这块是需要大家重视的一个知识点
特性
  电能数据线性度:在1000 :1 动态范围内线性度为 ±0.1%  片内功能:    ——可以测量瞬时电压,电流和功率;IRMS和 VRMS, 视在功率,有功和无功功率;有功的基波和谐波功;
无功的基波功率, 功率因数, 频率 —— 具有电能-脉冲转换功能 ——具有系统校准和相位补偿 ——具有温度传感器  两种无功计算方式  符合IEC, ANSI, JIS
工业标准  功耗<12mW  优化的分流器接口  单电源地参考信号  片内2.5V 参考电压(大温漂25ppm/℃)  内带电源监视器  简单的三线数字串行接口  可以从串行EEPROM 智能“自引导”,不需要微控制器  电源配置 VA+ = +5 V; AGND = 0 V; VD+ = +3.3V~+5 V

概述 CS5463 是一个包含两个ΔΣ模-数转换器(ADC)、功率计算功能、电能到频率转换器和一个串行接口的 完整的功率测量芯片。它可以精确测量瞬时电压,电流和计算IRMS、VRMS、瞬时功率、有功功率、无功功率,用 于研制开发单相、2线或3线电表。 CS5463可以使用低成本的分流器或互感器测量电流,使用分压电阻或电压互感器测量电压。 CS5463具有与微控制器通讯的双向串口,可编程的电能-脉冲输出功能。CS5463还具有方便的片上系统校准。


            pin24=SSOP  

5,整机程序


  1. //头文件
  2. #include <REG52.h>
  3. #include <string.h>
  4. #include <intrins.h>
  5. #define uint  unsigned int
  6. #define uchar unsigned char

  7. typedef bit  bool;
  8. typedef unsigned char  uint8;                   /* defined for unsigned 8-bits integer variable         无符号8位整型变量  */
  9. typedef signed   char  int8;                    /* defined for signed 8-bits integer variable                有符号8位整型变量  */
  10. typedef unsigned int   uint16;                  /* defined for unsigned 16-bits integer variable         无符号16位整型变量 */
  11. typedef signed   int   int16;                   /* defined for signed 16-bits integer variable                 有符号16位整型变量 */
  12. typedef unsigned long  uint32;                  /* defined for unsigned 32-bits integer variable         无符号32位整型变量 */
  13. typedef signed   long  int32;                   /* defined for signed 32-bits integer variable                 有符号32位整型变量 */
  14. typedef float          fp32;                    /* single precision floating point variable (32bits) 单精度浮点数(32位长度) */

  15. /*****************************************************************************/
  16. sbit LCM_cs   = P0^0;  //RS
  17. sbit LCM_std  = P0^1;  //SID
  18. sbit LCM_sclk = P0^2;  //SCLK
  19. //sbit LCM_psb  = P2^3;   //H=并口; L=串口;

  20. char a,b,c;
  21. char aa,bb,cc,dd,ee;
  22. char i,q,T=125;
  23. uchar code tab1[]={
  24. "电压:           "
  25. "功率:           "
  26. "电流:           "
  27. "温度:           "
  28. };
  29. /****************************************************************************/

  30. uchar r[3]={0x00,0x00,0x00};

  31. /******************************************************************
  32.                            接口定义
  33. ******************************************************************/
  34. sbit SCLK=P2^2;         //ck
  35. sbit MOSI=P2^1;         //DI
  36. sbit MISO=P2^0;         //DO
  37. sbit INT=P3^2;
  38. sbit CS=P2^3;
  39. sbit RST=P2^4;        //RST

  40. #define CS5463_VScale       525             //计算电压比例,220V*250mv/110mv=500V
  41. #define CS5463_IScale       (250/10)        //计算电流比例

  42. static uint8 RX_Buff[4];                                        //CS5463读写缓冲区
  43. uint8 sta;                                                                        //芯片状态

  44. #define READ_MASK                        0xBF        //读寄存器时的屏蔽码,与(写)地址相与
  45. #define CMD_SYNC0            0XFE          //结束串口重新初始化
  46. #define CMD_SYNC1            0XFF          //开始串口重新初始化
  47. #define REG_CONFR           0x40           //配置
  48. #define REG_CYCCONT         0x4A           //一个计算周期的A/D转换数
  49. #define REG_STATUSR         0x5E         //状态
  50. #define REG_MODER           0x64          //操作模式
  51. #define REG_MASKR           0x74          //中断屏蔽
  52. #define REG_CTRLR           0x78          //控制
  53. #define CMD_STARTC           0XE8          //执行连续计算周期

  54. #define REG_VRMSR           0X18          //VRMS
  55. #define REG_IRMSR           0X16          //IRMS
  56. #define REG_Pactive           0X14          //Pactive

  57. sbit Relay = P3^7;//断电器引脚定义
  58. uint32 CurrentCtl;//电流全局变量

  59. /*************************************************************
  60. ** 函数名称:uDelay
  61. ** 函数功能:延时
  62. ** 函数参数:j
  63. ** 返回值:无
  64. ** 创建时间:2009-4-23
  65. ** 第一次修改时间:无
  66. **************************************************************/
  67. static  void uDelay(uint8 j)
  68. {
  69.   uint8 i;
  70.   for(;j>0;j--)
  71.         { for(i=0;i<255;i--)
  72.                 {
  73.                 ;
  74.                 }
  75.         }
  76. }
  77. /*************************************************************
  78. ** 函数名称:CS5463CMD
  79. ** 函数功能:CS5463命令函数
  80. ** 函数参数:无
  81. ** 创建时间:2009-9-14
  82. ** 第一次修改时间:无
  83. **************************************************************/
  84. static void CS5463CMD(uint8 cmd)
  85. {
  86. uint8 i;
  87. SCLK = 1;
  88. CS = 0;
  89. i = 0;
  90. while(i<8)
  91. {
  92.   uDelay(50);
  93.         SCLK = 0;
  94.         if(cmd&0x80)MOSI = 1;
  95.         else                MOSI = 0;
  96.         uDelay(50);
  97.         SCLK = 1;                                         //在时钟上升沿,数据被写入CS5463
  98.         cmd <<= 1;
  99.         i++;
  100. }
  101. uDelay(50);
  102. CS = 1;
  103. }
  104. /*************************************************************
  105. ** 函数名称:CS5463WriteReg
  106. ** 函数功能:CS5463写寄存器函数
  107. ** 函数参数:无
  108. ** 创建时间:2009-9-14
  109. ** 第一次修改时间:无
  110. **************************************************************/
  111. void CS5463WriteReg(uint8 addr,uint8 *p)
  112. {
  113. uint8 i,j;
  114. uint8 dat;
  115. SCLK = 1;
  116. CS = 0;
  117. i = 0;
  118. while(i<8)
  119. {
  120.           uDelay(50);
  121.         SCLK = 0;
  122.         if(addr&0x80)MOSI = 1;
  123.         else                 MOSI = 0;
  124.         uDelay(50);
  125.         SCLK = 1;                                         //在时钟上升沿,数据被写入CS5463
  126.         addr <<= 1;
  127.         i++;
  128. }
  129. j = 0;
  130. while(j<3)
  131. {
  132.           dat = *(p+j);
  133.         i = 0;
  134.         while(i<8)
  135.         {
  136.                   uDelay(50);
  137.                 SCLK = 0;
  138.                 if(dat&0x80)MOSI = 1;
  139.                 else                MOSI = 0;
  140.                 uDelay(50);
  141.                 SCLK = 1;                                  //在时钟上升沿,数据被写入CS5463
  142.                 dat <<= 1;
  143.                 i++;
  144.         }
  145.         j++;
  146. }
  147. uDelay(50);
  148. CS = 1;
  149. }
  150. /*************************************************************
  151. ** 函数名称:CS5463ReadReg
  152. ** 函数功能:CS5463读寄存器函数
  153. ** 函数参数:无
  154. ** 创建时间:2009-9-14
  155. ** 第一次修改时间:无
  156. **************************************************************/
  157. void CS5463ReadReg(uint8 addr,uint8 *p)
  158. {
  159. uint8 i,j;
  160. uint8 dat;
  161. SCLK = 0;
  162. CS = 0;
  163. addr &= READ_MASK;
  164. i = 0;
  165. while(i<8)
  166. {
  167.           uDelay(50);
  168.         SCLK = 0;
  169.         if(addr&0x80)MOSI = 1;
  170.         else                 MOSI = 0;
  171.         uDelay(50);
  172.         SCLK = 1;
  173.         addr <<= 1;                                         //在时钟上升沿,数据被写入CS5463
  174.         i++;
  175. }
  176. uDelay(50);
  177. MOSI = 1;
  178. j = 0;
  179. while(j<3)
  180. {
  181.         i = 0;
  182.         dat = 0;
  183.         while(i<8)
  184.         {
  185.                 if(i==7)MOSI = 0;
  186.                 else        MOSI = 1;
  187.                 SCLK = 0;
  188.                 uDelay(50);
  189.                 dat <<= 1;                                                
  190.                 if(MISO)dat |= 0x01;
  191.                 else        dat &= 0xFE;
  192.                 SCLK = 1;
  193.                 uDelay(50);                                                         
  194.                 i++;
  195.         }
  196.         *(p+j) = dat;
  197.         j++;
  198. }
  199. MOSI = 1;
  200. CS = 1;
  201. }
  202. /*************************************************************************************************
  203. ** CS5463 应用函数
  204. *************************************************************************************************/
  205. /*************************************************************
  206. ** 函数名称:CS5463Init
  207. ** 函数功能:CS5463复位和初始化函数
  208. ** 函数参数:无
  209. ** 创建时间:2009-9-14
  210. ** 第一次修改时间:无
  211. **************************************************************/
  212. bit CS5463_Init(void)           //
  213. {
  214. RST = 0;
  215. uDelay(200);
  216. RST = 1;
  217. uDelay(100);
  218. //----------------------
  219. //发送同步序列
  220. RX_Buff[0] = CMD_SYNC1;
  221. RX_Buff[1] = CMD_SYNC1;
  222. RX_Buff[2] = CMD_SYNC0;
  223. CS5463WriteReg(CMD_SYNC1,RX_Buff);          //#define CMD_SYNC1            0XFF          //开始串口重新初始化               
  224. //----------------------
  225. //初始化--配置寄存器
  226. //相位补偿为PC[6:0]=[0000000];
  227. //电流通道增益为Igain=10;
  228. //EWA=0;
  229. //INT中断为低电平有效IMODE:IINV=[00]
  230. //iCPU=0
  231. //K[3:0]=[0001]
  232. RX_Buff[0] = 0x00;                                                
  233. RX_Buff[1] = 0x00;
  234. RX_Buff[2] = 0x01;
  235. CS5463WriteReg(REG_CONFR,RX_Buff);         //        #define REG_CONFR           0x40           //配置
  236. //----------------------
  237. //初始化--操作寄存器
  238. RX_Buff[0] = 0x00; //B0000_0000;                                 
  239. RX_Buff[1] = 0x00;//B0000_0000;
  240. RX_Buff[2] = 0x60;//B0110_0000;
  241. CS5463WriteReg(REG_MODER,RX_Buff);          //#define REG_MODER           0x64          //操作模式
  242. //----------------------
  243. //初始化--电流 交流偏置 校准寄存器
  244. // RW24XX(RX_Buff,3,EE_IACBIAS,0xA1);
  245. // CS5463WriteReg(REG_IACOFF,RX_Buff);        
  246. //----------------------
  247. //初始化--电流 增益校准寄存器
  248. // RW24XX(RX_Buff,3,EE_IACGAIN,0xA1);
  249. // CS5463WriteReg(REG_IGN,RX_Buff);               
  250. //----------------------
  251. //初始化--电压 交流偏置 校准寄存器
  252. // RW24XX(RX_Buff,3,EE_VACBIAS,0xA1);
  253. // CS5463WriteReg(REG_VACOFF,RX_Buff);        
  254. //----------------------
  255. //初始化--电压 增益校准寄存器
  256. // RW24XX(RX_Buff,3,EE_VACGAIN,0xA1);
  257. // CS5463WriteReg(REG_VGN,RX_Buff);               
  258. //----------------------
  259. RX_Buff[0] = 0x00;
  260. RX_Buff[1] = 0x0F;
  261. RX_Buff[2] = 0xA0;                                                //#define REG_CYCCONT         0x4A           //一个计算周期的A/D转换数
  262. CS5463WriteReg(REG_CYCCONT,RX_Buff);        //初始化--CYCLE COUNT 寄存器,4000
  263. //----------------------
  264. //初始化--脉冲速率寄存器
  265. // RX_Buff[0] = 0x00;
  266. // RX_Buff[1] = 0x34;
  267. // RX_Buff[2] = 0x9C;
  268. // CS5463WriteReg(REG_PULRATE,RX_Buff);        
  269. //----------------------
  270. RX_Buff[0] = 0xFF;
  271. RX_Buff[1] = 0xFF;
  272. RX_Buff[2] = 0xFF;
  273. CS5463WriteReg(REG_STATUSR,RX_Buff);        //初始化--状态寄存器  #define REG_STATUSR         0x5E         //状态
  274. //----------------------
  275. RX_Buff[0] = 0x80;                                                //开电流、电压、功率测量完毕中断
  276. RX_Buff[1] = 0x00;
  277. RX_Buff[2] = 0x80;                                                //开温度测量完毕中断
  278. CS5463WriteReg(REG_MASKR,RX_Buff);                //初始化--中断屏蔽寄存器    #define REG_MASKR           0x74          //中断屏蔽
  279. //----------------------
  280. RX_Buff[0] = 0x00;
  281. RX_Buff[1] = 0x00;
  282. RX_Buff[2] = 0x00;
  283. CS5463WriteReg(REG_CTRLR,RX_Buff);                //初始化--控制寄存器   #define REG_CTRLR           0x78          //控制  
  284. //----------------------
  285. CS5463CMD(CMD_STARTC);                                           //启动连续转换            #define CMD_STARTC           0XE8          //执行连续计算周期
  286. //CS5463_Status = 0;                                                //初始化任务进程状态
  287. //Load_Status = 0;
  288. //CS5463_CrmsSmallCunt = 0;
  289. //CS5463_CrmsOverCunt = 0;
  290. return(1);                    //只要做完这些步骤就返回true  1
  291. }
  292. /*************************************************************
  293. ** 函数名称:CS5463_ResetStatusReg
  294. ** 函数功能:复位状态寄存器函数
  295. ** 函数参数:无
  296. ** 创建时间:2009-9-15
  297. ** 第一次修改时间:无
  298. **************************************************************/
  299. static void CS5463_ResetStatusReg(void)
  300. {
  301. RX_Buff[0] = 0xFF;
  302. RX_Buff[1] = 0xFF;
  303. RX_Buff[2] = 0xFF;
  304. CS5463WriteReg(0x5E,RX_Buff);                //复位状态寄存器        #define REG_STATUSR         0x5E         //状态  
  305. }
  306. /*************************************************************
  307. ** 函数名称:CS5463_GetStatusReg
  308. ** 函数功能:读取状态寄存器函数
  309. ** 函数参数:无
  310. ** 创建时间:2009-9-15
  311. ** 第一次修改时间:无
  312. **************************************************************/
  313. static uint8 CS5463_GetStatusReg(void)
  314. {
  315. uint8 sta=0;
  316. CS5463ReadReg(0x1E,RX_Buff);           //1E 是什么?   状态寄存器
  317. if(RX_Buff[0]&0x80)                                           //检测:电流、电压、功率测量是否完毕
  318. {
  319.         //检测电流/电压是否超出范围
  320.         //检测电流有效值/电压有效值/电能是否超出范围
  321.         if((RX_Buff[0]&0x03)||(RX_Buff[1]&0x70))
  322.         {
  323.                  CS5463_ResetStatusReg();                //复位状态寄存器
  324.         }
  325.         else
  326.         {
  327.                 sta |= 0x01;//B0000_0001;        //
  328.         }
  329. }

  330. if(RX_Buff[2]&0x80)                                   //检测:温度测量是否完毕
  331. {
  332.           sta |=0x02; //B0000_0010;
  333. }
  334. return(sta);        
  335. }  

  336. void DelayM(unsigned int a)       //延时函数 1MS/次        
  337. {
  338.                 unsigned char i;
  339.                 while( --a != 0)
  340.        {               
  341.                 for(i = 0; i < 125; i++);  //一个 ; 表示空语句,CPU空转从0加到125
  342.                 }                                      
  343. }

  344. void Delay(int num)//延时函数
  345. {
  346.         while(num--);
  347. }

  348. /******************************************************************************/
  349. //写指令或数据  (0,指令) (1,数据)
  350. void LCM_WriteDatOrCom(bit dat_comm,uchar content)
  351. {
  352.   uchar a,i,j;
  353.   Delay(50);
  354.   a=content;
  355.   LCM_cs=1;
  356.   LCM_sclk=0;
  357.   LCM_std=1;
  358.   for(i=0;i<5;i++)
  359.   {
  360.     LCM_sclk=1;
  361.     LCM_sclk=0;
  362.   }
  363.   LCM_std=0;
  364.   LCM_sclk=1;
  365.   LCM_sclk=0;
  366.   if(dat_comm)
  367.     LCM_std=1;   //data
  368.   else
  369.    LCM_std=0;   //command
  370.   LCM_sclk=1;
  371.   LCM_sclk=0;
  372.   LCM_std=0;
  373.   LCM_sclk=1;
  374.   LCM_sclk=0;
  375.   for(j=0;j<2;j++)
  376.   {
  377.     for(i=0;i<4;i++)
  378.     {
  379.       a=a<<1;
  380.       LCM_std=CY;
  381.       LCM_sclk=1;
  382.       LCM_sclk=0;
  383.     }
  384.     LCM_std=0;
  385.     for(i=0;i<4;i++)
  386.     {
  387.       LCM_sclk=1;
  388.       LCM_sclk=0;
  389.     }
  390.   }
  391. }
  392. /*********************************************************************************/


  393. /*****************************************************************************/
  394. //初始化LCM
  395. void LCM_init(void)         
  396. {
  397. //  LCM_psb=0;
  398.   LCM_WriteDatOrCom (0,0x30);  /*30---基本指令动作*/   
  399.   LCM_WriteDatOrCom (0,0x01);  /*清屏,地址指针指向00H*/
  400.   Delay (100);
  401.   LCM_WriteDatOrCom (0,0x06);  /*光标的移动方向*/
  402.   LCM_WriteDatOrCom(0,0x0c);   /*开显示,关游标*/
  403. }

  404. void chn_disp (uchar code *chn)   //显示4行 指针
  405. {
  406.   uchar i,j;
  407.   LCM_WriteDatOrCom  (0,0x30);         //        
  408.   LCM_WriteDatOrCom  (0,0x80);         //
  409.   for (j=0;j<4;j++)
  410.   {
  411.     for (i=0;i<16;i++)
  412.     LCM_WriteDatOrCom  (1,chn[j*16+i]);
  413.   }
  414. }
  415. /*****************************************************************************/
  416. //清屏函数
  417. void LCM_clr(void)
  418. {
  419.   LCM_WriteDatOrCom (0,0x30);
  420.   LCM_WriteDatOrCom (0,0x01);   /*清屏,地址指针指向00H*/
  421.   Delay (180);
  422. }
  423. /*****************************************************************************/
  424. //向LCM发送一个字符串,长度64字符之内。
  425. //应用:LCM_WriteString("您好!");
  426. void LCM_WriteString(unsigned char *str)
  427. {
  428.                 while(*str != '\0')
  429.        {
  430.                         LCM_WriteDatOrCom(1,*str++);
  431.         }
  432.                 *str = 0;        
  433. }

  434. /*************************************************************
  435. ** 函数名称:CS5463_GetCurrentRMS
  436. ** 函数功能:读取电流有效值函数
  437. ** 函数参数:无
  438. ** 创建时间:2009-9-15
  439. ** 第一次修改时间:无
  440. **************************************************************/
  441. static void CS5463_GetCurrentRMS(void)
  442. {
  443. fp32 G = 0.5,result;
  444. uint32 temp1;
  445. uint8 temp,i,j;
  446. CS5463ReadReg(REG_IRMSR,RX_Buff);                   //读取电流有效值
  447. //SndCom1Data(RX_Buff,3);
  448. i = 0;
  449. result = 0;
  450. while(i<3)
  451. {
  452.           temp = RX_Buff[i];                                          
  453.         j = 0;
  454.         while(j<8)
  455.         {
  456.                  if(temp&0x80)
  457.                 {
  458.                          result += G;        
  459.                 }
  460.                 temp <<= 1;
  461.                 j++;
  462.                 G = G/2;        
  463.         }
  464.         i++;
  465. }
  466. result = result*CS5463_IScale;//I_Coff;                                                //计算电流值 暂时不用
  467. result *= 1000;                                                                //单位mA(毫安)  12345ma
  468. temp1 = (uint32)result;
  469. CurrentCtl = temp1;

  470. LCM_WriteDatOrCom  (0,0x94);
  471.         aa=        temp1/10000;
  472.         if(aa==0)
  473.                 LCM_WriteDatOrCom(1,' ');
  474.         else
  475.                 LCM_WriteDatOrCom(1,aa+0x30);
  476.         bb=        (temp1%10000)/1000;
  477.         if((aa==0)&&(bb==0))
  478.                 LCM_WriteDatOrCom(1,' ');
  479.         else
  480.                 LCM_WriteDatOrCom(1,bb+0x30);
  481.         cc=(temp1%1000)/100;
  482.         if((aa==0)&&(bb==0)&&(cc==0))
  483.                 LCM_WriteDatOrCom(1,' ');
  484.         else
  485.                 LCM_WriteDatOrCom(1,cc+0x30);
  486. //        LCM_WriteDatOrCom(1,0x2e);  //小数点  不需要小数点
  487.         dd=        (temp1%100)/10;
  488.         LCM_WriteDatOrCom(1,dd+0x30);
  489.         ee=temp1%10;
  490.         LCM_WriteDatOrCom(1,ee+0x30);
  491.         LCM_WriteString(" mA");

  492. }


  493. /*************************************************************
  494. ** 函数名称:CS5463_GetPactiveRMS
  495. ** 函数功能:读取有功功率函数
  496. ** 函数参数:无
  497. ** 创建时间:2009-9-15
  498. ** 第一次修改时间:无
  499. **************************************************************/
  500. static void CS5463_GetPactiveRMS(void)
  501. {
  502. fp32 G = 1.0,result;
  503. uint8 temp,i,j;
  504. uint32 temp1;
  505. CS5463ReadReg(0x14,RX_Buff);           //读取有功功率REG_Pactive
  506. //SndCom1Data(RX_Buff,3);
  507. temp = RX_Buff[0];
  508. if(temp&0x80)                                                          //如果为负数,计算原码
  509. {
  510.           RX_Buff[0] = ~RX_Buff[0];                        //本来为取反+1,这里因为精度的原因,不+1
  511.         RX_Buff[1] = ~RX_Buff[1];
  512.         RX_Buff[2] = ~RX_Buff[2];                        
  513. }
  514. i = 0;
  515. result = 0;
  516. while(i<3)
  517. {
  518.           temp = RX_Buff[i];                                          
  519.         j = 0;
  520.         while(j<8)
  521.         {
  522.                  if(temp&0x80)
  523.                 {
  524.                          result += G;        
  525.                 }
  526.                 temp <<= 1;
  527.                 j++;
  528.                 G = G/2;        
  529.         }
  530.         i++;
  531. }
  532. // result = result*P_Coff;                                //计算功率,单位W(瓦特)
  533. // result = Vrms*Irms;                                        ////////直接计算功率
  534.   result = result*13125;
  535. temp1 = (uint32)result;

  536.   LCM_WriteDatOrCom  (0,0x8C);                //26W  12345W
  537.         aa=        temp1/10000;
  538.         if(aa==0)
  539.                 LCM_WriteDatOrCom(1,' ');
  540.         else
  541.                 LCM_WriteDatOrCom(1,aa+0x30);
  542.         bb=        (temp1%10000)/1000;
  543.         if((aa==0)&&(bb==0))
  544.                 LCM_WriteDatOrCom(1,' ');
  545.         else
  546.                 LCM_WriteDatOrCom(1,bb+0x30);
  547.         cc=(temp1%1000)/100;
  548.         if((aa==0)&&(bb==0)&&(cc==0))
  549.                 LCM_WriteDatOrCom(1,' ');
  550.         else
  551.                 LCM_WriteDatOrCom(1,cc+0x30);
  552. //        LCM_WriteDatOrCom(1,0x2e);  //小数点  不需要小数点
  553.         dd=        (temp1%100)/10;
  554.         LCM_WriteDatOrCom(1,dd+0x30);
  555.         ee=temp1%10;
  556.         LCM_WriteDatOrCom(1,ee+0x30);
  557.         LCM_WriteString(" W");

  558. }
  559. /*************************************************************
  560. ** 函数名称:CS5463_GetPowerFactor
  561. ** 函数功能:读取功率因数函数
  562. ** 函数参数:无
  563. ** 创建时间:2009-11-02
  564. ** 第一次修改时间:无
  565. **************************************************************
  566. static void CS5463_GetPowerFactor(void)
  567. {
  568. fp32 G = 1.0,result;
  569. uint8 temp,i,j;
  570. uint32 temp1;
  571. CS5463ReadReg(0x32,RX_Buff);                   //读取功率因数
  572. //SndCom1Data(RX_Buff,3);
  573. temp = RX_Buff[0];
  574. if(temp&0x80)                                                          //如果为负数,计算原码
  575. {
  576.           RX_Buff[0] = ~RX_Buff[0];                        //本来为取反+1,这里因为精度的原因,不+1
  577.         RX_Buff[1] = ~RX_Buff[1];
  578.         RX_Buff[2] = ~RX_Buff[2];                        
  579. }
  580. i = 0;
  581. result = 0;
  582. while(i<3)
  583. {
  584.           temp = RX_Buff[i];                                          
  585.         j = 0;
  586.         while(j<8)
  587.         {
  588.                  if(temp&0x80)
  589.                 {
  590.                          result += G;        
  591.                 }
  592.                 temp <<= 1;
  593.                 j++;
  594.                 G = G/2;        
  595.         }
  596.         i++;
  597. }
  598. result *= 10000;
  599. temp1 = (uint32)result;

  600. }


  601. /*************************************************************
  602. ** 函数名称:CS5463_GetTemperature
  603. ** 函数功能:读取温度函数
  604. ** 函数参数:无
  605. ** 创建时间:2009-11-03
  606. ** 第一次修改时间:无
  607. **************************************************************/
  608. static void CS5463_GetTemperature(void)          //温度能显示了 PT2017-2-12
  609. {
  610. fp32 G = 128,result;
  611. uint8 temp,i,j,pn=0;
  612. uint32 temp1;
  613. CS5463ReadReg(0x26,RX_Buff);                   //读取温度        是的在这里就读到了温度
  614. //SndCom1Data(RX_Buff,3);
  615. temp = RX_Buff[0];
  616. if(temp&0x80)                                                          //如果为负数,计算原码
  617. {
  618.           pn = 1;                                                                //负数标志
  619.         RX_Buff[0] = ~RX_Buff[0];                        //本来为取反+1,这里因为精度的原因,不+1
  620.         RX_Buff[1] = ~RX_Buff[1];
  621.         RX_Buff[2] = ~RX_Buff[2];                        
  622. }
  623. i = 0;
  624. result = 0;    //这个值是浮点数 先清零 再逐个把0.5的权 数据加进来
  625. while(i<3)
  626. {
  627.           temp = RX_Buff[i];        //虽然这个数组定义了4个字节 实际就用了 Buff[0]  Buff[1]  RX_Buff[2]                                   
  628.         j = 0;
  629.         while(j<8)
  630.         {
  631.                  if(temp&0x80)
  632.                 {
  633.                          result += G;        //把0.5的权数据加进来                  
  634.                 }
  635.                 temp <<= 1;
  636.                 j++;
  637.                 G = G/2;        
  638.         }
  639.         i++;
  640. }
  641. if(result<128)                          //是的这个result 是 -127,128   这里已经获取了温度浮点值 最多是一个3位数? 还有小数点
  642. {
  643.          result *= 100;
  644.         temp1 = (uint32)result;          //是的 这里就是 例如12523  -----> 125.23  怎么去显示? 如何分离 从8A开始显示

  645.             LCM_WriteDatOrCom  (0,0x9C);        // 显示起始位置  第4行
  646.                 aa=        temp1/ 10000;
  647.                 if(pn==1)
  648.                         LCM_WriteDatOrCom(1,'-');        
  649.                 else
  650.                         LCM_WriteDatOrCom(1,'+');        
  651.                         
  652.                 bb=temp1/1000- aa*10;
  653.                 LCM_WriteDatOrCom(1,bb+0x30);

  654.                 cc=        temp1/100- aa*100-bb*10;
  655.                 LCM_WriteDatOrCom(1,cc+0x30);
  656.             LCM_WriteDatOrCom(1,0x2e);         //"."
  657.                 dd=        (temp1%100)/10;
  658.                 LCM_WriteDatOrCom(1,dd+0x30);
  659.                 ee=temp1%10;
  660.                 LCM_WriteDatOrCom(1,ee+0x30);
  661.                 LCM_WriteString("℃");

  662. }
  663. }
  664. /*************************************************************
  665. ** 函数名称:CS5463_GetVoltRMS
  666. ** 函数功能:读取电压有效值函数
  667. ** 函数参数:无
  668. ** 创建时间:2009-9-15
  669. ** 第一次修改时间:2009-9-23,修改电压系数(需验证)
  670. ** 第二次修改时间:2010-3-22,设定测量读数小于100V时数据无效
  671. ** 第三次修改时间:
  672. **************************************************************/
  673. static void CS5463_GetVoltRMS(void)                 //PT2017-2-12 电压显示OK
  674. {
  675. float G = 0.5,result;                //typedef float          fp32;          就是浮点类型
  676. int temp1;                          //  int
  677. uint8 temp,i,j;                  //  byte
  678. CS5463ReadReg(REG_VRMSR,RX_Buff);                   //读取电压有效值  #define REG_VRMSR           0x58
  679. //SndCom1Data(RX_Buff,3);
  680. i = 0;
  681. result = 0;
  682. while(i<3)
  683. {
  684.           temp = RX_Buff[i];                                          
  685.         j = 0;
  686.         while(j<8)
  687.         {
  688.                  if(temp&0x80)
  689.                 {
  690.                          result += G;        
  691.                 }
  692.                 temp <<= 1;
  693.                 j++;
  694.                 G = G/2;        
  695.         }
  696.         i++;                                                               
  697. }                                                                                //电压在220时取样电压为78mv
  698. result = result*CS5463_VScale;//V_Coff;                                //计算电压值220V*250mv/(110mv/1.414)=704.8V            可以暂时不用  
  699. // if(result<=100)return;                                        //如果测量读出电压小于100V,确认读数错误
  700. result *= 100;                                                //单位为mV(毫伏) 12345mv  5位你怎么显示
  701. temp1 = (uint32)result;

  702.         LCM_WriteDatOrCom  (0,0x84);
  703.         aa=        temp1/10000;
  704.         LCM_WriteDatOrCom(1,aa+0x30);
  705.         bb=        (temp1%10000)/1000;
  706.         LCM_WriteDatOrCom(1,bb+0x30);
  707.         cc=(temp1%1000)/100;
  708.         LCM_WriteDatOrCom(1,cc+0x30);
  709.         LCM_WriteDatOrCom(1,0x2e);
  710.         dd=        (temp1%100)/10;
  711.         LCM_WriteDatOrCom(1,dd+0x30);
  712.         ee=temp1%10;
  713.         LCM_WriteDatOrCom(1,ee+0x30);
  714.         LCM_WriteString(" V");

  715. }

  716. void main() //整个程序函数从这里开始执行
  717. {
  718.   CS5463_Init();
  719.   LCM_init();       //初始化液晶显示器
  720.         LCM_clr();       //清屏
  721.         chn_disp(tab1); //显示欢迎字
  722.         DelayM(500);  //显示等留3秒
  723.   Relay = 1;
  724.   
  725.           while(1)
  726.           {
  727.         //        if(INT)break;                                                        //检查中断信号

  728.                 sta        = CS5463_GetStatusReg();                          //检测中断产生的原因
  729.                 if(0x01==(sta&0x01))                                           //读取电流电压
  730.                 {        
  731.         //                CS5463Monitor_Cunt = 0;                                //如果有中断,表明芯片正常工作,清除监控定时器
  732.                         CS5463_ResetStatusReg();                        //清除标志
  733.                         CS5463_GetVoltRMS();                                //获取电压
  734.                         CS5463_GetCurrentRMS();                                //获取电流
  735.                         CS5463_GetPactiveRMS();                                //获取功率
  736. //                        CS5463_GetPowerFactor();                        //获取功率因数
  737.                         if(0x02==(sta&0x02))                                //读取温度
  738.                         {        
  739.                         CS5463_GetVoltRMS();                                //获取电压                                                               
  740.                         CS5463_GetTemperature();                    //温度读取不需要太频繁,所以跟电流电压一起读取

  741.                                 //CS5463_Init();                                //重新初始化芯片
  742.                         }                                                
  743.                         //SndCom1Data(MeasureData,16);
  744.                 }
  745.                 if(CurrentCtl > 5000)//如果电流大于要求设置的5A则断电
  746. …………
  747. …………
复制代码

  最后,如果这个设计对你有所帮助请给我个评论赞   谢谢



全部资料51hei下载地址:
单相用电器分析监测装置设计 CS5463.7z (4.49 MB, 下载次数: 345)

评分

参与人数 2黑币 +106 收起 理由
andyhallo + 6 共享资料的黑币奖励!
admin + 100 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:282095 发表于 2019-8-29 08:43 | 只看该作者
楼主名不符实啊
回复

使用道具 举报

板凳
ID:602704 发表于 2019-9-24 11:21 | 只看该作者

你这是褒义词还是贬义词啊
回复

使用道具 举报

地板
ID:440960 发表于 2020-4-16 20:45 | 只看该作者
楼主太强了
回复

使用道具 举报

5#
ID:230915 发表于 2020-12-15 08:29 | 只看该作者
谢谢分享!!资料相当好。
回复

使用道具 举报

6#
ID:902022 发表于 2021-4-8 22:17 | 只看该作者
学长,麻烦看到联系一下我,帮我添加视在、无功、有功功率的程序段呗
回复

使用道具 举报

7#
ID:904473 发表于 2021-4-16 12:56 | 只看该作者
你好,请问protues里面没有的元件怎么办呢?比如各种电能计量芯片
回复

使用道具 举报

8#
ID:59830 发表于 2021-11-5 18:29 | 只看该作者
市电产品不多,参考学习一下.
回复

使用道具 举报

9#
ID:405840 发表于 2021-11-6 18:22 | 只看该作者
感谢楼主分享 21年电赛正好能用上]
回复

使用道具 举报

10#
ID:1004160 发表于 2023-10-25 11:44 | 只看该作者
牛啊,希望楼主能看到,几年前的帖子还能发现这种宝贝。我最近被电压、电流检测折磨死了。 用ACS712测电流,输出的是交流电压,给到PCF8591后好像不可以。8591好像只认直流电压,没办法用低通滤波将ACS712输出的交流电压转成直流电压,再给到8591,这样算出来,最后把低通滤波二极管降压的部分给反加回去,这样是不是有点儿弱?不过,稍有些误差(1A以内误差大)。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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