1. 实验环境:
开发板:野火指南者(STM32F103VE)
STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0
IDE:KEIL5(代码编写很不方便,只在编译的时候用到)
代码编写工具:Source Insight 4.0(跟读代码、编写代码的最佳工具)
使用到的串口:USART1
硬件原理图:

效果:

2. 新建NVIC.h、NVIC.c、User_USART.h、User_USART.c、main.c 5个文件,并从
STM32官方库的例子中将stm32f10x_it.c、stm32f10x_it.h、stm32f10x_conf.h拷贝到自己的工程目录下。
3. 在NVIC.h中添加如下代码

11 #ifndef __NVIC_H 22 #define __NVIC_H 33 44 void User_NVIC_Config(void); 55 66 77 88 #endif
View Code
4. 在NVIC.c中添加如下代码

1 1 #include "NVIC.h" 2 2 #include "stm32f10x.h" 3 3 4 4 void User_NVIC_Config(void) 5 5 { 6 6 NVIC_InitTypeDef NVIC_Config; 7 7 8 8 //设置中断控制器优先级组类别 9 9 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 1010 1111 //初始化NVIC_InitTypeDef结构体 1212 NVIC_Config.NVIC_IRQChannel = USART1_IRQn; 1313 NVIC_Config.NVIC_IRQChannelPreemptionPriority = 1; 1414 NVIC_Config.NVIC_IRQChannelSubPriority = 1; 1515 NVIC_Config.NVIC_IRQChannelCmd = ENABLE; 1616 1717 //初始化NVIC中断控制器 1818 NVIC_Init(&NVIC_Config); 1919 2020 }
View Code
5. 在User_USART.h中添加如下代码

1 1 #ifndef __USER_USART_H 2 2 #define __USER_USART_H 3 3 #include "stm32f10x.h" 4 4 5 5 void User_USART_GPIO_Config(void); //USART使用到的GPIO口设置 6 6 void User_USART_Config(void); //USART相关寄存器设置 7 7 void User_USART_Send_Byte(USART_TypeDef* pUSARTX, uint8_t Data); //向串口发送一个字节数据 8 8 void User_UART_Send_String(USART_TypeDef* pUSARTX, char* str); //向串口发送一个字符串数据,即可以发送包含多个字节的数据 9 9 1010 1111 #endif
View Code
6. 在User_USART.c中添加如下代码

1 1 #include "User_USART.h" 2 2 #include "stm32f10x.h" 3 3 4 4 5 5 //USART使用到的GPIO口设置 6 6 void User_USART_GPIO_Config(void) 7 7 { 8 8 GPIO_InitTypeDef USART_GPIO_TX,USART_GPIO_RX; 9 9 1010 //先使能USART对应的GPIO口使用,USART使用的都是GPIOA组 1111 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 1212 1313 //初始化GPIO_InitTypeDef结构体--USART TX PIN 1414 USART_GPIO_TX.GPIO_Mode = GPIO_Mode_AF_PP; 1515 USART_GPIO_TX.GPIO_Pin = GPIO_Pin_9; 1616 USART_GPIO_TX.GPIO_Speed = GPIO_Speed_50MHz; 1717 1818 //设置USART TX PIN对应的控制寄存器 1919 GPIO_Init(GPIOA, &USART_GPIO_TX); 2020 2121 2222 //初始化GPIO_InitTypeDef结构体--USART RX PIN 此为输入,所以不用初始化速率GPIO_Speed成员 2323 USART_GPIO_RX.GPIO_Mode = GPIO_Mode_IN_FLOATING; 2424 USART_GPIO_RX.GPIO_Pin = GPIO_Pin_10; 2525 2626 //设置USART RX PIN对应的控制寄存器 2727 GPIO_Init(GPIOA, &USART_GPIO_RX); 2828 2929 3030 } 3131 3232 3333 //USART相关寄存器设置 3434 void User_USART_Config(void) 3535 { 3636 3737 USART_InitTypeDef USART_Config; 3838 3939 //使能USART1时钟 4040 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 4141 4242 //初始化USART_InitTypeDef结构体 4343 USART_Config.USART_BaudRate = 115200; 4444 USART_Config.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 4545 USART_Config.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 4646 USART_Config.USART_Parity = USART_Parity_No; 4747 USART_Config.USART_StopBits = USART_StopBits_1; 4848 USART_Config.USART_WordLength = USART_WordLength_8b; 4949 5050 //设置USART1对应的寄存器 5151 USART_Init(USART1, &USART_Config); 5252 5353 //使能USART1 数据接收RXEN中断寄存器,即接收数据寄存器有数据可读时,RXEN寄存器产生中断 5454 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 5555 5656 //使能串口USART1,使其进行工作 5757 USART_Cmd(USART1, ENABLE); 5858 5959 6060 } 6161 6262 6363 6464 //向串口发送一个字节数据 6565 void User_USART_Send_Byte(USART_TypeDef* pUSARTX, uint8_t Data) 6666 { 6767 6868 //向数据寄存器写入8bit数据 6969 pUSARTX->DR = (Data & (uint16_t)0x01FF); 7070 7171 //USART_GetFlagStatus检查数据是否发送完成 7272 while(USART_GetFlagStatus(pUSARTX, USART_FLAG_TXE) == RESET); 7373 7474 } 7575 7676 7777 //向串口发送一个字符串数据,即可以发送包含多个字节的数据,char类型为8bit,其字符串中的每个字符都可用一个int数表示,即ASCII标准 7878 void User_UART_Send_String(USART_TypeDef* pUSARTX, char* str) 7979 { 8080 int i; 8181 8282 for(i = 0; i < sizeof(str); i++) 8383 { 8484 User_USART_Send_Byte(pUSARTX, *(str + i)); 8585 8686 //USART_GetFlagStatus检查多个数据是否发送完成 8787 while(USART_GetFlagStatus(pUSARTX, USART_FLAG_TC) == RESET); 8888 8989 9090 } 9191 9292 }
View Code
7. 在stm32f10x_it.h中添加如下代码

1 void USART1_IRQHandler(void); //中断服务函数
View Code
8. 在stm32f10x_it.c中添加如下代码

1 1 //中断服务函数,前面在User_USART.c void User_USART_Config(void)函数中 2 2 //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);使能了数据接收中断,所以 3 3 //将处理接收数据时的中断服务 4 4 void USART1_IRQHandler(void) 5 5 { 6 6 7 7 uint8_t temp; 8 8 9 9 if(USART_GetFlagStatus(USART1, USART_IT_RXNE) != RESET) 1010 { 1111 temp = USART_ReceiveData(USART1); 1212 USART_SendData(USART1, temp); 1313 1414 1515 } 1616 1717 1818 }
View Code
9. 在main.c中添加如下代码

1 1 #include "NVIC.h" 2 2 #include "User_USART.h" 3 3 #include "stm32f10x.h" 4 4 5 5 int main(void) 6 6 { 7 7 8 8 User_USART_GPIO_Config(); 9 9 User_NVIC_Config(); 1010 User_USART_Config(); 1111 1212 User_UART_Send_String(USART1, "test!\n"); 1313 1414 while(1) 1515 { 1616 1717 } 1818 1919 }
View Code
总结:
1、设置USART硬件中实际使用到的GPIO口,这里为GPIOA的PIN8、PIN10,具体设置如下
1.1、使能GPIO时钟,使用RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)库函数
1.2、初始化GPIO_InitTypeDef结构体成员,若为输入则不需要初始化GPIO_Speed成员
1.3、将GPIO_InitTypeDef结构体的值写入到对应GPIO寄存器中,使用GPIO_Init(GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_InitStruct)库函数
2、设置USART对应的寄存器
2.1、使能USART时钟,使用RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)库函数,若不是USART1则需要使用RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)库函数,因为USART1挂载在APB2总线上,USART2~USART5挂载在APB1总线上。
2.2、初始化USART_InitTypeDef结构体成员。一般为8N1,即数据长度为8bit、无校验位、1个停止位
2.3、将USART_InitTypeDef结构体的值写入到对应的USART寄存器中,使用USART_Init(USART_TypeDef * USARTx, USART_InitTypeDef * USART_InitStruct)库函数
2.4、打开对应的中断寄存器来响应中断,即中断到来时可进入对应的中断服务程序,若不需要中断,则不用设置,跳过此不走。本实验使用了数据接收中断,使用USART_ITConfig(USART_TypeDef * USARTx, uint16_t USART_IT, FunctionalState NewState)库函数设置
2.5、使能串口USART1,使其进行工作,使用USART_Cmd(USART_TypeDef * USARTx, FunctionalState NewState)库函数
3、因为使用了中断,所以设置NVIC中断控制寄存器
3.1、设置中断优先级组,使用NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)库函数
3.2、初始化NVIC_InitTypeDef结构体成员
3.3、将NVIC_InitTypeDef结构体的值写入NVIC对应的寄存器中,使用NVIC_Init(NVIC_InitTypeDef * NVIC_InitStruct)库函数
4、编写中断服务程序
实验代码:
链接:https://pan.baidu.com/s/1Ghg1FzTQ8l0cvyGuQnIaZA
提取码:8rwq