STM32的USART讲解

本文详细介绍了STM32微控制器中串口通信的基本原理和技术实现,包括串口相关寄存器的功能介绍、波特率计算方法、串口库函数使用、硬件连接方式及配置步骤,并提供了完整的串口测试程序设计实例。

一,串口相关寄存器

USART_SR 状态寄存器
USART_DR 数据寄存器
USART_BRR 波特率寄存器
USART_CR1 控制寄存器

USART_SR-状态寄存器:

  这里写图片描述
  
  状态寄存器USART_SR,描述串口寄存器的一些状态:
  
  如位5:读数据寄存器非空
  
  这里写图片描述
  
  通过读取这个位的值,判断是否收到了完整的数据
  串口已经接收到了数据,并且已经写入到了USART_DR寄存器


USART_DR-数据寄存器:

  这里写图片描述
  
  数据寄存器USART_DR,只使用了位0-8,其他位保留
  
  这里写图片描述

  读寄存器:读取该寄存器获取接收到的数据值
  写寄存器:向该寄存器写入发送的数据对数据进行发送


USART_BRR-波特率寄存器:

  这里写图片描述
  
  波特率寄存器USART_BRR,只用到了低16位,高16位保留
  
  这里写图片描述

  0-3位[3:0]  : USART分频器的小数部分DIV_Fraction
  4-15位[15:4] : USART分频器的整数部分DIV_Mantissa


USART_CR1-控制寄存器:

  这里写图片描述
  
  USART_BRR波特率寄存器,设置串口寄存器使能位
  
  如:接收使能,发送使能
  
  这里写图片描述


二,波特率的计算方法

波特率发生器:

  这里写图片描述

如图:
    波特率由波特率发生器和PCLKx共同产生
    PCLKx的值由串口本身决定
    通过配置USART_BRR寄存器确定波特率发生器的值
    经过USARTDIV分频器除以16得到最终的波特率

波特率计算方法:

  这里写图片描述

设置串口1波特率为115200MHz

串口1的时钟来自PCLK2=72MHz

由公式得到:
    USARTDIV=72000000/(115200*16)=39.0625

整数部分DIV_Mantissa=39=0x27
小数部分DIV_Fraction=16*0,0625=1=0x01

所以设置USART->BRR=0x0271,就可以实现设置串口1的波特率为115200MHz

三,串口操作相关库函数

获取状态标志位函数-操作USART_SR寄存器

// 获取状态标志位
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
// 清除状态标志位
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
// 获取中断状态标志位
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
// 清除中断状态标志位
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

接收发送数据函数-操作USART_DR寄存器

// 发送数据到串口(通过写USART_DR寄存器发送数据)
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
// 接收数据(从USART_DR寄存器读取接收到的数据)
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
  • 1
  • 2
  • 3
  • 4

串口配置函数

// 串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
// 使能串口
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
// 使能相关中断
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

四,串口硬件连接

PA9-RXD
PA10-TXD
CH340  USB转串口    将USB虚拟为串口使用

五,串口配置的步骤

1,串口时钟使能,GPIO时钟使能
     RCC_APB2PeriphClockCmd()
2,串口复位
     USART_DeInit();
3,GPIO端口模式设置
     GPIO_Init();
4,串口参数初始化
     USART_Init()
5,开启中断并初始化NVIC
     NVIC_Init();
     USART_ITConfig();
6,使能串口
     USART_Cmd();
7,中断函数逻辑
     USARTx_IRQHandler();
8,串口数据发送
     void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
     uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
9,串口传输状态获取
     ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
     void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

六,串口测试程序设计

程序功能:

 电脑通过USB线连接开发板,开发板通过USB转串口实现和电脑的通信
 电脑使用串口工具想单片机发送数据,单片机收到数据后返回给电脑

 注:以串口1为例实现

七,串口测试程序实现分析

1,使能GPIO时钟

串口1的发送,接收引脚为PA9和PA10
所以我们要使能GPIOA和串口1的时钟
串口1和GPIOx时钟源为APB2
所以使用RCC_APB2PeriphClockCmd函数进行初始化

stm32f10x_rcc.c找到RCC_APB2PeriphClockCmd函数源码:

/**
  * @brief  Enables or disables the High Speed APB (APB2) peripheral clock.
  * @param  RCC_APB2Periph: specifies the APB2 peripheral to gates its clock.
  *   This parameter can be any combination of the following values:
  *     @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
  *          RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
  *          RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
  *          RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
  *          RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
  *          RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
  *          RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
  * @param  NewState: new state of the specified peripheral clock.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2ENR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2ENR &= ~RCC_APB2Periph;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

stm32f10x_rcc.h找到IS_RCC_APB2_PERIPH函数声明:

/** @defgroup APB2_peripheral
  * @{
  */

#define RCC_APB2Periph_AFIO              ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA             ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB             ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC             ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD             ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE             ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF             ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG             ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1              ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2              ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1              ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1              ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8              ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1            ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3              ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15             ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16             ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17             ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9              ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10             ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11             ((uint32_t)0x00200000)

#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

从参数定义验证了GPIOA-GPIOG 和串口1(USART1)的时钟使能由RCC_APB2PeriphClockCmd()控制

所以使能GPIOA和串口1时钟代码为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能GPIOA时钟源
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);    //使能串口1时钟源
  • 1
  • 2

2,初始化GPIOA的工作模式

通过查找STM32中文参考手册确定串口1引脚工作模式配置:

  这里写图片描述

如图:
串口1接收发送引脚配置
    发送端PA9配置为推挽复用输出
    接收端PA10配置为浮空输入或上拉输入

代码:

GPIO_InitTypeDef GPIO_InitStrue;

//发送端PA9配置
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;            //发送端-TXD
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;      //推挽输出
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStrue);

//接收端PA10配置
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;           //接收端-RXD
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStrue);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3,串口初始化

stm32f10x_usart.h头文件找到USART_Init函数声明:

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
  • 1

stm32f10x_usart.h找到入参USART_InitTypeDef结构体声明

/**
  * @brief  USART Init Structure definition
  */
typedef struct
{
  uint32_t USART_BaudRate;               // 设置波特率
  uint16_t USART_WordLength;             // 字长8或9(停止位)
  uint16_t USART_StopBits;               // 停止位
  uint16_t USART_Parity;                 // 奇偶校验
  uint16_t USART_Mode;                   // 发送接收使能
  uint16_t USART_HardwareFlowControl;    // 硬件流控制
} USART_InitTypeDef;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

USART_HardwareFlowControl-硬件流参数有效性验证

/** @defgroup USART_Hardware_Flow_Control
  * @{
  */
#define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
#define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
#define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
#define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)
#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL)\
                              (((CONTROL) == USART_HardwareFlowControl_None) || \
                               ((CONTROL) == USART_HardwareFlowControl_RTS) || \
                               ((CONTROL) == USART_HardwareFlowControl_CTS) || \
                               ((CONTROL) == USART_HardwareFlowControl_RTS_CTS))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

USART_Mode-使能参数有效性验证

/** @defgroup USART_Mode
  * @{
  */





#define USART_Mode_Rx ((uint16_t)0x0004) #define USART_Mode_Tx ((uint16_t)0x0008) #define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

USART_Parity-奇偶校验参数有效性

/** @defgroup USART_Parity
  * @{
  */





#define USART_Parity_No ((uint16_t)0x0000) #define USART_Parity_Even ((uint16_t)0x0400) #define USART_Parity_Odd ((uint16_t)0x0600) #define IS_USART_PARITY(PARITY) (((PARITY) == USART_Parity_No) || \ ((PARITY) == USART_Parity_Even) || \ ((PARITY) == USART_Parity_Odd))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

USART_StopBits-停止位参数有效性

/** @defgroup USART_Stop_Bits
  * @{
  */

#define USART_StopBits_1                     ((uint16_t)0x0000)
#define USART_StopBits_0_5                   ((uint16_t)0x1000)
#define USART_StopBits_2                     ((uint16_t)0x2000)
#define USART_StopBits_1_5                   ((uint16_t)0x3000)
#define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_StopBits_1) || \
                                     ((STOPBITS) == USART_StopBits_0_5) || \
                                     ((STOPBITS) == USART_StopBits_2) || \
                                     ((STOPBITS) == USART_StopBits_1_5))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

