1, What is a register
Register is a high-speed storage unit with limited storage capacity in CPU, which can be used to temporarily store instructions, data and addresses.
In short, if our computer is compared to a building, and the register is every house in the building, the register address can be regarded as the house number, but the house number is a little special, which is composed of 0.1 bit stream.
GPIO
GPIO is the abbreviation of general input and output port, that is, the controllable pin of STM32. The GPIO pin of STM32 chip is connected with external devices to realize the functions of external communication, control and data acquisition.
All GPIO pins have basic input and output functions.
Working mode:
typedef enum { GPIO_Mode_AIN = 0x0, // Analog input GPIO_Mode_IN_FLOATING = 0x04, // Floating input GPIO_Mode_IPD = 0x28, // Drop down input GPIO_Mode_IPU = 0x48, // Pull up input GPIO_Mode_Out_OD = 0x14, // Open drain output GPIO_Mode_Out_PP = 0x10, // Push pull output GPIO_Mode_AF_OD = 0x1C, // Multiplexed open drain output GPIO_Mode_AF_PP = 0x18 // Multiplexed push-pull output } GPIOMode_TypeDef;
When we turn on the LED, we need to set it to push-pull output mode.
See details: STM32 register introduction, address search, and direct operation register
2, Use the register to turn on the LED
1. Establish project template
stm32 provides a firmware library encapsulated in c language. We can directly call the corresponding library functions for what functions we want to achieve.
To use the ST firmware library, you can create a project template for us to call functions.
For detailed establishment process, please refer to: Establishment of stm32f103c8t6 engineering template
1.1 establishment of relevant documents
Create a new general folder to store all programs of the project, and then create six folders: CORE, HARDWARE, OBJ, FWLIB, SYSTEM and USER. Among them, HARDWARE folder is used to store peripheral HARDWARE code, OBJ is used to store generated debugging code, and FWLIB is various. c and. h files, as shown in the following figure:
CORE folder:
HARDWARE folder:
FWLib folder:
SYSTEM folder:
USER folder:
1.2 establishment of the project
Open Keil and create a new project in the USER folder. For the specific process, refer to:
Note that the chip model here is STM32F103C8 (selected according to its own chip);
In addition, you do not need to check Startup and CORE when selecting the running environment.
Add five custom folders in the Groups window:
Add corresponding files to each folder:
After adding, you can view it in the work bar:
1.3 configuration environment
Right click Target1 to enter Options for Target 'Target 1'
Click Target, you can see that the STM chip is STM32F103C8, and modify the crystal oscillator frequency value to 8
Click Output, where select folder for objects is the directory where the generated HEX is stored. Here, select and store it in the established OBJ folder. Create HEX File is used to generate executable code file (the HEX format file of MCU chip can be written by programmer, and the file extension is. HEX), which is used to download to the development board
of
Click the C/C + + option
a. First, set the definition to USE_STDPERIPH_DRIVER,STM32F10X_MD,
b. Then click Add Include Paths
The specific path is the path previously added to the project:
After adding, it is as follows:
So far, the establishment of the project has been basically completed.
- Configure GPIO ports
GPIO is the abbreviation of general input and output port. In short, it is the controllable pin of STM32. The GPIO pin of STM32 chip is connected with external devices to realize the functions of external communication, control and data acquisition.
There are three steps to initialize and set the GPIO port:
- Clock configuration
- Input / output mode setting
- Maximum rate setting
2.1. Configure clock enable
Why configure the clock? In order to save power, the default clock is off. Before configuring any resources of STM32, the clock must be enabled first.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //Turn on GPIOB port clock
2.2. Initialize structure
A structure is provided in the library function to configure the input / output mode setting and maximum rate setting of GPIO port.
The structure defined is as follows:
// @file stm32f10x_gpio.h typedef struct { uint16_t GPIO_Pin; /*!< Select the GPIO pin to configure */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Select the rate of the GPIO pin */ GPIOMode_TypeDef GPIO_Mode; /*!< Select the operating mode of GPIO pin */ }GPIO_InitTypeDef;
This structure contains the information required to initialize GPIO, including pin number, working mode and output rate.
The idea of designing this structure is: before initializing GPIO, first define such a structure variable, configure the GPIO mode as required, assign values to each member of this structure, and then take this variable as the input parameter of "GPIO initialization function". This function can configure registers according to the contents of this variable value, So as to realize the initialization of GPIO.
2.3. Configure input / output mode
The configuration port bit is universal push-pull output, and the speed is 2M
GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //The output mode is universal push-pull output GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ; //The selected output port is GPIO_ Pin_ four GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //The output speed is 2M GPIO_Init(GPIOA,&GPIO_InitStruct);
So far a GPIOB_Pin_4 after configuration, we can finally control an LED.
3. Main functions
3.1.led.h function
#ifndef _LED_H #define _LED_H #include "stm32f10x.h" void LED_R_TOGGLE(void); void LED_G_TOGGLE(void); void LED_Y_TOGGLE(void); void LED_Init(void); #endif
3.2.led.c function
#include "led.h" #include "delay.h" void LED_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); //Turn on the clock of the peripheral GPIOB GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //The output mode is universal push-pull output GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ; //The selected port is GPIO_ Pin_ four GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //The output speed is 2M GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //The output mode is universal push-pull output GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10 ; //The selected port is GPIO_ Pin_ one GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //The output speed is 2M GPIO_Init(GPIOB,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //The output mode is universal push-pull output GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14 ; //The selected port is GPIO_ Pin_ fourteen GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //The output speed is 2M GPIO_Init(GPIOC,&GPIO_InitStruct); } void LED_R_TOGGLE(void) { GPIO_SetBits(GPIOA, GPIO_Pin_4); delay_ms(500); GPIO_ResetBits(GPIOA,GPIO_Pin_4); } void LED_G_TOGGLE(void) { GPIO_SetBits(GPIOB, GPIO_Pin_10); delay_ms(500); GPIO_ResetBits(GPIOB,GPIO_Pin_10); } void LED_Y_TOGGLE(void) { GPIO_SetBits(GPIOC, GPIO_Pin_14); delay_ms(500); GPIO_ResetBits(GPIOC,GPIO_Pin_14); }
3.3.delay.h function
#ifndef __DELAY_H #define __DELAY_H #include "sys.h" void delay_init(void); void delay_ms(u16 nms); void delay_us(u32 nus); #endif
3.4.delay.c function
This experiment calls the delay function written by the punctual atom to realize that the three LED lights flash in turn after a delay of 1s. I won't introduce more here. If you are interested, you can try to write it yourself.
#include "delay.h" // //If you need to use OS, include the following header file #if SYSTEM_SUPPORT_OS #include "includes.h" // ucos usage #endif static u8 fac_us=0; //Delay multiplier static u16 fac_ms=0; //MS delay multiplier, in ucos, represents the number of ms per beat #if SYSTEM_SUPPORT_OS // If system_ SUPPORT_ The OS is defined, indicating that the OS is to be supported (not limited to UCOS) #ifdef OS_CRITICAL_METHOD // OS_CRITICAL_METHOD is defined to support UCOSII #define delay_osrunning OSRunning // Whether the OS is running flag, 0, not running; 1. In operation #define delay_ostickspersec OS_TICKS_PER_SEC // OS clock beat, i.e. scheduling times per second #define delay_osintnesting OSIntNesting // Break nesting level, that is, the number of times to break nesting #endif //Support UCOSIII #ifdef CPU_CFG_CRITICAL_METHOD // CPU_CFG_CRITICAL_METHOD is defined to support UCOSIII #define delay_osrunning OSRunning // Whether the OS is running flag, 0, not running; 1. In operation #define delay_ostickspersec OSCfg_TickRate_Hz // OS clock beat, i.e. scheduling times per second #define delay_osintnesting OSIntNestingCtr // Break nesting level, that is, the number of times to break nesting #endif //In case of us level delay, turn off task scheduling (to prevent interrupting us level delay) void delay_osschedlock(void) { #ifdef CPU_CFG_CRITICAL_METHOD // Use UCOSIII OS_ERR err; OSSchedLock(&err); //In ucosiiii mode, scheduling is prohibited to prevent interruption and delay #else // Otherwise, UCOSII OSSchedLock(); //In UCOSII mode, scheduling is prohibited to prevent interruption and delay #endif } //Resume task scheduling in case of us level delay void delay_osschedunlock(void) { #ifdef CPU_CFG_CRITICAL_METHOD // Use UCOSIII OS_ERR err; OSSchedUnlock(&err); //UCOSIII mode, resume scheduling #else // Otherwise, UCOSII OSSchedUnlock(); //UCOSII mode, resume scheduling #endif } //Call the delay function of the OS //ticks: delayed beats void delay_ostimedly(u32 ticks) { #ifdef CPU_CFG_CRITICAL_METHOD OS_ERR err; OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err); //Ucosiiii delay adopts periodic mode #else OSTimeDly(ticks); //UCOSII delay #endif } //systick interrupt service function, which is used when using ucos void SysTick_Handler(void) { if(delay_osrunning==1) //When the OS starts running, it performs normal scheduling processing { OSIntEnter(); //Entry interrupt OSTimeTick(); //Call ucos clock service program OSIntExit(); //Trigger task switching soft interrupt } } #endif //Initialization delay function //When using OS, this function initializes the clock beat of OS //SYSTICK's clock is fixed to 1 / 8 of HCLK's clock //SYSCLK: system clock void delay_init() { #if SYSTEM_SUPPORT_OS // If necessary, support OS u32 reload; #endif SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //Select external clock HCLK/8 fac_us=SystemCoreClock/8000000; //Is 1 / 8 of the system clock #if SYSTEM_SUPPORT_OS // If necessary, support OS reload=SystemCoreClock/8000000; //The number of counts per second is in M reload*=1000000/delay_ostickspersec; //According to delay_ostickspersec sets the overflow time //reload is a 24 bit register with a maximum value of 16777216. At 72M, it is about 1.86s fac_ms=1000/delay_ostickspersec; //Represents the minimum unit that the OS can delay SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //Enable SYSTICK interrupt SysTick->LOAD=reload; //Every 1/delay_ostickspersec is interrupted once per second SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //Turn on SYSTICK #else fac_ms=(u16)fac_us*1000; //Under non OS, it represents the number of systick clocks required for each ms #endif } #if SYSTEM_SUPPORT_OS // If necessary, support OS //Delay nus //nus is the number of us to delay void delay_us(u32 nus) { u32 ticks; u32 told,tnow,tcnt=0; u32 reload=SysTick->LOAD; //Value of LOAD ticks=nus*fac_us; //Number of beats required tcnt=0; delay_osschedlock(); //Prevent OS scheduling and interrupt us delay told=SysTick->VAL; //Counter value when entering while(1) { tnow=SysTick->VAL; if(tnow!=told) { if(tnow<told)tcnt+=told-tnow; //Note that SYSTICK is a decrement counter else tcnt+=reload-tnow+told; told=tnow; if(tcnt>=ticks)break; //If the time exceeds / equals the time to be delayed, exit } }; delay_osschedunlock(); //Resume OS scheduling } //Delay nms //nms: number of ms to delay void delay_ms(u16 nms) { if(delay_osrunning&&delay_osintnesting==0) //If the OS is already running and is not in an interrupt (task scheduling cannot be performed in an interrupt) { if(nms>=fac_ms) //The delay time is greater than the minimum time period of the OS { delay_ostimedly(nms/fac_ms); //OS delay } nms%=fac_ms; //The OS can no longer provide such a small delay, so it adopts the ordinary delay mode } delay_us((u32)(nms*1000)); //Common mode delay } #else / / when OS is not used //Delay nus //nus is the number of us to delay void delay_us(u32 nus) { u32 temp; SysTick->LOAD=nus*fac_us; //Time loading SysTick->VAL=0x00; //Clear counter SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //Start counting down do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //Waiting time arrives SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //Turn off counter SysTick->VAL =0X00; //Clear counter } //Delay nms //Note the range of nms //Systick - > load is a 24 bit register, so the maximum delay is: //nms<=0xffffff*8*1000/SYSCLK //SYSCLK is in Hz and NMS is in ms //For 72M, NMS < = 1864 void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms; //Time loading (systick - > load is 24bit) SysTick->VAL =0x00; //Clear counter SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //Start counting down do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //Waiting time arrives SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //Turn off counter SysTick->VAL =0X00; //Clear counter } #endif
3.5.main.c function
#include "stm32f10x.h" #include "delay.h" #include "led.h" int main(void) { LED_Init(); delay_init(); //Use the system tick timer and delay initialization while(1) //Cycle on { LED_R_TOGGLE(); delay_ms(500); //Delay 1s after the red light is on LED_G_TOGGLE(); delay_ms(500); //Delay 1 s after the green light is on LED_Y_TOGGLE(); delay_ms(500); //Delay 1s after the yellow light is on } }
- Create HEX File
Click the compile button in the upper left corner to debug and compile, and an error will pop up:
The reason for the search error is:
The default encoding mode of MDK5 is C89, which does not support the programming definition of string spaces in C++ / C. It needs to be supported after changing to C99 coding mode.
Solution: check C99 Mode of C/C + + in the configuration
You can also see the generated. hex file stored in the created OBJ folder
-
Build circuit
In this experiment, c8t6 is used on the bread board to control the flashing of red, green and yellow lights in turn. Therefore, it is necessary to be familiar with the use of bread board. For a brief introduction to the use of bread board, please refer to: Introduction to bread board
The built circuit diagram is as follows:
Be careful not to insert the pin incorrectly, otherwise the experiment will not succeed -
Download program with serial port
The USB to serial port driver chip for STM32 development board used in the experiment is CH340. To use the serial port, you must first install the USB to serial port driver - CH340 version in the computer. See the download link above.
If the USB to serial driver is successfully installed, there is no problem with the connection between the USB cable and the board. The serial port can be identified in computer - > Management - > Device Manager - > port.
Use the USB cable to connect the USB to serial port interface between the computer and the development board: USB TO UART to power up the development board.
Open the mcuisp software and configure it as follows:
① Search the serial port and set the baud rate to 115200 (try not to set it too high)
② Select the HEX file to download
③ Execute after verification and programming
④ DTR low level resets and RTS high level enters bootloader
⑤ Start programming. If it is always connected, press the reset key of the development board
The prompt after successful download after compilation is shown in the figure below, indicating that the HEX file has been successfully burned into the chip.
7. Experimental results
4, Summary
This experiment mainly carried out the LED register lighting experiment. Before, it had been written with library functions and had not used registers. This time, I really felt its cumbersome use, especially the GPIO address. I also needed to consult the manual, which was very poor in readability and encountered many difficulties in the programming process. However, I also learned the addressing principle of registers by consulting materials, Although cumbersome, it feels good to communicate with the computer more intuitively.
5, Reference articles
STM32F103 register mode turns on the LED water flow lamp