性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

stm32單片機(jī)的USB燒錄程序

先開門見上DFU是啥

DFU全稱為Download Firmware Update,是ST官方推出的一個(gè)通過USB接口進(jìn)行IAP升級(jí)的方案,同串口ISP一樣,他們都集成在了芯片內(nèi)部的Bootloader區(qū)段,可以通過配置boot引腳來(lái)啟動(dòng)。

當(dāng)用戶使用STM32F4 H7或者更高級(jí)MCU時(shí),自己編譯生成燒寫文件,或者通過其他途徑獲得燒寫文件,通常格式為hex,一般情況下用戶可以通過調(diào)試器例如JLink,ST-link等使用專用的軟件下載,或者配合BOOT設(shè)置使用串口進(jìn)行ISP下載,這時(shí)候則使用USB轉(zhuǎn)串口ttl設(shè)備,現(xiàn)在STM32F4 H7以上版本的可以通過USB口進(jìn)行下載,只需要一根USB線就OK. 這種技術(shù)叫作DFU模式燒寫

但是STM32內(nèi)置DFU的型號(hào)都比較新,像上面說的STM32F4系列是有的,但是像F0和F1系列則沒有,不過沒有關(guān)系,如果你用的型號(hào)沒有內(nèi)置DFU程序,也可以通過CubeMX來(lái)快速生成和移植一個(gè)DFU功能程序到你的Flash中來(lái)使用。

使用DFU的優(yōu)缺點(diǎn)?使用DFU的好處是不用自己制作Bootloader,因?yàn)檫@部分代碼在STM32出廠之前就已經(jīng)做好并且燒錄進(jìn)去了,而且不占用用戶代碼的Flash,另外,在PC端我們也不需要專門定制一個(gè)上位機(jī),因?yàn)楣俜骄陀袑iT的升級(jí)Tool以及USB驅(qū)動(dòng)。缺點(diǎn)是要改變boot引腳的電平,才能啟動(dòng)Bootloader,這樣的話在應(yīng)用場(chǎng)景上就有比較大的限制了。

F4系列就可以通過下面的方式來(lái)進(jìn)入DFU模式

下面是F103系列的話,上面操作就不行了,必須通過bootloader的方式的進(jìn)入dfu模式

今天我們看先USB如何燒錄,F(xiàn)103也可以的,通過cubemx方式來(lái)生成工程

首先打開STM32CubeMX,建立一個(gè)工程,選擇MCU型號(hào)為STM32F103C8。

如下圖對(duì)USB外設(shè)進(jìn)行設(shè)置。

MiddleWare設(shè)置:

Mode選為 Download Fireware Update Class(DFU)。USBD_DFU_APP_DEFAULT_ADD設(shè)置為0x08005800,這個(gè)地址即為升級(jí)時(shí)存入升級(jí)程序的起始地址,用FLASH中0x08000000~0x08005800 的0x5800/1024=22KB存儲(chǔ)空間存儲(chǔ)DFU程序。USB_DFU_MEDIA Interface設(shè)置為:@Internal Flash /0x08000000/22*001Ka,42*001Kg,其中22*001Ka表示flash的前22KB存儲(chǔ)空間為只讀(a)的,42*001Kg表示flash后42KB的存儲(chǔ)空間可寫(g),用于存儲(chǔ)升級(jí)下載的程序。這個(gè)需要按照MCU的flash的Flash module organization修改的,stm32f103c8為中等容量系列mcu,flash為64KB,下圖為中等容量MCU的flash存儲(chǔ)分布,根據(jù)這個(gè)圖可知stm32f103c8的64KB分為64頁(yè),每頁(yè)1KB,所以可以按照這個(gè)按需設(shè)置@Internal Flash的值,注意與USBD_DFU_APP_DEFAULT_ADD對(duì)應(yīng)。

為了能使STM32F103C8進(jìn)入DFU模式,選擇一個(gè)按鍵作為進(jìn)入DFU模式的開關(guān),此處我選擇PA5(COL5)和PA15(ROW3)這連個(gè)IO進(jìn)行設(shè)置,然后通過程序使得當(dāng)按下某個(gè)鍵,再插上USB后進(jìn)入DFU模式。

然后我們生成代碼,修改usbd_dfu_if.c文件:

//Flash初始化,即解鎖FLash
uint16_t MEM_If_Init_FS(void)
{
  /* USER CODE BEGIN 0 */
    HAL_FLASH_Unlock();
  return (USBD_OK);
  /* USER CODE END 0 */
}
//Flash去初始化,即鎖FLash
uint16_t MEM_If_DeInit_FS(void)
{
  /* USER CODE BEGIN 1 */
    HAL_FLASH_Lock();
  return (USBD_OK);
  /* USER CODE END 1 */
}
 
//擦除一個(gè)page
uint16_t MEM_If_Erase_FS(uint32_t Add)
{
  /* USER CODE BEGIN 2 */
    uint32_t PageError;
    /* Variable contains Flash operation status */
    HAL_StatusTypeDef status;
    FLASH_EraseInitTypeDef eraseinitstruct;
 
    eraseinitstruct.TypeErase = FLASH_TYPEERASE_PAGES;
    eraseinitstruct.PageAddress = Add;
    eraseinitstruct.NbPages = 1U;
    status = HAL_FLASHEx_Erase(&eraseinitstruct, &PageError);
 
    if (status != HAL_OK)
    {
    return (USBD_FAIL);
    }
    return (USBD_OK);
  /* USER CODE END 2 */
}
 
