此芯片性能不出差
無標題.png (124.35 KB, 下載次數: 247)
下載附件
2018-7-23 08:16 上傳
0.png (43.01 KB, 下載次數: 167)
下載附件
2018-7-23 17:14 上傳
HLW8012產品應用文檔目錄
摘要
1 硬件設計
11 參考設計圖
111 非隔離采樣應用電路
112 隔離采樣應用電路
12 器件選型
121 采樣電阻選型(非隔離方案)
122 互感器選型(隔離方案)
123 電源芯片選型
13 Layout說明
131 單路計量方案
132 2 路或2 路以上計量方案
2 軟件設計
21 HLW8012 輸入與輸出的關系
22 脈沖頻率(周期)的計算方法
23 軟件設計流程圖
24 參考代碼文件
25 校準
3 HLW8012 性能數據
4 FAQ附錄
5 硬件自查
1.2.1 采樣電阻選型(非隔離方案)
HLW8012 的最大采樣電流和采樣電阻的大小相關,HLW8012的最大電流采樣電壓(即PIN2和 PIN3 之間的電壓差)是30.9mV,
所以,最大采樣電流 = 30.9mV/采樣電阻阻值,以圖 1 為例,采樣電阻阻值為 1mR,則最大采樣電流 = 30.9mV/1mR = 30.9A。
采樣電阻分為錳銅電阻、鏮銅電阻、合金電阻和精密貼片電阻,一般設計 WIFI PLUG 產品以精密貼片電阻和鏮銅電阻比較多;
1.2.2 互感器選型(隔離方案)
電流互感器
以圖2 為例,電流采樣電阻R = 1Ω,假設電流互感器T1 的變比是1000:1,互感器的最大測量電流是50A,那么將此互感器接入采樣電路,最大的測量電流和電阻有以下關系:
I /1000= 30.9mV/R,
I = (30.9mV/1Ω)*1000 = 30.9A
如果需要測量更大量程的電流,則在選定互感器后,然后調整采樣電阻R,使得I*R<30.9mV 即可;
電壓互感器
以圖 2 為例,電壓互感器 T2 的變比是 1000:1000,初級通過 5 個 20K 的電阻串接,初級電流 = 220V/(5*20K) = 2.2mA;T2的次級關聯50R 的電阻,那么經過電壓互感器 T2 轉化成的電壓 = 2.2mA*50R = 110mV,芯片 V2P的輸入電壓信號是110mV; 一般建議V2P的輸入信號在100mV至 300mV之間,如果信號輸入接近滿幅值有效值時(490mV) ,噪聲會變大,精度會下降。
1.2.3 電源芯片選型
HLW8012 的供電電源是 5V,工作電流是 3mA,工作電流非常小,所以一般電源都可以滿足要求。設計圖紙都是以 MPS 的 MP150 為例,還有許多非隔離芯片同樣可以滿足要求,比如芯朋的 PN8015和 PN8016,夕力杰的SY50281和 SY50282,還有昂寶的OB2222等。 下面以使非隔離電源AP8015為例為例,列舉錯誤應用和正確應用。
錯誤的非隔離電源電路(GND和N 不是同一參考):
0.png (47.41 KB, 下載次數: 176)
下載附件
2018-7-24 02:27 上傳
為什么需要GND和N選擇同一參考?
因為 HLW8012 的信號采樣采的是 L 和 N 的信號,信號線是以 N 為參考點,HLW8012 的內部采樣電路是以 N 為參考點;另外,HLW8012 的供電電源是 5V 和 GND,是以 GND 為參考點,
同一系統需要保證參考點一致,才能進行信號采樣,所以必須 GND和 N是同一參考點。 風險提示:如果不進行短接,那么信號端到 8012 的 PIN2 和 PIN 的電壓大小是浮壓,會有炸機的危險。
正確的非隔離電源電路(GND和N是同一參考) :
0.png (129.42 KB, 下載次數: 175)
下載附件
2018-7-24 02:28 上傳
上圖是以 N為參考地,那么是否可以使用 L做為參考地?
可以的,如果以L為參考地,那么只需將 L和N對調,其它不變,下圖也是正確的。
0.png (133.29 KB, 下載次數: 169)
下載附件
2018-7-24 02:29 上傳
1.3.1 單路計量方案
由于電流采樣端最大輸入信號是 30.9mV,以 測 量10A為例,如需分辯1mA,則相當于30.9mV需要等分 10000份,也就是芯片需要分辨3.09uV的信號,這個信號非常微弱,所以在設計PCB時,需對 GND需要小心處理,將GND噪聲干擾降至最低。 一般會對 GND 分兩路進行處理,使兩個回路不會重合,不會相互影響,當兩路回路不重合時,電源部分和數字部分的地噪聲就不會影響到計量信號,如下圖,電路回路1 和電路回路的走線相互不重合,只在入口處N 匯集于一點,這樣數字信號就不會干擾到計量部分。
0.png (22.05 KB, 下載次數: 181)
下載附件
2018-7-24 02:30 上傳
計量芯片Layout設計規則:
此 layout 設計規則適合于深圳市合力為科技的所有型號計量芯片,如 HLW8012、HLW8032和 HLW8110/HLW8112 等。
單路 PCB設計原則
電能計量芯片屬于模擬器件芯片,它不同于數字芯片,對模擬器件的 layout 需要遵 守一些設計原則,以使芯片發揮最大性能,以下共有 10 條設計原則,請盡量遵守,若 不能遵守,可能會引起一些如數值不穩定,小信號噪聲大等問題,實際情況以 PCB 樣 板實測結果為準。 1、 去藕電容放置規則 芯片電源引腳處的0.1uf的去耦電容盡量靠近芯片的引腳,這樣才能起到比較好的濾 波效果。
2、 電壓通道設計規則 電壓通道電阻分壓網絡,應呈階梯式分布,逐漸降壓(從輸入端降壓直至計 量芯片的取樣電壓),應注意電阻與電阻之間的爬電距離。
3、 電壓通道和電流通道應盡可能不進行交叉走線
交叉走線后會引起信號噪聲,對于小信號的測量結果不準確,對大信號的影響比較 小,如果必須交叉,也應該是電壓通道經過分壓(降低電壓值)之后的線與電流信號線交 叉,下圖是沒有交叉的走線。 4、 差分信號線布線規則
a)差分信號線應走平行線,且兩條平行走線應當盡量靠近,這樣可以減少外部 信號的干擾; b)差分信號線應從采樣電阻兩端引線,且與采樣電阻的 PAD直接相連,差分信
號線路徑沒有電流回路流過。
正確的走線(從采樣電阻 Pad上引出差分信號線)
錯誤的走線(沒有從采樣電阻 Pad上引出差分信號線)
上述接法會帶來誤差,采樣電阻 r的阻值實際上己經不是 r了,而是
r+R1+R2,如下圖,因為銅皮也是有阻抗的,且銅皮的溫度特性非常差,這種接 法帶來的結果是在小電流時,信號輸出是線性關系,當電流過大時,隨著 PCB溫度的上升,整個輸入量程程的輸出信號會成不線性關系。
c)差分信號線有一根線是 GND,應把他當作信號線來看待,不能當做 GND來處 理,更不能同其它 GND線相連(只能在 GND地入口處相連),如下圖: 正確的接法:
上述在入口焊盤處相連,實際相當于是 GND入口分出兩條線,走星形線,
這樣處理實際是避免將 GND的噪聲(比如電源的噪聲)引入到差分信號端。
錯誤的接法:
上圖是錯誤的接法,因為電路回路的 GND經過采樣電阻再回到入口焊盤 N,這樣 會板子上的電源地噪聲引入到采樣電阻的差分信號上。
多路 PCB 設計原則
在使用多路計量電路的設計中,同樣需要注意 GND 的處理,如果布局不合理,每一路計 量電路就會相互產生干擾。為避免每一路計量電路之間的相互干擾,地線需要采用星形 地線的布局方式,參考布局方法如下:
正確的連接方式:
0.png (41.94 KB, 下載次數: 187)
下載附件
2018-7-24 02:25 上傳
單片機源程序如下:
- /*=============================================================================
- * File Name : HLW8012參考例程
- * Describe : 測量功率、電壓、電流及電量參數
- * Author : 深圳合力為
- * Version : V1.0
- =============================================================================*/
- /* Includes -----------------------------------------------------------------*/
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //Time1定時器定時,時間基數 = 1ms
- #define D_TIME1_20MS 20
- #define D_TIME1_100MS 100
- #define D_TIME1_150MS 150
- #define D_TIME1_200MS 200
- #define D_TIME1_400MS 400
- #define D_TIME1_500MS 500
- #define D_TIME1_1S 1000 //Time1定時器定時1S時間常數
- #define D_TIME1_2S 2000
- #define D_TIME1_3S 2000
- #define D_TIME1_4S 4000
- #define D_TIME1_6S 6000
- #define D_TIME1_8S 8000
- #define D_TIME1_9S 9000
- #define D_TIME1_10S 10000
- #define D_TIME1_20S 20000
- #define D_TIME1_V_OVERFLOW 500 //Time1定時器,電壓溢出常數設定為500mS,溢出說明脈寬周期大于500mS
- #define D_TIME1_I_OVERFLOW 8000 //Time1定時器,電流溢出常數設定為10S,溢出說明脈寬周期大于10S
- #define D_TIME1_P_OVERFLOW 12000 //Time1定時器,功率溢出常數設定為10S(約0.5W最小值),溢出說明脈寬周期大于10S
- //#define D_TIME1_P_OVERFLOW 40000 //Time1定時器,功率溢出常數設定為40S(約0.2W最小值)
- #define D_TIME1_CAL_TIME 36000 //校正時間,記錄在此時間內的脈沖數,1000W負載在用電36S時間內耗費0.01度電
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //HLW 8012 IO設置
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- #define IO_HLW8012_CF1_S PD_ODR_ODR3 //HLW8012 PIN8
- #define IO_HLW8012_CF1 PA_IDR_IDR2 //HLW8012 PIN7
- #define IO_HLW8012_CF PC_IDR_IDR5 //HLW8012 PIN6
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //工作模式
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- #define D_ERR_MODE 0x00 //錯誤提示模式
- #define D_NORMAL_MODE 0x10 //正常工作模式
- #define D_CAL_START_MODE 0x21 //校正模式,啟動
- #define D_CAL_END_MODE 0x23 //校正模式,完成
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //ROM定義
- //--------------------------------------------------------------------------------------------
- #define u1 _Bool
- #define u8 unsigned char
- #define u16 unsigned int
- #define u32 unsigned long
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- union IntData
- {
- u16 inte;
- u8 byte[2];
- };
- union LongData
- {
- u32 word;
- u16 inte[2];
- u8 byte[4];
- };
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- u16 U16_P_TotalTimes; //當前脈沖 功率測量總時間
- u16 U16_V_TotalTimes; //當前脈沖 電壓測量總時間
- u16 U16_I_TotalTimes; //當前脈沖 電流測量總時間
- u16 U16_P_OneCycleTime; //功率測量時間參數
- u16 U16_V_OneCycleTime; //電壓測量時間參數
- u16 U16_I_OneCycleTime; //電流測量時間參數
- u16 U16_P_Last_OneCycleTime; //功率測量時間參數,上一次數量值
- u16 U16_V_Last_OneCycleTime; //電壓測量時間參數,上一次數量值
- u16 U16_I_Last_OneCycleTime; //電流測量時間參數,上一次數量值
- u16 U16_P_CNT; //功率測量脈沖數量
- u16 U16_V_CNT; //電壓測量脈沖數量
- u16 U16_I_CNT; //電流測量脈沖數量
- u16 U16_P_Last_CNT; //功率測量脈沖數量,上一次數量值
- u16 U16_V_Last_CNT; //電壓測量脈沖數量,上一次數量值
- u16 U16_I_Last_CNT; //電流測量脈沖數量,上一次數量值
- u1 B_P_TestOneCycle_Mode; //功率測量模式 1:單周期測量,0:1S定時測量
- u1 B_V_TestOneCycle_Mode;
- u1 B_I_TestOneCycle_Mode;
- u1 B_P_Last_TestOneCycle_Mode;
- u1 B_V_Last_TestOneCycle_Mode;
- u1 B_I_Last_TestOneCycle_Mode;
-
- u1 B_P_OVERFLOW; // 功率脈沖周期 溢出標志位
- u1 B_V_OVERFLOW; // 電壓脈沖周期 溢出標志位
- u1 B_I_OVERFLOW; // 電流脈沖周期 溢出標志位
- u1 B_P_Last_OVERFLOW; // 功率脈沖周期 溢出標志位
- u1 B_V_Last_OVERFLOW; // 電壓脈沖周期 溢出標志位
- u1 B_I_Last_OVERFLOW; // 電流脈沖周期 溢出標志位
- u1 B_VI_Test_Mode; //1:電壓測量模式;0:電流測量模式
- u16 U16_VI_Test_Times;
- u16 U16_Cal_Times;
- u16 U16_AC_P; //功率值 1000.0W
- u16 U16_AC_V; //電壓值 220.0V
- u16 U16_AC_I; //電流值 4.545A
- u32 U32_AC_E; //用電量 0.01度
- u32 U32_AC_BACKUP_E; //用電量備份
- u8 U8_AC_COS; //功率因素 0.00
- u16 U16_REF_001_E_Pluse_CNT; //0.01度電脈沖總數參考值
- u16 U16_E_Pluse_CNT; //脈沖個數寄存器
- u32 U32_Cal_Times; //校正時間
- u32 U32_P_REF_PLUSEWIDTH_TIME; //參考功率 脈沖周期
- u32 U32_V_REF_PLUSEWIDTH_TIME; //參考電壓 脈沖周期
- u32 U32_I_REF_PLUSEWIDTH_TIME; //參考電流 脈沖周期
- u32 U32_P_CURRENT_PLUSEWIDTH_TIME; //當前功率 脈沖周期
- u32 U32_V_CURRENT_PLUSEWIDTH_TIME; //當前電壓 脈沖周期
- u32 U32_I_CURRENT_PLUSEWIDTH_TIME; //當前電流 脈沖周期
- u16 U16_P_REF_Data; //參考功率值,如以1000W校正。1000.0W
- u16 U16_V_REF_Data; //參考電壓 220.0V
- u16 U16_I_REF_Data; //參考電流 1000W,220V條件下是4.545A
- u8 U8_CURR_WorkMode;
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- void main(void)
- {
- //初始化MCU
- //初始化ROM
- Init_Rom();
- //讀取存放于EEPROM的校正數據
- Read_CalData_EEPROM(); //讀取參考功率、參考電壓、參考電流的脈沖周期
-
- while(1)
- {
- if (B_KeyScanEn == TRUE)
- {
- ScaningKey(); //按鍵
- KeyFun_NormalMode();
- }
-
- if (U8_CURR_WorkMode == D_NORMAL_MODE)
- {
- HLW8012_Measure(); //計算功率、電壓、電流
- }
- else if (U8_CURR_WorkMode == D_CAL_END_MODE) //校正模式
- {
- //記錄校正值,將當前功率、電壓、電流值存入EEPROM;將0.01度電的脈沖數參值也存入EEPROM
- Write_CalData_EEPROM();
- //讀取校正值,將用電量清零
- Read_CalData_EEPROM();
- //返回測量模式
- U8_CURR_WorkMode = D_NORMAL_MODE;
- }
-
- }
- }
- //--------------------------------------------------------------------------------------------
- //--------------------------------------------------------------------------------------------
- /*=====================================================
- * Function : void Init_Rom(void)
- * Describe : rom空間初始化
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void Init_Rom(void)
- {
- U8_CURR_WorkMode = D_NORMAL_MODE;
- U8_DspMode = 0;
-
- U16_AC_P = 0;
- U16_AC_V = 0;
- U16_AC_I = 0;
- U8_AC_COS = 0;
-
- U16_P_TotalTimes = 0;
- U16_V_TotalTimes = 0;
- U16_I_TotalTimes = 0;
-
- U16_P_OneCycleTime = 0;
- U16_V_OneCycleTime = 0;
- U16_I_OneCycleTime = 0;
- U16_P_Last_OneCycleTime = 0;
- U16_V_Last_OneCycleTime = 0;
- U16_I_Last_OneCycleTime = 0;
-
- U16_P_CNT = 0;
- U16_V_CNT = 0;
- U16_I_CNT = 0;
- U16_P_Last_CNT = 0;
- U16_V_Last_CNT = 0;
- U16_I_Last_CNT = 0;
-
- //初始化單周期測量模式
- B_P_TestOneCycle_Mode = 1;
- B_V_TestOneCycle_Mode = 1;
- B_I_TestOneCycle_Mode = 1;
- B_P_Last_TestOneCycle_Mode = 1;
- B_V_Last_TestOneCycle_Mode = 1;
- B_I_Last_TestOneCycle_Mode = 1;
- //開始測量,置溢出標志位為1
- B_P_OVERFLOW = 1;
- B_V_OVERFLOW = 1;
- B_I_OVERFLOW = 1;
-
- B_P_Last_OVERFLOW = 1;
- B_V_Last_OVERFLOW = 1;
- B_I_Last_OVERFLOW = 1;
-
- //上電初始化為電壓測試模式
- B_VI_Test_Mode = 1;
- IO_HLW8012_CF1_S = 1;
- U16_VI_Test_Times = D_TIME1_2S;
-
- //顯示初始化
- U8_DspMode = 0;
- B_DIS_EN = FALSE;
- U16_SendUart_Time = 0;
-
- }
- /*=====================================================
- * 函數名稱: PC中斷,IO---PC5
- * 函數功能: CF中斷 功率測量
- * 輸入參數: 無
- * 輸出參數:
- * 返 回:
- =====================================================*/
- #pragma vector = 7
- __interrupt void PC5_EXTI_Interrupt(void)
- {
- //功率測量
- U16_P_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_P_CNT++;
- if (B_P_OVERFLOW == TRUE)
- {
- //從溢出模式轉入,開始測量
- B_P_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_P_TotalTimes = 0; //清溢出寄存器清零
- U16_P_OneCycleTime = 0; //清測量寄存器
- U16_P_CNT = 1;
- B_P_OVERFLOW = FALSE; //清溢出標志位
- }
- else
- {
- if (B_P_TestOneCycle_Mode == 1)
- {
- if (U16_P_OneCycleTime >= D_TIME1_100MS)
- {
- //單周期測量模式
- U16_P_Last_OneCycleTime = U16_P_OneCycleTime;
- B_P_Last_TestOneCycle_Mode = B_P_TestOneCycle_Mode;
- B_P_OVERFLOW = FALSE; //溢出標志位清零
- B_P_Last_OVERFLOW = B_P_OVERFLOW;
- //清狀態參數,重新開始測試
- B_P_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_P_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_P_OneCycleTime = 0; //清測量寄存器
- U16_P_CNT = 1;
-
- }
- }
- else
- {
- if (U16_P_OneCycleTime >= D_TIME1_1S)
- {
- U16_P_Last_OneCycleTime = U16_P_OneCycleTime;
- U16_P_Last_CNT = U16_P_CNT;
- B_P_Last_TestOneCycle_Mode = B_P_TestOneCycle_Mode;
- B_P_OVERFLOW = FALSE; //溢出標志位清零
- B_P_Last_OVERFLOW = B_P_OVERFLOW;
- //清狀態參數,重新開始測試
- B_P_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_P_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_P_OneCycleTime = 0; //清測量寄存器
- U16_P_CNT = 1;
- }
- }
- }
-
-
- //校正模式
- if (U8_CURR_WorkMode == D_CAL_START_MODE)
- {
- //記錄單位時間內的用電量
- U16_E_Pluse_CNT++;
- }
-
- //用電量計量,每0.01度電,用電量寄存器增加0.01度
- if (U8_CURR_WorkMode == D_NORMAL_MODE)
- {
- U16_E_Pluse_CNT++;
- if (U16_E_Pluse_CNT == U16_REF_001_E_Pluse_CNT )
- {
- U16_E_Pluse_CNT = 0;
- U32_AC_E++;
- }
- }
- }
- /*=====================================================
- * 函數名稱: PD中斷,IO---PD2
- * 函數功能: CF1中斷 電壓、電流測量
- * 輸入參數:
- * 輸出參數:
- * 返 回:
- =====================================================*/
- #pragma vector = 8
- __interrupt void PD2_EXTI_Interrupt(void)
- {
-
- //電壓測試模式
- if (B_VI_Test_Mode == 1)
- {
- U16_V_TotalTimes = 0;
- U16_V_CNT++;
- if (B_V_OVERFLOW == TRUE)
- {
- //從溢出模式轉入,開始測量
- B_V_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_V_TotalTimes = 0; //清溢出寄存器清零
- U16_V_OneCycleTime = 0; //清測量寄存器
- U16_V_CNT = 1;
- B_V_OVERFLOW = FALSE; //清溢出標志位
- }
- else
- {
- if (B_V_TestOneCycle_Mode == 1)
- {
- if (U16_V_OneCycleTime >= D_TIME1_100MS)
- {
- //單周期測量模式
- U16_V_Last_OneCycleTime = U16_V_OneCycleTime;
- B_V_Last_TestOneCycle_Mode = B_V_TestOneCycle_Mode;
- B_V_OVERFLOW = FALSE; //溢出標志位清零
- B_V_Last_OVERFLOW = B_V_OVERFLOW;
- //清狀態參數,重新開始測試
- B_V_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_V_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_V_OneCycleTime = 0; //清測量寄存器
- U16_V_CNT = 1;
- }
- }
- else
- {
- if (U16_V_OneCycleTime >= D_TIME1_200MS)
- {
- U16_V_Last_OneCycleTime = U16_V_OneCycleTime;
- U16_V_Last_CNT = U16_V_CNT;
- B_V_Last_TestOneCycle_Mode = B_V_TestOneCycle_Mode;
- B_V_OVERFLOW = FALSE; //溢出標志位清零
- B_V_Last_OVERFLOW = B_V_OVERFLOW;
- //清狀態參數,重新開始測試
- B_V_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_V_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_V_OneCycleTime = 0; //清測量寄存器
- U16_V_CNT = 1;
- B_V_OVERFLOW = FALSE; //溢出標志位清零
- }
- }
- }
- }
- //電流測試模式
- if (B_VI_Test_Mode == 0)
- {
- U16_I_TotalTimes = 0;
- U16_I_CNT++;
- if (B_I_OVERFLOW == TRUE)
- {
- //從溢出模式轉入,開始測量
- B_I_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_I_TotalTimes = 0; //清溢出寄存器清零
- U16_I_OneCycleTime = 0; //清測量寄存器
- U16_I_CNT = 1;
- B_I_OVERFLOW = FALSE; //清溢出標志位
- }
- else
- {
- if (B_I_TestOneCycle_Mode == 1)
- {
- if (U16_I_OneCycleTime >= D_TIME1_100MS)
- {
- //單周期測量模式
- U16_I_Last_OneCycleTime = U16_I_OneCycleTime;
- B_I_Last_TestOneCycle_Mode = B_I_TestOneCycle_Mode;
- B_I_OVERFLOW = FALSE; //溢出標志位清零
- B_I_Last_OVERFLOW = B_I_OVERFLOW;
- //清狀態參數,重新開始測試
- B_I_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_I_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_I_OneCycleTime = 0; //清測量寄存器
- U16_I_CNT = 1;
- }
- }
- else
- {
- if (U16_I_OneCycleTime >= D_TIME1_1S)
- {
- U16_I_Last_OneCycleTime = U16_I_OneCycleTime;
- U16_I_Last_CNT = U16_I_CNT;
- B_I_Last_TestOneCycle_Mode = B_I_TestOneCycle_Mode;
- B_I_OVERFLOW = FALSE; //溢出標志位清零
- B_I_Last_OVERFLOW = B_I_OVERFLOW;
- //清狀態參數,重新開始測試
- B_I_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- U16_I_TotalTimes = 0; //完成一次有效的測量,溢出寄存器清零
- U16_I_OneCycleTime = 0; //清測量寄存器
- U16_I_CNT = 1;
- }
- }
- }
- }
- }
- /*=====================================================
- * 函數名稱: TIM1
- * 函數功能: 測量功率、電壓、電流
- * 輸入參數:
- * 輸出參數:
- * 返 回:
- =====================================================*/
- #pragma vector = 13
- __interrupt void TIM1_UPD_Interrupt(void)
- {
- //校正模式
- if (U8_CURR_WorkMode == D_CAL_START_MODE)
- {
- U32_Cal_Times++;//校正時間36S,1000W負載36S時間消耗0.01度電
- if (U32_Cal_Times == D_TIME1_CAL_TIME)
- {
- U8_CURR_WorkMode = D_CAL_END_MODE;
- U16_REF_001_E_Pluse_CNT = U16_E_Pluse_CNT; //記錄36S時間內的脈沖數,此脈沖數表示0.01度用電量
- }
- }
-
- //功率測量
- if (U16_P_CNT != 0)
- {
- U16_P_OneCycleTime++;
- U16_P_TotalTimes++;
- }
- if (U16_P_TotalTimes >= D_TIME1_P_OVERFLOW)
- {
- B_P_OVERFLOW = TRUE; //溢出,
- B_P_Last_OVERFLOW = B_P_OVERFLOW;
- //清狀態參數,重新開始測試
- U16_P_TotalTimes = 0; //清溢出寄存器
- U16_P_OneCycleTime = 0;
- U16_P_CNT = 0; //等待下一次中斷開始計數
- B_P_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- }
- else if (U16_P_OneCycleTime == D_TIME1_100MS)
- {
- if (U16_P_CNT < 2)
- {
- // 100ms內只有一次中斷,說明周期>100ms,采用單周期測量模式
- B_P_TestOneCycle_Mode = 1;
- }
- else
- {
- // 100ms內有2次或以上數量脈沖,說明周期<100ms,采用計數脈沖測量模式
- B_P_TestOneCycle_Mode = 0;
- }
- }
-
- //電壓、電流測量
- if (B_VI_Test_Mode == 1)
- {
- //電壓測量
- if (U16_V_CNT != 0)
- {
- U16_V_OneCycleTime++;
- U16_V_TotalTimes++;
- }
- if (U16_V_TotalTimes >= D_TIME1_V_OVERFLOW)
- {
- B_V_OVERFLOW = TRUE;
- B_V_Last_OVERFLOW = B_V_OVERFLOW;
- //清狀態參數,重新開始測試
- U16_V_TotalTimes = 0; //清溢出寄存器
- U16_V_OneCycleTime = 0;
- U16_V_CNT = 0;
- B_V_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- }
- else if (U16_V_OneCycleTime == D_TIME1_100MS)
- {
- if (U16_V_CNT < 2)
- {
- // 100ms內只有一次中斷,說明周期>100ms,采用單周期測量模式
- B_V_TestOneCycle_Mode = 1;
- }
- else
- {
- // 100ms內有2次或以上數量脈沖,說明周期<100ms,采用計數脈沖測量模式
- B_V_TestOneCycle_Mode = 0;
- }
- }
- }
- else
- {
- //電流測量
- if (U16_I_CNT != 0)
- {
- U16_I_OneCycleTime++;
- U16_I_TotalTimes++;
- }
- if (U16_I_TotalTimes >= D_TIME1_I_OVERFLOW)
- {
- B_I_OVERFLOW = TRUE;
- B_I_Last_OVERFLOW = B_I_OVERFLOW;
- //清狀態參數,重新開始測試
- U16_I_TotalTimes = 0; //清溢出寄存器
- U16_I_OneCycleTime = 0;
- U16_I_CNT = 0;
- B_I_TestOneCycle_Mode = 0; //初始化為計數脈沖測量模式
- }
- else if (U16_I_OneCycleTime == D_TIME1_100MS)
- {
- if (U16_I_CNT < 2)
- {
- // 100ms內只有一次中斷,說明周期>100ms,采用單周期測量模式
- B_I_TestOneCycle_Mode = 1;
- }
- else
- {
- // 100ms內有2次或以上數量脈沖,說明周期<100ms,采用計數脈沖測量模式
- B_I_TestOneCycle_Mode = 0;
- }
- }
- }
-
- //電壓、電流測量模式切換 B_VI_Test_Mode:(1:電壓測量模式) (0:電流測試模式)
- U16_VI_Test_Times--;
- if (U16_VI_Test_Times == 0)
- {
- if (B_VI_Test_Mode == 1)
- {
- //轉為電流測量模式
- B_VI_Test_Mode = 0;
- IO_HLW8012_CF1_S = 0;
- U16_VI_Test_Times = D_TIME1_10S;
-
- //清狀態參數
- U16_I_TotalTimes = 0;
- U16_I_OneCycleTime = 0;
- U16_I_CNT = 0;
- B_I_OVERFLOW = FALSE;
- }
- else
- {
- //轉為電壓測量模式
- B_VI_Test_Mode = 1;
- IO_HLW8012_CF1_S = 1;
- U16_VI_Test_Times = D_TIME1_1S;
-
- //清狀態參數
- U16_V_TotalTimes = 0;
- U16_V_OneCycleTime = 0;
- U16_V_CNT = 0;
- B_V_OVERFLOW = FALSE;
- }
- }
-
- //按鍵掃描,20mS一次
- U8_KeyScanTimes++;
- if (U8_KeyScanTimes > D_TIME1_20MS)
- {
- B_KeyScanEn = TRUE;
- U8_KeyScanTimes = 0;
- }
-
- // 每0.5S串口發送一次數據
- U16_SendUart_Time++;
- if (U16_SendUart_Time == D_TIME1_500MS)
- {
- B_DIS_EN = TRUE;
- U16_SendUart_Time = 0;
- }
- // Clear TIM1 INT FLAG
- TIM1_SR1 = 0x00;
- }
- /*-------------------------------------------- 功率、電壓、電流計算 -------------------------------------------*/
- *=====================================================
- * Function : void HLW8012_Measure_P(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_P(void)
- {
- u32 a;
- u32 b;
- u32 u32_P_Period;
-
- if (B_P_Last_TestOneCycle_Mode == 1)
- {
- //單周期測量模式
- b = U16_P_Last_OneCycleTime;
- b = b*1000; //ms轉換成us
- u32_P_Period = b;
- }
- else
- {
- //計數脈沖測量模式
- b = U16_P_Last_OneCycleTime;
- b = b*1000;
- u32_P_Period = b/(U16_P_Last_CNT-1);
- }
-
- U32_P_CURRENT_PLUSEWIDTH_TIME = u32_P_Period; // 校正時取U32_P_CURRENT_PLUSEWIDTH_TIME參數作為參考值
- a = U16_P_REF_Data * U32_P_REF_PLUSEWIDTH_TIME;
- U16_AC_P = a/U32_P_CURRENT_PLUSEWIDTH_TIME;
-
- if (U16_AC_P == 0xffff) //開機時U32_P_CURRENT_PLUSEWIDTH_TIME = 0,計算溢出
- {
- U16_AC_P = 0;
- }
-
- if (B_P_Last_OVERFLOW == TRUE)
- {
- U16_AC_P = 0;
- }
- }
- /*=====================================================
- * Function : void HLW8012_Measure_V(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_V(void)
- {
- u32 a;
- u32 b;
- u32 u32_V_Period;
-
- if (U16_VI_Test_Times < D_TIME1_100MS)
- {
- if (B_V_Last_TestOneCycle_Mode == 1)
- {
- b = U16_V_Last_OneCycleTime;
- u32_V_Period = b * 1000; //ms轉換成us
- U32_V_CURRENT_PLUSEWIDTH_TIME = u32_V_Period;
- }
- else
- {
- b = U16_V_Last_OneCycleTime;
- b = b*1000;
- u32_V_Period = b/(U16_V_Last_CNT-1);
- //u32_V_Period = b/U16_V_Last_CNT;
- U32_V_CURRENT_PLUSEWIDTH_TIME = u32_V_Period;
- }
- }
-
- a = U16_V_REF_Data * U32_V_REF_PLUSEWIDTH_TIME;
- U16_AC_V = a/U32_V_CURRENT_PLUSEWIDTH_TIME;
-
- if (U16_AC_V == 0xffff) //開機時U32_V_CURRENT_PLUSEWIDTH_TIME = 0,計算溢出
- {
- U16_AC_V = 0;
- }
-
- if (B_V_Last_OVERFLOW == TRUE)
- {
- U16_AC_V = 0;
- }
-
- if (U16_AC_P == 0)
- {
- U16_AC_V = 0;
-
- }
- }
- /*=====================================================
- * Function : void HLW8012_Measure_I(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_I(void)
- {
- u32 a;
- u32 b;
- u32 u32_I_Period;
-
- if (U16_VI_Test_Times < D_TIME1_6S)
- {
- if (B_I_Last_TestOneCycle_Mode == 1)
- {
- b = U16_I_Last_OneCycleTime;
- u32_I_Period = b * 1000; //ms轉換成us
- U32_I_CURRENT_PLUSEWIDTH_TIME = u32_I_Period;
- }
- else
- {
- b = U16_I_Last_OneCycleTime;
- b = b*1000;
- u32_I_Period = b/(U16_I_Last_CNT-1);
- //u32_I_Period = b/U16_I_Last_CNT;
- U32_I_CURRENT_PLUSEWIDTH_TIME = u32_I_Period;
- }
- }
-
-
- a = U16_I_REF_Data * U32_I_REF_PLUSEWIDTH_TIME;
- U16_AC_I = a/U32_I_CURRENT_PLUSEWIDTH_TIME;
-
-
- if (U16_AC_I > 180)
- {
- if (U16_AC_I != 0xffff)
- {
- NOP();
- NOP();
- }
- }
-
- if (U16_AC_P == 0)
- {
- U16_AC_I = 0;
-
- }
-
- if (U16_AC_I == 0xffff) //開機時U32_I_CURRENT_PLUSEWIDTH_TIME = 0,計算溢出
- {
- U16_AC_I = 0;
- }
-
- if (B_I_OVERFLOW == TRUE)
- {
- U16_AC_I = 0;
- }
- }
- /*=====================================================
- * Function : void HLW8012_Measure_COS(void)
- * Describe :
- * Input : none
- * Output : none
- * Return : none
- * Record : 2014/04/14
- =====================================================*/
- void HLW8012_Measure_COS(void)
- {
- u32 u32_P_Apparent;
- u32 a;
- u8 b;
- u32_P_Apparent = (u32)U16_AC_I*(u32)U16_AC_V;
- u32_P_Apparent = u32_P_Apparent/1000;
- a = U16_AC_P;
- a = a*100;
-
- b = (u8)(a/u32_P_Apparent);
- if (b > 100 )
- U8_AC_COS = 100; //由于相位延時造成的功率因素>1的情況,功率因素取值1
- else
- U8_AC_COS = b;
- }
- /*=====================================================
- * Function : void HLW8012_Measure_E(void)
- * Describe : 每1度電存儲一次
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
全部資料51hei下載地址:
HLW8012設計資料REV30.7z
(11.34 MB, 下載次數: 689)
2021-10-27 22:33 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|