加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入

嵌入式工具庫(kù)-脫機(jī)離線下載器(STM32F103C8T6)

03/20 16:33
5348
服務(wù)支持:
技術(shù)交流群

完成交易后在“購(gòu)買成功”頁(yè)面掃碼入群,即可與技術(shù)大咖們分享疑惑和經(jīng)驗(yàn)、收獲成長(zhǎng)和認(rèn)同、領(lǐng)取優(yōu)惠和紅包等。

虛擬商品不可退

當(dāng)前內(nèi)容為數(shù)字版權(quán)作品,購(gòu)買后不支持退換且無(wú)法轉(zhuǎn)移使用。

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論
放大
原理圖
電路板圖(3)
相關(guān)方案
  • 方案介紹
    • 前言
    • 原理圖:
    • 脫機(jī)下載器資料獲取
    • PCB
    • 3D效果
    • 實(shí)物圖
    • 主要代碼展示
    • 演示視頻
    • 若需要幫助,請(qǐng)咨詢博主
  • 相關(guān)文件
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

前言

在Gitee上發(fā)現(xiàn)了一個(gè)脫機(jī)下載器項(xiàng)目,我決定實(shí)踐復(fù)刻它。首先,我閱讀了項(xiàng)目的代碼,了解其實(shí)現(xiàn)原理和功能。接著,我自己進(jìn)行一個(gè)電路圖的繪畫(huà),并通過(guò)STM32系列的芯片進(jìn)行了配置和連接。然后,按照原理圖對(duì)代碼進(jìn)行了適當(dāng)?shù)男薷暮驼{(diào)整,以適配我的硬件環(huán)境。最后,我進(jìn)行了編譯、燒錄和調(diào)試的工作,測(cè)試了脫機(jī)下載器的功能,確保其正常工作。

最后進(jìn)行了整機(jī)的調(diào)試,完成了這個(gè)復(fù)刻,后續(xù)將添加在線下載功能 ~~~~~

原理圖:

主要運(yùn)用到的元器件

STM32F103C8T6,W25Q128,無(wú)源晶振(8M),3.3穩(wěn)壓模塊,RGB燈(0805)

使用立創(chuàng)經(jīng)行的換圖與連線,咱就圖個(gè)免費(fèi) ~~

完成功能

1.離線下載

2.設(shè)置下載地址

3.添加提示音以及狀態(tài)燈

脫機(jī)下載器資料獲取

關(guān)注微信公眾號(hào) -- 星之援工作室 發(fā)送關(guān)鍵字(脫機(jī)下載器

????

歡迎關(guān)注微信公眾號(hào)星之援工作室,公眾號(hào)不定時(shí)開(kāi)源設(shè)計(jì)項(xiàng)目

支持單片機(jī),Android系統(tǒng)設(shè)計(jì)成品定制,項(xiàng)目代做

請(qǐng)聯(lián)系微信:13648103287

PCB

繪制了兩板圖,一版是直接焊屏幕,一版就是直接買屏幕,個(gè)人偏向買屏幕,畢竟少焊點(diǎn)東西啦,節(jié)約時(shí)間以及提高容錯(cuò)率

3D效果

正面

反面

實(shí)物圖

主要代碼展示

main.c

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2022 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
#include "key.h"
#include "led.h"
#include "oled.h"
#include "ff.h"
#include "flash_blob.h"
#include "offline.h"
#include "hex2bin.h"
#include "stmflash.h"

FRESULT Res;
FIL fnew;				  /* file objects */
FATFS fs;				  /* FatFs文件系統(tǒng)對(duì)象 */
DIR DirInfo;			  /* 目錄信息 */
FILINFO FileInfo;		  /* 文件信息 */
int8_t name_cnt = 0;	  /* 文件個(gè)數(shù) */
BYTE work[FF_MAX_SS];	  /* FatFs文件工作區(qū)域 */
char Name_Buffer[20][20]; /* 文件名 */
int8_t Select_file = 0;	  /* 選中下載文件 */
uint32_t flash_addr = 0x8000000;
uint8_t mode = 0;

int main(void)
{
	uint8_t RES_FS = 0;
	uint8_t addr[4];
	HAL_Init();
	SystemClock_Config();
	OLED_Init();
	MX_USB_DEVICE_Init();
	MX_KEY_Init();
	MX_LED_Init();

	// 賦值falsh
	//  STMFLASH_Read(FLASH_SAVE_ADDR, (uint16_t *)addr, 4);
	//  flash_addr = ((addr[0] << 8 | addr[1]) << 8 | addr[2]) << 8 | addr[3];

	// FATFS文件系統(tǒng)掛載
	algo_init();				  // 下載算法初始化
	RES_FS = f_mount(&fs, "", 1); // 掛載文件系統(tǒng)
	if (RES_FS == FR_OK)
		;
	else if (RES_FS == FR_NO_FILESYSTEM) // 如果是新芯片還沒(méi)有文件系統(tǒng)
	{
		OLED_ShowString(0, 2, "Fatfs Format..", 12);
		f_mkfs("", 0, work, sizeof(work));
		OLED_ShowString(0, 2, "Format Finished", 12);
	}
	else
		OLED_ShowString(0, 2, "Fatfs Failed..", 12);

	// f_unlink("write.bin");
	//  讀取文件名到文件列表
	if (f_opendir(&DirInfo, (const TCHAR *)"0:") == FR_OK) // 讀取根目錄下文件信息
	{
		f_readdir(&DirInfo, &FileInfo);
		while (f_readdir(&DirInfo, &FileInfo) == FR_OK) // 讀文件信息到文件狀態(tài)結(jié)構(gòu)體中
		{
			if (!FileInfo.fname[0])
				break;
			strcpy(Name_Buffer[name_cnt], FileInfo.fname);
			if (strstr(Name_Buffer[name_cnt], ".BIN"))
			{
				name_cnt++;
				if (name_cnt >= 20) // 最多保存20個(gè)文件名
					break;
			}
			if (strstr(Name_Buffer[name_cnt], ".HEX"))
			{
				name_cnt++;
				if (name_cnt >= 20) // 最多保存20個(gè)文件名
					break;
			}
		}
	}
	while (1)
	{
		menu();
	}
	/* USER CODE END 3 */
}

void menu(void)
{
	static uint8_t mode_status = 0;
	switch (mode)
	{
	case 0: // 功能選擇
		select_function();
		break;
	case 1: // 離線下載模式
		Downloader();
		break;
	case 2: // flash下載地址
		FlashAddr_Set();
		break;
	}
	if (mode != mode_status)
	{
		mode_status = mode;
		OLED_Clear();
	}
}

void OLED_ShowMenu(uint8_t num)
{
	switch (num)
	{
	case 0: // 離線下載
		OLED_ShowCH(24, 0, 0);
		OLED_ShowCH(36, 0, 1);
		OLED_ShowCH(48, 0, 2);
		OLED_ShowCH(60, 0, 3);
		// 地址設(shè)置
		OLED_ShowCH(24, 2, 4);
		OLED_ShowCH(36, 2, 5);
		OLED_ShowCH(48, 2, 6);
		OLED_ShowCH(60, 2, 7);
		break;

	case 1: // 文件選擇
		OLED_ShowCH(0, 0, 8);
		OLED_ShowCH(12, 0, 9);
		OLED_ShowCH(24, 0, 10);
		OLED_ShowCH(36, 0, 11);
		break;

	case 2: // 地址
		OLED_ShowString(0, 0, "FLASH", 12);
		OLED_ShowCH(40, 0, 12);
		OLED_ShowCH(52, 0, 13);
		OLED_ShowCH(64, 0, 4);
		OLED_ShowCH(76, 0, 5);
		break;
	}
}

void select_function(void)
{
	static uint8_t t = 1;
	uint8_t key;
	key = KEY_Scan();
	if (key == KEY0_PRES)
	{
		t++;
		if (t > 2)
			t = 1;
	}
	else if (key == KEY1_PRES) // 返回主頁(yè)面
	{
		mode = 0;
		t = 1;
	}
	else if (key == KEY2_PRES) // 確認(rèn)
	{
		mode = t;
		t = 1;
	}
	switch (t)
	{
	case 1:
		OLED_ShowString(0, 2, "  ", 12);
		OLED_ShowString(0, 0, "->", 12);
		break;

	case 2:
		OLED_ShowString(0, 0, "  ", 12);
		OLED_ShowString(0, 2, "->", 12);
		break;
	}
	OLED_ShowMenu(0);
}

void Downloader(void)
{
	uint8_t key = 0;
	key = KEY_Scan();
	if (key == KEY0_PRES)
	{
		Select_file++;
		OLED_ShowString(0, 2, "                ", 12);
	}
	else if (key == KEY1_PRES) // 返回主頁(yè)面
		mode = 0;
	else if (key == KEY2_PRES)
		Auto_Fash();
	if (name_cnt == 0)
		Select_file = 0;
	else
	{
		if (Select_file >= name_cnt)
			Select_file = 0;
		else if (Select_file < 0)
			Select_file = name_cnt - 1;
	}
	OLED_ShowMenu(1);
	OLED_ShowString(0, 2, (uint8_t *)Name_Buffer[Select_file], 12);
	if (name_cnt == 0)
		OLED_ShowNum(90, 0, Select_file, 2, 12);
	else
		OLED_ShowNum(90, 0, Select_file + 1, 2, 12);
	OLED_ShowString(102, 0, "/", 12);
	OLED_ShowNum(114, 0, name_cnt, 2, 12);
}

void FlashAddr_Set(void)
{
	static uint8_t k = 0, k1 = 0;
	static uint8_t setmode = 0;
	static uint8_t ad[4];
	static uint8_t addr[8];
	uint8_t key = 0, i;
	addr[7] = (flash_addr / 0x01) % 16;
	addr[6] = (flash_addr / 0x10) % 16;
	addr[5] = (flash_addr / 0x100) % 16;
	addr[4] = (flash_addr / 0x1000) % 16;
	addr[3] = (flash_addr / 0x10000) % 16;
	addr[2] = (flash_addr / 0x100000) % 16;
	addr[1] = (flash_addr / 0x1000000) % 16;
	addr[0] = (flash_addr / 0x10000000) % 16;
	OLED_ShowMenu(2);
	OLED_ShowString(0, 2, "0x", 12);

	while (1)
	{
		for (i = 0; i < 8; i++)
		{
			if (addr[i] < 10)
				OLED_ShowChar(18 + 6 * i, 2, addr[i] + 48, 12);
			else
				OLED_ShowChar(18 + 6 * i, 2, addr[i] + 65 - 10, 12);
		}

		key = KEY_Scan();
		if (key == KEY0_PRES)
		{
			if (setmode == 0)
			{
				OLED_ShowString(18 + 6 * k, 3, "|", 12);
				setmode = 1;
			}
			else if (setmode == 1)
			{
				addr[k]++;
				if (addr[k] > 15)
					addr[k] = 0;
			}
		}
		else if (key == KEY1_PRES)
		{
			if (setmode == 0)
			{
				mode = 0;
				break;
			}
			else if (setmode == 1)
			{
				k++;
				if (k >= 8)
					k = 0;
			}
		}
		else if (key == KEY2_PRES)
		{
			if (setmode == 0)
			{
				// flash_addr = 0;

				ad[0] = addr[0] << 4 | addr[1];
				ad[1] = addr[2] << 4 | addr[3];
				ad[2] = addr[4] << 4 | addr[5];
				ad[3] = addr[6] << 4 | addr[7];

				flash_addr = ((ad[0] << 8 | ad[1]) << 8 | ad[2]) << 8 | ad[3];
				STMFLASH_Write(FLASH_SAVE_ADDR, (uint16_t *)ad, 4);
				HAL_Delay(1000);
				mode = 0;
				k = 0;
				break;
			}
			else if (setmode == 1)
			{
				setmode = 0;
				OLED_ShowString(18 + 6 * k1, 3, " ", 12);
			}
		}

		if (k1 != k)
		{
			OLED_ShowString(18 + 6 * k1, 3, " ", 12);
			OLED_ShowString(18 + 6 * k, 3, "|", 12);
			k1 = k;
		}
	}
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
	RCC_OscInitTypeDef RCC_OscInitStruct = {0};
	RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
	RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

	/** Initializes the RCC Oscillators according to the specified parameters
	 * in the RCC_OscInitTypeDef structure.
	 */
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState = RCC_HSE_ON;
	RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
	RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	{
		Error_Handler();
	}
	/** Initializes the CPU, AHB and APB buses clocks
	 */
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
	{
		Error_Handler();
	}
	PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
	PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
	if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
	{
		Error_Handler();
	}
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
	/* USER CODE BEGIN Error_Handler_Debug */
	/* User can add his own implementation to report the HAL error return state */
	__disable_irq();
	while (1)
	{
	}
	/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
	/* USER CODE BEGIN 6 */
	/* User can add his own implementation to report the file name and line number,
	   ex: printf("Wrong parameters value: file %s on line %drn", file, line) */
	/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

演示視頻

USB文件(自己使用自己的HEX文件即可)

百度網(wǎng)盤

鏈接:https://pan.baidu.com/s/1sz5dzR5yzwIxZ_9EqGQ5Yw?pwd=xzy0
提取碼:xzy0?

若需要幫助,請(qǐng)咨詢博主


????END????


聯(lián)系方式 微信號(hào):13648103287

  • 聯(lián)系方式.docx

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
FTLF8519P3BNL 1 Finisar Corporation Transceiver, 840nm Min, 860nm Max, 2125Mbps(Tx), 2125Mbps(Rx), LC Connector, Panel Mount, ROHS COMPLIANT PACKAGE

ECAD模型

下載ECAD模型
$39.4 查看
HFBR-2524 1 Agilent Technologies Inc Receiver, 5Mbps, DIP, Through Hole Mount
$14.66 查看
CSTCV16M0X51Q-R0 1 Murata Manufacturing Co Ltd Ceramic Resonator, 16MHz Nom, CERAMIC PACKAGE-3
$0.62 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

方案定制,程序設(shè)計(jì)方案、單片機(jī)程序設(shè)計(jì)與講解、APP定制開(kāi)發(fā)。本公眾號(hào)致力于向讀者傳遞關(guān)于程序設(shè)計(jì)和開(kāi)發(fā)的相關(guān)知識(shí),并分享一些關(guān)于軟件開(kāi)發(fā)的最佳實(shí)踐。如果您有什么問(wèn)題或建議,請(qǐng)隨時(shí)聯(lián)系我們。我們將竭誠(chéng)為您服務(wù)