历史上的今天

今天是:2024年10月21日(星期一)

正在发生

2021年10月21日 | stm32专题十一:USART(三)初始化结构体和标准库函数分析

发布者:开元轩 来源: eefocus关键字:stm32  USART  标准库函数 手机看文章 扫描二维码
随时随地手机看文章

在之前的博客中分析了stm32串口的结构,和详细的发送、接受过程。现在来分析固件库中对于USART的标准函数


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;

固件库中初始化函数,就是往前一篇博客中提到的控制寄存器USART_CR1  USART_CR2中写入相应的数据,并计算波特率的值,然后写入BRR寄存器。


/**

  * @brief  Initializes the USARTx peripheral according to the specified

  *         parameters in the USART_InitStruct .

  * @param  USARTx: Select the USART or the UART peripheral. 

  *   This parameter can be one of the following values:

  *   USART1, USART2, USART3, UART4 or UART5.

  * @param  USART_InitStruct: pointer to a USART_InitTypeDef structure

  *         that contains the configuration information for the specified USART 

  *         peripheral.

  * @retval None

  */

void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)

{

  uint32_t tmpreg = 0x00, apbclock = 0x00;

  uint32_t integerdivider = 0x00;

  uint32_t fractionaldivider = 0x00;

  uint32_t usartxbase = 0;

  RCC_ClocksTypeDef RCC_ClocksStatus;

 

  /* The hardware flow control is available only for USART1, USART2 and USART3 */

  // 硬件流控只有在USART中才能使用,UART中不能用

  if (USART_InitStruct->USART_HardwareFlowControl != USART_HardwareFlowControl_None)

  {

    assert_param(IS_USART_123_PERIPH(USARTx));

  }

 

  usartxbase = (uint32_t)USARTx;

 

/*---------------------------- USART CR2 Configuration -----------------------*/

  // 先保存USART_CR2寄存器的状态

  tmpreg = USARTx->CR2;

  /* Clear STOP[13:12] bits */

  // 清除CR2的停止位,其他位保持不变

  tmpreg &= CR2_STOP_CLEAR_Mask;

  /* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/

  /* Set STOP[13:12] bits according to USART_StopBits value */

  // 根据配置的停止位,写入到相应的位置

  tmpreg |= (uint32_t)USART_InitStruct->USART_StopBits;

  

  /* Write to USART CR2 */

  // 八停止位配置写进CR2寄存器

  USARTx->CR2 = (uint16_t)tmpreg;

 

/*---------------------------- USART CR1 Configuration -----------------------*/

  tmpreg = USARTx->CR1;

  /* Clear M, PCE, PS, TE and RE bits */

  // 清除字长、校验、校验使能、发送和接收使能的位,再根据配置写入

  tmpreg &= CR1_CLEAR_Mask;

  /* Configure the USART Word Length, Parity and mode ----------------------- */

  /* Set the M bits according to USART_WordLength value */

  /* Set PCE and PS bits according to USART_Parity value */

  /* Set TE and RE bits according to USART_Mode value */

  tmpreg |= (uint32_t)USART_InitStruct->USART_WordLength | USART_InitStruct->USART_Parity |

            USART_InitStruct->USART_Mode;

  /* Write to USART CR1 */

  // 把配置的字长、校验、模式写入到CR1寄存器

  USARTx->CR1 = (uint16_t)tmpreg;

 

/*---------------------------- USART CR3 Configuration -----------------------*/  

  tmpreg = USARTx->CR3;

  /* Clear CTSE and RTSE bits */

  // 清除串口的发送、接收硬件流控

  tmpreg &= CR3_CLEAR_Mask;

  /* Configure the USART HFC -------------------------------------------------*/

  /* Set CTSE and RTSE bits according to USART_HardwareFlowControl value */

  tmpreg |= USART_InitStruct->USART_HardwareFlowControl;

  /* Write to USART CR3 */

  // 把配置的硬件流控制写入到CR3寄存器(通常不适用硬件流控)

  USARTx->CR3 = (uint16_t)tmpreg;

 

/*---------------------------- USART BRR Configuration -----------------------*/

  /* Configure the USART Baud Rate -------------------------------------------*/

  RCC_GetClocksFreq(&RCC_ClocksStatus);

  if (usartxbase == USART1_BASE)

  {

    apbclock = RCC_ClocksStatus.PCLK2_Frequency;

  }

  else

  {

    apbclock = RCC_ClocksStatus.PCLK1_Frequency;

  }

  

  /* Determine the integer part */

  if ((USARTx->CR1 & CR1_OVER8_Set) != 0)

  {

    /* Integer part computing in case Oversampling mode is 8 Samples */

    integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate)));    

  }

  else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */

  {

    /* Integer part computing in case Oversampling mode is 16 Samples */

    integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));    

  }

  tmpreg = (integerdivider / 100) << 4;

 

  /* Determine the fractional part */

  fractionaldivider = integerdivider - (100 * (tmpreg >> 4));

 

  /* Implement the fractional part in the register */

  if ((USARTx->CR1 & CR1_OVER8_Set) != 0)

  {

    tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);

  }

  else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */

  {

    tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);

  }

  

  /* Write to USART BRR */

  USARTx->BRR = (uint16_t)tmpreg;

}

