我对如何编写高质量的程序的看法
我对嵌入式软件开发的时间也不是很长,仅仅只有5年,算不上高手,也不是老手只能算是5岁的老菜鸟
,在前面的3年里没有高人指点,靠着自己摸索也写了不少的程序吧,那时侯我没有想过要写出容易理解
和维护以及移植的问题,仅仅想着如何把这个功能实现出来,所以在我工作的的第一个项目GSM汽车防盗
器,我用汇编写到5000行的时候逻辑就开始乱了,记得在快要完成所有功能的时候老板要我再增加一个
小功能时我不能决定在原有的程序的基础上哪个地方下手来增加,因为程序的逻辑关系太乱了,修改一
个地方会牵涉到很多功能,经过那一次以后我就下决心下次再写程序的时候一定要避免这个问题,一定
要作到容易修改,逻辑关系清晰。
后面有幸到一个外资公司做单片机软件开发工作,一个工程师给了我一本台湾出版的关于C语言面向
对象的编程的书(书名字忘记了),我在那本书里面找到了我为什么我第一个项目GSM汽车防盗器程序逻辑
乱的原因,我当时认认真真地读了那本书,真的感觉很好,在那本书里我学到了一个重要的概念---模块
化编程,加上那位台湾的工程师的指导,我觉得我的单片机编程水平有了质的飞跃,在以后的编程里我
不会再因为偷懒而不写注释,不会因为仅仅简单而放弃可维护,可移植,易懂的方案,这样慢慢养成了
习惯,在第二年我就用C写出了大约80KBYTE 的产品程序,而且自认为逻辑清晰,只要客户说需要修改哪
里我能马上作出响应。
现在我已经习惯模块化程序设计,不管是8位的单片机还是32位的MPU, 都会按照这样的思路去做,我
觉得写出好的,高质量的程序,
1.不要怕麻烦,该写的就要写,该做的就要做。
2.尽量模块化设计,虽然这样做在写小程序时会浪费时间,可这样会养成模块化程序的习惯。
3.最好多看看老外写的关于编程的书籍,你会发现很多东西你以前见到的。
4.学习下PSP,CMMI的课程.
下面是我用队列来实现CPU SCI 底层驱动程序的一个文件,希望能起到点点引用的作用。
最早是在freescale的CPU上使用,后来移植到了51,h8/3062,凌阳等MCU上,表现性能相当地好,在开发
产品节约了大把的时间,老板大大开心,我也大大开心。。
#define SCI_DRIVER
/*****************************************************************************************
*Copyright: xxxxxCorporation
*
*File name: SciDriver.c
*
*Author: Kenny_wang
*
*Version: V1.0
*
*Date: *
******************************************************************************************/
#include "SciDriver\SciDriver.h"
#include "SciDriver\Source\FunLst.h"
#include "SciDriver\Ports\Sciconfig.h"
/********************************************************************************
* Constant Define *
********************************************************************************/
#define cQBufNormal 0
#define cQBufFull 1
#define cQBufEmpty 2
/********************************************************************************
* Queue structure *
********************************************************************************/
typedef struct{
unsigned char *pIn;
unsigned char *pOut;
unsigned char *pStart;
unsigned int bLength;
unsigned int wSize;
}QUEUE;
/********************************************************************************
* Sci structure *
* Including tranmit and receive queue structure and Tx,Rx threshold variabls *
********************************************************************************/
typedef struct{
unsigned char bTxStatus;
unsigned int wTxLength;
unsigned char *pbTx;
QUEUE *pqRx;
unsigned char bSciType;
}SciStruct;
/********************************************************************************
* List of Sci structure and queue *
********************************************************************************/
SciStruct SciList;
SciStruct *pSciIndex;
QUEUE QList;
unsigned char bSciRxBuf[MAX_SCI_BUF_SIZE];
unsigned char *pSciBuf = bSciRxBuf;
unsigned char bSciNo = 0;
/********************************************************************************
* Internal Function Declaration *
********************************************************************************/
void sQInit(QUEUE *pq,unsigned char *pStart,unsigned int wSize);
unsigned char sQDataIn(QUEUE *pq,unsigned char bData);
unsigned char sQDataOut(QUEUE *pq,unsigned char *pData);
/********************************************************************************
*Function name: sQInit *
*Parameters: pq: pointer to queue structure to be initialized *
* start: start address of ring buffer *
* size: the size of the ring buffer *
*Description: initialize a queue structure *
********************************************************************************/
void sQInit(QUEUE *pq,unsigned char *pStart,unsigned int wSize)
{
pq->pIn = pStart;
pq->pOut = pStart;
pq->pStart = pStart;
pq->bLength = 0;
pq->wSize = wSize;
}
/********************************************************************************
*Function name: sQDataIn *
*Parameters: pq: pointer to queue structure to be initialized *
* data: the data to be inserted into the queue *
*Returns: cQBufNormal: data has been inserted into the queue *
* cQBufFull: the buffer is full *
*Description: insert a data into the queue *
********************************************************************************/
unsigned char sQDataIn(QUEUE *pq,unsigned char bData)
{
if(pq->bLength == pq->wSize)
{
if(pq->pIn == pq->pStart)
{
*(pq->pStart + pq->wSize) = bData;
}
else
{
*(pq->pIn-1) = bData;
}
return(cQBufFull);
}
else
{
*(pq->pIn) = bData;
pq->bLength++;
if(pq->pIn == pq->pStart + pq->wSize - 1)
{
pq->pIn = pq->pStart;
}
else
{
pq->pIn++;
}
return(cQBufNormal);
}
}
/********************************************************************************
*Function name: sQDataOut *
*Parameters: pq: pointer to queue structure to be initialized *
* pdata: the address to save the data *
*Returns: cQBufNormal: data has been inserted into the queue *
* cQBufEmpty: the buffer is empty *
*Description: Get a data from the queue *
********************************************************************************/
unsigned char sQDataOut(QUEUE *pq,unsigned char *pData)
{
if(pq->bLength == 0)
{
return(cQBufEmpty);
}
*pData = *(pq->pOut);
pq->bLength--;
if(pq->pOut == pq->pStart + pq->wSize - 1)
{
pq->pOut = pq->pStart;
}
else
{
pq->pOut++;
}
return(cQBufNormal);
}
/********************************************************************************
*Function Name: sInitialSci *
*Parameters: bSciId: sci id *
* *bRxBuf: receive buffer start address *
* wRxSize: receive buffer length *
* bTxBuf: transmit buffer start address *
* wTxSize: transmit buffer length *
* type: sci type *
*Descriptions: assign and initialize the sci control struct to sci *
********************************************************************************/
void sInitialSci(unsigned int wRxSize,unsigned char bType)
{
QUEUE *pq;
SciStruct *pSci;
pSci = &SciList;
pSciIndex = pSci;
pSci->pqRx = &QList;
pq = pSci->pqRx;
sQInit(pq,pSciBuf,wRxSize);
pSciBuf += wRxSize;
bSciNo++;
pSci->bTxStatus = cSciTxRdy;
pSci->wTxLength = 0;
pSci->bSciType = bType;
}
/********************************************************************************
*Function Name: sSciRxISR *
*Parameters: bSciId: sci id *
*Description: This function is executed in Sci rx interrupt io2sci rx compare *
* interrupt. *
********************************************************************************/
void sSciRxISR(void)
{
unsigned char bData;
QUEUE *pq;
SciStruct *pSci;
pSci = pSciIndex;
pq = pSci->pqRx;
if(sbGetSciRxRdy() == cSciRxRdy)
{
sSciResetRx();
bData = sbGetSciRxData();
sQDataIn(pq,bData);
}
}
/********************************************************************************
*Function Name: sSciRead *
*Parameters: bSciId: sci id *
* *pBuf: address to save data received *
*Returns: cSciRxBufEmpty: receive buffer is empty *
* cSciRxRdy: get one byte data successfully *
*Description: This function is executed in AP *
********************************************************************************/
unsigned char sSciRead(unsigned char *pBuf)
{
QUEUE *pq;
unsigned char bTemp;
SciStruct *pSci;
pSci = pSciIndex;
pq = pSci->pqRx;
OS_ENTER_CRITICAL();
bTemp = sQDataOut(pq,pBuf);
OS_EXIT_CRITICAL();
if(bTemp == cQBufEmpty)
{
return(cSciRxBufEmpty);
}
else
{
return(cSciRxRdy);
}
}
/********************************************************************************
*Function Name: sSciTxISR *
*Parameters: bSciId: sci id *
*Description: This function is executed in Sci Tx interrupt io2sci Tx compare *
* interrupt. *
********************************************************************************/
void sSciTxISR(void)
{
SciStruct *pSci;
pSci = pSciIndex;
if(sbGetSciTxRdy() == cSciTxRdy)
{
if(pSci->wTxLength == 0)
{
pSci->bTxStatus = cSciTxRdy;
sSciResetTx();
}
else
{
sSciTxData(*(pSci->pbTx));
(pSci->pbTx)++;
(pSci->wTxLength)--;
sSciResetTx();
}
}
}
/********************************************************************************
*Function Name: sSciWrite *
*Parameters: bSciId: sci id *
* *pstart: start address of data to be sent *
* wLength: the length of data to be send *
*Returns: cSciTxBufFull: transmit buffer is empty *
* cSciTxRdy: send one byte data successfully *
*Description: This function is executed in AP *
********************************************************************************/
unsigned char sSciWrite(unsigned char *pStart,unsigned int wLength)
{
SciStruct *pSci;
pSci = pSciIndex;
if(pSci->bTxStatus == cSciTxBusy)
{
return(cSciTxBusy);
}
OS_ENTER_CRITICAL();
pSci->pbTx = pStart;
pSci->wTxLength = wLength;
pSci->bTxStatus = cSciTxBusy;
sSciTxData(*(pSci->pbTx));
(pSci->pbTx)++;
(pSci->wTxLength)--;
OS_EXIT_CRITICAL();
return(cSciTxRdy);
}
/********************************************************************************
*Function Name: sbGetSciTxStatus *
*Parameters: bSciId: sci id *
*Returns: sci tx status cSciTxRdy *
* cSciTxBusy *
*Description: Get the sci trasmit status *
********************************************************************************/
unsigned char sbGetSciTxStatus(void)
{
SciStruct *pSci;
pSci = pSciIndex;
return(pSci->bTxStatus);
}
/********************************************************************************
*Function Name: sSetSciBaudRate *
*Parameters: bSciId: sci id *
*Returns: bBaudrate Sci Baudrate *
*Description: Set the sci baudrate *
********************************************************************************/
void sSetSciBaudRate(unsigned char bBaudrate)
{
sSciChangeBaudRate(bBaudrate);
} |