lvxinn2006 发表于 2019-1-10 13:00

【 ST NUCLEO-G071RB测评】_04_UART实验

<div class='showpostmsg'> 本帖最后由 lvxinn2006 于 2019-1-11 08:55 编辑

本次活动测评开发板ST NUCLEO-G071RB由ST意法半导体提供,感谢意法半导体对EEWorld测评的支持!
https://www.stmcu.com.cn/Product/pro_detail/cat_code/STM32G0/family/81/sub_family/261/layout/product


【实验目的】
· 掌握GPIO复用功能的配置方法· 掌握USART中断的使用· 理解USART串口使用的基本原理

【实验环境】· NUCLEO-G071RB开发板· Keil MDK-ARM(Keil uVision 5.25.2.0)· Keil.STM32G0xx_DFP.1.0.0.pack
【实验资料】· NUCLEO-G071RB开发板原理图· STM32G071x8/xB Data Sheet· STM32G071芯片用户参考手册
【实验分析】· 查看原理图在NUCLEO-G071RB中,最方便使用的UART串口就是UART2,直接连接到了ST_LINK的虚拟串口,原理图如下:
现就以UART2为例,一步一步实现串口的通信。根据原理图中的PORT,可以找到TX和RX引脚所对应的GPIO引脚,TX-->PA2, RX-->PA3,如下图所示:
· 查看STM32G071芯片用户参考手册 启用GPIO时钟与前面实验一样,使用GPIO端口之前,需要先开启时钟,这里使用了GPIOA,所以需要将RCC_IOPENR的位置1,原理如下图所示:
设置GPIO引脚功能开启GPIOA的时钟以后,设置GPIO的功能,即设置GPIOA_MODER寄存器,根据参考手册,MODER寄存器定义如下:对应PA2和PA3引脚的位置分别位于、四个位中,在位段的描述说明中,可以看到00为输入模式,01为通用输出模式,10为复用功能模式,根据应用需求,我们需要把PA2和PA3作为UART的Tx和Rx来使用,所以我们需要把MODER都配置成10,即复用功能模式(AF)
当MODER寄存器配置为AF模式时,需要使用AFRL、AFRH两个寄存器对引脚功能进行进一步设置,寄存器定义如下:在这个寄存器中,每4个位控制一个引脚的功能,PA2引脚的功能位于四个位中,PA3引脚的功能位于四个位中,每4个位中0000~0111共8个组合表示引脚的8种功能,这里把对应的值用AF0~AF8来表示,每个引脚对应的值,所对应的功能也不同,下表描述的是引脚AF值所对应功能,其中PA2的AF1表示USART2_TX,PA3的AF1表示USART2_RX功能至此,我们基本就确定了AF寄存器的配置方法,需要把配置为0x1 (0001:AF1),也配置为0x1 (0001:AF1)。这样,PA2和PA3的引脚功能就配置好了,接下来就需要配置USART外设模块了。
启用USART2时钟USART连接在系统的APB总线,所以USART的时钟控制,在APBENR1中,如下图所示:需要把寄存器的位置位,即可开启USART2的时钟。
使能USART2模块USART寄存器比较多,但是大多数默认参数已经满足需求,我们需要设置的寄存器并不多,首先要配置CR1寄存器,重点要设置下图所示的三个数据位:寄存器中的两个位用来使能Tx和Rx,位用来使能USART设备,位用来启用接收数据中断。
设置波特率
波特率的计算方法计算方法详见文档。本人根据文档,总结了一个公式,可以直接用在代码中:      //Baudrate         = Fclk/(16*USARTDIV)      //USARTDIV      = Fclk / Baudrate / 16      //                                        = 16000000 / 115200 / 16      //                                        = 8.68      temp = SystemCoreClock * 100 / baud / 16;      brr = ((temp / 100)<<4) | ((temp%100) * 16 / 100) + (((temp%100) * 16 / 100)%100)/50;      USART2->BRR = brr;
串口的初始化函数实现void UART2_Init(int baud)
{
      uint32_t temp;
      uint32_t brr;
      RCC->IOPENR |= (1<<0);      //Enable GPIOA
      RCC->APBENR1 |= (1<<17);      //Enable USART2
      
      GPIOA->MODER &= ~((0x3<<4) | (0x3<<6)); //PA2 PA3
      GPIOA->MODER |= (0x2<<4) | (0x2<<6); //PA2 PA3
      GPIOA->AFR &= ~((0xFUL<<12) | (0xFUL<<8));      //PA2 TxPA3 Rx
      GPIOA->AFR |= (0x1<<12) | (0x1<<8);      //PA2 TxPA3 Rx
      
      temp = SystemCoreClock * 100 / baud / 16;
      brr = ((temp / 100)<<4) | ((temp%100) * 16 / 100) + (((temp%100) * 16 / 100)%100)/50;
      USART2->BRR = brr;
      
      USART2->CR1 |= (1<<0)         //UE=1 USART Enable
                        | (1<<3)                                                 //TE=1 Transmitter Enable
                        | (1<<2);                                                //RE=1 Revicer Enable
                        
      USART2->CR1 |= (1<<5);      //enable RXNEIE
      NVIC_EnableIRQ(USART2_IRQn);
}

