找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 20421|回复: 21
收起左侧

51单片机12Mhz晶振精准设置波特率

  [复制链接]
ID:401113 发表于 2019-2-9 16:35 | 显示全部楼层 |阅读模式
本帖最后由 海洋渔业 于 2019-2-10 00:05 编辑

相信很多朋友在学习串口通讯的时候,因为晶振是12Mhz而不能设置4800bps以上的波特率,我在学习中也是如此,网上也没有什么靠谱的方法。
作为一个新时代的青少年,通过不懈的学习(其实是看器件手册无意间看到的)终于有了突破。
1:晶振为11.0592Mhz
我们知道T1可以作为波特率发生器,也知道波特率计算公式(方式1、3):2的SMOD的次方除以32再乘T1溢出率(晶振频率除以12乘(256-TH1));
即:波特率=(2的SMOD次方/32)X晶振频率/[12x(256-TH1)]

我们可以轻松的算出TH1和TL1内的值,列如:
计算9600bps ,设SMOD=1;

9600bps=(2/32)X[11059200/12X(256-TH1)]
算得(256-TH1)=6,则TH1=250 (0XFA);

计算波特率为9600、串口工作方式为方式1的程序:
void init_serial()
{
     TMOD=0X20;//设置T1工作方式为8位自动重装
     SCON=0X50;//设置串口工作方式为10位异步收发器
     PCON=0X80;//SMOD置为1
     TH1=(256-6);//6的由来[(11059200/12)/16]/9600 (9600为所求波特率)
     TL1=(256-6);
     EA=1;//开总中断
     ES=1;//开串口中断
     TR1=1;//启动T1
}
2:晶振为12Mhz
如果我们继续将T1作为波特率发生器,那么计算的公式也没变化。
列如:
波特率为2400,SMOD=1;
2400bps=(2/32)X[12000000/12X(256-TH1)]
算得(256-TH1)=26.041666,是个无限循环小数,如果取26带进公式里算,波特率四舍五入后是2404,误差不是很大。
  1. void init_serial()
  2. {
  3.     TMOD=0X20;//设置T1工作方式为8位自动重装
  4.     SCON=0X50;//设置串口工作方式为10位异步收发器
  5.     PCON=0X80;//SMOD置为1
  6.     TH1=(256-26);
  7.     TL1=(256-26);
  8.     EA=1;//开总中断
  9.     ES=1;//开串口中断
  10.     TR1=1;//启动T1
  11. }
复制代码



如果4800bps,SMOD=1;
4800bps=(2/32)X[12000000/12X(256-TH1)]

算得(256-TH1)=13.0208333,也是个无限循环小数,取13,算出波特率约为4808,误差也不大。

  1. void init_serial()
  2. {
  3.     TMOD=0X20;//设置T1工作方式为8位自动重装
  4.     SCON=0X50;//设置串口工作方式为10位异步收发器
  5.     PCON=0X80;//SMOD置为1
  6.     TH1=(256-13);
  7.     TL1=(256-13);
  8.     EA=1;//开放总中断
  9.     ES=1;//开放串口中断
  10.     TR1=1;//启动T1
  11. }
复制代码


那么,就T1作为波特率发生器就够了吗?不行,高波特率误差大。

如:9600bps,SMOD=1;
9600bps=(2/32)X[12000000/12X(256-TH1)]
算得(256-TH1)=6.510416(6的循环)
如果我们取7,则计算出来的波特率为8928.571428(571428的循环),取6,波特率则为10416.66666(6的循环),误差太大。

这该怎么办呢?
有两种方法:1.换晶振(不推荐)  2.使用T2作为波特率发生器(推荐)
以下是有关T2的器件手册截图

T2

T2


这里着重注意TCLK与RCLK,手册上的描述是:RCLK=0时,将定时器1的溢出率脉冲作为串口模式1和模式3的接受时钟,TCLK=0时,将定时器1的溢出率脉冲作为串口模式1和模式3的(这个“的”是我加上的,不知道为什么前面有后面没有)发送时钟。
这两句话讲的已经够清楚了,我们只把RCLK置为1,那我们的接受波特率就是(2的SMOD的次方/32)X(T2溢出率);如果我们只把TCLK置为1,那么我们的发送波特率就为(2的SMOD的次方/32)X(T2溢出率);如果我们将RCLK与TCLK都置为1,那么我们的波特率就是(2的SMOD的次方/32)X(T2溢出率)
T2溢出率和T1溢出率不同它的计算公式为:晶振频率/[2X(65536-RCAP2H RCAP2L)],此外T2是一个16位的定时/计数器,不像T0、T1既是8位又是16位

使用T2作为波特率发生器的波特率计算公式为:(2的SMOD的次方/32)X(T2溢出率)
波特率=
(2的SMOD的次方/32)X晶振频率/[2X(65536-RCAP2H RCAP2L)];

