最近想要写个更新航模接收机固件的小项目,移植opentx项目的部分代码到我的最小系统板上。不经意间发现vscode上也可以开发stm32了,于是,一个填坑行动开始了!!!
先写怎么才能编译调试吧!
环境:
windows10x64,8G内存,i5 4200
stlink v2
1.你要有个vscode,不用我说了。
安装完毕,点击重新加载。之后会提示正在安装PlatformIO 核心。
再次重新加载
3.安装完毕后,在vscode的左下角会有一个家的图标,可以从这里新件工程。第一次启动也会自动打开PIO Home页面。
4.新建工程。因为它是以开发板为选择,不是芯片,只能选择BluePill F103C8,这个关系不大,只是运行内存和Flash大小不同。记得选一个空目录。
5.打开工程,新建的工程会在PIO Home的下发列出。点击打开,如果打不开,关闭编辑器重新打开一次,或者直接用vscode打开那个目录。
6开打工程后,目录树中无源码,需要自己添加,按一下Ctrl+Alt+B,platformio自动下载编译组件。然后提示无文件可以编译。
我们添加一个main.c,然后再编译。
然后插上stlink,接上单片机,按CTRL+ALT+U,烧到单片机上(首次上传会安装stlink)。
-----------------------------------------------------------------分割线--------------------------------------------------------------------------
你以为就完了吗,那我写这个文章干嘛!
看起来编译完成,上传也通过了,然而,你的单片机并没有让c13口的灯闪亮,串口也并没有发送字母c!由于以前都是使用keil开发,对启动项目和内存定义并不清楚,加之platformio使用了arm-none-eabi-gcc编译,隐藏了太多的细节。经过一个礼拜的刻苦钻研,最终找到了解决方法。方法如下:
在你的电脑上找到这个文件,C:\Users\<你的用户名>\.platformio\packages\framework-stm32cube\platformio\ldscripts\STM32F103C8_DEFAULT.ld,打开。
把红框里的内容改为 _estack = 0x20005000; 加一个0,就这一个0,天大的坑的存在,对于熟悉使用gcc编译的人,可能并不很难,但对于我等新手,这个问题实在太难找!!!之后,把这个文件另存为STM32F103C8_flash.ld,不另存也可以,但我喜欢完美,Platformio的源码是先寻找_FLASH.ld再寻找DEFAULT.ld的。
好了,再编译,上传(CTRL+ALT+B,CTRL+ALT+U)。享受使用vscode编写stm32的乐趣吧!
main.c
#include
#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
#define LED_PIN GPIO_PIN_13
#define LED_GPIO_PORT GPIOC
#define LED_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
void SysTick_Handler(void)
{
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
}
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef clkinitstruct = { 0 };
RCC_OscInitTypeDef oscinitstruct = { 0 };
/* Configure PLL ------------------------------------------------------*/
/* PLL configuration: PLLCLK = (HSI / 2) * PLLMUL = (8 / 2) * 16 = 64 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLLCLK / HSEPredivValue = 64 / 1 = 64 MHz */
/* Enable HSI and activate PLL with HSi_DIV2 as source */
oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
oscinitstruct.HSEState = RCC_HSE_OFF;
oscinitstruct.LSEState = RCC_LSE_OFF;
oscinitstruct.HSIState = RCC_HSI_ON;
oscinitstruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
oscinitstruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
oscinitstruct.PLL.PLLState = RCC_PLL_ON;
oscinitstruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
oscinitstruct.PLL.PLLMUL = RCC_PLL_MUL16;
if (HAL_RCC_OscConfig(&oscinitstruct) != HAL_OK)
{
/* Initialization Error */
while (1)
;
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2) != HAL_OK)
{
/* Initialization Error */
while (1)
;
}
}
GPIO_InitTypeDef GPIO_InitStruct;
UART_HandleTypeDef com1;
int main(void)
{
HAL_Init();
SystemClock_Config();
__GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
com1.Instance = USART1;
com1.Init.BaudRate = 9600;
com1.Init.WordLength = UART_WORDLENGTH_8B;
com1.Init.StopBits = UART_STOPBITS_1;
com1.Init.Parity = UART_PARITY_NONE;
com1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
com1.Init.Mode = UART_MODE_TX_RX;
if (HAL_UART_Init(&com1) != HAL_OK)
{
for (;;)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(200);
}
}
for (;;)
{
uint8_t ch = 'c';
HAL_UART_Transmit(&com1, (uint8_t *)&ch, 1, 0xFFFF);
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(1000);
}
}
#define USARTx_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE();
#define USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define USARTx_FORCE_RESET() __HAL_RCC_USART1_FORCE_RESET()
#define USARTx_RELEASE_RESET() __HAL_RCC_USART1_RELEASE_RESET()
/* Definition for USARTx Pins */
#define USARTx_TX_PIN GPIO_PIN_9
#define USARTx_TX_GPIO_PORT GPIOA
#define USARTx_RX_PIN GPIO_PIN_10
#define USARTx_RX_GPIO_PORT GPIOA
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USARTx_TX_GPIO_CLK_ENABLE();
USARTx_RX_GPIO_CLK_ENABLE();
/* Enable USARTx clock */
USARTx_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
/* UART RX GPIO pin configuration */
GPIO_InitStruct.Pin = USARTx_RX_PIN;
HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
}
/**
* @brief UART MSP De-Initialization
* This function frees the hardware resources used in this example:
* - Disable the Peripheral's clock
* - Revert GPIO and NVIC configuration to their default state
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
{
/*##-1- Reset peripherals ##################################################*/
USARTx_FORCE_RESET();
USARTx_RELEASE_RESET();
/*##-2- Disable peripherals and GPIO Clocks #################################*/
/* Configure UART Tx as alternate function */
HAL_GPIO_DeInit(USARTx_TX_GPIO_PORT, USARTx_TX_PIN);
/* Configure UART Rx as alternate function */
HAL_GPIO_DeInit(USARTx_RX_GPIO_PORT, USARTx_RX_PIN);
}