新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > MAXQ3120電表參考設計的定制功能

        MAXQ3120電表參考設計的定制功能

        ——
        作者: 時間:2007-01-26 來源:《Maxim公司》 收藏

        介紹

        maxq3120電表(em)參考設計構建了一款多功能、多費率電表,它符合世界范圍的全部可用標準。參考設計構成了一款能夠適合各地要求和各種性能要求的電表原型。這篇文檔將指導軟件工程師,通過定制代碼實現一些特殊的需求。

        本文引用地址:http://www.104case.com/article/21553.htm

        目標讀者
        本文檔假定讀者熟悉c語言、maxq20微控制器架構以及匯編語言。讀者也需熟知全電子式電表的基理。

        工具

        電表參考設計采用iar embedded workbench工具進行編譯。為便于將軟件移植到其它開發環境中,除了一種例外情況外,整個軟件避免了與iar相關的語言特性。這種例外情況位于匯編語言文件中,其中包括了一些對標準匯編偽指令集的特定iar擴展。這些特定iar擴展命令,不僅可告知連接器各不同段的分配情況,而且告知調試器有關某些機器資源的變化情況。在其它開發環境下構建工程,可將這些偽指令去除。

        高層硬件描述

        硬件的核心器件是maxq3120微控制器。maxq3120幾乎囊括了實現多功能、多費率電表所需要的所有功能,這些功能包括:雙通道、高精度a/d轉換器(adc),一個乘法累加器(mac),通信端口和一個顯示控制器。完成一個電表設計,僅需要少量的外部元件。

        在參考設計中,提供兩個通信通道:一路紅外通道,包含一個可解碼38khz載波頻率的接收模塊和一個直接由微控制器驅動的紅外led,一路完全隔離的rs-485通道;用作非易失存儲器的128kb i2c eeprom;一個可視led和一路隔離光耦通道,用于指示電表脈沖;一個用于設置網絡地址的按鈕;和一個用于顯示的lcd。

        這種硬件構成預示著以下一些應用信息。選擇一個外置i2c eeprom,意味著系統中必須包含i2c軟件,而不提供硬件i2c主機。電表脈沖硬件意味著軟件必須能夠產生極為精確的脈沖定時。兩路通信端口表明,微控制器有限的資源要被兩路通道所共享。


        軟件系統綜述

        軟件系統必須同時跟蹤多個進程。首先也是最重要的一點,軟件系統必須監測adc,計算用電量并報告其它額外信息,這些信息包括rms電壓和電流、功率因數和峰值功率。這個基本進程非常關鍵,其它任何進程都不能干擾這個最重要的基礎任務。在持續監視用電量的同時,軟件還必須驅動顯示、監視兩路通信端口、監視按鈕以及電力線路上的電源失效事件,完成從外部eeprom獲取信息的請求,并跟蹤費率時段的變化。

        任務管理方式

        初始一看,要完成以上多個實時任務,迫切需要某種實時操作系統(rtos)來進行調度管理和資源分配。但進一步分析后,就會發現不用傳統rtos的兩個充分理由。

        首先,要求即時響應adc中斷。當adc有可用的采樣數據時,必須在48μs內提取該采樣數據。并且,當檢測到一個過零點時,電源周期處理程序為了在下一個電源周期之前完成執行操作,必須獨占cpu資源。(電源周期處理程序將占用cpu運算能力的25%到30%。) 盡管rtos可以滿足這些要求,卻不能最有效地利用資源。

        其次,用于保存任務上下文的空間非常有限。大多數rtos都要給每個任務提供一個完整的虛擬處理器,以在其中執行操作,而這需要保存各個任務的上下文。由于僅有256個16位字ram可供使用,少量任務就會耗盡存儲器空間。

        所以,本參考設計選擇了一個簡單的任務輪。在這種配置方式下,任務會被按順序調用,而每個任務在鎖定事件發生時,都要釋放cpu的控制權。鎖定事件是指所有其它任務都必須等待的事件,它包括:從eeprom中提取數據,等待一個電源周期或是等待通信通道上的字符。如果當前任務需要等待其它任務完成時才能結束自身任務,這時也會產生一個鎖定事件。在任何鎖定事件中,任務必須存儲它的當前狀態并返回任務輪。這種協作式多任務機制,使得一個處理能力相對低些的控制器就能夠勝任工作。

        任務間的通信是通過一組公共數據結構來完成的,這些數據結構要根據一套嚴格的規則才允許被修改。這些數據結構中最重要的部分是消息板,當發生某個事件時,一個任務要設置消息板中的一組數據位以通知另一個任務。例如,假設接收到一個消息并將其正確譯碼,則消息譯碼器任務會告知另一個需要該消息的任務(比如寄存器管理器)已經收到了消息,并要求第二個任務必須執行某些操作。

        缺省任務列表

        以下是參考設計中采用的缺省任務列表:

        dsp:對應每個電源周期,這個程序會計算電力線路的所有參數,并累加本電源周期的用電量。

        串口驅動器:檢測兩路通信通道的狀態,并將第一個發出字符的通道置為“活動”通道。在消息檢查器任務確定消息完成或產生超時之前,通道將始終保持活動狀態。

        消息檢查器:驗證輸入字符串符合協議規范,并在完整接收消息后通知消息譯碼器。

        消息譯碼器:解釋接受到的消息并執行相應的請求操作。

        異步事件管理器:執行那些不是按照時間表進行的事件任務,比如峰值檢測和電能累計。

        時段表管理器:周期性檢查時鐘,并按照時段表調整費率寄存器的值。
        顯示管理器:根據時間和其它事件刷新lcd顯示。

        消息格式器:為消息譯碼器解釋的消息準備回復信息。

        消息構建器:接收格式化后的消息并加上用于傳輸的消息頭和消息尾。
        寄存器管理器:執行讀/寫eeprom操作。

        計時管理器:通告按固定時基啟動的任務。

        負載曲線記錄器:被請求時,向eeprom記入用電量,便于將來報告這些數據。
        添加任務

        如電表參考設計中所定義,任務是一段單線程代碼,它執行電表要求的某項功能,并快速(通常只有幾毫秒)返回調用函數。然而,大多數任務都需要比這更長的時間才能完成。比如,在任何合理的速率下發送一個消息都需要多個周期。因此,大多數任務都需要一個狀態變量,以便將其分解為數個子任務。

        一旦任務編寫完成,你就可以在spintaskwheel.c文件的任務列表中加入該調用。注意,你可以將任務加在執行流程的任何位置,并根據你的需要多次頻繁調用它。你將發現,dsp任務調用非常頻繁,串口驅動器serialportdriver任務也被調用了幾次。因為要保持電能測量的完整性,dsp任務不允許被擱置數個周期,同時不允許serialportdriver任務錯過輸入字符。

        最后,測試你的代碼。任務輪循環時,你的新任務將伴隨其它任務被調用。

        全局變量
        由于未使用真正意義上的多任務操作系統,也就意味著不會有編程人員所熟知的、真正意義上的消息傳遞、信號量或其它機制。通信是通過上文提到的消息板以及一組全局變量實現的,各個任務必須按照嚴格的規則來設置和讀取這些變量信息。這些全局變量列舉如下:

        g_commsystemstate: 這個變量包括一組通信通道控制位。具體來說,每個通道包括:一個active (活動)位,用于指明某個特定通道處于活動狀態(從而可丟棄到達另一個通道的字符);一個tbe位,用于使閑置通道做好工作準備;以及一個data loss (數據丟失)位,當閑置通道收到字符而另一通道正忙于通信時,該位被置高。
        g_transmitbyte; g_receivebyte: 分別保存著下一個要傳送的字節和最新接收到的字節。
        g_commbuffer: 一個50字節數組,包含剛接收到的消息或要發送的消息。注意系統僅有一個通信緩存。它不僅被兩個通信通道所共享,也被發送和接收通道所共享。
        g_meteraddress: 一個包含電表網絡地址的6字節數組。初始化時從eeprom內讀取該信息,并存放在ram中。
        g_messageformatterdata; g_dispformatterdata; g_schedulemanagerdata; g_aemdata; g_lclregdata: 這些寄存器在寄存器管理器和各種任務間傳送數據。例如,一個需要發送的寄存器內容,會被寄存器管理器放入g_messageformatterdata中。
        g_aemregisterneeded; g_dispformatterregrequest; g_requestschedulemanager; g_lclregrequest: 這些寄存器里,包含了特定任務需要讀或寫的寄存器。注意,消息譯碼器沒有全局地址寄存器:寄存器管理器可以智能地從消息緩存中找出這個信息。
        g_lcdmode: 包含顯示器的模式字節。見下面的顯示定制部分。
        g_tariffineffect: 包含當前有效的費率號碼。這個函數有自己的全局變量,以便每次累計電能時,無需通過多次eeprom讀操作來確定將采樣值存在什么位置。
        g_pw: 包含當前有效的各個通信通道的口令號碼。
        g_irtimer; g_rstimer: 用于計數各個通道口令有效時間的定時器。一旦接收到口令后,它的有效期限是60秒。一個口令的有效時間結束后,g_pw中相關的4位數據就會被清零。
        g_loadcurveusage; g_loadcurvepeak; g_loadcurvetimestamp: 與負載曲線記錄任務相關的變量。g_loadcurveusage累計用電量,并會最終報告給負載曲線記錄任務。負載曲線記錄任務會定期地將該值寫入eeprom并隨后清除該變量。g_loadcurvepeak和g_loadcurvetimestamp跟蹤負載曲線的最大功率值,并記錄峰值功率產生的間隔和時間。
        aemstate: 包含一組與異步事件相關的變量。當接收到一個設置電表地址消息時,msg_rx標志被置為高。地址設置邏輯電路被激活后,變量timer包含恢復正常顯示所需的秒數。dspstate和register變量跟蹤寄存器用電量信息從dsp邏輯傳送到用電量報告函數的過程。通常,寄存器變量包括所有用電類型(有功、無功、正功率和負功率等)。
        g_new_baud: dl/t 645協議規范提供了一種只改變單個消息波特率的機制。當收到波特率變更請求并得到確認后,下一個消息就會以更高的波特率傳送。隨后,波特率恢復到正常值(本設計中采用1,200bps)。g_new_baud總是保存下一個消息的波特率。
        g_transmitdelay: 一些rs-485轉換器在發送完最后一個字符后會延遲一段固定時間,隨后切換回接收模式。因此,當主機傳送完一個請求后,它可能會丟失電表發送的前幾個字符,因為與主機串口相連的rs-485轉換器仍處在發送模式下。這個變量保存了發送狀態保持的固定延時,延時結束后主機的rs-485轉換器切換回接收模式。
        current_temp: 如果引用該變量,它將包含從ds3231 rtc/溫度傳感器中讀出的最新數值。

        定制功能
        本參考設計符合dl/t 645-多功能、瓦時電表通信協議。但這篇文檔不僅僅對通信協議進行說明。dl/t 645確實對一個多功能電表需要執行的操作進行了規定,包括測量、時段管理和報告功能。因此,如果你要選擇其它電表協議,你必須替換掉寄存器管理器以及除串口管理器之外的所有消息函數,或者至少對其進行重大修改。修改的細節不在本文討論范疇內。
        本文檔將著重討論三個定制領域:顯示定制、寄存器映射定制和dsp函數定制。


        顯示定制
        顯示器完全由顯示管理器控制。其它任何任務都不會向maxq3120的lcd寄存器寫入數據。displayformatter.c模塊包含了顯示管理器及其主要子程序updatelcd。
        如果你只是想在電表中使用一個不同的lcd模塊,則只需修改updatelcd。所以我們將從這個模塊的定制開始說起。如果你想改變顯示信息的類型,你就要修改displaymanager,并且可能需要給電表的其它部分提供額外的鉤子(hook)函數。

        定制updatelcd
        updatelcd接收兩個參數:一個待顯示的32位數值和一個8位信號指示器數值。32位顯示值包括8個4位數值。因此,updatelcd支持8位、7段顯示器。注意,maxq3120支持112段顯示,所以可以定制該程序以支持更大規模的顯示器。 如果想用不同的顯示器,你需要修改lcdfont結構。它被定義為static const類型。這樣定義的結構進行編譯和連接后,將駐留在程序空間,而不是數據空間。

        lcd空間分配表:

        這里有個重要的假設:每個字符都可填入一個lcd寄存器。如果所采用的lcd結構中,屬于1位顯示的某些段要占用多個lcd寄存器,則需要修改整個updatelcd。

        數字的顯示順序是什么?
        程序假設最右端的顯示數字,是32位顯示參數的低四位。這是最自然的順序;如果你將“123456”傳遞給參數,則顯示器會顯示“123456”。

        信號指示器
        如果你想在顯示特定信息的情況下,同時點亮特定的信號指示器,則需要另外一個8位變量來存儲指示信息。updatelcd程序使用一個switch結構,以在顯示數字之后馬上點亮這些指示器。

        特殊狀態顯示
        在displayformatter.c文件的最后還有一組程序。這些程序控制特殊狀態顯示,例如電表初始化、eeprom初始化和程序故障(異常)。它們被直接寫入lcd寄存器,而且要針對不同的顯示進行定制。

        定制顯示管理器
        除了顯示用電量、時間和日期以外,如果你還想顯示其它信息,則需要修改顯示管理器。

        顯示管理器的第一部分,處理電表地址設置信息的顯示。僅當地址設置按鈕被按下時才起作用,不需要修改這一部分。

        顯示管理器的其它部分,通過全局變量g_lcdmode來獲取類別。為確定要顯示的下一個條目,這個變量在一個字節內包括了所有必要的信息。它的格式如下所示:

        總會顯示電表使用過程中累計的總用電量,并顯示由g_lcdmode字節所指定的條目。在本參考設計中,這個變量被固定為1―除了顯示總用電量以外,只顯示時間和日期。

        控制變量
        顯示管理器由狀態變量disp所控制,該變量有兩個元素:item和state。由名字可以得知,disp.state存放顯示控制器的當前狀態,而disp.item跟蹤將要顯示的信息,具體含義如下:

        定制這個程序提供兩種選項。你可以選擇改變disp.item的賦值,以及改變程序中它們的選擇順序,或者你可以選擇完全替換掉該程序。后一種選擇可能更好。如果為可能顯示的每個條目指定一個獨立位,或為可顯示條目分配一個列表索引,顯然這樣的條目選擇結構更加靈活。選擇上面的結構是因為它需要的ram空間最小。


        添加寄存器
        dl/t 645規定了大量寄存器,用于控制電表運行的各個方面。每個寄存器由一個16位寄存器號指定。在參考設計中,增加了很多寄存器來控制電表運行的各個方面;在代碼中給出了這些寄存器的說明。本討論內容提供了必要的信息,以便通過擴展寄存器映射從電表中獲取更多信息,或者控制新的電表運行特性。
        寄存器管理器如何工作
        所有任務都不能掛起正常的任務輪操作,寄存器管理器任務要遵循這一原則有很大難度。這是因為寄存器管理器是唯一能夠讀/寫eeprom的任務,并且eeprom寫操作需要(相對)較長的時間―幾個毫秒。因為每20ms (60hz環境下是16.7ms)就要為dsp程序提供處理器時間,寄存器管理器在eeprom寫周期過程中,絕不允許將系統掛起幾十毫秒的。

        要解決eeprom寫入時間問題,一個顯而易見的方法是將i2c程序置為中斷處理方式。這樣一來,寄存器管理器可以啟動一個eeprom傳輸過程,隨即返回主函數入口main();之后每次被調用時,寄存器管理器都會通過檢查eeprom子系統的狀態,來確定任務是否已經完成。采用這種方案帶來一個問題,adc周期非常短,以至于adc中斷服務程序需要獨占中斷子系統。因此,必須采取一些其它保障機制。

        解決的方法是采用一個全局標志位:eepromoppending。當這個標志位為低時,任務輪實質上是一個無限循環過程,反復調用系統中的每一個任務。當標志位為高時,任務輪被調用時執行一次并返回,并不調用寄存器管理器。這樣有什么幫助嗎?

        當寄存器管理器需要執行一個耗時很長的功能時,它啟動這個功能并通過輪詢來確定其是否完成。在輪詢期間,寄存器管理器將eepromoppending置為高,并遞歸調用任務輪。下面的代碼給出了一個實際例子:


        01: uint8 readeeprom(uint16 address, uint8 length, uint8 *pdata)
        02: {
        03: int i;
        04: g_messageboard.eepromoppending = 1;
        05: for(i=0; i 06: {
        07: if(i>0)spintaskwheel();
        08: eeprom_address = address++;
        09: while(eeprom_read_byte())
        10: spintaskwheel();
        11: *pdata++ = eeprom_data;
        12: } // for
        13: g_messageboard.eepromoppending = 0;
        14: return 1;
        15: }

        在上面的第4行,eepromoppending標志位被置為高。在第7和10行中,spintaskwheel被調用。如果eeprom標志位為高時調用任務輪,則spintaskwheel函數運行一次,并在不調用寄存器管理器的情況下返回。這樣,即使由于寄存器管理器等候eeprom完成操作而停止下來,電表的其它部分仍可持續正常運行。

        哪些任務知曉這些寄存器?
        只有兩個任務知道寄存器號:寄存器管理器和消息譯碼器。這些程序中,通常只需要對寄存器管理器進行修改。消息譯碼器識別出與口令管理和其它監控功能有關的寄存器,并且必須在采用正常處理規則之前獲取這些信息。因此,要構建自己的寄存器,只需要熟悉寄存器管理器。 三類寄存器
        通常,有三類寄存器:只讀、讀寫和具有額外功能的讀寫寄存器。只讀寄存器的一個例子是b611,rms volts、phase a。主機向這個寄存器寫數據是不能執行的;實際上,如果電表收到寫數據會將其丟棄。而且,多數只讀寄存器都不在eeprom中:通常,在線計算這些寄存器的結果,并根據需要報告結果。

        讀寫寄存器的一個例子是c032,meter number (電表號)。寫入數值不會對電表操作產生任何影響,而且可以隨時提取該數據。最后,一個具有額外功能的讀寫寄存器例子是c030,meter constant, active (有效電表常數)。當這個寄存器被寫入數據時,寄存器管理器不僅要更新eeprom,同時也要更新dsp程序使用的電表常數。

        哪些任務需要寄存器信息?
        下表列出了需要寄存器信息的任務。

        通常,你主要考慮添加可通過消息譯碼器訪問的寄存器。你可以增加用于顯示的寄存器(或者用于其它任務的寄存器,但是依據慣例,你會主要考慮那些可通過通信端口檢索的寄存器)。

        讀寫寄存器
        首先考慮第一種情況,即存儲和讀取無額外功能的讀寫寄存器。為了添加一個存儲于eeprom內的寄存器,你必須添加兩處信息:maxq3120rd.h文件和寄存器管理器中的processregisternumber程序。

        maxq3120rd.h包含一個由typedef定義的名為eeprom_data的數據類型。這個定義并沒有被真正實例化;而僅僅是作為模板,用于定義數據如何存入eeprom。在eeprom_data定義的下面,還定義了兩個宏,用來返回兩個值,分別是結構中某成員的偏移地址和某成員占用的字節數。定義新寄存器的第一步,是在結構中添加成員(最好是在尾部),從而為寄存器分配eeprom存儲空間。

        下一步是定義寄存器號。這需要編輯寄存器管理器中定義的regparmtable結構。這個表包含了電表中定義的每個寄存器,并按編號排序。每個成員包括:

        寄存器號,16位無符號值。
        物理數據單元編號,用于計算實際寄存器值。例如,寄存器9110請求當月總的正向無功用電量。它是兩個電能累加器的和:包括1象限的用電量和4象限的用電量。因此,物理單元的個數是二。寄存器管理器必須提取指定單元(currentquadrant1accumtariff)和下一個單元(currentquadrant4accumtariff)的數據,并求和以獲得所需信息。
        每個單元的長度,以字節為單位。
        存儲的數據類型:int_reg,表示寄存器包含被視為整數的二進制數據;bcd_reg,表示寄存器包含的是傳輸前無需進一步轉換的bcd碼數據;或者mdh_reg,表示寄存器包含的是日期信息(月:日:小時)。
        eeprom中數據的偏移量(單位為字節數)。
        為了節約處理時間,processregisternumber程序采用二元搜索算法找出寄存器地址。因此,表格保持排序狀態是非常重要的。如果寄存器表變得無序,結果就無法預料了。

        一旦表格被更新,新的寄存器可以通過通信通道進行讀寫。電表到底如何處理該信息,是下一部分的主要內容。

        具有額外功能的讀寫寄存器
        還有一種應用情況,即你想讓一個寫事件觸發額外的功能。為了達到這種效果,必須讓寄存器管理器向額外任務發送一個消息,或者更新執行額外功能所涉及的ram內容。作為樣例說明,可在寄存器管理器中搜索c030,你會找到下面這段代碼:

        switch(register.word)
        {
        case 0xc030: // meter constant, real
        action_value = 0;
        for(i=4; i>1; i--)
        {
        action_value *= 100;
        action_value += (g_commbuffer.message[i] & 0xf) +
        (g_commbuffer.message[i] >> 4) * 10;
        }
        set_e_pulse(action_value); // this will set e_pulse
        break;

        這段代碼在eeprom的寄存器數據更新完畢之后運行。在這個條件下,主機請求改變電表常數。存儲在eeprom中的電表常數寄存器更新過后,傳輸到通信緩沖器的毫秒數值被轉換成內部電表單位,并通過set_e_pulse函數發送給dsp程序。

        只讀寄存器
        一些只讀寄存器只是簡單地從eeprom中讀取數據(如用電量),并通過電表的其它進程來更新其中的數據。然而,另外一些只讀寄存器(如rms電壓)并未存儲在eeprom內。這些寄存器數據存儲在eeprom內是沒有任何意義的,而且如果這樣做并連續更新數據,會迅速損耗eeprom!你可以在processregisternumber中的表格注釋里找到這些寄存器,表述為“not stored in eeprom”(未存儲在eeprom內)。

        這些寄存器由寄存器管理器的getspecialregister程序來控制。對應每個只讀寄存器,程序都在switch分支選擇語句中提供相應的條件。例如:

        case 0xb611:// voltage (phase a)
        g_messageboard.eepromoppending = 1;
        request_rms(rms_voltage_request);
        spintaskwheel();
        while(!(dsp_ctrl & 0x20))
        spintaskwheel();
        *value = get_rms() / 1000;
        g_messageboard.eepromoppending = 0;
        *size = 2;
        break;

        這個例子闡明了一個重要事實,即任何任務都不能掛起任務輪。case的第一條語句將消息板中的eepromoppending標志位置為高。然后它要求dsp函數計算rms電壓值,并在dsp函數忙時遞歸調用任務輪。當eepromoppending標志位置為高后,執行一次任務輪循環,并且不調用寄存器管理器,從而避免了無限遞歸。一旦dsp函數完成,將提取rms值并清除eepromoppending標志位。

        請注意,對于這種類型的只讀寄存器,不必在maxq3120rd.h文件中添加結構來保留eeprom存儲空間。也不必向processregisternumber表添加成員。在處理基于eeprom的寄存器之前,寄存器管理器主程序總要調用getspecialregister。


        定制dsp程序
        參考設計的dsp程序是一套匯編語言模塊,它負責處理從adc到脈沖生成以及報告電壓、電流、功率和用電量的整個信號流。大部分程序不需要修改,但也許你希望修改以下方面:
        采用一個不同的電流或電壓變換器,從而需要不同的增益因子。
        改變系統生成電表脈沖的方式。
        改變前端濾波。
        dsp程序是如何工作的,以及你可以安全地改變哪些單元,以下部分從較高的層次對此進行了說明。

        注意:dsp模塊以預編譯的目標文件形式公開發布。只有在簽署了保密協議(nda)的情況下才可以提供匯編語言源代碼。更多信息,請聯系dallas semiconductor/maxim。

        存儲
        dsp程序用到ram空間的低地址部分。在dsp模塊中搜索“data memory map”,可以看到dsp程序用到的一系列ram變量。前兩個字節是一組控制dsp函數運行的數據位。

        常數
        可通過調整兩個常數來設置電壓和電流通道的滿量程讀數。它們分別是w_v_scale和w_i_scale。缺省情況下,這兩個常量被設置為400v和250a。電壓被設置為正常條件下不會超越的電平值(280vrms以上),而電流設定值與可能的電表分流值相一致(250μ至500μ,典型值)。

        接口程序
        用戶程序可以直接使用一些內置程序的返回值。如果可能,你應該通過這些內置程序與dsp函數接口,而不是直接與dsp函數使用的內部變量接口。

        get_and_clear_usage: 這是c代碼用來提取電量累計值的主程序。通常情況下,需要對用電量進行累計時,dsp程序會通知異步事件管理器。然而,隨時都可以調用這個程序以獲取精確的用電量讀數(截至當前)。注意,iar編譯器會自動傳遞a[0]內的函數參數,并將結果返回給a[0]。
        get_frequency: 返回0.1mhz步長的線路頻率。值得注意的是,這個子程序缺省情況下并未加載;dl/t 645標準并未要求頻率結果。
        get_power_factor: 返回負載的功率因子。
        get_power: 根據參數不同,返回無功或有功功率。
        get_maxd: 返回自上次調用該函數后,電表記錄的最大需量(功率)值。
        request_rms: 根據參數不同,要求dsp計算rms電流或電壓值。
        get_rms: 返回最近一次請求的rms值。
        set_e_pulse: 接受一個電表常數,并設置適當的dsp變量以使該電表常數生效。
        中斷服務程序
        參考設計只使能了一個中斷:就是afe中斷,adc上有一組新的采樣數據時產生該中斷。因為adc采樣周期為48μs,實際上中斷服務程序會很快地結束它的工作,并返回到主代碼中―在兩個中斷之間只有384個指令周期!

        中斷服務程序執行以下功能:

        生成輸出脈沖:如果需要一個脈沖,則啟動它。如果脈沖正在進行中,則遞減持續時間計數器的值,并在計數器回零時終止脈沖。
        累加求和:將最近的能量采樣值累加到所有適當的寄存器中。
        累計rms值:如果被請求,則累計i2或v2。
        檢查電壓下限:如果電壓低于門限值,則遞增一個計數器值。
        過零檢測:如果電壓信號正向過零,則設置一個標志位。




        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 广灵县| 四平市| 峨眉山市| 哈尔滨市| 安国市| 上林县| 大兴区| 陆丰市| 东光县| 新干县| 南靖县| 马鞍山市| 镇平县| 六盘水市| 车险| 定边县| 大姚县| 白玉县| 普宁市| 宁陵县| 大庆市| 无极县| 博湖县| 大冶市| 青浦区| 陇川县| 南陵县| 木里| 广东省| 阿瓦提县| 百色市| 鄂伦春自治旗| 远安县| 昭通市| 阳曲县| 永丰县| 衡山县| 衡阳县| 武陟县| 平江县| 清苑县|