STM32
直播中

张飞雄

7年用户 952经验值
私信 关注
[问答]

如何对STM32F4串口相关的参数进行初始化呢

如何对STM32F4串口相关的参数进行初始化呢?如何写来定义这些参数呢?

回帖(1)

h1654155275.5669

2021-12-6 14:20:10
STM32F4工程--串口--配置一个发送函数(库函数)

一、初始化串口相关的参数

  首先在usart.c文件中编写入下代码,稍后为大家解释如何得到的此函数。

#include "usart.h"                 //包含.h函数
UART_HandleTypeDef usrt1_handler;  //定义句柄
void uart1_init(void)              //自定义串口初始化函数
{
    usrt1_handler.Instance=USART1;                     //定义为串口1  
        usrt1_handler.Init.BaudRate=115200;                //波特率为115200
        usrt1_handler.Init.WordLength=UART_WORDLENGTH_8B;  //自长为8
        usrt1_handler.Init.StopBits=UART_STOPBITS_1;       //1位停止位
        usrt1_handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;  //不设置硬件流
        usrt1_handler.Init.Mode=UART_MODE_TX_RX;           //模式为收发模式
        usrt1_handler.Init.Parity=UART_PARITY_NONE;        //无奇偶检验位
        HAL_UART_Init(&usrt1_handler);                     //使能串口1
}
1、首先需要定义添加usart.h文件,我想这个大家都知道为什么。
  #include "usart.h"  
2、定义一个串口1初始化函数uart1_init(){},在这里编写一些串口的初始化语句。
  在这个函数中,首先需要使能串口1,于是在函数中添加HAL_UART_Init();函数,这个函数声明在stm32f4xx_hal_usart.h,函数在stm32f4xx_hal_usart.c文件中,将.h文件中的HAL_UART_Init函数复制过去。如下图
  
  

  

  这个函数的入口函数是一个结构体的指针地址。

#include "usart.h"
void uart1_init(void)
{
        HAL_UART_Init(UART_HandleTypeDef *huart);
}
3、右击HAL_UART_Init(UART_HandleTypeDef *huart);中的UART_HandleTypeDef,点击Go To Definition Of"......."
  来找到这个结构体的定义。
  
  

  

  4、这样我们就找到了这个结构体,结构体在stm32f4xx_hal_usart.h文件的第116行,这里定义的变量有很多,其中我们这次只用到其中的一部分。结构体如下图:
  
  

  

   这个结构体的 USART_TypeDef   *Instance;定义串口的基地址。UART_InitTypeDef     Init;  这个为定义串口初始化结构体,其余的为串口的收发以及DMA等的配置,在本例程中用不到,就先不解释了。
  5、UART_HandleTypeDef usrt1_handler;
  这个函数的意思是使用串口初始化结构体定义usrt1_handler变量。我们把它定义为全局变量。一般外设函数都有一个结构体指针,这个叫句柄,其他地方也会引用,故定义为全局变量。

#include "usart.h"

UART_HandleTypeDef usrt1_handler;
void uart1_init(void)
{
        HAL_UART_Init(UART_HandleTypeDef *huart);
}
6、HAL_UART_Init入口参数为指针类型,入口是一个地址,我们就将结构体的地址值赋给他,因为入口参数为一个地址,所以要在usrt1_handler前加取地址符号&。

#include "usart.h"

UART_HandleTypeDef usrt1_handler;
void uart1_init(void)
{
        HAL_UART_Init(&usrt1_handler);
}
7、现在我们只是定义了结构体,但是没有对结构体的成员变量进行初始化。下面我们将对串口结构体进行初始化。
  首先是  usrt1_handler.Instance,Instance为USART_TypeDef结构体定义的变量。
  
  

  

  右键点击USART_TypeDef,点击Go To Definition Of".......",寻找到他的定义。
  
  

  

  好像也看不出什么。
  快捷键Ctrl+F,在寻找USART_TypeDef还定义过那些,我们发现了USART1等等。我们将USART1赋值给Instance
  
  

  

  于是有了

#include "usart.h"

UART_HandleTypeDef usrt1_handler;
void uart1_init(void)
{
        usrt1_handler.Instance=USART1;
       
        HAL_UART_Init(&usrt1_handler);
}
8、选好了串口1.我们将对串口1进行初始化,方法为:usrt1_handler.Init.=?,init为结构体UART_InitTypeDef所定义的变量,UART_InitTypeDef结构体的定义如下:
  
  

  

  结构体中定义了波特率、字长、停止位、模式、硬件流控制、过采量等等,这才是串口外设的一些特性参数。
  那么我们应该如何写来定义这些参数呢。
  首先定义的为波特率,一般我们使用的为115200、9600都可以。这里使用的是115200.
  其次定义的是字长,我们选择的是八位,那我们usrt1_handler.Init.WordLength=8;    我们这样直接等于8?这样合适吗,很显然是不正确的。
  我们使用Ctrl+F快捷键,在stm32f4xx_hal_usart.c中搜索WordLength,我们可以搜索到如下语句。
  
  

  

  我们查看一下IS_UART_WORD_LENGTH的定义,我们可以看到如下
  
  

  

  这里我们可以看到我们可以选择UART_WORDLENGTH_8B和UART_WORDLENGTH_9B,我们这里选择的是UART_WORDLENGTH_8B

#include "usart.h"

UART_HandleTypeDef usrt1_handler;
void uart1_init(void)
{
        usrt1_handler.Instance=USART1;
        usrt1_handler.Init.BaudRate=115200;
        usrt1_handler.Init.WordLength=UART_WORDLENGTH_8B;
        HAL_UART_Init(&usrt1_handler);
}
9、我们可以用同样于字长定义的方法将下面一些参数进行定义,就可以得到本节最开始的那个函数。
   二、初始化串口IO口时钟等参数

  usart.c文件中编写入下代码

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
                GPIO_InitTypeDef GPIO_Initure;
    if(huart->Instance==USART1)
    {
                        __HAL_RCC_GPIOA_CLK_ENABLE();                        //使能GPIOA时钟
                        __HAL_RCC_USART1_CLK_ENABLE();                        //使能USART1时钟
               
                        GPIO_Initure.Pin=GPIO_PIN_9;                        //PA9
                        GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //复用推挽输出
                        GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
                        GPIO_Initure.Speed=GPIO_SPEED_HIGH;                //高速
                        GPIO_Initure.Alternate=GPIO_AF7_USART1;        //复用为USART1
                        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA9

                        GPIO_Initure.Pin=GPIO_PIN_10;                        //PA10
                        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA10
                }
}
1、这个函数我想大家都能看懂,但是大家可能想为什么使用这个函数名,因为这个函数在stm32f4xx_hal.c函数中有定义,并定义为__weak函数
  
  

  

  在hal库中这个函数被HAL_UART_Init();函数所调用。
  2、也正是因为被HAL_UART_Init函数所调用,于是我们在函数内添加了 if(huart->Instance==USART1) 来判断是否是串口1,如果是串口1,才会执行下面的IO等参数的初始化。
   三、函数声明

  usart.h文件中编写入下代码,来进行函数声明和句柄的引用。

#ifndef _USART_H
#define _USART_H
#include "sys.h"
#include "stdio.h"       

extern UART_HandleTypeDef usrt1_handler;
void uart1_init(void);
#endif  
四、主函数(执行函数)

  在main.c文件中加入如下代码

/**************************************************************************
**作者:        小丁工程               
**时间:        2020.10.19
***************************************************************************/
#include "sys.h"
//---------------------主函数-------------------------------------------------


int main(void)
{
    u8 p[]="test";
    HAL_Init();//========================初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);//======设置时钟,180Mhz
    delay_init(180);//===================初始化延时函数
    uart1_init();       
    while(1)
    {                       
                        HAL_UART_Transmit(&usrt1_handler,p,sizeof(p),1000 );
                        delay_ms(300);       
                }
}
//---------------------end-----------------------------------------------------


HAL_UART_Transmit();函数为发送函数,入口参数有四个,基地址、数据、数据长度、最大等等时间。
   五、补充

  1、__weak函数为弱函数,意义为在没有用户函数的情况下执行此函数,当有用户定义此函数时,__weak函数视为没有。两个不冲突。
  2、sizeof(),求字符串的长度。
   (写此文章远远比想象的难,可能还有一些地方说的不是很清楚,非常欢迎私信和留言进行交流,如果对大佬您有帮助的话,还希望能给点个赞)
举报

更多回帖

发帖
×
20
完善资料,
赚取积分