数据的发送数据的发送,主要使用了TDR寄存器,当往TDR寄存器写数据时,数据会通过TxD引脚发送出去,并且一旦发送完成,会把完成状态体现在ISR寄存器中,封装发送函数如下:void UART2_PutChar(int data)
{
      while((USART2->ISR&(1u<<7)) == 0);      //Wait TXE=1
      USART2->TDR = data;
}

启用USART中断启用中断,直接使用CMSIS提供的NVIC_EnableIRQ()函数NVIC_EnableIRQ(USART2_IRQn);
数据的接收当RxD引脚收到数据时,数据会保存在RDR寄存器中,如果在CR1中设置了RXNE位,收到数据时会触发中断,在中断处理函数中可以处理收到的数据#define UART2_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 USART2_IRQHandler(void)      //中断处理函数
{
      if (USART2->ISR & (1<<5)){ //收到数据
                  UARTBuffer = USART2->RDR;
      if (UARTCount >= UART2_RBUF_SIZE)
      {
      UARTCount = 0;                /* buffer overflow */
      }      
      }
}

int UART2_GetChar(uint8_t *ch)
{
if(UART_op != UARTCount)
{
    *ch = UARTBuffer;
      UART_op ++;
      if(UART_op >= UART2_RBUF_SIZE)
          UART_op = 0;
                return 1;
}
return 0;
}

主函数int main(void)
{
      uint8_t ch;
      UART2_Init(115200);
      printf ("Welcom to EEWORLD!\n");
      printf ("Your input will be echo!\n");
      while(1){
                if (UART2_GetChar(&ch)){
                        UART2_PutChar(ch);
                }
      }
}

【实验现象】开发板复位以后会打印输出两句话,然后在发送区发送任何数据,都会反显到接收区,效果如下:
下一个实验用串口+超级终端实现一个简单的俄罗斯方块游戏。

此内容由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>

lising 发表于 2019-1-10 18:12

不错,学习了!

lvxinn2006 发表于 2019-1-10 20:43

lising 发表于 2019-1-10 18:12
不错,学习了!

互相学习,我这直接配寄存器的方法可能看起来比较笨

lising 发表于 2019-1-10 21:29

lvxinn2006 发表于 2019-1-10 20:43
互相学习,我这直接配寄存器的方法可能看起来比较笨

使用寄存器对底层的了解能更加透彻,能学习的更扎实,代码也比较简洁。库尤其是利用CUBE个人感觉就是比较快捷方便。各有所长。

freebsder 发表于 2019-1-10 22:38

看前面想起自己上学的时候,呵呵。加油。

lvxinn2006 发表于 2019-1-10 22:58

freebsder 发表于 2019-1-10 22:38
看前面想起自己上学的时候,呵呵。加油。

哈哈,就是按照学校实验手册的形式写的:lol

周小北 发表于 2019-3-25 18:05

楼主能发下工程么,我试了不知道怎么回事发送可以成功,但是接收不到数据,不知道什么原因很尴尬
页: [1]
查看完整版本: 【 ST NUCLEO-G071RB测评】_04_UART实验