你的位置:首页 > 知识课堂 > 正文

波特率发生器

发布时间:2013-06-05

波特率发生器

路由器,我们在日常生活、工作中都经常用到,但不知道大家对“波特率发生器”是否知道呢?本文收集整理了一些资料,希望本文能对各位读者有比较大的参考价值。
波特率发生器
波特率发生器

所谓波特率发生器就是从输入时钟转换出需要的波特率clk。

波特率发生器不是产生波特率时钟的,波特率时钟频率/波特率因子=波特率。

FPGA波特率发生器

这里我们使用串行连接的最大速度115200波特,其他较慢的波特也很容易由此产生。

FPGA通常运行在远高于115200Hz的时钟频率上(对于今天的标准的来说RS-232真是太慢了),这就意味着我们需要用一个较高的时钟来分频产生尽量接近于115200Hz的时钟信号。

从1.8432MHz的时钟产生

通常RS-232芯片使用1.8432MHz的时钟,以为这个时钟很容易产生标准的波特率,所以我们假设已经拥有了一个这样的时钟源。

只需要将 1.8432MHz 16分频便可得到 115200Hz的时钟,多方便啊!

reg [3:0] BaudDivCnt;

always @(posedge clk) BaudDivCnt <= BaudDivCnt + 1;

wire BaudTick = (BaudDivCnt==15);

所以 "BaudTick" 每16个时钟周期需要置位一次,从而从1.8432MHz的时钟得到115200Hz的时钟。

从任意频率产生


早期的发生器假设使用1.8432MHz的时钟。但如果我们使用2MHz的时钟怎么办呢?要从2MHz的时钟得到 115200Hz,需要将时钟 "17.361111111..." 分频,并不是一个整数。我的解决办法是有时候17分频,有时候18分频,使得整体的分频比保持在 "17.361111111"。这是很容易做到的。

下面是实现这个想法的C语言代码:

while(1) // 死循环

{

acc += 115200;

if(acc >=2000000) printf("*"); else printf(" ");

acc %= 2000000;

}

这段代码会精确的以平均每 "17.361111111..." 个时钟间隔打印出一个"*"。

为了从FPGA得到同样的效果,考虑到串行接口可以容忍一定的波特率误差,所以即使我们使用17.3或者17.4这样的分频比也是没有关系的。

FPGA波特率发生器


我们希望2000000是2的整数幂,但很可惜,它不是。所以我们改变分频比,"2000000/115200" 约等于 "1024/59" = 17.356. 这跟我们要求的分频比很接近,并且使得在FPGA上实现起来相当有效。

//10 位的累加器 ([9:0]), 1位进位输出 ([10])

reg [10:0] acc; //一共11位!

always @(posedge clk)

acc <= acc[9:0] + 59; //我们使用上一次结果的低10位,但是保留11位结果

wire BaudTick = acc[10]; //第11位作为进位输出

使用 2MHz 时钟, "BaudTick" 为 115234 波特, 跟理想的115200波特存在 0.03% 的误差。

参数化的FPGA波特率发生器

前面的设计我们使用的是10位的累加器,如果时钟频率提高的话,需要更多的位数。

下面是一个使用 25MHz 时钟和 16 位累加器的设计,该设计是参数化的,所以很容易根据具体情况修改。

parameter ClkFrequency = 25000000; // 25MHz

parameter Baud = 115200;

parameter BaudGeneratorAccWidth = 16;

parameter BaudGeneratorInc = (Baud<<BaudGeneratorAccWidth)/ClkFrequency;

reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;

always @(posedge clk)

BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;

wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];

上面的设计中存在一个错误: "BaudGeneratorInc"的计算是错误的, 因为 Verilog 使用 32 位的默认结果, 但实际计算过程中的某些数据超过了32位,所以改变一种计算方法。
波特率发生器
波特率发生器

parameter BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-4))+(ClkFrequency>>5))/(ClkFrequency>>4);

这行程序也使得结果成为整数,从而避免截断。

这就是整个的设计方法了。现在我们已经得到了足够精确的波特率,可以继续设计串行接收和发送模块了。

经改造的DDS功能用作波特率发生器

一般情况下,可以用一个现有的振荡器,为一个UART产生一个波特率时钟。振荡器频率必须作分频,而分频会带来波特率误差。表1表示当用一个8 MHz晶振和一个普通的二进制分频器生成波特率时,产生误差的百分比。本例中的系统可以获得一个比波特率快16倍的时钟。

当示波器频率不相匹配时,波特率设置中的误差会增加。此时,可以增加一个工作在18.432 MHz的振荡器,以尽可能减小误差率。另外,可以采用DDS(直接数字综合)方法,以较高波特率使用相同振荡器,从而降低误差。

综上所述,本文已为讲解FPGA波特率发生器、经改造的DDS功能用作波特率发生器等等,相信大家对波特率发生器的认识越来越深入,希望本文能对各位读者有比较大的参考价值。

浏览过本文<波特率发生器>文的人也浏览了

串口波特率

http://baike.cntronics.com/abc/2424

波特率是什么?

http://baike.cntronics.com/abc/2391

基于单片机串行口红外通信的设计

http://club.cntronics.com/space.php?uid=198349&do=blog&id=32318

要采购振荡器么,点这里了解一下价格!
特别推荐
技术文章更多>>
技术白皮书下载更多>>
热门搜索
 

关闭

 

关闭