串口实验_STM32F1开发指南_第九章——串口学习笔记

本章将实现的功能:

    ① STM32F1通过串口和上位机对话;
    ② STM32F1在收到上位机发过来的字符串后,原本地返回给上位机。

本章目录:

    9.1 STM32串口简介
    9.2 硬件设计
    9.3 软件设计
    9.4 下载验证

9.1 STM32串口简介

1)STM32F1串口资源介绍: 

    串口作为MCU的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。现在基本上所有的
MCU 都带有串口。
    STM32的串口资源相当丰富,功能很强劲。STM32F103ZET6最多可提供5路串口,有分数波特率发生器、支持
同步 单线通信和半双工单线通信、支持LIN、支持调制解调器操作、智能卡协议和IrDA SIR ENDEC规范、具有DMA等。

2)串口管脚在芯片上的位置和特性:

    表21  USART管脚配置
序号 USART引脚 配置 GPIO配置
1 USARTx_TX 全双工模式 推挽复用输出
2 半双工同步模式 推挽复用输出
3 USARTx_RX 全双工模式 浮空输入或带上拉输入
4 半双工同步模式 未用,可做为通用I/O
5 USARTx_CK 同步模式 推挽复用输出
6 USARTx_RTS 硬件流量控制 推挽复用输出
7 USARTx_CTS 硬件流量控制 浮空输入或带上拉输入
8.3.8 USART复用功能重映射
参见复用重映射和调试I/O配置寄存器(AFIO_MAPR)
表45 USART3重映射
(注:部分重映射只适用于64、100和144脚的封装;完全重映射只适用于100和144脚的封装)
序号 复用功能 USAART3_REMAP[1:0] = 00(没有重映射) USART3_REMAP[1:0] = 01(部分重映射) USART3_REMAP[1:0] = 11(完全重映射)
1 USART3_TX PB10 PC10 PD8
2 USART3_RX PB11 PC11 PD9
3 USART3_CK PB12 PC12 PD10
4 USART3_CTS PB13 PD11
5 USART3_RTS PB14 PD12
表46 USART2重映射(重映射只适用于100和144脚的封装)
序号 复用功能 USART2_REMAP = 0 USART2_REMAP = 1
1 USART2_CTS PA0 PD3
2 USART2_RTS PA1 PD4
3 USART2_TX PA2 PD5
4 USART2_RX PA3 PD6
5 USART2_CK PA4 PD7
表47 USART1重映射
序号 复用功能 USART1_REMAP = 0 USART1_REMAP = 1
1 USART1_TX PA9 PB6
2 USART1_RX PA10 PB7
串口相关的管脚:
序号 管教名称 默认的其他功能
1 PA8 USART1_CK
2 PA9 USART1_TX
3 PA10 USART1_RX
4 PA11 USART1_CTS
5 PA12 USART1_RTS
6 PA0 USART2_CTS
7 PA1 USART2_RTS
8 PA2 USART2_TX
9 PA3 USART2_RX
10 PB10 USART3_TX
11 PB11 USART3_RX
12 PB12 USART3_CK
13 PB13 USART3_CTS
14 PB14 USART3_RTS

3)串口相关库函数