按照T2的波特率计算公式我们就可以随着自己的想法设置波特率了,列如我们要设置9600bps,SMOD=1:
将9600bps代入
波特率=
(2的SMOD的次方/32)X晶振频率/[2X(65536-RCAP2H RCAP2L)],

得:
           9600bps=(2/32)X12000000/[2X(65536-RCAP2H RCAP2L)]
算得(65536-RCAP2H RCAP2L)=39;
所以有
  1. void init_serial()//设值9600bps的程序,大家可以试试
  2. {
  3.         SCON=0X50; //设置串口工作模式为10位异步收发器               
  4.         T2CON=0X34; //RCLK=1,TCLK=1,TR2=1               
  5.         PCON=0X80; //SMOD=1               
  6.         RCAP2H=(65536-39)/256; // 装入计算好的值,这是我喜欢的懒方法
  7.         RCAP2L=(65536-39)%256;//同上,不过这是对(65536-39)求余,前者是求模(也就是求商)
  8.         ES=1;//开串口中断
  9.         EA=1;//开总中断
  10. }
复制代码
本人属于发贴新手和单片机新手,如有错误请您委婉点地指出。
感谢您的浏览,同时也要谢谢审核我的管理员,真是麻烦您了!

【这是我第一次发稿】


评分

参与人数 1黑币 +100 收起 理由
admin + 100

查看全部评分

回复

使用道具 举报

ID:475247 发表于 2019-2-10 15:12 | 显示全部楼层
很不错的资料,收下了
回复

使用道具 举报

ID:137231 发表于 2019-2-17 12:20 来自手机 | 显示全部楼层
没那么麻烦,用内部晶振,完全匹配
回复

使用道具 举报

ID:440534 发表于 2019-2-28 13:40 | 显示全部楼层
楼主东西不错,解决了我的问题。
回复

使用道具 举报

ID:401113 发表于 2019-3-31 18:35 | 显示全部楼层
faxa1 发表于 2019-2-17 12:20
没那么麻烦,用内部晶振,完全匹配

请问什么是内部晶振?我读书少
回复

使用道具 举报

ID:73182 发表于 2019-4-1 15:24 | 显示全部楼层
赞一个
回复

使用道具 举报

ID:502872 发表于 2019-4-2 10:00 来自手机 | 显示全部楼层
太好了,刚遇到一个问题,解决了
回复

使用道具 举报

ID:411550 发表于 2019-11-17 15:52 | 显示全部楼层
好帖子!解决了想要精准定时和串口通信的问题
回复

使用道具 举报

ID:74784 发表于 2019-11-18 02:29 | 显示全部楼层
我习惯用11.0592Mhz~~~~~~~~~
回复

使用道具 举报

ID:25310 发表于 2019-12-25 10:47 | 显示全部楼层
直接24MHZ ,速度快,波特率都没问题
回复

使用道具 举报

ID:117433 发表于 2019-12-25 11:19 | 显示全部楼层
STC单片机都不用接晶振了,内部的就够用了
回复

使用道具 举报

ID:728623 发表于 2020-5-10 17:58 | 显示全部楼层
很有用,谢谢分享
回复

使用道具 举报

ID:110875 发表于 2020-5-10 22:17 | 显示全部楼层
一个善于钻研的人,值得尊敬。
回复

使用道具 举报

ID:65956 发表于 2020-5-11 08:14 | 显示全部楼层
51单片机用12M的晶振设置波特率是有误差没错,但这种通讯波特有他的误差范围,听我们这边的工程师说,误差到0.3%都没问题,所以用这个晶振最大只能9600都可以用的
回复

使用道具 举报

ID:67085 发表于 2020-7-9 10:42 | 显示全部楼层
给楼主点个赞。
回复

使用道具 举报

ID:550624 发表于 2020-10-20 19:23 | 显示全部楼层
楼主,这个解决了大问题,很感谢
回复

使用道具 举报

ID:891323 发表于 2021-3-12 21:19 | 显示全部楼层
太好了,刚遇到一个问题,解决了  赞赞
回复

使用道具 举报

ID:892209 发表于 2021-3-20 10:44 | 显示全部楼层
xizhe2005 发表于 2019-12-25 11:19
STC单片机都不用接晶振了,内部的就够用了

内部怎么调用?
回复

使用道具 举报

ID:748788 发表于 2021-3-20 16:32 | 显示全部楼层
rootn 发表于 2021-3-20 10:44
内部怎么调用?

没有晶振的stc下载时有设置频率的选项,见下图: ClipBoard.jpg

回复

使用道具 举报

ID:1005936 发表于 2022-3-15 10:01 | 显示全部楼层
感谢分享,帮助很大
回复

使用道具 举报

ID:969210 发表于 2022-5-31 11:50 来自手机 | 显示全部楼层
赞赞赞,才发现是晶振的问题,没想到9600差这么大,换2400就好了
回复

使用道具 举报

ID:891089 发表于 2022-6-5 10:20 来自手机 | 显示全部楼层
不错,用得到
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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