一個完整的信號采集系統項目開發流程


一. 摘要

    這篇文章詳細介紹了一個“多路信號采集系統”的開發過程。“多路信號采集系統”是一個可伸縮的信號采集系統,通道可以選擇從0~100路不同的信號源。單個采集板都能夠采集10路數據,用戶可以根據自己的需求方便地擴展或者收縮信號通道數。本系統可以用於常見的民用或者工業現場監控、儀器儀表等數據采集場合。該系統基於Arm Context M3內核處理器實現,有基板和采集板兩大部分組成,基板主要負責整個采集時序的控制,而采集板則完成真是的數據采集並將采集到的數據發送到數據總線,進而傳輸到主機端。數據傳輸采用了串口通信的方式(RS485),並采用Modbus協議實現,從而方便地實現了采集板地址的檢索、數據量控制、以及CRC校驗值確定等功能。軟件系統則采用了固件庫編程的方式,全程開發均使用C語言完成,從而為以后升級做好准備。開發使用了今日標企業工作平台以及Github代碼托管平台相結合完成開發的方式,使用今日標企業工作平台管理項目開發流程,而使用Github則方便地實現了不同地區開發者協作開發的目的。而系統調試則選擇了傳統的調試方式,先進行單個功能模塊測試,再測試系統功能,進而Burning實驗。
 

二. 本文提綱

    1. 摘要
    2. 本文提綱
    3. 項目起始
    4. 開發方式選擇
    5. 系統構架
    6. 硬件設計
    7. 軟件設計
    8. 系統調試
    9. 總結
 

三. 項目起始

    該系統是應蘭州交通大學自動化研究所(一下簡稱為研究所)的項目需求進行開發。項目開始的時候談的最多的問題主要有兩個,一個是“錢”的問題,還有一個就是項目需求了。至於錢最后的商定結果為,天佑電子有限公司(以下簡稱天佑)只負責產品研發,開發過程中所有的元器件、材料、以及測試系統的所有成本均由研究所承擔,而天佑則只承擔人力成本。最后研究所應該支付天佑XXX研發費用。由於以前有過很多次的合作經歷了,所以談判過程也比較順利,也沒有書面的合同約束雙方。不過這也僅僅建立在雙方已經有過很多次的合作經歷,彼此都是很熟的人,項目本身技術上沒有太大的復雜度,而且最終產品的應用場合也不會造成大的損失的基礎之上。不過一般的項目合同是很重要的一個方面,合同不僅僅為雙方的行為建立起了約束,而且如果項目失敗等造成損失,雙方也能夠明確自己的責任。至於項目需求,則只有以下幾點需求:
    1. 信號通道數必須在50~100路之間(可伸縮)
    2. 單路信號誤差限定在0.03V之內
    3. 數據傳輸使用485協議
    4. 數據協議遵循Modbus協議
    5. 傳送數據中必須包含數據量以及CRC校驗值
    6. 上電或者數據傳送過程都需要有相應的指示燈指示其狀態
    項目本身是個很簡單的項目,幾乎沒有技術上的難點。產品需求也一目了然,看了項目需求之后解決方案就已經呼之欲出了。經初步分析,整個設計過程中唯一可能需要仔細斟酌的也就是多個板子之間通信時的時序問題,事實證明,這部分到后面的確測試了挺長時間才實現功能,而且測試了好多邊界條件才最終確定下來最后的最優化參數。
 

四. 開發方式選擇

    項目的開發方式選擇了“今日標企業工作平台”和Github結合進行開發的方式。
    在本次開發中使用金目標的目的在於管控項目開發流程,實現整個開發過程簡單的文檔化。雖然該開發過程與現在所倡導的敏捷開發模式相違背,但是考慮到目前我們的開發條件,最后還是決定使用傳統的文檔化開發模式。在本次開發中由於參與開發的主要人員在不同的地方(軟件開發在江蘇,而硬件開發在廣東),造成了溝通上的諸多不便,而文檔化則會改善一些溝通上的困難。將所有的開發過程都存放在一個公共平台上,大家可以隨時查閱。這樣也最大化地降低了溝通歧義所帶來的項目風險。
    眾所周知,Github是一個不僅強大而且簡單易用的分布式代碼托管平台。對於不同地域開發人員之間的協作開發來說,擁有一個強大的代碼共享平台至關重要。而Github剛好滿足這些需求:
    1. 多方開發人員同時參與一個工程的開發
    2. 平台必須是分布式的,開發人員同時必須能編輯同一個文件
    2. 整個調試過程中各個開發人員的代碼必須要保持一致
    有關這兩個平台的使用方法,這里就不做介紹了,在各自的官網上都有很詳細的教程。在這里只提供兩個平台分別的鏈接。金目標的鏈接為:http://www.jingoal.com ,Github的鏈接為:https://github.com 。
 