接下来是在同步串口通信中使用的结构体,虽然这个用的很少,但学习时还是应该全面,因此也分析一下


typedef struct

{

 

  uint16_t USART_Clock;   // 时钟使能

 

  uint16_t USART_CPOL;    // 时钟极性(High或者Low)

                          // 表示串口空闲时时钟是高电平还是低电平

 

  uint16_t USART_CPHA;    // 时钟相位(USART_CPHA_1Edge或者USART_CPHA_2Edge)

                          // 表示在时钟的第一个边沿采集数据还是第二个边沿采集数据

  // 时钟的极性和相位一定是配合使用的

 

  uint16_t USART_LastBit; // 选择最后一位数据的时钟会不会发出

} USART_ClockInitTypeDef;

我们再看以一下固件库中的其他常用的配置函数


// 使能串口,配置的是CR1_UE位

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)

{

  /* Check the parameters */

  assert_param(IS_USART_ALL_PERIPH(USARTx));

  assert_param(IS_FUNCTIONAL_STATE(NewState));

  

  if (NewState != DISABLE)

  {

    /* Enable the selected USART by setting the UE bit in the CR1 register */

    USARTx->CR1 |= CR1_UE_Set;

  }

  else

  {

    /* Disable the selected USART by clearing the UE bit in the CR1 register */

    USARTx->CR1 &= CR1_UE_Reset;

  }

}

// DMA请求

void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)

{

  /* Check the parameters */

  assert_param(IS_USART_ALL_PERIPH(USARTx));

  assert_param(IS_USART_DMAREQ(USART_DMAReq));  

  assert_param(IS_FUNCTIONAL_STATE(NewState)); 

  if (NewState != DISABLE)

  {

    /* Enable the DMA transfer for selected requests by setting the DMAT and/or

       DMAR bits in the USART CR3 register */

    USARTx->CR3 |= USART_DMAReq;

  }

  else

  {

    /* Disable the DMA transfer for selected requests by clearing the DMAT and/or

       DMAR bits in the USART CR3 register */

    USARTx->CR3 &= (uint16_t)~USART_DMAReq;

  }

}

然后是中断配置函数,有很多个中断可以选择。这个函数写的还是有点复杂,仔细看,起始可以发现,基本就是如下过程。通过中断标志,来判断该中断由CR1(偏移地址0X0C)还是CR2(偏移0X10),或者是CR3(偏移0X14)。然后把相应寄存器的中断使能标志位置1。


/**

  * @brief  Enables or disables the specified USART interrupts.

  * @param  USARTx: Select the USART or the UART peripheral. 

  *   This parameter can be one of the following values:

  *   USART1, USART2, USART3, UART4 or UART5.

  * @param  USART_IT: specifies the USART interrupt sources to be enabled or disabled.

  *   This parameter can be one of the following values:

  *     @arg USART_IT_CTS:  CTS change interrupt (not available for UART4 and UART5)

  *     @arg USART_IT_LBD:  LIN Break detection interrupt

  *     @arg USART_IT_TXE:  Transmit Data Register empty interrupt

  *     @arg USART_IT_TC:   Transmission complete interrupt

  *     @arg USART_IT_RXNE: Receive Data register not empty interrupt

  *     @arg USART_IT_IDLE: Idle line detection interrupt

  *     @arg USART_IT_PE:   Parity Error interrupt

  *     @arg USART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)

  * @param  NewState: new state of the specified USARTx interrupts.

  *   This parameter can be: ENABLE or DISABLE.

  * @retval None

  */

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 */

[1] [2] [3]
关键字:stm32  USART  标准库函数 引用地址:stm32专题十一:USART(三)初始化结构体和标准库函数分析

上一篇:stm32专题十一:USART(二)结构框图
下一篇:stm32专题十一:USART(四)USART编程

推荐阅读

FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列采用一种新型的存储器扩展技术。在外部存储器扩展方面具有独特的优势,可根据系统的应用需要,方便地进行不同类型大容量静态存储器的扩展。使用FSMC控制器后,可以把FSMC提供的FSMC_A[25:0]作为地址线,而把FSMC提供的FSMC_D[15:0]作为数据总线。(1)当存储数据设为8位时,(FSMC...
10月16日和17日,山东—河北环网工程特高压菏泽、枣庄变电站500千伏送出工程先后建成投运,两座变电站500千伏部分及公用系统启动送电发挥作用,为山东—河北环网工程顺利投运奠定了基础。 特高压菏泽变电站500千伏送出工程本期新建特高压菏泽站至500千伏桂陵变电站500千伏双回线路9.6千米、铁塔25基,扩建特高压菏泽站和桂陵站各2个间隔。该工程的建成...
今年8月份,三星推出了一款外形酷似“腰果”形状的耳机产品,名叫三星Galaxy Buds Live。这是一款具备主动降噪能力的耳机,一经上市已获得不少网友的好评。10月21日,有消息称,该产品的美国版本现在增加了红色和蓝色两种配色,消费者可选择的款式更多了。  此前,三星Galaxy Buds Live发布时,只有迷雾金、白色和黑色三种配色版本可选,现在...
10月22日-24日,华为开发者大会2021将在东莞松山湖举办,与全球开发者携手共建智能世界的繁荣生态。根据官方邀请函上透露出来的信息,鸿蒙HarmonyOS 3.0、HMS Core 6、全屋智能等黑科技也将悉数亮相。随着万物互联新时代蓬勃兴起,众多开发者在用智慧赋能“泛在连接”的过程中,不断探索跨设备协同,应用和服务体验创新的新路径,加速底层技术持续进化...

史海拾趣

问答坊 | AI 解惑

您是否也曾有过想在论坛中发问,却不知如何开口的困惑?

本人计算机专业本科,去年毕业,现在在一家生产(确切的定义应该是“研发”,因为地质仪器需求量比较少,我们更多的精力投放在手头的科研项目上)地质勘探仪器的公司工作,公司的总工曾是文革后中科院电子所第一届研究生,我就在他的手下学习。大学 ...…

查看全部问答∨

模拟的今年找工作是啥情况啊

模拟的今年找工作是啥情况啊…

查看全部问答∨

转:看看开关电源厂家是如何骗人的

把主机拆开除灰尘,想想顺便也把电源也除除灰,拆开一看,感觉哪个PFC有点不对,顺便拆开看看,由于这台电脑是第一次配的,是一款杂牌电源,当时那JS说230块机箱电源随便选,觉得有问题,不过当时没经验,也就没管那么多~ 凡来坛里的一看就知道, ...…

查看全部问答∨

在控制面板中添加硬件错误!

我在“控制面板\\添加硬件"中按照向导安装到最后,点击完成的哪个界面 出现如下提示信息: 安装设备时出现了一个错误 名称已用作服务或服务显示名 各位大哥指点一下,可能是那里错误!说出解决的方法,越详细越好,哈哈 先谢谢各位捧场的大 ...…

查看全部问答∨

MSP-EXP430FR5739实验板套件团购

因为本来对MSP430暂时还是在数据上面的了解,并没有真正的深入学习过!所以希望申请个实验板学习!   再次感谢论坛提供这么好的机会!…

查看全部问答∨

头文件里0x0001u 十六进制数后加u是什么意思?

#define IE2_                (0x0001u)  /* Interrupt Enable 2 */DEFC(   IE2            ...…

查看全部问答∨

Quartus 并转串

代码如下:   always @(negedge clk or negedge rst_n)   begin     if(!rst_n)       begin         address      <=  1 ...…

查看全部问答∨

Beaglebone学习之5-外围电路设计完成(含原理图和PCB)

最近公司事情太忙,迟到这么久的设计终于完成了,不然真的辜负EEWORLD和大家的信任了(板子和奖金都到手了),今天已经把板子发出去做,周末应该就能回来了,到时再分享硬件调试和软件开发细节 另外板子做了10块,有兴趣的我可以赠送几块出来,还有 ...…

查看全部问答∨

请问大侠们,IAR怎么样在一个工程中建立多个文件

怎样在IAR中建立一个project含有多个file? 不同file之间的变量信息通过什么传输?全局变量为什么不行? (像下图一样,一个工程中包含多个文件)…

查看全部问答∨

【TI首届低功耗设计大赛】刷卡水表之程序略解+设计完结篇

         最近工作各种忙啊,不过还好终于今天抽点时间来写点东西咯,好了不说废话了,上篇主要介绍了硬件部分的设计,今天就说说程序设计吧。          MF RC522 利用了先进的调制 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved