STM32F407 串口配置步骤

发布时间:2024-08-09  

介绍STM32F407串口配置步骤,完成串口的数据发送与接收、实现中断接收,支持printf重定向。


STM32F407 串口配置说明

STM32F4 的串口资源相当丰富的,功能也相当强劲,STM32F407ZGT6 最多可提供 6 路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持 LIN、 支持调制解调器操作、 智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA 等。


【1】串口硬件引脚分析

img

img

img

【2】串口复用引脚介绍

串口寄存器介绍在手册第26章

img

GPIO口复用功能引脚配置

img

img

F407串口对应的引脚

img

配置复用功能的寄存器

img

串口时钟频率配置分析

img

【3】串口1配置示例

Usart.c代码示例:


#include "usart.h"

 

 /*

 函数功能:串口1初始化

 函数形参:

  u32 clock   :时钟频率(默认*1000000HZ)  注意:APB1最大时钟频率为42MHZ  APB2最大时钟频率为84MHZ

  u32 baud :波特率

 硬件连接:

 PA9--- >TX

 PA10-- >RX

 */

 void USART1_Init(u32 clock,u32 baud)

 {

 /*1. 开时钟*/

 RCC- >AHB1ENR|=1< < 0;//使能PORTA时钟

 RCC- >APB2ENR|=1< < 4;//使能USART1时钟

 

 /*2. 复位串口时钟*/

 RCC- >APB2RSTR|=1< < 4; //使能USART1复位时钟

 RCC- >APB2RSTR&=~(1< < 4); //关闭USART1复位时钟

 

 /*3. 配置GPIO口模式*/

   GPIOA- >MODER&=~(0x3< < 9*2); //清除模式

 GPIOA- >MODER|=0x2< < 9*2;    //配置复用功能模式

 

 GPIOA- >MODER&=~(0x3< < 10*2); //清除模式

 GPIOA- >MODER|=0x2< < 10*2;    //配置复用功能模式

 

 GPIOA- >OTYPER&=~(0x1< < 9);  //0表示推挽输出

 

 GPIOA- >OSPEEDR&=~(0x3< < 9*2); //清除之前配置

 GPIOA- >OSPEEDR|=0x2< < 9*2;    //50MHZ输出速度

 

 GPIOA- >PUPDR&=~(0x3< < 10*2); //清除之前配置

 GPIOA- >PUPDR|=0x1< < 10*2;    //配置上拉

 

 GPIOA- >AFR[1]&=~(0xF< < 4*1); //清除PA9配置

 GPIOA- >AFR[1]|=0x7< < 4*1;    //配置PA9复用功能模式为串口1

 

 GPIOA- >AFR[1]&=~(0xF< < 4*2); //清除PA10配置

 GPIOA- >AFR[1]|=0x7< < 4*2;    //配置PA10复用功能模式为串口1

 

 /*4. 配置USART-CR寄存器*/

 USART1- >BRR=(clock*1000000)/baud;//配置波特率

 USART1- >CR1|=1< < 3;  //使能发送

 USART1- >CR1|=1< < 2;  //使能接收,并开始搜寻RX引脚上的起始位

 USART1- >CR1|=1< < 13; //USART模块使能。

 }

 

 

 /*

 函数功能:串口字符串发送

 函数形参:

 USART_TypeDef *USARTx :串口的类型 (USART1 USART2 USART3)

 u8 *str:将要发送的字符串

 */

 void USARTxSendString(USART_TypeDef *USARTx,u8 *str)

 {

 while(*str!='')

 {

 USARTx- >DR=*str;

   while(!(USARTx- >SR&1< < 7)){} //等待发送完成

 str++;

 }

 }

 

Usart.h代码示例


#ifndef USART_H

 #define USART_H

 #include "stm32f4xx.h"

 void USART1_Init(u32 clock,u32 baud);

 void USARTxSendString(USART_TypeDef *USARTx,u8 *str);

 #endif

 

Main.c代码示例


