2011年11月3日 星期四

int 2 ascii

之前寫了一個程式優化的文章


參考了BEE大大的建議,今天寫了一個int 2 ascii 的function


 


 


void int2ascii(BYTE *cp, WORD uquad)


{


    #define to_char(cp) (cp)+'0'


 


    memset(cp-5, '0', 5); // set all byte is ascii of '0'


   


    while (uquad >= 10) {


        *--cp = to_char(uquad % 10);


        uquad /= 10;


    }


    *--cp = to_char(uquad);


}


使用方式:


 




    BYTE CP[6]={0};


    WORD TEST = 4;


    int2ascii(&CP[5],TEST);


 


cool~  挺方便的


 


實在沒有多少時間寫文章,只能說抱歉了……


 


另外因為工作上的需求,要來做點工具了,又要停頓一陣子了,有空再來整理。



2011年11月2日 星期三

神奇的選單

如何寫一個容易維護的選單程式,當初只會寫了一堆if then else, 或者是switch case……


維護的好辛苦,今天寫了一個神奇的選單程式,維護上就簡單多了


VBITS_16 Menu_Flag_All,
         Menu_Flag_0,
         Menu_Flag_1,
         Menu_Flag_2,
         Menu_Flag_3,
         Menu_Flag_4;



void Null_Menu(void)
{
   ;
}


void Task_Menu_0(void)
{
    Menu_Flag_0.word = 0x0002;
    Menu_Service(&Menu_Flag_0, Menu_Table_0);
}


void Task_Menu_1(void)
{
    Menu_Flag_1.word = 0x0002;
    Menu_Service(&Menu_Flag_1, Menu_Table_1);
}


void Task_Menu_2(void)
{
    Menu_Flag_2.word = 0x0002;
    Menu_Service(&Menu_Flag_2, Menu_Table_2);
}


void Task_Menu_3(void)
{
    Menu_Flag_3.word = 0x0001;
    Menu_Service(&Menu_Flag_3, Menu_Table_3);
}


void Task_Menu_4(void)
{
    Menu_Flag_4.word = 0x0001;
    Menu_Service(&Menu_Flag_4, Menu_Table_4);
}


void test(void)
{
   ;
}


const FUNCT_PTR_V_V Menu_Table_0[16] =
{
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
};


const FUNCT_PTR_V_V Menu_Table_1[16] =
{
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
};
const FUNCT_PTR_V_V Menu_Table_2[16] =
{
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
};
const FUNCT_PTR_V_V Menu_Table_3[16] =
{
    test, //test
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
};
const FUNCT_PTR_V_V Menu_Table_4[16] =
{
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
};


const FUNCT_PTR_V_V Menu_Table_All[16] =
{
    Task_Menu_0,
    Task_Menu_1,
    Task_Menu_2,
    Task_Menu_3,
    Task_Menu_4,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
    Null_Menu,
};


 


void Menu_Service(VBITS_16 *service_flags, const FUNCT_PTR_V_V *service_table)
{


    WORD flags;
    int index = 0;
    if ( 0 == service_flags->word) return;
    flags = service_flags->word;
    while((flags & 1) == 0)
    {
       flags >>= 1;
       index++;
    }


    service_flags->word &= ~(1<<index);  /* Clear service request. */


    (*service_table[index])();              /* Dispatch to service handler. */


}


 


使用上也不複雜


  Menu_Flag_All.word = 0x0008;
  Menu_Service(&Menu_Flag_All, Menu_Table_All);


一樣也是call 副程式來使用,應該還可以寫得更好才對。


 


今天就先這樣吧!


PID 寫法

回想以前寫的程式,和現在在公司被訓練的結果,果然還是有差


今天播空寫一下PID 的寫法,功能可能不太正常,不過大至上應該是正常的


typedef enum _PIDType_e
{
    CTR_TYPE_PID = 0,
    CTR_TYPE_P,
    CTR_TYPE_PD,
    CTR_TYPE_PI,
} PIDType_e;


 