USART_WordLength-字长参数有效性

/** @defgroup USART_Word_Length
  * @{
  */





#define USART_WordLength_8b ((uint16_t)0x0000) #define USART_WordLength_9b ((uint16_t)0x1000) #define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WordLength_8b) || \ ((LENGTH) == USART_WordLength_9b))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

串口初始化代码:

USART_InitTypeDef     USART_InitStrue;

USART_InitStrue.USART_BaudRate=115200;                      //设置波特率-115200MHz
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制-不使用
USART_InitStrue.USART_Mode=USART_Mode_Rx| USART_Mode_Tx;    //使能设置-发送接收都使能
USART_InitStrue.USART_Parity=USART_Parity_No;               //奇偶校验-不使用奇偶校验
USART_InitStrue.USART_StopBits=USART_StopBits_1;            //停止位-一个停止位
USART_InitStrue.USART_WordLength=USART_WordLength_8b        //字长-8位字长

USART_Init(USART1, &USART_InitStrue);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4,使能串口1:

stm32f10x_usart.h头文件找到USART_Cmd函数定义

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
USART_Cmd(USART1, ENABLE);
  • 1
  • 2

5,由于使用了中断首先要配置中断优先级分组-在主函数

misc.h头文件中找到NVIC_PriorityGroupConfig函数声明:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
  • 1

misc.c中找到NVIC_PriorityGroupConfig函数实现:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));

  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

查看参数IS_NVIC_PRIORITY_GROUP有效性校验-misc.h

#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
                                                            4 bits for subpriority */
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
                                                            3 bits for subpriority */
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
                                                            2 bits for subpriority */
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
                                                            1 bits for subpriority */
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
                                                            0 bits for subpriority */

#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
                                       ((GROUP) == NVIC_PriorityGroup_1) || \
                                       ((GROUP) == NVIC_PriorityGroup_2) || \
                                       ((GROUP) == NVIC_PriorityGroup_3) || \
                                       ((GROUP) == NVIC_PriorityGroup_4))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

中断分组配置代码:

//配置中断分组为2,即2位抢占优先级和2位响应优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2)
  • 1
  • 2

6,开启接收中断

stm32f10x_usart.h头文件中找到USART_ITConfig函数声明:

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
  • 1

stm32f10x_usart.c中找到USART_ITConfig函数实现:

void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
{
  uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;
  uint32_t usartxbase = 0x00;
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_CONFIG_IT(USART_IT));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  /* The CTS interrupt is not available for UART4 and UART5 */
  if (USART_IT == USART_IT_CTS)
  {
    assert_param(IS_USART_123_PERIPH(USARTx));
  }

  usartxbase = (uint32_t)USARTx;

  /* Get the USART register index */
  usartreg = (((uint8_t)USART_IT) >> 0x05);

  /* Get the interrupt position */
  itpos = USART_IT & IT_Mask;
  itmask = (((uint32_t)0x01) << itpos);

  if (usartreg == 0x01) /* The IT is in CR1 register */
  {
    usartxbase += 0x0C;
  }
  else if (usartreg == 0x02) /* The IT is in CR2 register */
  {
    usartxbase += 0x10;
  }
  else /* The IT is in CR3 register */
  {
    usartxbase += 0x14;
  }
  if (NewState != DISABLE)
  {
    *(__IO uint32_t*)usartxbase  |= itmask;
  }
  else
  {
    *(__IO uint32_t*)usartxbase &= ~itmask;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

第二个参数USART_IT的有效性校验IS_USART_CONFIG_IT:
stm32f10x_usart.h头文件找到IS_USART_CONFIG_IT声明:

#define USART_IT_PE                          ((uint16_t)0x0028)
#define USART_IT_TXE                         ((uint16_t)0x0727)
#define USART_IT_TC                          ((uint16_t)0x0626)
#define USART_IT_RXNE                        ((uint16_t)0x0525)
#define USART_IT_IDLE                        ((uint16_t)0x0424)
#define USART_IT_LBD                         ((uint16_t)0x0846)
#define USART_IT_CTS                         ((uint16_t)0x096A)
#define USART_IT_ERR                         ((uint16_t)0x0060)
#define USART_IT_ORE                         ((uint16_t)0x0360)
#define USART_IT_NE                          ((uint16_t)0x0260)
#define USART_IT_FE                          ((uint16_t)0x0160)
#define IS_USART_CONFIG_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \
                               ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \
                               ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \
                               ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ERR))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