#include "stm32f4xx.h" // Device header

 #include "led.h"

 #include "delay.h"

 #include "key.h"

 #include "usart.h"

 int main(void)

 {

 u8 key,i,c;

 LED_Init();

 KEY_Init();

 USART1_Init(84,115200);

 while(1)

 {

  key=ScanKeyVal(0);

  if(key)

  {

   i=!i;

 LED0(i);

   LED1(i);

 USARTxSendString(USART1,"万邦易嵌嵌入式开发! ");

  }

  

  if(USART1- >SR&1< < 5) //接收到数据

  {

  c=USART1- >DR;

  USART1- >DR=c; //将接收到的数据原路返回

  }

 }

 }

 

【4】串口标准输入输出重定向

Usart.c文件增加代码:


#include "usart.h"

 

 /*

 函数功能:串口1初始化

 函数形参:

  u32 clock   :时钟频率(默认*1000000HZ)  注意:APB1最大时钟频率为42MHZ  APB2最大时钟频率为84MHZ

  u32 baud :波特率

 硬件连接:

 PA9--- >TX

 PA10-- >RX

 */

 void USART1_Init(u32 clock,u32 baud)

 {

 /*1. 开时钟*/

 RCC- >AHB1ENR|=1< < 0;//使能PORTA时钟

 RCC- >APB2ENR|=1< < 4;//使能USART1时钟

 

 /*2. 复位串口时钟*/

 RCC- >APB2RSTR|=1< < 4; //使能USART1复位时钟

 RCC- >APB2RSTR&=~(1< < 4); //关闭USART1复位时钟

 

 /*3. 配置GPIO口模式*/

   GPIOA- >MODER&=~(0x3< < 9*2); //清除模式

 GPIOA- >MODER|=0x2< < 9*2;    //配置复用功能模式

 

 GPIOA- >MODER&=~(0x3< < 10*2); //清除模式

 GPIOA- >MODER|=0x2< < 10*2;    //配置复用功能模式

 

 GPIOA- >OTYPER&=~(0x1< < 9);  //0表示推挽输出

 

 GPIOA- >OSPEEDR&=~(0x3< < 9*2); //清除之前配置

 GPIOA- >OSPEEDR|=0x2< < 9*2;    //50MHZ输出速度

 

 GPIOA- >PUPDR&=~(0x3< < 10*2); //清除之前配置

 GPIOA- >PUPDR|=0x1< < 10*2;    //配置上拉

 

 GPIOA- >AFR[1]&=~(0xF< < 4*1); //清除PA9配置

 GPIOA- >AFR[1]|=0x7< < 4*1;    //配置PA9复用功能模式为串口1

 

 GPIOA- >AFR[1]&=~(0xF< < 4*2); //清除PA10配置

 GPIOA- >AFR[1]|=0x7< < 4*2;    //配置PA10复用功能模式为串口1

 

 /*4. 配置USART-CR寄存器*/

 USART1- >BRR=(clock*1000000)/baud;//配置波特率

 USART1- >CR1|=1< < 3;  //使能发送

 #ifdef USART1_INTERRUPT

 USART1- >CR1|=1< < 5;  //开启串口接收中断

 SetNVICPriorityGrouping(USART1_IRQn,1,3); //设置中断优先级

 #endif

 USART1- >CR1|=1< < 2;  //使能接收,并开始搜寻RX引脚上的起始位

 USART1- >CR1|=1< < 13; //USART模块使能。

 }

 

 

 /*

 函数功能:串口字符串发送

 函数形参:

 USART_TypeDef *USARTx :串口的类型 (USART1 USART2 USART3)

 u8 *str:将要发送的字符串

 */

 void USARTxSendString(USART_TypeDef *USARTx,u8 *str)

 {

 while(*str!='')

 {

 USARTx- >DR=*str;

 while(!(USARTx- >SR&1< < 7)){} //等待发送完成

 str++;

 }

 }

 

 

 /*

 函数功能:重写printf底层函数接口

 */

 int fputc(int c,FILE *stream)

 {

   USART1- >DR=c; //发送一个字符

   while(!(USART1- >SR&1< < 7)){}

 return c;

 }

 

 

 /*

 函数功能:重新scanf底层函数接口

 */

 int fgetc(FILE *stream) 

 {

   while(!(USART1- >SR&1< < 5)){}

     return USART1- >DR;

 }

 

 

 /*

 函数功能:串口1的中断服务函数

 */

 void USART1_IRQHandler(void)

 {

   u8 data;

 if(USART1- >SR&1< < 5)

 {

  data=USART1- >DR;

    USART1- >DR=data;

 }

 }