五. 系統架構

   
 
  系統架構
 
  系統設計時考慮到可伸縮性,以及采集通道要求太多,故而將數據采集任務分給多個采集板去完成。每個采集板各自完成自己的采集任務,並將采集到的數據傳送到數據總線。而具體的何時采集數據,以及何時傳送數據到數據總線並交給PC段,則有Base Board控制。在這里設計的時候並沒有將采集到的數據由Base Board傳送到PC上,而是放到數據總線上直接由PC提取。這種設計是基於以下考慮,如果所有采集到的數據全都交由Base Board向上傳送,則相當於多了一級路由,這樣會降低整個系統的數據采集速率。也加重了Base Board的工作任務,使其控制邏輯變得復雜,嚴重違背“簡單即為美”的編程原則。
 

六. 硬件設計

    有關硬件設計的部分,由於我本人對於硬件不是很擅長,所以可能總結不好。故而請了我們團隊中的另一位硬件工程師撰寫。在這里我就只上兩張設計的電路圖。
采集板電路圖
 
基板電路圖

七. 軟件設計

    在本系統中軟件設計分為兩個部分,采集板軟件設計和基板軟件設計。下面分別就這兩方面介紹整個軟件開發的過程。
    1. 采集板軟件設計:
    在確定了采集板功能的情況下再開始軟件設計。本次設計中采用了“從兩端到中間”的軟件開發模式。所謂“從兩端到中間的開發模式”是指在軟件開發過程中,首先按照軟件的架構層次習慣,將軟件分為前端界面、中間邏輯控制層、以及底層的模型層(這是PC軟件的開發框架)。而對於我們嵌入式軟件來說,也可以分為類似的層。我在這次開發過程中,則是將整個軟件分為:業務邏輯、中間件、以及底層驅動模型。而從兩端到中間的開發則是指先開發底層驅動,然后再確定 業務邏輯 ,然后通過中間件將兩個部分銜接起來,並進行測試的方法。
    首先根據需求確定軟件中需要使用到的底層硬件驅動分別有:AD、USART、DMA、GPIO、外部硬件中斷。而在嵌入式系統中,一般還需要一些延時之類的功能,故而還需要提供一些延時函數的驅動。下圖顯示的是本次設計中用到的所有驅動,雖然開發過程選擇了使用STM32官方提供的固件庫編程方式,但是如果完全使用固件庫中的函數,而沒有經過封裝。則主函數將會顯得很臃腫,而且整個軟件系統的業務邏輯和底層驅動也嚴重耦合在一起,不便於以后系統維護、升級,也會大大降低系統的可移植性。
    這里的驅動設計,其實從本質上來講的話只是對固件庫中的一些函數或者是宏定義進行進一步的封裝。例如ADC部分的驅動,在~/ADC/adc.c文件中只需要系統一個Adc_Init函數,在該函數中完成對CPU ADC資源的初始化。而對應的USART設備。不僅要提供初始化函數,還需要提供一些發送數據以及接收數據等的函數。而且為了調試方便期間,一般按照我個人的習慣的話還會添加一部分代碼,用以支持printf函數,利用該函數通過串口向PC端,打印出一些程序執行的信息,這樣會大大方便嵌入式軟件調試。對於STM32來說,要支持printf函數只需要加入以下代碼:
//加入以下代碼,支持printf函數,而不需要選擇use MicroLIB
#if 1
#pragma import(__use_no_semihosting)             
//標准庫需要的支持函數                 
struct __FILE 
{ 
int handle; 
 
}; 
 
FILE __stdout;       
//定義_sys_exit()以避免使用半主機模式    
_sys_exit(int x) 
{ 
x = x; 
} 
//重定義fputc函數 
int fputc(int ch, FILE *f)
{      
while((USART1->SR&0X40)==0);//循環發送,直到發送完畢   
    USART1->DR = (u8) ch;      
return ch;
}
#endif
View Code

驅動文件列表
 
    完成了驅動程序的設計之后,則設計業務邏輯。 業務邏輯 是指從用戶需求的角度完成用戶需要的功能的一部分代碼。這部分代碼一般都是指Main函數中的邏輯。在此次設計中主要的執行流程可以使用以下的圖表示。
 