串口1初始化代码:

//打开串口1的接收中断,当串口1接收到数据时会触发此中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  • 1
  • 2

6,中断优先级的设置

初始化NVIC,设置中断的抢占优先级和响应优先级
参考:NVIC

NVIC_InitTypeDef     NVIC_InitTypeStrue;

NVIC_InitTypeStrue.NVIC_IRQChannel=USART1_IRQn;    // 哪个通道-stm32f10x.h顶层头文件包含参数定义
NVIC_InitTypeStrue.NVIC_IRQChannelCmd=ENABLE;      // 是否开启中断通道-使能
NVIC_InitTypeStrue.NVIC_IRQChannelPreemptionPriority=1;     // 抢占优先级
NVIC_InitTypeStrue.NVIC_IRQChannelSubPriority=1;   // 响应优先级,子优先级

NVIC_Init(&NVIC_InitTypeStrue);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

7,编写中断服务函数

格式: USARTx_IRQHandler();

在启动文件startup_stm32f10x_hd.s中找到串口123的中断服务函数
               DCD     USART1_IRQHandler          ; USART1
               DCD     USART2_IRQHandler          ; USART2
               DCD     USART3_IRQHandler          ; USART3
  • 1
  • 2
  • 3
  • 4

中断服务函数代码

void USART1_IRQHandler(void){
     u8 res;
     //判断中断类型
     //参数1:哪个串口  参数2:中断类型
     if(USART_GetITStatus(USART1, USART_IT_RXNE)){//接收数据中断
          res = USART_ReceiveData(USART1);//读取串口1接收到的数据
          //回发
          USART_SendData(USART1, res);
     }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

八,串口程序完整代码

USER文件夹新建main.c函数:

#include "stm32f10x.h"

// 主函数
int main(void)
{   
    // 设置中断优先级分组位2 - 2位抢占2位相应
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    // 调用函数 初始化USART1相关引脚配置
    My_USART1_Init();

    while(1);
}

// 串口初始化函数
void My_USART1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStrue;
    USART_InitTypeDef USART_InitStrue;
    NVIC_InitTypeDef NVIC_InitStrue;

    // 1,使能GPIOA,USART1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

    // 2,设置PGIO工作模式-PA9 PA10复用为串口1
    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;
    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(GPIOA,&GPIO_InitStrue);

    GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;
    GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;
    GPIO_Init(GPIOA,&GPIO_InitStrue);

    // 3,串口1初始化配置
    USART_InitStrue.USART_BaudRate=115200;
    USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
    USART_InitStrue.USART_Parity=USART_Parity_No;
    USART_InitStrue.USART_StopBits=USART_StopBits_1;
    USART_InitStrue.USART_WordLength=USART_WordLength_8b;

    USART_Init(USART1,&USART_InitStrue);

    // 4,打开串口1
    USART_Cmd(USART1,ENABLE);

    // 5,使能串口1中断-接收数据完成中断
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

    // 6,设置中断优先级-主函数中设置中断优先级分组
    NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
    NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;
    NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStrue);

}

// 中断服务函数
void USART1_IRQHandler(void)
{
    u8 res;
    if(USART_GetITStatus(USART1,USART_IT_RXNE))// 接收到数据
    {
        res= USART_ReceiveData(USART1); // 获得串口1接收到的数据
        USART_SendData(USART1,res);     // 通过串口1发送数据
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

以上代码实现:
    电脑通过串口助手发送数据给单片机
    单片机接收数据进入接收数据串口中断
    读取DR寄存器中接收到的数据
    将接收到的数据再通过串口回写给电脑
(function () {('pre.prettyprint code').each(function () { var lines = (this).text().split(\n).length;varnumbering = $('
  • ').addClass('pre-numbering').hide(); (this).addClass(hasnumbering).parent().append(numbering); for (i = 1; i
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值