×
单片机 > 单片机程序设计 > 详情

关于89C52单片机11.0592M晶振产生115200波特率的方法

发布时间:2020-09-02 发布时间:
|

当然下面所讨论产生115200波特率的最大难题就是因为它的时钟周期是等于12个机器周期的(12T模式)


定时器T1要想作为波特率发生器,必须是工作在8位自动重装载模式下,并且禁止使能T1的中断! 


还有一个重要的寄存器就是PCON了,最高位SMOD可以使得波特率加倍!当然这里由于这里的8位自动重装载模式的限制,也并不是像我们想象的那样,既然可以产生9600的波特率那个加倍以下不就是115200了嘛?!


Too young, Too simple!


先看两个公式吧,, 


当波特率不加倍使用定时器T1,产生波特率的计算方法:


TH1 = TL1 = 256 - 晶振值/12/2/16/波特率


使用波特率加倍后的计算公式为:


TH1 = TL1 = 256 - 晶振值/12/16/波特率


当我们不加倍的时候,产生的最大波特率(让TH1 = 0xFF) 28800


加倍后产生的最大波特率为57600(刚好就是28800的两倍)


所以就增强型的51单片机89C52来说,T0是可定不能作为波特率发生器的,而T1貌似又达不到要求,没辙了吗? 别忘了,它还有T2呢!!!


先来简单的认识一下T2及其有关的寄存器!


先看主要的,咱们要用的! 


①作为波特率发生器


T2CON的TCLK和RCLK位为0(默认)时,串行口发送和接受的波特率由定时器1提供;置位为1时,由定时器2提供。可以一个通过定时器1,一个通过定时器2,这样可以获得发送和接受时不同的波特率。


注意的地方: 定时器2作为定时器时,递增频率为晶振频率的12分频,而定时器2作为波特率发生器时,它的递增频率为晶振频率的2分频。


定时器2作为波特率发生器的时候,TH2溢出并不会置位TF2,所以此时可以不用禁止定时器2中断,若是EXEN2位被置位时,可以将T2EX作为附加的外部中断。


定时器2作为波特率发生器的时候,不要对TH2和TL2读写,可以读陷阱寄存器,但是也不要写。当对定时器2的陷阱寄存器进行访问时,应关闭定时器(TR2清0)。


波特率 = 模式1和模式3的波特率=(振荡器频率/32) * [65535-(RCAP2H,RCAP2L)]


115200时对应的初值


#include

#include


void init_com( void ) 

   SCON=0x50;   

   TH2=0xFF;           

   TL2=0xFD;   

   RCAP2H=0xFF;   

   RCAP2L=0xFD; 


/*****************/

   TCLK=1;   

   RCLK=1;   

   C_T2=0;   

   EXEN2=0;


/*****************/

   TR2=1 ;

   TI = 1;

}


void main()

{

    init_com();


    while(1)

    {

         printf("Hello World\n");

    }

}


然后再次选择115200的波特率实验现象 


emmmmm,本来写到这里这篇算是完结了,,但是突然的收尾似乎显得有点意犹未尽,没错,想说的还没说完,继续造起来,一起来再来领悟一下神奇的T2以及探索一下还有哪些神奇的操作。



继续来看T2吧, 


对了,它自身定时功能。。


16位自动重装模式中,定时器2可通过C/T2位配置为定时器/计数器,根据外部使能标志位EXEN2的置位和清0,可分为两种情况:


  定时器2为16位自动重装的普通定时器,由陷阱寄存器提供重装的值,只需要预设一下即可,可用于定时精度要求高,定时时间长(16位)的情况。


A1、T2MOD=0x00(DCEN=0;默认情况);


与上一种情况相比,此时16位自动重新装载可由外部T2EX的负跳变,和溢出任意一种触发,并都能产生中断。


A2、T2MOD=0x01(DCEN=1);


 此时允许T2EX控制计数的方向;T2EX=0时,重装的值为0FF和0FF,递减计数与陷阱寄存器预存值相等时,置位TF2产生中断。T2EX=1时;自动重装值为陷阱寄存器中的值,溢出时置位TF2产生中断。


#include "reg51.h"


typedef unsigned char BYTE;

