Three ways for Keil to develop STM32 MCU projects

    Compared with the 51 single-chip microcomputer, the internal structure of the STM32 single-chip microcomputer is much more complicated, so it is relatively complicated to encode the underlying registers directly. This requires us to understand the chip manual. For complex projects, these operations may need to be written repeatedly, so there is a standard library. The operation is encapsulated and the operation is relatively simple. As the complexity of the project increases, a library HAL with more powerful packaging appears. This requires the help of the STM32CubeMx tool to generate code.

    In simple terms, there are three ways of STM32 encoding:

    1. Register encoding.

    2. Standard library operation code.

    3. HAL library operation code.

    These three methods have their own advantages and disadvantages. The register coding is more biased towards the bottom layer, which is convenient for us to be familiar with the internal structure of the microcontroller. The development efficiency is relatively low, because many initialization and assignment operations need to be written repeatedly. Using the HAL library can reduce a lot of code and improve development. Efficiency, but it is not easy to understand the underlying logic, you need to be very proficient in the working logic of the STM32 microcontroller before you can get started.

    In the first register encoding method, the construction project can directly create a new ordinary project, as shown below:

 

    After the project is created, there is nothing, we need to manually add a startup file and a main.c file to the project directory:

 

    In the keil tool, we add these two files to Source Group 1 by adding existing items, as follows:

     At this time, the compilation will report an error:

    It is said that the SystemInit symbol is undefined. In fact, the SystemInit() method is missing in the project code (main.c) we built, so just add it.

    There are only two files in this project, one is the startup file and the other is the main program main.c. The code for our operation register is written in main.c, here is a simple sample code to realize the flashing of the LED light:

#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB2PERIPH_BASE (PERIPH_BASE+ 0x10000)
#define GPIOA_BASE (APB2PERIPH_BASE+0x0800)
#define GPIOB_BASE (APB2PERIPH_BASE+0x0C00)
#define GPIOC_BASE (APB2PERIPH_BASE+0x1000)
#define GPIOD_BASE (APB2PERIPH_BASE+0x1400)
#define GPIOE_BASE (APB2PERIPH_BASE+0x1800)
#define GPIOF_BASE (APB2PERIPH_BASE+0x1C00)
#define GPIOG_BASE (APB2PERIPH_BASE+0x2000)

#define GPIOA_ODR_Addr (GPIOA_BASE+12)
#define GPIOB_ODR_Addr (GPIOB_BASE+12)
#define GPIOC_ODR_Addr (GPIOC_BASE+12)
#define GPIOD_ODR_Addr (GPIOD_BASE+12)
#define GPIOE_ODR_Addr (GPIOE_BASE+12)
#define GPIOF_ODR_Addr (GPIOF_BASE+12)
#define GPIOG_ODR_Addr (GPIOG_BASE+12)

#define BITBAND(addr,bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr&0xFFFFF)<<5) + (bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define LED0 MEM_ADDR(BITBAND(GPIOA_ODR_Addr, 5))


typedef struct
{
  volatile unsigned int CR;
	volatile unsigned int CFGR;
	volatile unsigned int CIR;
	volatile unsigned int APB2RSTR;
	volatile unsigned int APB1RSTR;
	volatile unsigned int AHBENR;
	volatile unsigned int APB2ENR;
	volatile unsigned int APB1ENR;
	volatile unsigned int BDCR;
	volatile unsigned int CSR;
}RCC_TypeDef;

#define RCC ((RCC_TypeDef*)0x40021000)

typedef struct
{
	volatile unsigned int CRL;
	volatile unsigned int CRH;
	volatile unsigned int IDR;
	volatile unsigned int ODR;
	volatile unsigned int BSRR;
	volatile unsigned int BRR;
	volatile unsigned int LCKR;
}GPIO_TypeDef;

#define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)

void LEDInit(void)
{
	RCC->APB2ENR|=1<<2;
	GPIOA->CRL &= 0xFF0FFFFF;
	GPIOA->CRL |= 0x00300000;
}

