溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

c#代碼Bug怎么解決

發(fā)布時間:2022-01-05 17:00:41 來源:億速云 閱讀:126 作者:iii 欄目:互聯(lián)網(wǎng)科技

本篇內(nèi)容介紹了“c#代碼Bug怎么解決”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

BUG記錄5——數(shù)組訪問越界,導(dǎo)致軟件進(jìn)入HardFault

這是一個比較常見也比較容易忽略的問題,從學(xué)習(xí)C語言數(shù)組開始,我們就被告知數(shù)組的下標(biāo)從0開始,但是我們在實際的案例應(yīng)用中,序號一般都是從1開始。在一次實際的應(yīng)用中,采集板采集通道1-通道6的數(shù)值,主控板也對應(yīng)的定義了一個大小為6的數(shù)據(jù)緩沖區(qū),index從0到5,采集板采集完六個通道的數(shù)據(jù),將數(shù)據(jù)按照幀首、通道號、采樣值、幀尾的格式進(jìn)行打包,然后發(fā)送給主控板,主控則對應(yīng)的根據(jù)通道號將采樣值存儲到緩沖區(qū),因為疏忽編碼時采集板的通道號是從1到6寫入數(shù)據(jù)幀的,所以當(dāng)主控板接收到通道號為6的數(shù)據(jù)幀就出現(xiàn)了數(shù)組越界存儲了,此時軟件就進(jìn)入HardFault死循環(huán)里面了。

void HardFault_Handler(void){
  /* Go to infinite loop when Hard Fault exception occurs */  while (1)
  {
  }
}
BUG記錄6——左右移運算符<<、>>和按位與或運算符&、|的優(yōu)先級問題
//Righthost_control_slave[2] = (gRtcDate&0xFF0000) >> 16;
host_control_slave[3] = (gRtcDate&0xFF00) >> 8;
host_control_slave[4] =  gRtcDate & 0xFF;//Errorhost_control_slave[2] = gRtcDate & 0xFF0000 >> 16;
host_control_slave[3] = gRtcDate & 0xFF00 >> 8;
host_control_slave[4] =  gRtcDate & 0xFF;

左右移運算符和按位與或運算符的結(jié)合性都是自左向右,前者的優(yōu)先級高于后者,所以上面兩段代碼塊會得出不同的結(jié)果,后面一段代碼會先進(jìn)行右移運算,再進(jìn)行按位與的運算。我比較懶,一般不怎么去記優(yōu)先級順序表,一般都是用()來框起來,這樣也有一定的弊端,就是太多括弧看起來也很費勁,所以還是建議常用的一些運算符優(yōu)先級順序還是要記一下。

BUG記錄7——GPIO模式的配置問題
void GpioConfigInit(void){
 GPIO_InitTypeDef  GPIO_InitStructure;
  
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
 
    //設(shè)置GPIOC_12為推挽輸出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;     
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    
    //設(shè)置GPIOC_13為上拉輸入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;     
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    
 GPIO_Init(GPIOC, &GPIO_InitStructure);           
}

在實際的嵌入式項目中,操作GPIO是比較普遍的,但是也隱藏了一些潛在的坑,上面的初始化函數(shù)在配置完GPIOC_12和GPIO_13之后,GPIOC_12的推挽輸出其實是沒有配置成功的,因為此函數(shù)中在最后進(jìn)行了一次結(jié)構(gòu)體初始化的操作,相當(dāng)于只是把GPIOC_13的模式寫入了結(jié)構(gòu)體參數(shù),所以此時兩個IO口的模式均為上拉輸入,具體我們來分析下GPIO這個結(jié)構(gòu)體的成員參數(shù):