typedef struct _PIDStruct
{
PIDType_e Type;
    int Kp;
    int Ki;
    int Kd;
    long Error;
    long Error_Differential;
    long Error_Last;
    long Error_Accumulate;
    long Error_Saturation;
    long Output;
    long Output_Saturation;
   
}PIDStruct;


#define PIDStruct_Size sizeof(PIDStruct)


void PID_Control(PIDStruct *PID_ST)
{
    PID_ST->Error_Differential = PID_ST->Error - PID_ST->Error_Last;
    PID_ST->Error_Accumulate += PID_ST->Error;
    SATURATION(PID_ST->Error_Accumulate,
        PID_ST->Error_Saturation,
        -PID_ST->Error_Saturation);
    PID_ST->Error_Last = PID_ST->Error;


    switch (PID_ST->Type)
    {
    case CTR_TYPE_PID:
        PID_ST->Output = PID_ST->Kp * PID_ST->Error +
                         PID_ST->Ki * PID_ST->Error_Accumulate +
                         PID_ST->Kd * PID_ST->Error_Differential;      
        break;
    case CTR_TYPE_P:
        PID_ST->Output = PID_ST->Kp * PID_ST->Error;
    break;
    case CTR_TYPE_PD:
        PID_ST->Output = PID_ST->Kp * PID_ST->Error +
                         PID_ST->Kd * PID_ST->Error_Differential;      
    break;
    case CTR_TYPE_PI:
        PID_ST->Output = PID_ST->Kp * PID_ST->Error +
                         PID_ST->Ki * PID_ST->Error_Accumulate;
    break;


    default:
        // Error
        break;
    }
   
    if (0 != PID_ST->Output_Saturation)
    {
        // do not judgement if saturation is zero.
        SATURATION(PID_ST->Output,
        PID_ST->Output_Saturation,
        -PID_ST->Output_Saturation);
    }


}


這樣在做應用的時後,如果整支程式重複的地方,就不需要重複的貼上PID的寫法,只要CALL 這支副程式就可以搞定了


用之前先初始化變數


PIDStruct Motor_CTR_L;


void PID_Init(void)
{
    memset(&Motor_CTR_L, 0, PIDStruct_Size);
    Motor_CTR_L.Type = CTR_TYPE_PID;
    Motor_CTR_L.Kp = 10;
    Motor_CTR_L.Ki = 1;
    Motor_CTR_L.Kd = 2;
    Motor_CTR_L.Output_Saturation = -4000;
    Motor_CTR_L.Error_Saturation = -3000;
   
}


把誤差丟進去 Motor_CTR_L.Error = -1000;


最後CALL 副程式


PID_Control(&Motor_CTR_L);


我只有貼比較重要的片段,不過也差不多是所有的程式碼了。


 


忙裡偷閒的練習寫自己有興趣的程式,還滿爽的!


2011年6月1日 星期三

keil c compiler 流呈

上班後才發現,自己的會的東西太少


這是keil compiler的流呈


其實看懂這個不難,但如果要用make file 把這個流呈寫出來,那應該功力是超強


之前看不懂以為就算了,現在看懂他在寫什麼,真的覺得他超強。


 




2011年5月31日 星期二

版本控制 - Mercurial

之前使用的版本控制是SVN,不過最近同事在使用Mercurial,今天花了1天玩了一下,發現確實是有些優點。


可以先去mercurial 下載軟體並看介紹:mercurial 官方網址

mercurial 介紹





這個作者寫的非常好懂


這是作者內文中的2張圖,非常的清楚了解到中控式和分散分的版本控制軟體的差別。


 


其中他寫了一段


Even if you’re working by yourself, you should use Mercurial to get the benefits of version control. This tutorial shows how easy it is to check a directory into Mercurial so you can track old versions easily.


即使程式只有自己在譔寫,他還是建議使用mercurial 來當版本控制。




 

以下是一些mercurial 的教學,有興趣的看看



mercurial 教學




mercurial coommand line




 


還有一個也是分散式的Git,不過大家可以參考這篇文



http://zoomquiet.org/res/scrapbook/ZqFLOSS/data/20100927101141/