業務邏輯
 
    最后設計的是中間件,中間件的設計不僅要考慮到業務邏輯的需求,更要兼顧底層驅動模型的實現方式。只有將這兩者比較好地結合起來,最終才能得到比較理想的產品。
    從底層往上層看,中間件是對底層驅動更高一級的封裝,底層驅動只是實現獨立的單個功能點。而通過中間件不僅實現了這些功能點,而且融入了一部分系統功能的成分在里面。從上層往底層看,中間件則可以理解成對於系統業務邏輯的細化。業務邏輯類似於將用戶需求文本化或者“代碼化”,從本質上來講,它還是在用戶需求一級。而通過中間件的作用,則將抽象的業務邏輯實現了具體化,成為對於處理器來說能夠識別並執行的真實代碼。
    以上就是采集板的整個軟件開發思路以及開發過程,這里的程序從其流程來看,的確是幾乎沒有復雜度。但是在這里提出了一些軟件開發過程中的框架,一種分層機制。框架的出現將系統級的軟件分成各個不同的模塊,或者分為不同的層。從而實現了軟件良好的可維護性,也大大方便了后期系統升級。對於軟件框架的理解,我也只是一個初學者,在這里提出權當是拋磚引玉了吧。
    1. 基板軟件設計:
    從軟件的角度來講,基板是整個系統時序的控制者。就仿佛人的大腦一般,它可以發出各種指令讓系統的各個部分能夠各司其職,而不會導致系統紊亂。本次設計中,基板主要的工作流程如下:
基板的主要工作流程
 
    設計過程中基板中有一個唯一值得注意的地方就是板子復位后在線板的檢測,在這個系統中掛在基板上的采集板的個數在0~10個之間是隨意的,而控制板發送采集信號命令的時候應該只對當前系統中已經掛載的采集板發送。故而在設計之時,軟件中設計了一個鏈表,大家知道鏈表是一個大小可以動態分配的數據結構,所以我們可以講在線板的信息存儲在這個鏈表當中,而每次需要發送控制命令的時候只要遍歷整個鏈表,並發送控制命令即可。
 

八. 系統調試

    在完成了系統硬件設計以及軟件設計之后,接下來的主要任務就是單個模組測試以及系統測試。測試過程主要地可以分為以下幾個部分:
    1. 單個驅動功能點測試
    2. 采集板功能測試
    3. BaseBoard功能測試
    4. 系統功能測試
    5. 系統穩定性測試
 
    下面分別介紹此次開發過程中針對前面5個測試點的具體實現過程。
    1. 單個驅動功能點測試:
    單個驅動功能點測試是指在測試單個功能塊,比如在系統中用到的串口通信模塊、GPIO模塊、中斷模塊等。包括硬件電路測試和軟件驅動測試。這部分的測試對於整個系統測試來說是一個基礎測試,但也是至關重要的部分。只有保證了所有單個功能點能夠正確地工作才使得后續系統邏輯無誤成為可能。根據前面的介紹,在本次設計過程中,用到的所有驅動全都封裝在相應的驅動文件中,並且單個功能點都非常獨立。前面所有的驅動都能夠獨立出來形成一個完整的測試用例。而我的做法則是先創建一個通用的測試模板(一個沒有實現任何功能只包含main函數的工程)。在測試過程中只需要分別將需要測試的驅動移植到該測試工程中,並且在main函數中調用驅動中提供的函數進行測試即可。
    2. 采集板功能測試:
    在本系統中,采集板的主要任務是根據基板的控制命令,完成采集數據的動作,並將采集到的數據按照之前的協定進行整理,然后傳送到基板數據總線。所以對於基板的測試,則需要再使用一個模擬基板控制流程的電路板,或信號發生器之類的控制器。而我的做法是使用了一個51板,該板只完成產生一個定時跳變的功能。
采集板功能測試
    3. BaseBoard功能測試
    對於基板而言,測試的關鍵有兩個方面:
        1> 檢測在線板,並將在線板信息保存在隊列中
        2> 按照隊列中的信息,將控制信息發送到采集板中
    其測試過程反而比較簡單,只需要將測試的信息全部通過串口發送到PC段,根據PC端的顯示信息即可判斷是否實現了需要的功能。但是在測試的過程中發現了一個問題:串口要使用printf函數向上位機發送信息,則需要實現前面所示代碼,但是這部分代碼與工程中使用的malloc函數所在庫stdlib沖突,故而產生了編譯不過去的問題。也就是說在一個工程中這兩個功能只能使用其中一個。而malloc函數是實現雙向鏈表的關鍵,不能卻去掉。所以我選擇了自己實現一個向上位機發送字符串的方法。具體實現的代碼如下:
void Send_Data(USART_TypeDef* usartx, uint16_t data)
{
USART_SendData(usartx, data);
}
 
