91视频免费?看_蜜芽MY188精品TV在线观看_国产免费无遮挡在线观看视频_深夜国产_亚洲精品欧洲精品_欧美黑人粗暴多交

stm32單片機的USB燒錄程序

先開門見上DFU是啥

DFU全稱為Download Firmware Update,是ST官方推出的一個通過USB接口進行IAP升級的方案,同串口ISP一樣,他們都集成在了芯片內部的Bootloader區段,可以通過配置boot引腳來啟動。

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

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

使用DFU的優缺點?使用DFU的好處是不用自己制作Bootloader,因為這部分代碼在STM32出廠之前就已經做好并且燒錄進去了,而且不占用用戶代碼的Flash,另外,在PC端我們也不需要專門定制一個上位機,因為官方就有專門的升級Tool以及USB驅動。缺點是要改變boot引腳的電平,才能啟動Bootloader,這樣的話在應用場景上就有比較大的限制了。

F4系列就可以通過下面的方式來進入DFU模式

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

今天我們看先USB如何燒錄,F103也可以的,通過cubemx方式來生成工程

首先打開STM32CubeMX,建立一個工程,選擇MCU型號為STM32F103C8。

如下圖對USB外設進行設置。

MiddleWare設置:

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

為了能使STM32F103C8進入DFU模式,選擇一個按鍵作為進入DFU模式的開關,此處我選擇PA5(COL5)和PA15(ROW3)這連個IO進行設置,然后通過程序使得當按下某個鍵,再插上USB后進入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 */
}
 
//擦除一個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寫入數據
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讀取數據
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狀態
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進入DFU模式,
   //否則讀到值為GPIO_PIN_RESET,則執行if代碼段,跳轉到0x08005800處執行應用程序代碼。
   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(); //此處官方代碼未放置關閉中斷,在跳轉app的時候會出問題!!!!!!
          JumpToApplication();
        }
    }
  MX_USB_DEVICE_Init();
  while (1)
  {
  }
}

燒錄程序,然后按住某個按鍵,USB查到電腦上,安裝驅動,后設備管理器會出現一個dfu設備,然后通過dfu-util或者stm32cubeprogramer就能通過usb升級程序了。

連接成功

注意APP的程序地址需要改動一下

這幾天的問題簡單總結一下

安裝使用了 STM32CubeProgrammer 之后,再使用DfuSeDemo ,發現DfuSeDemo 不能識別出設備( STM Device in DFU Mode ) 。

打開我的電腦-> 設備管理器,發現在通用串行總線設備下面出現: STM32 Download Firmware Update 這個設備。

右鍵點擊 STM32 Download Firmware Update , 選擇卸載設備,并刪除設備驅動程序。

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

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 212
成為作者 賺取收益
全部留言
0/200
  • dy-3rTDlD7J 2024-02-05 11:13
    你好哥 太陽能智能充電管理系統那個具體的原理圖有點模糊 想要一張清晰的可以嗎哥
    回復
主站蜘蛛池模板: 龙门县| 会宁县| 平昌县| 昆明市| 留坝县| 崇信县| 榆社县| 裕民县| 雅安市| 宜城市| 出国| 陆河县| 东台市| 临江市| 福建省| 色达县| 得荣县| 霍城县| 满城县| 武乡县| 上蔡县| 菏泽市| 钟祥市| 万年县| 修水县| 黄浦区| 安徽省| 三门县| 谢通门县| 泉州市| 和龙市| 平武县| 定远县| 马山县| 安达市| 吴忠市| 鲁甸县| 平原县| 遵化市| 天峻县| 盈江县|