/** 
  * @brief  GPIO Init structure definition  
  */typedef struct{   uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                      This parameter can be any value of @ref GPIO_pins_define */  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                      This parameter can be a value of @ref GPIOMode_TypeDef */}GPIO_InitTypeDef;/**
  * @brief  Initializes the GPIOx peripheral according to the specified
  *         parameters in the GPIO_InitStruct.
  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
  *         contains the configuration information for the specified GPIO peripheral.
  * @retval None
  */void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct){
  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
  uint32_t tmpreg = 0x00, pinmask = 0x00;
  /* Check the parameters */  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
  /*---------------------------- GPIO Mode Configuration -----------------------*/  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
  { 
    /* Check the parameters */    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
    /* Output mode */    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
  }/*---------------------------- GPIO CRL Configuration ------------------------*/  /* Configure the eight low port pins */  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
  {
    tmpreg = GPIOx->CRL;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = ((uint32_t)0x01) << pinpos;
      /* Get the port pins position */      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
      if (currentpin == pos)
      {
        pos = pinpos << 2;
        /* Clear the corresponding low control register bits */        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);
        }
        else        {
          /* Set the corresponding ODR bit */          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          {
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
          }
        }
      }
    }
    GPIOx->CRL = tmpreg;
  }/*---------------------------- GPIO CRH Configuration ------------------------*/  /* Configure the eight high port pins */  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
  {
    tmpreg = GPIOx->CRH;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = (((uint32_t)0x01) << (pinpos + 0x08));
      /* Get the port pins position */      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
      if (currentpin == pos)
      {
        pos = pinpos << 2;
        /* Clear the corresponding high control register bits */        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
        /* Set the corresponding ODR bit */        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
        {
          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
      }
    }
    GPIOx->CRH = tmpreg;
  }
}

上述的函數(shù)會把GPIO的引腳、速度、模式,寫入到相關(guān)的寄存器中去,在GpioConfigInit()函數(shù)中如果只寫入一次引腳、速度、模式等參數(shù),那么只會以最后一次的參數(shù)為準(zhǔn),因為這里定義的結(jié)構(gòu)體變量為局部變量,在配置GPIOC_13時又重新被賦值,然后再被寫入,所以就會出現(xiàn)GPIOC_12模式配置失敗的問題,正確的配置函數(shù)為:

void GpioConfigInit(void){
 GPIO_InitTypeDef  GPIO_InitStructure;
  
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
 
    //設(shè)置GPIOC_12為推挽輸出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;     
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOC, &GPIO_InitStructure); 
    
    //設(shè)置GPIOC_13為上拉輸入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;     
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOC, &GPIO_InitStructure);           
}
BUG記錄8——觸摸屏刷新頻率,并不是越快越好

提高觸摸屏的刷新頻率主要是為了提高用戶體驗感,讓用戶用起來感覺更加流暢,但是也不是越快越好,最好要參考觸摸屏廠商提供的推薦刷新頻率來設(shè)置,如下為某款觸摸屏的推薦參數(shù):

MCU不要頻繁向串口屏發(fā)送數(shù)據(jù),否則串口屏的內(nèi)部緩存區(qū)會滿,從而導(dǎo)致數(shù)據(jù)丟失(緩沖區(qū)大?。簶?biāo)準(zhǔn)型8K,基本型4.7K)
1) 一般情況下,控制MCU向串口屏發(fā)送數(shù)據(jù)的周期大于100ms,就可以避免數(shù)據(jù)丟失的問題;
2) 如果仍然有數(shù)據(jù)丟失的問題,請判斷串口屏的BUSY引腳,為高時不能發(fā)送數(shù)據(jù)給串口屏。

我之前試過10ms來刷新一些參數(shù),然后發(fā)現(xiàn)觸摸屏的其他一些操作就非??D,因為觸摸屏自帶的MCU一直在不斷的進(jìn)入數(shù)據(jù)接收中斷并需要不斷的處理,有時候還會出現(xiàn)數(shù)據(jù)亂碼,其原因也就是內(nèi)部的一級緩沖區(qū)產(chǎn)生了溢出。

BUG記錄9——指針數(shù)組的錯誤尋址

在編程過程中,我一般將指針數(shù)組用來存放字符串信息,如下代碼塊:

