Popular introduction and use of STM32 and serial port (Usart) (example: serial port control small lights)

Popular introduction and use of STM32 and serial port (Usart) (example: serial port control small lights)

1. Description

The purpose of writing this article is to help such friends understand and master the configuration and use of serial ports from the perspective of friends who have no clear knowledge of serial ports or who are new to them.
The specific configuration of the three groups of serial ports is introduced above, and an example is given at the end of the article: the serial port controls a small light.

2. A brief introduction to the serial port

What is a serial port?
To put it simply, it is to implement printf(""), getchar() and other functions, that is, to realize the receiving and sending of characters or strings, so as to realize communication.
Among them, the serial port is divided into: USART (Synchronous Asynchronous Transceiver) - full-duplex data exchange and UART (Asynchronous Transceiver) - only asynchronous transmission function, this article only introduces the configuration and use of three USARTs.

3. The flow chart of the serial interrupt function (from right to left)

This diagram is used to help understand the interrupt execution flow

4. Introduction to the circuit schematic diagram of the pins

Circuit schematic diagram about pins
As shown in the figure above: the board has three sets of serial ports (TX is the sending pin, RX is the receiving pin), corresponding to:
RX1/TX1 ——> PA10/PA9 ——> USART1
RX2/TX2 ——> PA3/ PA2 ——> USART2
RX3/TX3 ——> PB11/PB10 ——> USART3

pin USART1 USART2 USART3
TX PA9 PA2 PB10
RX PA10 PA3 PB11
clock line APB2 APB1 APB1
Interrupt function name USART1_IRQHandler(void) USART2_IRQHandler(void) USART3_IRQHandler(void)

Five, code configuration

1.USART1
(1) send, receive pin configuration and serial port configuration

void USART1_Config(void)  
{
    
      
  	GPIO_InitTypeDef x;
	USART_InitTypeDef y;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);		//开启管脚PA9,PA10对应的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);		//开启串口USART1的时钟,注意:**APB2**
	
	x.GPIO_Pin=GPIO_Pin_9;
	x.GPIO_Mode=GPIO_Mode_AF_PP;
	x.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&x);				//配置发送引脚——选择管脚9,模式为复用推挽输出(因为是发送引脚),频率为50MHz,初始化到GPIOA
	
	x.GPIO_Pin=GPIO_Pin_10;
	x.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&x);				//配置接收引脚——选择管脚10,模式为浮空输入(因为是接收引脚),输入模式不用配置频率,初始化到GPIOA
	
	y.USART_BaudRate=9600;											//配置波特率9600/115200等,具体看你的硬件配置要求
	y.USART_WordLength=USART_WordLength_8b;							//配置数据位8位
	y.USART_StopBits=USART_StopBits_1;								//配置停止位为1
	y.USART_Parity=USART_Parity_No;									//奇偶校验位为无校验
	y.USART_HardwareFlowControl=USART_HardwareFlowControl_None;		//配置硬件控制流选择为无
	y.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;						//配置串口模式为接收和发送
	USART_Init(USART1,&y);				//初始化到USART1
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);		//开启窗口接收中断(即当发生接收数据或发送数据时将触发对应的中断处理函数)
	USART_Cmd(USART1,ENABLE);			//使能USART1,也就是打开USART1功能
	
	NVIC_Configuration();    			//中断优先级配置
} 

(2) Configure interrupt priority

priority grouping master priority sub-priority
NVIC_PriorityGroup0 (0 bit for preemption priority 4 bits for subpriority) 0 0~15
NVIC_PriorityGroup1 (1 bit for preemption priority 3 bits for subpriority) 0~1 0~7
NVIC_PriorityGroup2 (2 bits for preemption priority and 2 bits for subpriority) 0~3 0~3
NVIC_PriorityGroup3 (3 bits for preemption priority 1 bit for sub-priority) 0~7 0~1
NVIC_PriorityGroup4 (4 bits for preemption priority 0 bits for sub-priority) 0~15 0
void NVIC_Configuration()
{
    
    
	NVIC_InitTypeDef NVIC_InitStruct;	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//配置分组为组2
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;				//配置中断源为USART1
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;		//配置主优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;				//配置子优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;				//中断使能
	NVIC_Init(&NVIC_InitStruct);		//初始化NVIC
}

(3) Interrupt processing function

void USART1_IRQHandler(void)  
{
    
      
  	u8 res;  
	if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)  		//若当前USART1的状态为接收
	{
    
     
		res= USART_ReceiveData(USART1);   		//读取此时接收的数据
		USART_SendData(USART1,res);				//将数据重新发回去,用于告诉它接收成功
	}
}

(4) Redirection sending and receiving functions (in keil's C standard functions, functions like printf have not implemented their bottom layer, and program developers need to redirect the fgets and fputs functions to use standard functions such as printf, scanf, gets, puts, etc. , remember to add #include " stdio.h " oh)

#include "stdio.h"
int fputc(int ch,FILE *f)
{
    
    
	USART_SendData(USART1,(uint8_t)ch);		//发送一个字符
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);	//直到发送完毕
	return (ch);	
}
int fgetc(FILE *f)
{
    
    
	while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);	//直到接收完毕
	return (int)USART_ReceiveData(USART1);
}

(5) Finally the main function

int main(void)  
{
    
      
	USART1_Config();
  	while(1);
} 