void Delay_ms(volatile unsigned int t)
{
  unsigned int i,j;
	for(j=0;j<t;j++)
	  for(i=0;i<800;i++);
}

void SystemInit(void)
{

}

int main(void)
{
	LEDInit();
	while(1)
	{
	  LED0 = 0;
		Delay_ms(500);
		LED0 = 1;
		Delay_ms(500);
	}
}


    If the project is built successfully, it can be simulated without reporting an error, or downloaded to the microcontroller for debugging.

    The second way is to build the STM32 standard library project directly in the Keil tool, without additionally copying the standard library file to the project folder, and then add the existing item to the group, build the project, select the chip series, and pop up a confirmation box Here you can choose the required library:

    Check CMSIS->CORE, Device->Startup, Device->StdPeriph Drivers->Framework, GPIO, RCC here.

    The automatically generated code structure is as follows:

    Except that main.c is manually added, the rest are automatically generated by keil. If you have manually added the standard library, you will be familiar with some of the files in it, stm32f10x_gpio.c, stm32f10x_rcc.c, startup_stm32f10x_ld .s,system_stm32f10x.c.

    Compiling directly here will report an error:

    Error: L6218E: Undefined symbol assert_param (referred from misc.o).

    The problem is that the function assert_param cannot be found, and this function is in stm32f10x_conf.h. From the above project structure, we can see that there is a header file of stm32f10x_conf.h in the code. The solution is to use the macro definition USE_STDPERIPH_DRIVER to find:

    Click the magic wand tool Options for Targets, select c/c++ in the pop-up box, enter USE_STDPERIPH_DRIVER in Define, and Include Paths specify the RTE directory under the current project path.

    Finally, it can be compiled successfully.

    Here is also given a piece of code to make the LED blink.

#include "stm32f10x.h"

void Delay()
{
  unsigned int i,j;
	for(i=0;i<1000;i++)
	  for(j=0;j<1000;j++);
}

void LED_Config()
{
    GPIO_InitTypeDef GPIO_InitStructure;                 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;             
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

int main(void)
{
	LED_Config();
	while(1)
	{
	    GPIO_SetBits(GPIOA, GPIO_Pin_5);
		Delay();
		GPIO_ResetBits(GPIOA, GPIO_Pin_5);
		Delay();
	}
}

    The PA5 port is used as a level output, and the clock enable and GPIO initialization all call the methods in the standard library.

    The third method of building an STM32 project requires the help of the STM32CubeMx tool, which is free. After installation, it can be operated with a graphical interface, as shown below:

    1) After opening the tool, create a new project and come to the chip selection interface:

    Entering STM32F103 in the Commercial Part Number here will automatically complete C6A, select a chip in the right panel and double-click,

   2) Enter the configuration interface.

    Expand the System Core menu, SYS is selected by default, we click, and select Debug: Serial Wire in the middle mode.

    Then, check the RCC

    Set HSE/LSE to Crystal/Ceramic Resonator. After the change, the right chip will change.

    Next, use the PA5 port on the chip as GPIO_Output, click on PA5, and a menu option will appear, just select it directly. 

   3) Project location and compilation tool settings

    Set the project name, project location, select MDK-ARM for Toolchain/IDE, and select V5 for the version.

    4) Code generation. Click the GENERATE CODE button.

    5) The generated code can be opened directly with Keil, the structure is as follows:

 

    Even main.c has been written, and there is no problem with direct compilation. To achieve LED blinking, we only need to add the following code in the while(1) loop body:

  while (1)
  {
    /* USER CODE END WHILE */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
	HAL_Delay(200);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
	HAL_Delay(200);
    /* USER CODE BEGIN 3 */
  }

    The code generated in this way not only helps us do a lot of work, but even prepares for compilation. Let's take a look at the c/c++ options of Options for Targets:

 

   The macro definition search is set, we don’t need to manually set it, and the hex file is compiled and generated, which is also checked for us.

   Using the HAL library, there is very little code written by myself, but it takes time to understand, what does the default operation do, and what operations are implied in it.   

Guess you like

Origin blog.csdn.net/feinifi/article/details/132295892