序号 功能 函数名
1 Deinitializes the USARTx peripheral registers to their default reset values. void USART_DeInit(USART_TypeDef* USARTx);
2 Initializes the USARTx peripheral according to the specified. void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
3 Fills each USART_InitStruct member with its default value. void USART_StructInit(USART_InitTypeDef* USART_InitStruct);
4 Initializes the USARTx peripheral Clock according to the  void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);
5 Fills each USART_ClockInitStruct member with its default value. void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);
6 Enables or disables the specified USART peripheral. void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
7 Enables or disables the specified USART interrupts. void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
8 Enables or disables the USART抯 DMA interface. void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);
9 Sets the address of the USART node. void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address);
10 Selects the USART WakeUp method. void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp);
11 Determines if the USART is in mute mode or not. void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState);
12 Sets the USART LIN Break detection length. void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength);
13 Enables or disables the USART抯 LIN mode. void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState);
14 Transmits single data through the USARTx peripheral. void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
15 Returns the most recent received data by the USARTx peripheral. uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
16 Transmits break characters. void USART_SendBreak(USART_TypeDef* USARTx);
17 Sets the specified USART guard time. void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime);
18 Sets the system clock prescaler. void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler);
19 Enables or disables the USART抯 Smart Card mode. void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState);
20 Enables or disables NACK transmission. void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState);
21 Enables or disables the USART抯 Half Duplex communication. void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState);
22 Enables or disables the USART's 8x oversampling mode. void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
23 Enables or disables the USART's one bit sampling method. void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState);
24  Configures the USART's IrDA interface. void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode);
25 Enables or disables the USART's IrDA interface.
void  USART_IrDACmd (USART_TypeDef* USARTx, FunctionalState NewState);
26 Checks whether the specified USART flag is set or not. FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
27 Clears the USARTx's pending flags. void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
28 Checks whether the specified USART interrupt has occurred or not. ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
29 Clears the USARTx's interrupt pending bits. void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

4)设置串口:

    对于复用功能的IO口,首先要使能GPIO时钟,然后使能复用功能时钟,同时,把GPIO模式设置为复用功能
对应的模式。 之后 就是初始化设置串口参数,包括波特率、停止位等。接下来使能串口。 同时 ,如果开启了
串口的中断,要初始化NVIC 设置中断优先级,最后编写中断服务函数。
     串口设置的一般步骤总结:
① 使能串口时钟,使能GPIO时钟;
② 复位串口;
③ 设置GPIO端口模式;
④ 初始化串口参数;
⑤ 开启中断并初始化NVIC(如果需要开启中断才需要这个步骤);
⑥ 使能串口;
⑦ 编写中断处理函数。
 
    下面简单介绍一下与串口基本配置直接相关的几个固件库函数。
    ① 串口时钟使能。
    串口是挂在APB2下面的外设,所以使能函数为:
        
        
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);
    ② 串口复位。
    当外设出现异常时,需要通过复位设置,实现该外设的复位,然后重新配置这个外设以达到使其重新工作
的目的。 一般在系统刚开始配置外设时,先执行复位该外设的操作。复位是在USART_DeInit()函数中完成的。
         
         
  1. void USART_DeInit(USART_TypeDef* USARTx); //串口复位
比如要复位串口1,调用:
          
          
  1. USART_DeInit(USART1); //串口1复位
    ③ 串口参数初始化。
         
         
  1. void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);
    这个函数的第一个参数是指定初始化的串口标号,这里选择USART1。
    第二个参数是一个USART_InitTypeDef类型的结构体指针,其成员变量用来配置串口的一些参数。一般格式如下:
          
          
  1. USART_InitStructure.USART_BaudRate = bound; //设置波特率;
  2. USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
  3. USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
  4. USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
  5. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
  6. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  7. USART_Init(USART1, &USART_InitStructure); //初始化串口
    从上面的初始化格式可以看出,初始化需要配置参数为:波特率、字长、停止位、奇偶校验位、硬件数据流控制、模式(收/发)。我们可以根据需要设置这些参数。
    ④ 数据发送和接收。
    STM32的发送和接收是通过数据寄存器USART_DR来实现的,这是一个双寄存器,包含了TDR和RDR。
当向该寄存器写数据时,串口就会自动发送;当收到数据时,也存在该寄存器中。
         
         
  1. void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);    //向USART_DR寄存器写入一个数据
  2. uint16_t USART_ReceiveData(USART_TypeDef* USARTx);            //读取串口接收到的数据
    ⑤ 串口状态。
    串口的状态可以通过寄存器USART_SR读取,各位描述如下:
