社区导航

 

搜索
查看: 387|回复: 6

[原创] 【 ST NUCLEO-G071RB测评】_04_UART实验

[复制链接]

24

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2019-1-10 13:00 | 显示全部楼层 |阅读模式
本帖最后由 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的虚拟串口,原理图如下:
图片6.png
现就以UART2为例,一步一步实现串口的通信。
根据原理图中的PORT,可以找到TXRX引脚所对应的GPIO引脚,TX-->PA2, RX-->PA3,如下图所示:
图片7.png

· 查看STM32G071芯片用户参考手册
启用GPIO时钟
与前面实验一样,使用GPIO端口之前,需要先开启时钟,这里使用了GPIOA,所以需要将RCC_IOPENR[0]位置1,原理如下图所示:
图片8.png

设置GPIO引脚功能
开启GPIOA的时钟以后,设置GPIO的功能,即设置GPIOA_MODER寄存器,根据参考手册,MODER寄存器定义如下:
图片9.png
对应PA2PA3引脚的位置分别位于[5:4][7:6]四个位中,在位段的描述说明中,可以看到00为输入模式,01为通用输出模式,10为复用功能模式,根据应用需求,我们需要把PA2PA3作为UARTTxRx来使用,所以我们需要把MODER[5:4][7:6]都配置成10,即复用功能模式(AF

MODER寄存器配置为AF模式时,需要使用AFRLAFRH两个寄存器对引脚功能进行进一步设置,寄存器定义如下:
图片10.png
在这个寄存器中,每4个位控制一个引脚的功能,PA2引脚的功能位于[11:8]四个位中,PA3引脚的功能位于[15:12]四个位中,每4个位中0000~01118个组合表示引脚的8种功能,这里把对应的值用AF0~AF8来表示,每个引脚对应的值,所对应的功能也不同,下表描述的是引脚AF值所对应功能,其中PA2AF1表示USART2_TXPA3AF1表示USART2_RX功能
图片11.png
至此,我们基本就确定了AF寄存器的配置方法,需要把[11:8]配置为0x1 (0001:AF1)[15:12]也配置为0x1 (0001:AF1)
这样,PA2PA3的引脚功能就配置好了,接下来就需要配置USART外设模块了。

启用USART2时钟
USART连接在系统的APB总线,所以USART的时钟控制,在APBENR1中,如下图所示:
图片12.png
需要把寄存器的[17]位置位,即可开启USART2的时钟。

使能USART2模块
USART寄存器比较多,但是大多数默认参数已经满足需求,我们需要设置的寄存器并不多,首先要配置CR1寄存器,重点要设置下图所示的三个数据位:
图片13.png
图片14.png
寄存器中的[3][2]两个位用来使能TxRx[0]位用来使能USART设备,[5]位用来启用接收数据中断。

设置波特率
图片15.png

波特率的计算方法
图片16.png
计算方法详见文档。
本人根据文档,总结了一个公式,可以直接用在代码中:
        //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;

串口的初始化函数实现
  1. void UART2_Init(int baud)
  2. {
  3.         uint32_t temp;
  4.         uint32_t brr;
  5.         RCC->IOPENR |= (1<<0);        //Enable GPIOA
  6.         RCC->APBENR1 |= (1<<17);        //Enable USART2
  7.         
  8.         GPIOA->MODER &= ~((0x3<<4) | (0x3<<6)); //PA2 PA3
  9.         GPIOA->MODER |= (0x2<<4) | (0x2<<6); //PA2 PA3
  10.         GPIOA->AFR[0] &= ~((0xFUL<<12) | (0xFUL<<8));        //PA2 Tx  PA3 Rx
  11.         GPIOA->AFR[0] |= (0x1<<12) | (0x1<<8);        //PA2 Tx  PA3 Rx
  12.         
  13.         temp = SystemCoreClock * 100 / baud / 16;
  14.         brr = ((temp / 100)<<4) | ((temp%100) * 16 / 100) + (((temp%100) * 16 / 100)%100)/50;
  15.         USART2->BRR = brr;
  16.         
  17.         USART2->CR1 |= (1<<0)         //UE=1 USART Enable
  18.                         | (1<<3)                                                 //TE=1 Transmitter Enable
  19.                         | (1<<2);                                                //RE=1 Revicer Enable
  20.                         
  21.         USART2->CR1 |= (1<<5);        //enable RXNEIE
  22.         NVIC_EnableIRQ(USART2_IRQn);
  23. }
复制代码


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


启用USART中断
启用中断,直接使用CMSIS提供的NVIC_EnableIRQ()函数
NVIC_EnableIRQ(USART2_IRQn);

数据的接收
RxD引脚收到数据时,数据会保存在RDR寄存器中,如果在CR1中设置了RXNE位,收到数据时会触发中断,在中断处理函数中可以处理收到的数据
  1. #define UART2_RBUF_SIZE         64
  2. volatile uint32_t UARTStatus;
  3. volatile uint8_t  UARTTxEmpty = 1;
  4. volatile uint8_t  UARTBuffer[UART2_RBUF_SIZE];
  5. volatile uint32_t UARTCount = 0;
  6. volatile uint32_t UART_op = 0;

  7. void USART2_IRQHandler(void)        //中断处理函数
  8. {
  9.         if (USART2->ISR & (1<<5)){ //收到数据
  10.                   UARTBuffer[UARTCount++] = USART2->RDR;
  11.       if (UARTCount >= UART2_RBUF_SIZE)
  12.       {
  13.         UARTCount = 0;                /* buffer overflow */
  14.       }        
  15.         }
  16. }

  17. int UART2_GetChar(uint8_t *ch)
  18. {
  19.   if(UART_op != UARTCount)
  20.   {
  21.     *ch = UARTBuffer[UART_op];
  22.         UART_op ++;
  23.         if(UART_op >= UART2_RBUF_SIZE)
  24.           UART_op = 0;
  25.                 return 1;
  26.   }
  27.   return 0;
  28. }
复制代码


主函数
  1. int main(void)
  2. {
  3.         uint8_t ch;
  4.         UART2_Init(115200);
  5.         printf ("Welcom to EEWORLD!\n");
  6.         printf ("Your input will be echo!\n");
  7.         while(1){
  8.                 if (UART2_GetChar(&ch)){
  9.                         UART2_PutChar(ch);
  10.                 }
  11.         }
  12. }
复制代码


【实验现象】
开发板复位以后会打印输出两句话,然后在发送区发送任何数据,都会反显到接收区,效果如下:
图片17.png

下一个实验用串口+超级终端实现一个简单的俄罗斯方块游戏。


此内容由EEWORLD论坛网友lvxinn2006原创,如需转载或用于商业用途需征得作者同意并注明出处

此帖出自stm32/stm8论坛


回复

使用道具 举报

720

TA的帖子

0

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

发表于 2019-1-10 18:12 | 显示全部楼层
不错,学习了!


回复

使用道具 举报

24

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2019-1-10 20:43 来自手机 | 显示全部楼层
lising 发表于 2019-1-10 18:12
不错,学习了!

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

点评

使用寄存器对底层的了解能更加透彻,能学习的更扎实,代码也比较简洁。库尤其是利用CUBE个人感觉就是比较快捷方便。各有所长。  详情 回复 发表于 2019-1-10 21:29


回复

使用道具 举报

720

TA的帖子

0

TA的资源

一粒金砂(高级)

Rank: 3Rank: 3

发表于 2019-1-10 21:29 | 显示全部楼层
lvxinn2006 发表于 2019-1-10 20:43
互相学习,我这直接配寄存器的方法可能看起来比较笨

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


回复

使用道具 举报

1645

TA的帖子

1

TA的资源

纯净的硅(高级)

Rank: 6Rank: 6

发表于 2019-1-10 22:38 | 显示全部楼层
看前面想起自己上学的时候,呵呵。加油。
人已离开,无事别找,找也找不到。


回复

使用道具 举报

24

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2019-1-10 22:58 | 显示全部楼层
freebsder 发表于 2019-1-10 22:38
看前面想起自己上学的时候,呵呵。加油。

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


回复

使用道具 举报

11

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2019-3-25 18:05 | 显示全部楼层
楼主能发下工程么,我试了不知道怎么回事发送可以成功,但是接收不到数据,不知道什么原因很尴尬


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2019-4-21 14:40 , Processed in 0.210775 second(s), 19 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表