img


Main.c代码示例


#include "stm32f4xx.h" // Device header

 #include "led.h"

 #include "delay.h"

 #include "key.h"

 #include "usart.h"

 int main(void)

 {

 u8 i;

 u8 buff[100];

 LED_Init();

 KEY_Init();

 USART1_Init(84,115200);

 while(1)

 {

 i=!i;

 LED0(i);

 LED1(i);

 printf("STM32F407串口测试! ");

 printf("请输入数据按回车键结束: (串口软件需要勾选发送新行) ");

 scanf("%s",buff);

 printf("你输入的数据为:%s ",buff);

 }

 }

 

 

第一步需要先编写设置中断优先级的函数:


sys.c代码示例


#include "sys.h"

 /*

 函数功能:设置NVIC中断控制器优先级

 函数形参:

 IRQn_Type IRQn:中断线

 uint32_t PreemptPriority:抢占优先级

 uint32_t SubPriority:次优先级

 */

 void SetNVICPriorityGrouping(IRQn_Type IRQn,uint32_t PreemptPriority, uint32_t SubPriority)

 {

  uint32_t Priority;

  NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2); //设置优先级分组,每个工程只能设置一次

    Priority=NVIC_EncodePriority(NVIC_PriorityGroup_2,PreemptPriority,SubPriority); //编码优先级

    NVIC_SetPriority(IRQn,Priority); //设置优先级

    NVIC_EnableIRQ(IRQn);

 }

 

 

Sys.h文件代码示例:


 #ifndef _SYS_H

 #define _SYS_H

 #include "stm32f4xx.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 */

 

 /**

 @code  

  The table below gives the allowed values of the pre-emption priority and subpriority according

  to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function

   ============================================================================================================================

     NVIC_PriorityGroup   | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority  | Description

   ============================================================================================================================

    NVIC_PriorityGroup_0  |                0                  |            0-15             |   0 bits for pre-emption priority

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    概要:   原理图分析   串口中断编程步骤分析   串口中断编程实例   串口原理图分析   串口中断编程步骤分析:   1、使能相应的时钟   2、配置GPIO管脚为串口功能   3、设置中断......
    们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。 想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤发送到电脑上,我们......
    软件都有很完整的程序调试功能。使用起来很方便。而我们的开发虽然也是用C语言,但我们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤......
    起来很方便。而我们的开发虽然也是用C语言,但我们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。 想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤......
    语言,但我们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。 想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤......
    们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。 想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤......
    软件的使用。 掌握STM32CubeIDE软件的基本设计流程和设计步骤,能够使用工具进行设计、编程、仿真调试。 学习UART串口的使用方法,掌握如何利用STM32MP157A芯片的串口输入输出。 实验环境 FS......
    编写 步骤:1、确定TMOD(计数器)工作方式2、配置TH1和TL1初值3、配置SCON、PCON4、打开中断允许位(总中断串口中断),配置中断中断内主要是SBUF读取发送数据),配置TCON打开中断......
    = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}```1.3 配置串口中断如果需要通过中断的方式进行数据接收和发送,还需要配置串口中断......
    向量表当中查看)   中断优先级分组,因为中断优先级只使用了高4位,所以,中断优先级的分组分别有以下几种情况:   最后,总结一下中断编程的三步曲:   第一步:使能外设某个中断,具体由对应的中断......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>