31~10 9 8 7 6 5 4 3 2 1 0
保留 CTS LBD TXE TC RXNE IDLE ORE NE FE PE
    这里关注两位:Bit5:RXNE;Bit6:TC
    RXNE(读数据寄存器非空):当该位被置一时,说明已经有数据被接收了,并且可以读出来了。此时应尽快读取USART_DR。
    读取USART_DR或向该位写0,都可以清除该位。
    TC(发送完成):当该位被置位时,说明USART_DR中的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。
    清零该位的两种方法:a、读取USART_SR,写USART_DR。b、直接向该位写0。
    读取串口状态的函数
          
          
  1. FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
函数的第二个参数很关键,它表示我们要查看串口的哪个状态,比如要判断读寄存器是否为非kong(RXNE),执行:
          
          
  1. USART_GetFlagStatus(USART1, USART_FLAG_RXNE);
如果要判断发送是否完成(TC),执行:
          
          
  1. USART_GetFlagStatus(USART1, USART_FLAG_TC);
这些标志号在MDK里面通过宏定义实现:
          
          
  1. #define USART_IT_PE ((uint16_t)0x0028)
  2. #define USART_IT_TXE ((uint16_t)0x0727)
  3. #define USART_IT_TC ((uint16_t)0x0626)
  4. #define USART_IT_RXNE ((uint16_t)0x0525)
  5. #define USART_IT_IDLE ((uint16_t)0x0424)
  6. #define USART_IT_LBD ((uint16_t)0x0846)
  7. #define USART_IT_CTS ((uint16_t)0x096A)
  8. #define USART_IT_ERR ((uint16_t)0x0060)
  9. #define USART_IT_ORE ((uint16_t)0x0360)
  10. #define USART_IT_NE ((uint16_t)0x0260)
  11. #define USART_IT_FE ((uint16_t)0x0160)
    ⑥ 串口使能。
        
        
  1. USART_Cmd(USART1, ENABLE); //使能串口
    ⑦ 开启串口响应中断。
      
      
  1. void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);
    函数第二个参数很关键,它表示使能串口的类型,即使能哪种串口中断,因为串口中断有很多种。比如:
在接收到数据时(RXNE读寄存器非空),产生中断,则开启中断的方法为:
       
       
  1. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断,接收到数据中断
在发送数据结束时(TC,发送完成)要产生中断,则开启中断的方法为:
       
       
  1. USART_ITConfig(USART1, USART_IT_TC, ENABLE);
    ⑧ 获取相应中断状态。
     我们使能了某个中断,则当中断发生时,就会设置状态寄存器中的某个标志位。
    在中断处理函数中,要判断哪种中断是否发生,可以判断对应的某个标志位。使用的函数是:
       
       
  1. ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
    比如,使能了串口发送完成中断,则当中断发生时,可以在中断处理函数中使用下面语句来判断是否发生串口发送完成中断。
       
       
  1. USART_GetITStatus(USART1, USART_IT_TC);
返回值是SET,说明串口发送完成中断发生了。

9.2 硬件设计

    本实验用到的硬件资源有:
1)指示灯DS0;
2)串口1。

9.3 软件设计

本章代码设计比较简单,因为串口初始化和接收的代码用的是SYSTEM文件夹下面的串口内容。这里对代码部分稍作讲解。
             
             
  1. //初始化IO串口1
  2. //bound:波特率
  3. void uart_init(u32 bound)
  4. {
  5. GPIO_InitTypeDef GPIO_InitStructure;
  6. USART_InitTypeDef USART_InitStructure;
  7. NVIC_InitTypeDef NVIC_InitStructure;
  8. //① 串口时钟使能,GPIO时钟使能,复用时钟使能:在使用一个内置外设的时候,首先要使能相应的GPIO时钟,然后使能复用功能时钟和内置外设时钟
  9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART1和GPIOA时钟
  10. //② 串口复位
  11. USART_DeInit(USART1); //复位串口1
  12. //③ GPIO端口模式配置
  13. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1_TX PA.9
  14. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  16. GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.9
  17. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX PA.10
  18. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  19. GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10
  20. //④ 串口参数初始化
  21. USART_InitStructure.USART_BaudRate = bound; //设置波特率
  22. USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8位
  23. USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
  24. USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
  25. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控
  26. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  27. USART_Init(USART1, &USART_InitStructure); //初始化串口
  28. #ifEN_USART1_RX //如果使能了接收
  29. //⑤ NVIC初始化
  30. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  31. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级 3
  32. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
  33. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能IRQ通道
  34. NVIC_Init(&NVIC_InitStructure); //初始化中断优先级
  35. //⑥ 开启中断
  36. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
  37. //⑦ 使能串口
  38. USART_Cmd(USART1, ENABLE); //使能串口
  39. }
    从代码中看出,初始化串口的过程,和前面介绍的一致,用标号①~⑦表示了顺序:
