转载自:http://www.cnblogs.com/TrueElement/archive/2012/09/14/2684298.html

几个问题:

1、状态寄存器(USART_SR)中的TC(Transmission complete)何时置位?它和TXE(Transmit data register empty,发送数据寄存器空)有何区别?可以先看看下面的图:

根据上面的图,TC置位的条件就是在上一个字节发完之后,数据寄存器仍为空(TXE=1)。USART_DR中的数据,只要移位寄存器把上一字节发完,马上就可以移入移位寄存器,而USART_DR可以装入新的数据。

2、波特率(Baud)的设置

从手册知道,stm32的串口可以设置分数波特率,可以从APB时钟得到精确的波特率。查看标准库(v3.5)的设置波特率的部分函数,这种设置的方法精度足够,以及发现一个在手册里面(rev 14)没有提到的位,先看代码:

/* USART OverSampling-8 Mask */
#define CR1_OVER8_Set ((u16)0x8000) /* USART OVER8 mode Enable Mask */
#define CR1_OVER8_Reset ((u16)0x7FFF) /* USART OVER8 mode Disable Mask */ uint32_t tmpreg = 0x00, apbclock = 0x00;
uint32_t integerdivider = 0x00;
uint32_t fractionaldivider = 0x00;
/*---------------------------- 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;
/* USART OverSampling-8 Mask */
#define CR1_OVER8_Set ((u16)0x8000) /* USART OVER8 mode Enable Mask */
#define CR1_OVER8_Reset ((u16)0x7FFF) /* USART OVER8 mode Disable Mask */ uint32_t tmpreg = 0x00, apbclock = 0x00;
uint32_t integerdivider = 0x00;
uint32_t fractionaldivider = 0x00;
/*---------------------------- 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;

a、新的设置位:CR1_OVER8_Set,位于CR1的第15位,但是手册里面没有提到(rev14);根据手册里面提到的波特率计算公式,估计默认这个位是0,代表每个bit采样16次,而置位的时候,每bit采样8次。手册里的计算公式:

这个计算公式即按照每bit采样16周期来计算的,所以上面的代码在采样8周期的时候,除以2了。

b、integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));  的计算与上面公式不一致,这是因为这行代码下面还有这么一句:

tmpreg = (integerdivider / 100) << 4;

所以再除以100,合起来就相当于除以16了,为什么这样子做?因为integerdivider是一个uint32,为了提高精度,所以那里乘以100了。

c、这个精度够不够?乘以100,相当于保留到小数点后两位,而我们知道BRR的分数部分有4位,精度为1/16 = 0.0625,所以可以看到这个精度是够的。那么上面可以不可以改成乘以250再除以1000呢?不行,因为加入apbclock用最高的频率(72M),那么250*apbclock/4将溢出(uint32).

d、如果波特率特别高,而apbclock又较低,导致按照上面公式计算,结果USARTDIV小于1,则这样是不行的,你不能指望USART还能自己提时钟速度。这个时候,CR1_OVER8应该会有些作用,可以将在目前APB时钟下的最大的波特率提升一倍。

STM32的USART的更多相关文章

  1. STM32的USART DMA传输(转)

    源:STM32的USART DMA传输 问题描述: 我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目( ...

  2. STM32串行通信USART解说笔记

    STM32串行通信USART程序例举链接:http://blog.csdn.net/dragon12345666/article/details/24883111 1.STM32串行通信USART的相 ...

  3. STM32的USART中断死循环,形成死机。

    作者:观海  QQ:531622 直接说重点:我用的是 STM32F103 芯片 USART2_IRQHandler 总是中断,程序死循环. 1.出现问题: 原程序的中断处理程序是: void USA ...

  4. [stm32] NRF24L01+USART搞定有线和无线通信

    前言 一般进行远程监控时,2.4G无线通信是充当远程数据传输的一种方法.这时就需要在现场部分具备无线数据发送装置,而在上位机部分由于一般只有串口,所以将采集到的数据送到电脑里又要在上位机端设计一个数据 ...

  5. stm32之USART学习

    首先,我是看着这位博主的文章受到的启发,进而加深了自己对USART的理解.下面是自己改装并实验过的程序. 原文:http://www.cnblogs.com/greatwgb/archive/2011 ...

  6. STM32基础分析——USART的DMA模式

    有关USART的DMA传输模式,其基本的概念和配置,网上有很多博客和教程都有,这里不再赘述,只是记录一下比较容易忽视而造成调试不通的问题. 1. 串口发送和接收分属两个DMA通道 一般方式操作串口时, ...

  7. STM32 串口USART DMA方式发送接收数据

    硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 文章目录 头文件 USART3_DR的地址 DMA的通道 DMA的中断 USART接收回调函数 头 ...

  8. STM32串口USART的使用方法和程序

    通用同步异步收发器(USART)提供了一种灵活的方法来与使用工业标准NR 异步串行数据格式的外部设备之间进行全双工数据交换. USART利用分数波特率发生器提供宽范围的波特率选择,支持同步单向通信和半 ...

  9. stm32串口USART 硬件流控 --学习笔记

    流控的概念源于 RS232 这个标准,在 RS232 标准里面包含了串口.流控的定义.大家一定了解,RS232 中的"RS"是Recommend Standard 的缩写,即&qu ...

随机推荐

  1. 当EL遇到char

    在EL表达式中,假设某个entity的status属性为char类型,此处假设为'1',在jsp中,对于${entity.status=='1'},我们预期的结果是true,但实际上是false - ...

  2. Nuget很慢,我们该怎么办

    在VS中给项目添加程序已经采用NuGet 十分方便 不过很多时候速度很慢,一直显示“正在检索信息” 其实直接使用程序包管理控制台,速度就会好很多 如果命令不太会写,安装包名不是确认,可以先登录 htt ...

  3. 在Java中如何实现“Pless presss any key to continue.”

    import java.util.*; class Continue{ public static void main(String[] args){ Scanner scanner=new Scan ...

  4. Nodejs与ES6系列4:ES6中的类

    ES6中的类 4.1.class基本语法 在之前的javascript语法中是不存在class这样的概念,如果要通过构造函数生成一个新对象代码 function Shape(width,height) ...

  5. Nivo Slider - 世界上最棒的 jQuery 图片轮播插件

    Nivo Slider 号称世界上最棒的图片轮播插件,有独立的 jQuery 插件和 WordPress 插件两个版本.目前下载量已经突破 1,800,000 次!jQuery 独立版本的插件主要有如 ...

  6. 为Titanium创建自己的安卓推送模块

    在手机应用中,推送是一个非常重要的功能.相对来说ios应用的推送功能很容易做,因为它统一都是用苹果的APNS服务实现的.但安卓这边就比较混乱了,虽然谷歌也推出了类似苹果的官方推送服务,但由于谷歌的服务 ...

  7. 在不知下面有几个元素的时候,要去除最后一个元素的下边框jquery代码

    <script> $(document).ready(function() { $(".search_list dl").each(function() {//遍历所有 ...

  8. 总结CSS3新特性(Transition篇)

    CSS 过渡(transition), 是 CSS3 规范的一部分, 用来控制 CSS 属性的变化速率. 可以让属性的变化过程持续一段时间,而不是立即生效.比如,将元素的颜色从白色改为黑色,通常这个改 ...

  9. OC单例快速实现

    首先新建一个头文件,定义如下宏: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ...

  10. Java中的经典算法之选择排序(SelectionSort)

    Java中的经典算法之选择排序(SelectionSort) 神话丿小王子的博客主页 a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕.也就是:每一趟 ...