美容儀器IPL激光脫毛儀程序設計


今日再次把幾年前做過的脫毛儀拿出來,重新換了個8051的更便宜的單片機做了一遍,重復是最沒有意義的,做的更快更好,才有意義,所以我綜合了近年來編程方面的心得,特意記下來,形成總結文檔,既是拋磚引玉,也是自我提高。 我常常思考,怎么樣才能提高代碼復用,像高級語言那樣,基本上調用一些接口就可以了,驅動和應用分離,這種思路就可以實現。 開局一張圖,內容全靠吹

在這個功能多樣,雜散的局面下,我綜合采取了面向對象+模塊化+狀態機+分層封裝的方法,下面分別總結下。

  • 狀態機

    最核心的部分就是復雜的升壓和出光了。要求是額定功率下最快的速度升壓,出光之前要穩住電壓400V左右(根據檔位)。此時還有自動模式和手動模式,根據設置和皮膚觸摸情況來出光。 狀態機切換程序原則上只做狀態的切換,不要做功能上的實現。功能方面另外單獨做個函數去實現。 主題的狀態機就是:

 1 //系統狀態
 2  enum systermstate
 3 {
 4   SYSERROR, //系統錯誤
 5   SYSIDLE, //待機
 6   AGINGMODE, //老化模式
 7   NOGETVOL, //未滿電,升壓
 8   GETVOL,   //滿電待出光
 9   SHINING, //出光
10   AGINGDONE, //老化模式完成
11   LIFEAPANREDUCE, //出光后壽命減
12 };
13 //----------------------------------------------------------------------
14 // Function: static void sysStateDispatch(void) 
15 // Description:
16 // 狀態機切換
17 //-------------------------------------------------------------------
18 static void sysStateDispatch(void) //
19 {
20   switch (sysState)
21   {
22   case SYSERROR: //系統錯誤SYSERROR
23   { 
24     PWM1SetdutyCycle((UINT8)0); 
25   }
26   break;
27    case SYSIDLE: //待機
28   { 
29     PWM1SetdutyCycle(0); 
30     if (keyPowerLongFlag) // 開機鍵
31     {
32       keyPowerLongFlag = 0;
33       sysState = NOGETVOL;
34       PWM1ChargeInit();
35       timeOuts = 0;
36       timeOutsConts = 0;
37       pwm1DutyCycle = 13;
38     }
39   }
40   break;
41   case NOGETVOL: //升壓
42   {
43     timeOuts++;
44     if (timeOuts > 30) //
45     {
46       timeOuts = 0;
47       timeOutsConts++;
48       adcSelectADCCh(POWER_I_CHA);
49       if(gadcValue < 80)
50      {
51       pwm1DutyCycle++;
52      }
53     }
54     PWM1SetdutyCycle(pwm1DutyCycle);      adcSelectADCCh(HIGHVOL);
55     if ((timeOutsConts > 80) ||(gadcValue > ADCMAX[gearAdjustment])) 時間和電壓綜合判斷
56     {
57       timeOuts = 0;
58       timeOutsConts = 0;
59       pwm1DutyCycle = 0;
60       //PWM1dutyCycle((UINT8)0); //測試
61       sysState = GETVOL; //電壓升滿,去發射    
62  }
63   }
64   break;
  • 模塊化:

       雖然狀態機囊裹了幾乎程序所有的狀態,理論上所有的功能都可以在狀態機哈函數實現,但是我還是強烈建議分開實現,目的是為了程序可讀性,方便維護。例如一個簡單的燈光只是,我本來是在狀態機函數去做的,后來我還是獨立出來了,其中sysState 是狀態機變量:

 1 //-----------------------------------------------------------------------------
 2 // Function: static void ledtask(void)
 3 // Description:
 4 // 指示燈任務,在每個任務下的表現。 在100Ms輪詢事件里調用
 5 //-----------------------------------------------------------------------------
 6  static void ledtask(void)
 7 {
 8   if (sysState == SYSERROR || sysState == AGINGDONE || (sysState == GETVOL && !touchIn)) //異常或者測試完成后
 9   {
10     timeOuts++;
11     if (timeOuts > ((sysState == SYSERROR) ? 1 : 6))
12     {
13       timeOuts = 0;
14       greenled = !greenled; //指示燈閃爍
15     }
16   }
17   if (sysState == SYSIDLE || sysState == SYSIDLEPRE || sysState == NOGETVOL) //異常或者測試完成后
18   {
19     greenled = 0;
20   }
21   if ((sysState == GETVOL && touchIn) || sysState == SHINING) // 滿電和出光
22   {
23     greenled = 1;
24   }
25 }

如此一來,就把指示燈獨立出來了,客戶更改了需求,可以快速更改!否則會有啥情況,是不是你得全局搜索這個led,然后滿大街的去修改? 其他的比如風扇控制,放電控制,等等都獨立出來,依據狀態去改變。

  • 分層封裝:

      以斷碼屏為例,斷碼屏驅動芯片是HT1621B,最終是需要把相關數據傳送在HT1621。那么此時,驅動層和應用層應該獨立,只保留一個接口來調用即可。 接口類型聲明:

1 typedef struct { 
2    void (*Init)(void); //初始化
3 void (*sendCmd)(unsigned char); //發命令
4    void (*writeData)(unsigned char addr, unsigned char xdata *buf, unsigned char cnt); //更新顯示數據 
5 }HT1621funs_t;
6 HT1621funs_t HT1621funs;接口類型定義:

在底層驅動文件HT1621Dri.c里面定義好每一個驅動函數:

1 static void HT1621B_SendCmd(unsigned char command)
2 static void HT1621B_SendBit(unsigned char ddata, unsigned char cnt)
3 。。。

在應用層文件diaplcd.c中,只需要調用: HT1621funs.writeData(0, bufferDisp.Icon_buf, 8); //刷新數據 即可。

  • 面向對象:

       還是以HT1621為例,如果下次換成了HT1902(假設),可能驅動有所不同,此時再實例化一個: HT1621funs_t HT1902funs; 實例化的時候,使用1902的驅動去實例化即可,接口HT1621funs_t類型還是不變。

 1 //-----------------------------------------------------------------------------------------
 2 //函數名稱:void HT1902funsInit(void)
 3 //功能描述: HT1902實例化接口成員函數
 4 //說 明:初始化后,其他文件只需要調用HT1902funs結構體成員函數即可
 5 //-----------------------------------------------------------------------------------------
 6 void HT1902funsInit(void)
 7 {
 8 HT1902funs.Init = HT1902_Init; //初始化
 9 HT1902funs.sendCmd = HT1902_SendCmd;//發命令
10 HT1902funs.writeData = HT1902_WriteData;//更新顯示數據 
11 } 

以上,基本上說完了使用到的方法,思想,細節方面歡迎討論。綜合采用這些編程思想,基本可以做到既快又好的完成項目開發或者修改需求。穩定性也得到充分的保證。

接下來我嘗試移植RTThread到此項目上,目的是在狀態復雜的項目里面,多使用分時系統,以應對更復雜的需求。 歡迎交流,交流技術和項目合作均可。 

專業提供PCBA設計,軟件設計。

        這里美容儀器市場上一般有的功能,這里都能實現,常用的市場上這些美容類的產品,這里開發周期短,最快一到兩周出樣,配合您的idea設計,配合不錯的話,一般一個月內可以上市。

市場上能找到美容類的方案板,我們這里都可以開發,市場上面找不到的板,我們這里也可以快速開發,這個世界快魚吃慢魚,抓住機會,美容儀器方案開發,選專業的我們,期待與您合作!

我們的合作模式:

1、和客戶電話,面談,電子聯絡方式郵箱:1920844004@qq.com確定開發電路板的規格及2D圖等資料

2、簽訂開發合同,根據客戶的產品難易程序收取一定的誠意金。

3、開發產品,軟硬件開發,制作樣品,客戶確認或復驗至合格。

4、以上視開發階段完成,客戶提出需求,訂制PCBA

5、PCBA按客戶需求出貨,出貨一般到20K無條件退還誠意金。

 


免責聲明!

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



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