typedef unsigned int WORD;


//-----------------------------------------------


/* define constants */

#define FOSC 11059200L


#define T1MS (65536-FOSC/12/1000)   //1ms timer calculation method in 12T mode


/* define SFR */

sbit ET2 = IE^5;


sfr T2CON = 0xc8;                   //timer2 control register

sbit TF2  = T2CON^7;

sbit TR2  = T2CON^2;


sfr T2MOD = 0xc9;                   //timer2 mode register

sfr RCAP2L = 0xca;

sfr RCAP2H = 0xcb;

sfr TL2 = 0xcc;

sfr TH2 = 0xcd;


sbit TEST_LED = P1^0;               //work LED, flash once per second


/* define variables */

WORD count;                         //1000 times counter


//-----------------------------------------------


/* Timer2 interrupt routine */

void tm2_isr() interrupt 5 using 1

{

    TF2 = 0;

    if (count-- == 0)               //1ms * 1000 -> 1s

    {

        count = 1000;               //reset counter

        TEST_LED = ! TEST_LED;      //work LED flash

    }

}


//-----------------------------------------------


/* main program */

void main()

{

    RCAP2L = TL2 = T1MS;            //initial timer2 low byte

    RCAP2H = TH2 = T1MS >> 8;       //initial timer2 high byte

    TR2 = 1;                        //timer2 start running

    ET2 = 1;                        //enable timer2 interrupt

    EA = 1;                         //open global interrupt switch

    count = 0;                      //initial counter


    while (1);                      //loop

}


②当然不外乎还有时钟输出功能 


可参考这里看下其他时钟输出


52系列单片机,可设定定时器/计数器2通过T2(p1^0)引脚输出时钟。


P1^0除了可以作为普通I/O口外,还可以作为定时器2的外部计数输入和时钟信号输出。


 C/T2=0并且T2MOD的T2OE位为1时,可将定时器2选为时钟信号发生器,自动装初值。设置公式:


  时钟信号输出频率=(振荡器频率/4)* (65535-N)


1


2


3


在时钟输出模式下,计数器溢出不会产生中断请求。这种功能相当于定时器2可同时作为波特率发生器和时钟发生器。


因为此时外部中断并没有被暂用,若是在设置上不冲突的话可能同时还可以响应T2EX引入的外部信号,这个只是猜想,还没有用实验证明过,哈哈*


注:单片机对于外来脉冲信号具有计数功能,但是有要求: 计数脉冲的最高频率=振荡器的频率/24 


并且为了确保给定电平在电平变化之前能被采样一次,则这个电平至少要维持一个机器周期。


#include "reg51.h"


typedef unsigned char BYTE;

typedef unsigned int WORD;


//-----------------------------------------------


/* define constants */

#define FOSC 11059200L


#define F38_4KHz    (65536-18432000/4/38400)


/* define SFR */


sfr T2CON = 0xc8;                   //timer2 control register

sbit TF2  = T2CON^7;

sbit TR2  = T2CON^2;


sfr T2MOD = 0xc9;                   //timer2 mode register

sfr RCAP2L = 0xca;

sfr RCAP2H = 0xcb;

sfr TL2 = 0xcc;

sfr TH2 = 0xcd;


sbit T2 = P1^0;                     //Clock Output pin


//-----------------------------------------------


/* main program */

void main()

{

    T2MOD = 0x02;                   //enable timer2 output clock

    RCAP2L = TL2 = F38_4KHz;        //initial timer2 low byte

    RCAP2H = TH2 = F38_4KHz >> 8;   //initial timer2 high byte

    TR2 = 1;                        //timer2 start running

    EA = 1;                         //open global interrupt switch


    while (1);                      //loop

}


其实,额,,虽然51很是LOW,但是有限的资源玩的花了,有了更多更大的资源后,也更能会合理利用,那才是本事对不对。。。


嗯,就是这样。。


对了,除了T2还有哪些种方法嘞? 


1,把11.0592M换成22.1184M晶振。那么当在TH1=0xff时,刚好可以产生115200波特率。


2、换个IT的单片机。。。哈哈。。


关键字:89C52  单片机  晶振  波特率

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机制作超级流水灯