GD32F130之USART通信基础

GD32F130之USART通信基础
简介
家用水果榨汁机
GD32F130系列最多⽀持2个串⼝:USART0和USART1,其中USART0功能⽐USART1丰富。
机制
告诉我们,当采样频率⼤于信号频率的2倍时,就可以真实还原线路上的信号。⽽实际应⽤中,采样频率⼀般都远⼤于信号频率的2倍。
GD32F130的USART的接收电路,就可以选择以16倍频率或者8倍频率Rx引脚上的信号。当选择16倍频率过采样⽅式时,USART接收器在接收⼀个位的时候,会在⼀个⽐特率位的时间内对Rx采样16次,并选择中间3个采样点(第7、8、9个)进⾏评估,作为本次接收到的数据位逻辑值。当选择8倍频率过采样⽅式时,USART接收器在接收⼀个位的时候,会在⼀个⽐特率位的时间内对Rx采样8次,并选择中间3个采样点(第3、4、5个)进⾏评估,作为本次接收到的数据位逻辑值。如下图所⽰。
通过USART_CTL0的OVSMOD位来选择过采样率
OVSMOD=0:16倍过采样(常⽤)
OVSMOD=1:8倍过采样
除了可以配置过采样率,还可以选择采样点(评估点)个数:三采样点  或者  ⼀采样点。
当选择三个采样点⽅式时,其评估机制如下表。可以发现,如果 中间的3个采样点中有1个采样点的值与其他两个不同,不管是起始位,数据位,奇偶校验位或者停⽌位,都将产⽣噪声错误(NERR)。使得串⼝拥有检测通信是否产⽣了噪声⼲扰的能⼒(虽然可能很少使⽤这个功能)。
使⽤三个采样点⽅式时
三个采样点的值接收到的帧位是否噪声错误(NERR)
0000否
1111否
两个0,⼀个1(如001)0是
两个1,⼀个0(如110)1是
当使⽤⼀个采样点⽅式时,则⽆论如何都不会检测到噪声错误。通过USART_CTL2的OSB位来选择采样点的个数:
OSB=0:取中间3个采样点进⾏评估(常⽤)
OSB=1:取中间1个采样点进⾏评估,此时永远不会产⽣噪声错误NERR
⼤名⿍⿍的STC15单⽚机串⼝,就是使⽤的16过采样率,三采样点的⽅式进⾏接收串⼝数据的。可见这种组合⽅式⽤的⽐较多,实际开发⼀般使⽤这种。
帧数据部分长度
通过USART_CTL0寄存器的WL位来配置数据长度:
WL=0:使⽤8位数据位
WL=1:使⽤9位数据位
因为我们的应⽤层数据都是以字节(8位)为单位的,因此如果要启⽤校验位,则应该配置数据长度为9位,这样校验位是帧格式中数据位的最⾼位(MSB),低8位为应⽤层数据。如果不使⽤校验位,则配置数据长度为8位即可。
校验位
通过USART_CTL0的PCEN位来选择是否启⽤串⼝帧校验机制:
PCEN=0,禁⽤校验机制
PCEN=1,启⽤校验机制
通过USART_CTL0的PM位来选择校验⽅式:
PM=0,偶校验
PM=1,奇校验
停⽌位长度
通过USART_CTL1寄存器的STB[1:0]位段来选择停⽌位长度:
STB[1:0]=00,1位停⽌位(最常⽤)
STB[1:0]=01,保留
STB[1:0]=10,2位停⽌位
STB[1:0]=11,1.5位停⽌位
帧数据⼤⼩端
通过USART_CTL1寄存器中的MSBF位,控制帧中的数据部分的位在接收/发送时的顺序:
MSBF=0:数据发送/接收,采⽤低位在前(最常⽤,标准的串⼝通信使⽤的⽅式,LSB first)
MSBF=1:数据发送/接收,采⽤⾼位在前(⼏乎不⽤)
波特率的配置
波特率时钟由USART外设所在的外设时钟(USART_CLK)经过分频后产⽣,因此在确定波特率之前,要配置USART外设的外设总线时钟(USART_CLK)。
对于USART1,其外设时钟(USART_CLK)只能是APB1的时钟。
对于USART0,其外设时钟(USART_CLK)要通过寄存器RCU_CFG2的USART0SEL[1:0]来选择,可以使⽤下⾯的库函数来设置:
1//⽂件:gd32f10x_rcu.h
2//作⽤:设置USART0外设的时钟源
3//参数:
4//      RCU_USART0SRC_CKAPB2: CK_USART0 select CK_APB2  APB2时钟
智能卡制作5//      RCU_USART0SRC_CKSYS: CK_USART0 select CK_SYS    系统时钟
6//      RCU_USART0SRC_LXTAL: CK_USART0 select CK_LXTAL  LXTAL时钟
7//      RCU_USART0SRC_IRC8M: CK_USART0 select CK_IRC8M  内部8M IRC时钟
8void rcu_usart_clock_config(uint32_t ck_usart)
波特率(baudrate)与分频系数(USARTDIV)的关系(时钟单位是Hz,波特率单位是bps):
当使⽤16倍的过采样率时:USARTDIV = USART_CLK / (16*baudrate)
当使⽤8倍的过采样率时:USARTDIV = USART_CLK / (8*baudrate)
例如使⽤16倍的过采样率,USART_CLK = 72MHz,需要设置波特率为115200bps,则分频系数USARTDIV = 72000000 /
(16*115200) =  39.0625 。那么分频系数如何填写到USART_BAUD寄存器中呢?这就需要知道USART_BAUD寄存器在存储分频系数时的编码⽅式。
GD32⽀持⼩数波特率发⽣器,这样做的好处是,⽆论串⼝外设总线时钟(USART_CLK)是多少,都可以产⽣⾮常接近需要波特率的实际波特率。像51单⽚机它不⽀持⼩数波特率发⽣器,所以就需要在CPU时钟上做出调整,这就是为什么51单⽚机会使⽤
11.0592MHz这种奇怪的晶振的原因了。
USART_BAUD寄存器分为两个连续的部分:
USART_BAUD[15:4] = INTDIV,⽤来存储和编码分频系数的整数部分,整数部分直接存储到这⾥。
USART_BAUD[3:0] = FRADIV,⽤来存储和编码分频系数的⼩数部分,分频系数的⼩数部分在编码时要乘以16再存储到
USART_BAUD[3:0],所以解码分频系数的⼩数部的时候,就要⽤USART_BAUD[3:0]除以16。
例如,假设已知USART_BAUD=0x21D,则分频系数整数部分为USART_BAUD[15:4]  = 33。分频系数⼩数部分为
USART_BAUD[3:0] / 16 = 13 / 16 = 0.81,则分频系数等于33+0.81=33.81。
再例如,前⾯提到的分频系数 39.0625,其整数部分39直接存储到USART_BAUD[15:4],其⼩数部分 0.0625 要乘以 16后
(0.0625*16=1)在存储到USART_BAUD[3:0]。
以上就是设置波特率的具体过程,然⽽实际上外设库中已经帮我们编写好了设置波特率的函数,设置起来⾮常⽅便,如下:
1//作⽤:设置USARTx(x=0,1)的波特率
2//参数1:USARTx(x=0,1)
3//参数2:波特率
4usart_baudrate_set(USART0, (uint32_t)115200);    //设置USART0的波特率为115200
交换和反转
通过USART_CTL1寄存器可以配置下⾯4个交换和翻转机制,⼏乎都不需要使⽤,仅作了解。程序配置的时候可以忽略,保持默认值就⾏。
STRP:即将原本的RX引脚功能变为TX引脚,原本的TX引脚功能变为RX引脚。
TINV:将TX引脚电平反转,即⽤持续的低电代表空闲,起始位为1个波特率周期的⾼电平,结束位为1个波特率周期的低电平,数据位如果是逻辑1,则⽤低电平表⽰,如果是逻辑0,则⽤⾼电平表⽰。
RINV:将RX引脚电平反转,即接收时,将低电平视为空闲,将起始位视为1个波特率周期的⾼电平,将结束位视为1个波特率周期的低电平,数据位如果收到⾼电平,则解析为逻辑0,反之解析为逻辑1。
DINV:将帧格式中的数据位的逻辑值和电平反转,即数据位如果是逻辑1,则⽤低电平表⽰,如果是逻辑0,则⽤⾼电平表⽰。
接收溢出错误检测机制
当使⽤⾮DMA模式(查询法或者中断法)接收串⼝数据时,可能因为CPU太过于繁忙,来不及读取接收缓冲寄存器USART_ RDATA中的数据,导致接收溢出错误发⽣。
USART_CTL2寄存器中的OVRD位⽤于选择是否开启接收溢出检测机制。
OVRD=0:接收溢出检测功能使能。当接收到了⼀个新的串⼝帧但发现接收缓冲寄存器USART_ RDATA中的数据还没有被读⾛,ORERR 错误标志位将被置位,并且新接收的数据将会被丢弃。
OVRD=1:接收溢出检测功能禁⽌。当接收到了⼀个新的串⼝帧但发现接收缓冲寄存器USART_ RDATA中的数据还没有被读
发送器的发送过程
串⼝发送器是将来⾃CPU或者DMA的数据在波特率时钟的驱动下从TX引脚上发送出去。发送器内部主要由发送缓冲寄存器
USART_TDATA和发送移位寄存器构成。前者可以供开发者读写,后者是隐藏的。写⼊到发送缓冲寄存器USART_TDATA中的数据会⾃动转移到发送移位寄存器中,然后串⾏发送出去。如下图所⽰。在串⼝数据发送过程中,会发⽣两个事件TBE和TC,分别对应状态寄存器USART_STAT中的TBE标志位和TC标志位。
TBE事件和TBE标志位
TBE,即Transmit Buffer Empty,意思是发送缓冲寄存器空。状态寄存器USART_STAT的TBE标志位硬件置1来表⽰TBE事件发⽣。TBE标志位只读,完全由硬件设置,软件不能写。TBE标志位通过软件写⼊⼀个数据到USART_TDATA来清零。
当TBE事件发⽣时,表⽰当前发送数据缓冲寄存器USART_TDATA已经空了,可以写⼊新的数据到USART_TDATA⽽不会覆盖上⼀次写⼊发送缓冲器的数据。
系统上电后,TBE 默认为⾼电平,软件可以写⼊⼀个数据到USART_TDATA来清零TBE标志位,当USART_TDATA中的数据转移到发送移位寄存器后,TBE⼜被硬件置1,然后软件可以⽴刻再次写⼊⼀个新数据到USART_TDATA,重复这个过程,实现⽆间隔的串⼝数据连续发送过程。
TC事件和TC标志位
TC,即Transmission Completed,意思是发送完成。TBE硬件置1时,只表⽰USART_TDATA为空,不代表最近⼀次写⼊到
USART_TDATA的字节数据已经完全通过TX引脚发送出去了,这个字节可能还在移位寄存器中进⾏移位发送,所以不能⽤TBE标志来判断串⼝数据是否已经完全发送出去了。这个时候我们要使⽤TC标志:当TBE硬件置1(USART_TDATA为空)且移位寄存器中也是空的时候,发⽣TC事件,硬件置TC=1,
这样才代表最近⼀次的N个串⼝字节完全发送完成了。在禁⽤ USART 或进⼊低功耗状态之前,必须等待 TC 硬件置位,否则不能保证发送的数据完全发送完成。
TC标志由硬件置位,通过软件写USART_INTC寄存器的TCC位来清零。
系统上电后,TC默认为1。所以在初始化串⼝最后,应该软件清零TC标志位,为后⾯数据发送时使⽤TC标志做准备。同理,每次发送完成⼀串数据后,也要软件清除TC标志位。
连体滑雪服来⼀个例⼦:使⽤USART0,PA9为TX,PA10为RX,波特率9600,使⽤查询法连续发送字符A和B。
1#include "gd32f1x0.h"
2#include <stdio.h>
3#include <string.h>
4
5汽车智能防盗系统
6//软件延时n个毫秒
7void delay_ms(uint32_t n)
8{
9 uint32_t j;
10 while(n--)
11 {
12  j=18888;
13  while(j--);
16
17void RCU_config(void)
18{
19 rcu_periph_clock_enable(RCU_GPIOA);  //使能GPIOA时钟
20 rcu_usart_clock_config(CK_APB2);        //选择USART0外设的时钟源
21 rcu_periph_clock_enable(RCU_USART0) ;    //使能USART0外设时钟
22}
23
24void NVIC_config(void)
25{
26 nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
27 //没有使⽤USART0的中断
28}
29
30void GPIO_config(void)
31{
32 //====================【USART0的引脚配置】=====================================
33 //PA9-USART0-TX引脚的GPIO参数(USART0-TX:PA9,AF1)
34 gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9);
35 gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9 );
36 gpio_output_options_set(GPIOA,GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_9);
37 //PA10-USART0-RX引脚的GPIO参数(USART0-RX:PA10,AF1)
38 gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10);
39 gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10 );
40
41}
42
43void USART0_config(void)
44{
45 usart_deinit(USART0);    //复位USART0
46
47 //--------串⼝基本配置-------
48 usart_baudrate_set(USART0,9600);
49 usart_parity_config(USART0,USART_PM_NONE);
50 usart_word_length_set(USART0,USART_WL_8BIT);
51 usart_stop_bit_set(USART0,USART_STB_1BIT);
52
53 //--------过采样⽅式设置-------
54 usart_oversample_config(USART0,USART_OVSMOD_16);
55 usart_sample_bit_config(USART0,USART_OSB_3BIT);
56
57 //----------接收溢出检测机制---------
58 usart_overrun_disable(USART0);
59
60 usart_enable(USART0);                                //使能USART(UEN=1)
61 usart_transmit_config(USART0,USART_TRANSMIT_ENABLE);  //使能发送器(TEN=1)
62 usart_receive_config(USART0,USART_RECEIVE_ENABLE);    //使能接收器(REN=1)
63
64 usart_flag_clear(USART0,USART_FLAG_TC);  //初始化完成最后清零TC标志,为下次使⽤做准备65}
66
67//查询法发送字符串
68void USART0_sendStr(const char*msg)
69{
70 uint32_t i;
71 for(i=0;msg[i];i++)
72 {
73  while(!usart_flag_get(USART0,USART_FLAG_TBE)){}  //等待TBE硬件置1
手术台74  usart_data_transmit(USART0,msg[i]);    //向TDATA寄存器写⼊字节数据
75 }
76
77 while(!usart_flag_get(USART0,USART_FLAG_TC)){}  //等待TC硬件置1
微型压力传感器芯片78 usart_flag_clear(USART0,USART_FLAG_TC);        //清除TC标志,为下次使⽤准备

本文发布于:2024-09-22 13:25:51,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/177703.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:发送   接收   数据   时钟
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议