① 串口时钟使能,GPIO时钟使能;
② 串口复位;
③ GPIO端口模式设置;
④ 串口参数初始化;
⑤ 初始化NVIC;
⑥ 开启中断;
⑦ 使能串口。
    复用功能下GPIO模式怎么判定:
    需要查看《中文参考手册V10》P110的表格“8.1.11外设的GPIO配置”,这个我们在前面的端口复用章节有提到,这里再讲解一下。
    串口GPIO模式配置表:
序号 USART引脚 配置 GPIO配置
1 USARTx_TX 全双工模式 推挽复用输出
半双工模式 推挽复用输出
1 USARTx_Rx 全双工模式 浮空输入或带上拉输入
半双工模式 未用,可作为通用I/O
    查看手册得知,配置全双工的串口1,则TX(PA9)需要配置为推挽复用输出,RX(PA10)配置为浮空输入或带上拉输入。
 中断处理函数
            
            
  1. void USART1_IRQHandler(void) //串口1中断服务程序
  2. {
  3. u8 Res;
  4. if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  5. {
  6. Res =USART_ReceiveData(USART1); //读取接收到的数据
  7. if((USART_RX_STA&0x8000)==0) //接收未完成
  8. {
  9. if(USART_RX_STA&0x4000) //接收到了0x0d
  10. {
  11. if(Res!=0x0a)
  12. USART_RX_STA=0; //接收错误,重新开始
  13. else
  14. USART_RX_STA|=0x8000; //接收完成了
  15. }
  16. else //还没收到0X0D
  17. {
  18. if(Res==0x0d)
  19. USART_RX_STA|=0x4000;
  20. else
  21. {
  22. USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
  23. USART_RX_STA++;
  24. if(USART_RX_STA>(USART_REC_LEN-1))
  25. USART_RX_STA=0; //接收数据错误,重新开始接收
  26. }
  27. }
  28. }
  29. }
  30. }
    函数体里面通过函数:
if(USART_GetITStatus(USART1, USART_IT_RXNE)!= RESET)
判断是否是接收中断, 如果是,则读取串口接收到的数据:
Res=USART_ReceiveData(USART1);
    接下来对数据进行分析:
    这里设计了一个小小的接收协议:通过这个函数,配合一个数组USART_RX_BUF[],一个接收状态标志
USART_RX_STA实现对串口数据的接收管理。
    USART_RX_STA各位定义如下:
                                              USART_RX_STA
bit15 bit14 bit13~0
接收完成标志 接收到0x0d标志 接收到的有效数据个数
    USART_RX_BUF的大小由USART_REC_LEN定义。
    设计思路如下:
    当接收到从电脑发过来的数据后,把接收到的数据保存在USART_RX_BUF中,同时在接收状态标志
USART_RX_STA 中计算接收到的有效数据个数,当收到回车(0x0d、0x0a)的第一个字节0x0d时,计时器
将不再增加,等待0x0a的到来。
    如果0x0a没有到,则认为此次接收失败,重新开始下一次接收。
    如果顺利接收到0x0a,则标记USART_RX_STA的第15位,这样完成一次接收,并等待该位被其他程序
清除,从而开始下一次接收。
    如果在收到数据超过 USART_REC_LEN的时候,还没有收到0x0d,则会丢弃前面的数据,重新接收。

9.4 下载验证

 



















  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值