void Send_String(USART_TypeDef* usartx, char *str)
{
while(*str != '\0')           //判斷字符串是否發送完畢
{
Send_Data(usartx, *str);        //發送單個字符
str++;                 //字符地址加1,指向先下一個字符
delay_ms(5);
}
}
View Code

 

    4. 系統功能測試
    在完成了前面幾個部分的測試之后,對於后面系統功能測試,其實需要做的工作就少了很多。基本上只需要處理好整個系統工作時的時序即可。
    測試的過程中,首先不是將所有的采集板全都掛載到基板上去測試,而是只掛載一個測試基板和采集板的協同工作是否正確。這部分的測試大概使用了4個小時的時間,期間調整了兩個板子同時上電后的時序,這個時序是通過延時來控制的。基本的流程是上電之后采集板完成系統初始化之后,置位在線信號(置位這個信號之后基板就能夠檢測到采集板是否在線,如果采集板不在線,對應的端口呈現的狀態應該是低電平輸入),然后以個比較長的延時(我用了大概5S的時間),而基板則是完成初始化之后也是在一個比較長的延時(我選擇2S)之后,再檢測采集板的在線情況。使用這樣的時序,就可以保證只要整個系統同時上電,能夠安全采集到在線采集板的信息。這里雖然是一個比較簡單的邏輯,但是設計之時由於忽略了兩個板子上電之后完成初始化的過程所使用的時間相差比較大,在經過了很多的測試,並評估之后還是決定采用長延時這種安全的方式去處理上電后檢測采集板在線信息的任務。
    完成了在線檢測之后,就能夠確定在線板的信息已經存在於前面設計的隊列之中了。后面需要測試的就是能否根據采集板的在線信息發送了控制指令之后采集板是否能夠采集到數據並傳送上上位機上。經測試這部分的邏輯很容易實現,只要發送了控制信息,采集板就能夠發送控制信息到上位機上,但是發送了信息之后對於基板而言,還需要做的工作是等待采集板給它發送閑信號。基板的設計使用了while等待的方式,發送完控制命令之后一直等待直到收到當前工作的采集板發送了閑信號給它之后才推出循環,再對下一塊采集板發送控制指令。如此循環,便能實現一直輪詢采集的任務。
    在完成了單個采集板的系統測試之后,就需要測試同時掛載多個采集板時系統的工作情況了。在測試的過程中發現了一個問題,采集板的個數比較少的時候系統才能正常工作,但是當個數超過三個的時候指示燈顯示系統是在正常采集數據,但是485就是無法接收到數據。懷疑為所有模塊都為發送使能,有可能是相互之間的干擾造成數據通訊異常,建議軟體方面改變使能端口狀態,當空閑時關斷使能,將總線釋放,用示波器實測AB輸出波形發現,當單個模塊介入系統,不進行數據通訊時A為“1”,B為“0”,當進行數據通訊時,A變為“0”時,B將變為“1”,高電平值3.3v,當接入2個模塊,不進行數據通訊時A為“1”,B為“0”,當進行數據通訊時,A變為“0”時,B將變為“1”,但A的低電平值變為1.56v,而B的高電平值也變為了1.56V。從此可以推斷,非通訊模塊要將A上拉的3.3V,B要下拉的0V,而通訊的模塊想讓A變為0V,B變為3.3V,並聯的模塊越多,電平值越小,直至AB差分判斷失效,造成相互干擾。切記一點:但不使用總線時要釋放總線,防止相互干擾。
    經過以上的測試,就能夠確定從功能的角度來講,系統是沒有問題了。穩定性還有待測試。
    5. 系統穩定性測試
    系統穩定性的測試,無外乎就是測試系統長時間的工作是否能夠依然正常。因為系統長時間工作會造成系統發熱,而如果熱量過高,則有可能導致整個系統阻抗以及容抗等都發生變化,造成系統不能正常工作。經測試系統工作20小時以上功能依然能夠滿足,電源部分會有一點熱。經過再三考慮,最后還是加了一個散熱風扇(使用了普通PC機上的散熱風扇)。再加了風扇之后發現電源部分的發熱現象明顯有了好轉。最后經過48小時的燒機實驗,確定系統無誤!!!
 

九. 總結

    以上就是整個這次《信號采集系統》的開發過程。就如在前文所說,這個系統是一個很簡單的系統,沒有任何技術難點可言。寫這篇博文,只是想拋磚引玉,希望大家以后可以多推出類似的關於開發流程管理等的文章,大家共同學習進步。在開發的過程中肯定還有很多不完善的地方,非常期待有這方面愛好的朋友能夠提出寶貴的意見,以便我改進。最后再上幾張產品的圖片吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM