1. 项目:野火stm32f10指南者开发板,使用USART实现数据的发送和接收。
2. 代码
- 主函数main.c
#include "stm32f10x.h" #include "bsp_usart.h" int main(void) { USART_Config(); //发送一个字符 Usart_SendByte(DEBUG_USARTx,'A'); while(1) { } }
- bsp_usart.c
#include "bsp_usart.h" static void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*配置NVIC为优先级组2*/ NVIC_InitStruct.NVIC_IRQChannel= DEBUG_USART_IRQ; /*配置USART中断源*/ NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; /*使能中断通道*/ NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; /*配置抢占优先级:1*/ NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; /*配置子优先级:1*/ NVIC_Init(&NVIC_InitStruct); /*初始化配置NVIC*/ } void USART_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; //打开串口GPIO时钟 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); //打开串口外设时钟 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); //将USART Tx的GPIO配置为推挽复用模式 GPIO_InitStruct.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DEBUG_USART_TX_GPIO_PORT,&GPIO_InitStruct); //将USART Rx的GPIO配置为浮空输入模式 GPIO_InitStruct.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DEBUG_USART_RX_GPIO_PORT,&GPIO_InitStruct); //配置串口的工作参数 //配置波特率 USART_InitStruct.USART_BaudRate = DEBUG_USART_BAUNDRATE; //配置针数据字长 USART_InitStruct.USART_WordLength = USART_WordLength_8b; //配置停止位 USART_InitStruct.USART_StopBits = USART_StopBits_1; //配置校验位 USART_InitStruct.USART_Parity = USART_Parity_No; //配置硬件流控制 USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //配置工作模式,收发一起 USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //完成串口的初始化配置 USART_Init(DEBUG_USARTx, &USART_InitStruct); //串口中断优先级配置 NVIC_Config(); //使能串口接收中断 USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); //使能串口 USART_Cmd(DEBUG_USARTx,ENABLE); } //发送字节函数 void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data) { USART_SendData(pUSARTx, data); while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); }
- bsp_usart.h
#ifndef __bsp_usart_h #define __bsp_usart_h #include "stm32f10x.h" //串口USART宏定义 #define DEBUG_USARTx USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_BAUNDRATE 115200 //USART GPIO宏定义 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA) #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_IRQ USART1_IRQn #define DEBUG_USART_IRQHandler USART1_IRQHandler void USART_Config(void); void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data); #endif /*bsp_usart_h*/
- stm32f10x_it.c函数添加中断函数
/* Includes ------------------------------------------------------------------*/ #include "stm32f10x_it.h" #include "bsp_usart.h" /** @addtogroup STM32F10x_StdPeriph_Template * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /******************************************************************************/ /* Cortex-M3 Processor Exceptions Handlers */ /******************************************************************************/ /** * @brief This function handles NMI exception. * @param None * @retval None */ void NMI_Handler(void) { } /** * @brief This function handles Hard Fault exception. * @param None * @retval None */ void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** * @brief This function handles Memory Manage exception. * @param None * @retval None */ void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { } } /** * @brief This function handles Bus Fault exception. * @param None * @retval None */ void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { } } /** * @brief This function handles Usage Fault exception. * @param None * @retval None */ void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { } } /** * @brief This function handles SVCall exception. * @param None * @retval None */ void SVC_Handler(void) { } /** * @brief This function handles Debug Monitor exception. * @param None * @retval None */ void DebugMon_Handler(void) { } /** * @brief This function handles PendSVC exception. * @param None * @retval None */ void PendSV_Handler(void) { } /** * @brief This function handles SysTick Handler. * @param None * @retval None */ void SysTick_Handler(void) { } void DEBUG_USART_IRQHandler(void) { uint8_t ucTemp; if (USART_GetITStatus(DEBUG_USARTx, USART_IT_RXNE) != RESET) { ucTemp = USART_ReceiveData(DEBUG_USARTx); USART_SendData(DEBUG_USARTx,ucTemp); } }
Keil5编程总览:
3. 执行结果:
打开串口调试助手,配置好串口、波特率等参数。按下开发板上的复位键,接收区域显示A
4. 参考资料
- 原理图
-
- 编程要点
- 使能RX和TX引脚GPIO时钟和USART时钟;
- 初始化GPIO,并将GPIO复用到USART上;
- 配置USART参数;
- 配置中断控制器并使能USART接收中断;
- 使能USART;
- 在USART接收中断服务函数实现数据接收和发送。
5. 总结
- 串口时钟使能与控制器使能的关系:为何USART时钟使能了,还需要在配置USART控制器的时候再使能一次?(为什么需要同时打开串口时钟和GPIO时钟)
- 转自:STM32之串口通信 (bbsmax.com)
-
//打开串口GPIO时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
//打开串口外设时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
-
(1)USART的时钟使能
- Note: 当外部时钟没有被激活时,外设寄存器值可能不可读,并且返回值为0x0.
- (2)USART控制器使能
-
- 寄存器内部控制关系图
-
RCC_APB2ENR: 控制APB2时钟是否供应给USART控制器
USART_CR1: 控制USART控制器的分频器和输出是否工作
- USART1要用到GPIOA的复用管脚输入输出功能,不使能的话只能内部串口外设工作,但是没办法与外界(即串口线)通信。也就是说只使
- 能USART1的话就只是让USART1这个外设工作,GPIOA作为一个USART1与外界通信的桥梁没有打通,所以不行。
6. 常见的几种通讯协议的参数
转自:
(71条消息) 通信方式梳理:GPIO,I2C,SPI,UART,USART,USB的区别_步印的博客-CSDN博客_gpio i2c spi uart