//flash寫入數(shù)據(jù)
uint16_t MEM_If_Write_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{
  /* USER CODE BEGIN 3 */
    uint32_t i = 0;
 
    for (i = 0; i < Len; i += 4)
    {
        /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
        * be done by byte */
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t) (dest + i),
                *(uint32_t *) (src + i)) == HAL_OK)
        {
            /* Check the written value */
            if (*(uint32_t *) (src + i) != *(uint32_t *) (dest + i))
            {
                /* Flash content doesn't match SRAM content */
                return (USBD_FAIL);
            }
        }
        else
        {
            /* Error occurred while writing data in Flash memory */
            return (USBD_FAIL);
        }
    }
    return (USBD_OK);
  /* USER CODE END 3 */
}
//從Flash讀取數(shù)據(jù)
uint8_t *MEM_If_Read_FS(uint8_t *src, uint8_t *dest, uint32_t Len)
{
  /* Return a valid address to avoid HardFault */
  /* USER CODE BEGIN 4 */
    uint32_t i = 0;
    uint8_t *psrc = src;
    for (i = 0; i < Len; i++)
    {
        dest[i] = *psrc++;
    }
    /* Return a valid address to avoid HardFault */
    return (uint8_t *) (dest);
  /* USER CODE END 4 */
}
//獲取FLash狀態(tài)
uint16_t MEM_If_GetStatus_FS(uint32_t Add, uint8_t Cmd, uint8_t *buffer)
{
  /* USER CODE BEGIN 5 */
    switch (Cmd)
    {
    case DFU_MEDIA_PROGRAM:
        buffer[1] = (uint8_t) FLASH_PROGRAM_TIME;
        buffer[2] = (uint8_t) (FLASH_PROGRAM_TIME << 8);
        buffer[3] = 0;
        break;
    case DFU_MEDIA_ERASE:
    default:
        buffer[1] = (uint8_t) FLASH_ERASE_TIME;
        buffer[2] = (uint8_t) (FLASH_ERASE_TIME << 8);
        buffer[3] = 0;
        break;
    }
    return (USBD_OK);
  /* USER CODE END 5 */
}

修改main.c

int main(void)
{
 
    pFunction JumpToApplication;
    uint32_t JumpAddress;
   
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
   
  //BOOTKEY_OUTPUT_PIN_Pin輸出高
   HAL_GPIO_WritePin(BOOTKEY_OUTPUT_PIN_GPIO_Port, BOOTKEY_OUTPUT_PIN_Pin, GPIO_PIN_SET);
   HAL_Delay(200);
   //如果Enter按鍵被按下,BOOTKEY_INPUT_PIN_Pin讀到值為GPIO_PIN_SET,則跳過下面if代碼段,MCU進(jìn)入DFU模式,
   //否則讀到值為GPIO_PIN_RESET,則執(zhí)行if代碼段,跳轉(zhuǎn)到0x08005800處執(zhí)行應(yīng)用程序代碼。
   if (HAL_GPIO_ReadPin(BOOTKEY_INPUT_PIN_GPIO_Port, BOOTKEY_INPUT_PIN_Pin) == GPIO_PIN_RESET)
    {
    /* Test if user code is programmed starting from address 0x08007000 */
        if (((*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD) & 0x2FFFB000) == 0x20000000)
        {
          /* Jump to user application */
          JumpAddress = *(__IO uint32_t *) (USBD_DFU_APP_DEFAULT_ADD + 4);
          JumpToApplication = (pFunction) JumpAddress;
 
          /* Initialize user application's Stack Pointer */
          __set_MSP(*(__IO uint32_t *) USBD_DFU_APP_DEFAULT_ADD);
          __disable_irq(); //此處官方代碼未放置關(guān)閉中斷,在跳轉(zhuǎn)app的時(shí)候會(huì)出問題?。。。。。?          JumpToApplication();
        }
    }
  MX_USB_DEVICE_Init();
  while (1)
  {
  }
}

燒錄程序,然后按住某個(gè)按鍵,USB查到電腦上,安裝驅(qū)動(dòng),后設(shè)備管理器會(huì)出現(xiàn)一個(gè)dfu設(shè)備,然后通過dfu-util或者stm32cubeprogramer就能通過usb升級(jí)程序了。

連接成功

注意APP的程序地址需要改動(dòng)一下

這幾天的問題簡(jiǎn)單總結(jié)一下

安裝使用了 STM32CubeProgrammer 之后,再使用DfuSeDemo ,發(fā)現(xiàn)DfuSeDemo 不能識(shí)別出設(shè)備( STM Device in DFU Mode ) 。

打開我的電腦-> 設(shè)備管理器,發(fā)現(xiàn)在通用串行總線設(shè)備下面出現(xiàn): STM32 Download Firmware Update 這個(gè)設(shè)備。

右鍵點(diǎn)擊 STM32 Download Firmware Update , 選擇卸載設(shè)備,并刪除設(shè)備驅(qū)動(dòng)程序。

將usb線拔出設(shè)備,然后再插入設(shè)備,DfuSeDemo 重新能識(shí)別出設(shè)備。

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場(chǎng)。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關(guān)注 210
成為作者 賺取收益
全部留言
0/200
  • dy-3rTDlD7J 2024-02-05 11:13
    你好哥 太陽(yáng)能智能充電管理系統(tǒng)那個(gè)具體的原理圖有點(diǎn)模糊 想要一張清晰的可以嗎哥
    回復(fù)