const char *ErrInf[5] = 
{
 "光子計數(shù)器故障!",
 "空杯測試故障!",
 "溫控儀通訊故障!",
 "打印機(jī)缺紙!",
 "過溫或欠溫!"};

那我們看下這些字符串信息如何在內(nèi)存中存儲:

c#代碼Bug怎么解決

/*! 
*  \brief     文本框更新
*  \param  screen_id 畫面ID
*  \param  control_id 控件ID
*/void WriteTextValue(uint16 screen_id, uint16 control_id, uint8 *pData, uint16 nDataLen){
    BEGIN_CMD();
    TX_8(0xB1);
    TX_8(0x10);
    TX_16(screen_id);
    TX_16(control_id);
    SendNU8(pData, nDataLen);
    END_CMD();
}

如果需要更新上面的第一個字符串信息,就該按照如下來調(diào)用文本框更新函數(shù):

//RightWriteTextValue(0x01, 0x01, (uint8*)ErrInf[0], strlen(ErrInf[0]));//ErrorWriteTextValue(0x01, 0x01, (uint8*)&ErrInf[0], strlen(ErrInf[0]));

因為第一個字符串存儲的首地址為ErrInf[0],而非&ErrInf[0],&ErrInf[0]是ErrInf[0]的地址,這兩個地址是有區(qū)別的,所以千萬不要加取地址符&。

BUG記錄10——自減運算符引發(fā)的問題
typedef struct{ char  *HybDenName;
 u8  SetHybDenTemp[2];
 u32 SetHybDenTime[2];
}HybDenPrgPara_TypeDef;typedef struct{ u8 HybDenRow;
 u8 HybRow;
 u8 MulRow;
 u8 HybDenCol;
 u8 MulCol;
}PrgFlowIndex_TypeDef;

HybDenPrgPara_TypeDef HybDenFlowPara[PRG_FLOW_NUM_MAX] = 
{
 {"DenHyb01", 0, 0, 0, 0},
 {"DenHyb02", 0, 0, 0, 0},
 {"DenHyb03", 0, 0, 0, 0},
 {"DenHyb04", 0, 0, 0, 0},
 {"DenHyb05", 0, 0, 0, 0},
 {"DenHyb06", 0, 0, 0, 0},
 {"DenHyb07", 0, 0, 0, 0},
 {"DenHyb08", 0, 0, 0, 0},
 {"DenHyb09", 0, 0, 0, 0},
 {"DenHyb10", 0, 0, 0, 0},
};

PrgFlowIndex_TypeDef       PrgFlowIndex = {0x00, 0x00, 0x00, 0x00, 0x00};//code blockcase LoadPgUp:
{
    if(0x00 == PrgFlowIndex.HybDenRow)
    {
     PrgFlowIndex.HybDenRow = PRG_FLOW_NUM_MAX-0x01;
    }
    else    {
     PrgFlowIndex.HybDenRow--;
    }

 //在程序加載界面、運行界面、名稱編輯寫入新的程序名稱 SetTextValue(HybDenLoad, LoadName,       (u8*)HybDenFlowPara[PrgFlowIndex.HybDenRow].HybDenName);
 SetTextValue(HybDenRun, LoadName, (u8*)HybDenFlowPara[PrgFlowIndex.HybDenRow].HybDenName);
 SetTextValue(HybDenNameEdit, LoadName, (u8*)HybDenFlowPara[PrgFlowIndex.HybDenRow].HybDenName);

 break;
}

如果將PrgFlowIndex.HybDenRow--放置到if-else之前會引發(fā)什么問題?當(dāng)PrgFlowIndex.HybDenRow等于0時,再自減1,其值就變成了255,下面的SetTextValue()函數(shù)在寫入結(jié)構(gòu)體數(shù)組參數(shù)時就會寫入到非法的內(nèi)存中去,也會造成HardFault錯誤。

“c#代碼Bug怎么解決”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI