【 STM32WB55 测评】_05_UART寄存器配置实验
<div class='showpostmsg'>本次活动测评开发板STM32WB55 Nucleo Pack由ST意法半导体提供,感谢意法半导体对EEWorld测评的支持! https://www.stmcu.com.cn/Product/pro_detail/cat_code/STM32WB/family/81/sub_family/252/sub_child_family/0/layout/product 【实验目的】· 熟悉STM32WB55的串口模块的配置与使用。【实验环境】· NUCLEO-WB55 Nucleo Pack开发板· Keil MDK-ARM(Keil uVision 5.25.2.0)· Keil.STM32WBxx_DFP.1.0.0.pack
【实验资料】· NUCLEO-WB55 Nucleo Pack开发板原理图· STM32WB55xx Data Sheets· STM32WB55xx Reference manual(参考手册) 【实验分析】· 查看原理图在NUCLEO-WB55中,最方便使用的UART串口就是USART,直接连接到了ST_LINK的虚拟串口,原理图如下: 在STM32WB55中,有两组串口模块:LPUART和USART,通过查询手册STM32WB55xx Data Sheets,可知这两个引脚对应着USART1功能模块,如下图所示: · 查看STM32WB55xx Reference manual1. 启用GPIO时钟与前面实验一样,使用GPIO端口之前,需要先开启时钟,这里使用了GPIOB,所以需要将RCC->AHB2ENR的位置1,原理如下图所示: 2. 设置GPIO引脚功能开启GPIOB的时钟以后,设置GPIO的功能,即设置GPIOB_MODER寄存器,根据参考手册,MODER寄存器定义如下: 对应PB6和PB7引脚的位置分别位于、四个位中,在位段的描述说明中,可以看到00为输入模式,01为通用输出模式,10为复用功能模式,根据应用需求,我们需要把PB6和PB7作为UART的Tx和Rx来使用,所以我们需要把MODER都配置成10,即复用功能模式(AF)当MODER寄存器配置为AF模式时,需要使用AFRL、AFRH两个寄存器对引脚功能进行进一步设置,寄存器定义如下: 在这个寄存器中,每4个位控制一个引脚的功能,PB6引脚的功能位于四个位中,PB7引脚的功能位于四个位中,每4个位中0000~0111共8个组合表示引脚的8种功能,这里把对应的值用AF0~AF8来表示,每个引脚对应的值,所对应的功能也不同,下表描述的是引脚AF值所对应功能,其中PB6的AF7表示USART1_TX,PB7的AF7表示USART1_RX功能 至此,我们基本就确定了AF寄存器的配置方法,需要把配置为0x7 (0111:AF7),也配置为0x7 (0111:AF7)。这样,PB6和PB7的引脚功能就配置好了,接下来就需要配置USART外设模块了。 3. 启用USART1时钟USART连接在系统的APB2总线,所以USART的时钟控制,在APB2ENR中,如下图所示: 需要把寄存器的位置位,即可开启USART1的时钟。 4. 使能USART1模块USART寄存器比较多,但是大多数默认参数已经满足需求,我们需要设置的寄存器并不多,首先要配置CR1寄存器,重点要设置下图所示的三个数据位: 寄存器中的两个位用来使能Tx和Rx,位用来使能USART设备,位用来启用接收数据中断。 5. 设置波特率BRR寄存器 波特率的计算方法 计算方法详见文档。本人根据文档,总结了一个公式,可以直接用在代码中: //Baudrate = Fclk/(16*USARTDIV) //USARTDIV = Fclk / Baudrate / 16 // = SystemCoreClock / 115200 / 16 temp = SystemCoreClock * 100 / baud / 16; brr = ((temp / 100)<<4) | ((temp%100) * 16 / 100) + (((temp%100) * 16 / 100)%100)/50; USART2->BRR = brr; 6. 串口的初始化函数实现void USART1_Init(int baud)
{
uint64_t temp;
uint32_t brr;
RCC->AHB2ENR |= (1<<1); //使能GPIOB时钟
GPIOB->MODER &= ~((0x3<<12) | (0x3<<14));
GPIOB->MODER |= (0x2<<12) | (0x2<<14); //设置PB6 PB7为功能模式
GPIOB->AFR &= ~((0xFUL<<24) | (0xFUL<<28));
GPIOB->AFR |= (0x7<<24) | (0x7<<28); //PB6 TxPB7 Rx
RCC->APB2ENR |= (1<<14);
//Baudrate = Fclk/(16*USARTDIV)
//USARTDIV = Fclk / Baudrate / 16
temp = (uint64_t)SystemCoreClock * 100 / baud / 16;
brr = ((temp / 100)<<4) | ((temp%100) * 16 / 100) + (((temp%100) * 16 / 100)%100)/50;
USART1->BRR = brr;
USART1->CR1 |= (1<<29);
USART1->CR1 |= (1<<0) //UE=1 USART Enable
| (1<<3) //TE=1 Transmitter Enable
| (1<<2); //RE=1 Revicer Enable
USART1->CR1 |= (1<<5); //enable RXNEIE
NVIC_EnableIRQ(USART1_IRQn);
}
7. 数据的发送数据的发送,主要使用了TDR寄存器,当往TDR寄存器写数据时,数据会通过TxD引脚发送出去,并且一旦发送完成,会把完成状态体现在ISR寄存器中,封装发送函数如下:void UART1_PutChar(int data)
{
while((USART1->ISR&(1u<<7)) == 0); //Wait TXE=1
USART1->TDR = data;
}
8. 启用USART中断启用中断,直接使用CMSIS提供的NVIC_EnableIRQ()函数NVIC_EnableIRQ(USART1_IRQn); 9. 数据的接收当RxD引脚收到数据时,数据会保存在RDR寄存器中,如果在CR1中设置了RXNE位,收到数据时会触发中断,在中断处理函数中可以处理收到的数据,#define UART1_RBUF_SIZE 64
volatile uint32_t UARTStatus;
volatile uint8_tUARTTxEmpty = 1;
volatile uint8_tUARTBuffer;
volatile uint32_t UARTCount = 0;
volatile uint32_t UART_op = 0;
void USART1_IRQHandler(void)
{
if (USART1->ISR & (1<<5)){ //收到数据
UARTBuffer = USART1->RDR;
if (UARTCount >= UART1_RBUF_SIZE)
{
UARTCount = 0; /* buffer overflow */
}
}
}
int UART2_GetChar(uint8_t *ch)
{
if(UART_op != UARTCount)
{
*ch = UARTBuffer;
UART_op ++;
if(UART_op >= UART1_RBUF_SIZE)
UART_op = 0;
return 1;
}
return 0;
}
10. 主函数#include <stdio.h>
#include <stdint.h>
#include "uart.h"
int main(void)
{
uint8_t ch;
USART1_Init(115200);
printf ("Welcome to EEWORLD!\n");
printf ("Your input will be echo!\n");
while(1){
if (USART1_GetChar(&ch)){
USART1_PutChar(ch);
}
}
}
【实验现象】· 开发板复位以后会打印输出两句话,然后在发送区发送任何数据,都会反显到接收区,效果如下: 下一个实验用串口+ADC实现光照强度检测。
此内容由EEWORLD论坛网友lvxinn2006原创,如需转载或用于商业用途需征得作者同意并注明出处
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]