Such a complete serial port configuration is realized! ! !
Next, follow the same steps to use the other two serial ports to realize this function.

2.USART2
(1) send, receive pin configuration and serial port configuration

void USART2_Config(void)  
{
    
      
  	GPIO_InitTypeDef x;
	USART_InitTypeDef y;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);		//注意**APB1**,**USART2**
	
	x.GPIO_Pin=GPIO_Pin_2;
	x.GPIO_Mode=GPIO_Mode_AF_PP;
	x.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&x);
	
	x.GPIO_Pin=GPIO_Pin_3;
	x.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&x);
	
	y.USART_BaudRate=9600;
	y.USART_WordLength=USART_WordLength_8b;
	y.USART_StopBits=USART_StopBits_1;
	y.USART_Parity=USART_Parity_No;
	y.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	y.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_Init(USART2,&y);
	
	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
	USART_Cmd(USART2,ENABLE);
	
	NVIC_Configuration();    
} 

(2) Configure interrupt priority

void NVIC_Configuration()
{
    
    
	NVIC_InitTypeDef NVIC_InitStruct;	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;		//注意:**USART2_IRQn**
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

(3) Interrupt processing function

void USART2_IRQHandler(void)  		//注意:**USART2_IRQHandler**
{
    
      
  	u8 res;  
	if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)  
	{
    
     
		res= USART_ReceiveData(USART2);   
		USART_SendData(USART2,res);	
  }  
}

(4) Redirect the sending and receiving function (remember to add #include " stdio.h ")

#include "stdio.h"
int fputc(int ch,FILE *f)
{
    
    
	USART_SendData(USART2,(uint8_t)ch);
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
	return (ch);
}
int fgetc(FILE *f)
{
    
    
	while(USART_GetFlagStatus(USART2,USART_FLAG_RXNE)==RESET);
	return (int)USART_ReceiveData(USART2);
}

(5) Finally the main function

int main(void)  
{
    
      
	USART2_Config();
  	while(1);
} 

2.USART3
(1) send, receive pin configuration and serial port configuration

void USART3_Config(void)  
{
    
      
  GPIO_InitTypeDef x;
	USART_InitTypeDef y;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);		//注意:**GPIOB**
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);		//注意:**APB1**,**USART3**
	
	x.GPIO_Pin=GPIO_Pin_10;
	x.GPIO_Mode=GPIO_Mode_AF_PP;
	x.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&x);			//注意:**GPIOB**
	
	x.GPIO_Pin=GPIO_Pin_11;
	x.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB,&x);			//注意:**GPIOB**
	
	y.USART_BaudRate=9600;
	y.USART_WordLength=USART_WordLength_8b;
	y.USART_StopBits=USART_StopBits_1;
	y.USART_Parity=USART_Parity_No;
	y.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	y.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_Init(USART3,&y);
	
	USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
	USART_Cmd(USART3,ENABLE);
	
	NVIC_Configuration();    
} 

(2) Configure interrupt priority

void NVIC_Configuration()
{
    
    
	NVIC_InitTypeDef NVIC_InitStruct;	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;		//注意:**USART3_IRQn**
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
}

(3) Interrupt processing function

void USART3_IRQHandler(void)  		//注意:**USART3_IRQHandler**
{
    
      
 	u8 res;  
	if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)  
	{
    
     
		res= USART_ReceiveData(USART3);   
		USART_SendData(USART3,res);	
  }  
}

(4) Redirect the sending and receiving function (remember to add #include " stdio.h ")

#include "stdio.h"
int fputc(int ch,FILE *f)
{
    
    
	USART_SendData(USART3,(uint8_t)ch);
	while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);
	return (ch);
}
int fgetc(FILE *f)
{
    
    
	while(USART_GetFlagStatus(USART3,USART_FLAG_RXNE)==RESET);
	return (int)USART_ReceiveData(USART3);
}

(5) Finally the main function

int main(void)  
{
    
      
	USART3_Config();
  	while(1);
} 

6. Finally, an example of controlling a small light through a serial port

(1) Configure the serial port (select one of the above three groups randomly, here we take group 1-PA9, PA10 as an example)
(2) Initialize the small light (the pin of my STM32 to control the LED light is PC13)
LED

void LED_GPIO_Config(void)
{
    
    
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);    
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
}

(3) Small light control function

void LED_G(uint8_t n)                    //LED_G(0): 灯亮            LED_G(1):灯灭
{
    
    
    if(n)
                GPIO_SetBits(GPIOC, GPIO_Pin_13);
    else
                GPIO_ResetBits(GPIOC, GPIO_Pin_13);
}

(4) Modify the main function

#include "stm32f10x.h"

int main(void)  
{
    
      
    USART_Config();
    LED_GPIO_Config(); 
    while(1);
} 

(5) Modify the serial interrupt function

void USART1_IRQHandler(void)    //如果串口发送‘0’则灯亮,(若其他数据)否则灯灭
{
    
      
    u8 res;  
    if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)  
    {
    
     
        res= USART_ReceiveData(USART1);   
        USART_SendData(USART1,res);
        if(res=='0')
        {
    
    
            LED_G(0);
        }
        else
        {
    
    
            LED_G(1);
        }        
  }  
}

7. Complete project resource sharing

Link: https://pan.baidu.com/s/1UvxMlFSzKVpQfpDA3zxnBA
Extraction code: o8c7

Guess you like

Origin blog.csdn.net/weiybin/article/details/107378505