模拟串口自动测量波特率的单片机程序

发布者:幸福之星最新更新时间:2015-07-20 来源: 51hei关键字:模拟串口  波特率  单片机 手机看文章 扫描二维码
随时随地手机看文章
我这个程序能够测量串口的波特率,并且将自身的波特率设置到通讯波特率。

这个在STC89C52/STC15F104(其实主要针对STC15F104,因为它没有串口)上面通过。不过因为是模拟串口,在11.0592 12T的情况下,最多到19200。
然后在STC15F104上面,要适量的减少补偿值……
顺便说一句,编译器建议使用sdcc。keil的SB printf函数搞死我了……在22.1184 6T的情况下大约能到57600.
当然在STC15F系列到115200毫无压力,可是是半双工的。要做全双工只能减倍波特率……
测量波特率的方法很简单。校准他的波特率的方法就是发送没有连续低电平的字符,类似0x55/0xff/0x7f之类的。使用这个特性还可以将它用在STC自动冷启动下载器中。不过注意要限制校准波特率。否则你的正常串口通讯可能会被干扰,因为你比如115200通讯的时候,正好波形类似57600的7F,校准上去了把你的连接掐了,估计很多人都会看看程序是不是跑飞了……所以一定要把同步波特率降到4800以下,因为STC-ISP的默认最低波特率是从1200~4800.
这个也可以适用于不准晶振的单片机和计算机通讯。方法就是计算机以不同波特率发送校准信号,找出误码率最低的波特率,然后发送确认,让单片机在这个重载值下运行,也适用于时钟速度可能变化的单片机/懒得计算重载值的人使用。
然后低于4800的波特率在11.0592的速度下面只能分频,这也是不得已的……
上代码:

/*
* 自适应波特率模拟串口程序,
* BY 万致远@rwzy.co.cc
* CRYSTAL:任意
*/
#include
#include
#include
#define MIS_0 0
#define MIS_2 1
#define MIS_4 2
#define MIS_8 3 
#define MIS_16 4 
#define TX1 P1_0 //发送数据端口
#define RX1 P1_1 //接收数据端口
BYTE min_mode;//减倍模式
void WaitTF1()
{
    while(!TF1);
    TF1=0;
    if(min_mode==MIS_2)
    {// /2
        while(!TF1);
        TF1=0;
    }
    else if(min_mode == MIS_4)
    {// /4
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
    }
    else if(min_mode == MIS_8)
    {// /8
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
    }
    else if(min_mode == MIS_16)
    {// /16
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
        while(!TF1);
        TF1=0;
    }
}

void WByte(BYTE out)
{
    //发送启始位
    BYTE i=8;
    BYTE tmp=out;
    TR1=1;//开定时器
    TX1=0;
    WaitTF1();
    //发送8位数据位
    while(i--)
    {
        TX1=(tmp&0x01);     //先传低位
        tmp=tmp>>1;
        WaitTF1();
    }
    //发送校验位(无)
    //发送结束位
    TX1=1;
    WaitTF1();
    TR1=0;
}    [page]
void putchar(char ch)
{
    WByte(ch);
}
BYTE RByte()
{
    BYTE in=0;
    BYTE cnt;
    while(RX1==1);//等待RXD变低,启动定时器,这个是阻塞模式
    TR1=1;//同步开定时器//这里……
    //while(!TF1);
    //TF1=0;    
    WaitTF1();
    if(min_mode !=0)
    {
        while(!TF1);//注意这里的周期稍微长。要补偿
        TF1=0;
    }
    for(cnt=0;cnt<8;cnt++)
    {
        in=in >>1;//从高移到低
        if(RX1==1) in = in | 0x80;//如果RXD=1,则最高置位
        WaitTF1();//等待一位过去
    }
    while(!TF1);//注意这里的周期稍微长。要补偿
    TF1=0;
    TR1=0;//关闭定时器
    return in;
}

UINT f_Test(void)//测试脉宽
{
    TMOD=0x10;//设置计数器1为方式一计数器模式
    TH1=0;
    TL1=0;//定时器CLR
    while(!RX1);//等待频率脚变高,这个是测低电平的
    while(RX1);//等待脚变低,更换符号可以测正脉冲
    TR1=1;//开启定时器
    while(!RX1);//等待变高
    TR1=0;//停止计数
    //cyc=TH0<<8;
    //cyc=cyc+TL0;
    return (TH1<<8)+TL1;
}
void baud_t()
{
    BYTE k;//复用变量 
    ULONG frq=0; //周期变量
    for(k=0;k<5;k++)// 变量复用大法
    {
        frq=frq+f_Test();//测试
    }//测量5次取平均
    frq=frq/5;
    if(frq<0xff)
    {
        k=0x100-(frq&0xff);
        min_mode=MIS_0;
    }
    else
    {
        if(frq / 2 < 0xff)
        {//2400baud
            k=0x100-((frq/2)&0xff); //2分频
            min_mode=MIS_2;
        }
        else if(frq / 4 < 0xff)
        {//1200baud
            k=0x100-((frq/4)&0xff);//4分频
            min_mode=MIS_4;
        }
        else if(frq / 8 < 0xff)
        {//1200baud
            k=0x100-((frq/8)&0xff);//8分频
            min_mode=MIS_8;
        }
        else if(frq / 16 < 0xff)
        {//1200baud
            k=0x100-((frq/16)&0xff);//16分频
            min_mode=MIS_16;
        }
    }
    if(k > 0x50)
    {
        k=k+6;//加补偿,因为if语句让机器周期加长
        //如果对于STC的新MCU,这里要按照情况调整
    }
    TMOD=0x20;//设置定时器1为自动装载模式
    TH1=k;//载入新波特率
    TL1=k;
}
void main()
{
    while(1)
    {
        baud_t();//测量波特率,阻塞模式
        printf("Hello world! ");
        printf("Here:mode=%d,T1=0x%X ",min_mode,TH1);//这里如果你要使用keil请自己写字符串发送函数,和sprintf配合使用
        printf("Could you please test another baudrate? ");
        printf("But I think that I couldn't to do..... ");
    }
}

关键字:模拟串口  波特率  单片机 引用地址:模拟串口自动测量波特率的单片机程序

上一篇:再次发模拟串口,51自适应波特率
下一篇:用单片机+PWM来解码WAV真人声乐

推荐阅读最新更新时间:2024-03-16 14:25

51单片机流水灯控制(5种方法)
实现流程: 1. 新建一个工程(新项目) 2. 查看原理图确定需求(流水灯)对应LED引脚在单片机上的哪个引脚 3. 编写程序(通过查看原理图可以看到我们需要控制整个P2口以控制8个LED灯) 4. 编译程序,下载程序至开发板 5. 查看效果(调试) 进制转换表(因为单片机首先处理的是十六进制的数据,所以我们需要将二进制控制需求转换成十六进制去写代码): 控制代码: #include REGX52.H //头文件 #include Delay.h #include intrins.h /* ---------------------------------------------
[单片机]
51<font color='red'>单片机</font>流水灯控制(5种方法)
基于CC1100和P89LPC922微控制器实现无线传输测试系统的设计
引言 无线数据通信技术被越来越多地使用到嵌入式系统中,在简化布线的同时,也使数据交换变得更加便捷。本文介绍一种适用于远程计数无线传输的测试系统,该系统主要由德州仪器(TI)公司的CC1100射频收发器和飞利浦(Philips)公司的微处理器P89LPC922构成。 1 硬件设计 (1)总体方案设计 本设计由1个主机和1~32台终端从机组成。从机通过内部传感器计数后将数据以无线方式传送给主机,主机负责整个系统的调度、显示、配置。 (2)微控制器P89LPC922 P89LPC922芯片具有8 KB Flash程序存储器、1 KB可擦除扇区和64字节可擦除页,可擦除单个字节,指令执行时间只需2~4个时钟周期,指令执行速率6倍于标准
[单片机]
基于CC1100和P89LPC922<font color='red'>微控制器</font>实现无线传输测试系统的设计
华为智能电动获TUV南德大中华区首个车载MCU ISO 26262 ASIL D级证书
携手提速汽车产业电动化进程 东莞2022年8月16日 /美通社/ -- 8月15日,TUV南德意志集团(以下简称 TUV南德 )向华为数字能源技术有限公司智能电动领域(以下简称 华为智能电动 )旗下的车载电机控制器(以下简称 MCU )平台产品,授予ISO 26262:2018 ASIL D级功能安全产品认证证书。该证书的颁发不仅证明了这款产品的全生命周期符合ISO 26262汽车安全完整性(ASIL)最高等级的功能安全要求,充分显示了华为智能电动电控系统在提升效率、功率密度、EMC等方面不断突破创新边界的同时,在安全领域也在持续探索、追求卓越,为下一代高压化、智能化产品安全需求打下坚实的基础;同时也彰显了TUV南德作为在功能
[汽车电子]
华为智能电动获TUV南德大中华区首个车载<font color='red'>MCU</font> ISO 26262 ASIL D级证书
基于单片机的低功耗高精度融雪测量仪的设计
我国对于积雪的实时检测技术还比较落后,如通过利用卫星来实时监视积雪融化动态,但在实际的运作中,由于地面环境的复杂性存在比较大的误差与缺陷 。早在1973年,MrClain等人指出雪的表面反射率可以作为雪深的指示因子 ,但是由于地表土壤成分各不相同以及表面杂物不同,其检测效果也并不可观。因此,研制一套低功耗高精度的融雪测量仪是有必要的,而且具有广阔的应用前景。 1 总体设计方案  本设计提出以超声波传感器进行积雪厚度的实时监测,采用“渡越时间检测法”进行雪厚的测量。其测量原理为:超声波发射器垂直地向雪表面发射超声波,同时采集板上微控制器内部定时器开始计时,碰到雪面反射回来。当超声波接收器接收到反射波时,定时器就立即停止计时,根据定时
[单片机]
基于<font color='red'>单片机</font>的低功耗高精度融雪测量仪的设计
基于MSP430F448单片机的交流数字电压表设计
摘要:描述了一种简易的交流数字电压表的系统设计。系统以MSP430F448为核心,该单片机内部集成了12位的A/D转换器,转换器带有内部参考源、采样保持、自动扫描特性,极大地简化了硬件设计。因为单片机内部中断资源丰富,电压转换、定时等都采用中断触发,减少了系统响应时间,提高了软件执行效率。此外该单片机的液晶驱动能力可达160段,可以直接将A/D转化数据显示在LCD上。 MSP430F44x系列是TI公司推出的一款超低功耗的16位单片机,其运算速度快而且体积小。片内集成了8路12位A/D、串行通信接口、看门狗定时器、比较器、硬件乘法器等外围设备模块,从而降低了应用电路的复杂程度,提高了系统的可靠性。该芯片可以工作于2.5 V和3
[单片机]
基于MSP430F448<font color='red'>单片机</font>的交流数字电压表设计
单片机超声波测距原理图
这是一款单片机超声波测距原理图,这款单片机超声波测距板电路简单,制作容易,无需进行调试,电路焊焊接好后,下装程序后即可工作。 #include REG2051.H #define csbout P3_5 //超声波发送 #define csbint P3_7 //超声波接收 #define csbc=0.034 #define bg P3_4 unsigned char csbds,opto,digit,buffer ,xm1,xm2,xm0,key,jpjs,ki;//显示标识 unsigned char convert ={0x3F,0x06,0x5b,0x4f,0x66,0x6d
[单片机]
介绍单片机上的几种按键输入实现方法
按键作为一种简单实用的输入设备已经应用于各种单片机应用系统中,称得上是无处不在。 但是在不同的实用场合下所使用的按键也是各不相同。现在就对几种经常用到的按键及其使用方法进行介绍。 一、传统按键: 传统按键是现在在各种电子设备中应用最为广泛的按键,可能它们的形状各有不 同,但其控制方法却大同小异,利用按键是否按下的IO 电平状态变化来对其进行识别。 1)直接按键 最简单的键盘就是把电平信号直接接到IO 上。在程序里面读取IO 电平状态,如 果读到相应的电平,则说明此IO 上所接的按键被按下。这种方法原理与控制方法都非 常简单,但造成了IO 资源的浪费。这种按键方式的示意图如下: 2)扫描按键矩阵 这种按键输入方式很巧妙地利
[单片机]
基于C8051F060单片机和K9F2808UOC存储器实现数据采集系统的设计
从上个世纪九十年代起,电子技术在钻井井下得到应用。但井下钻具的振动会给很多传感器带来不利影响。 特别是对测量井下钻头姿态的惯性导航传感器影响巨大,在随钻振动环境中,如果对信号不作处理,根本就不能测量出正确的井斜角和方位角,也就无法实现井眼轨迹随钻控制的要求。本文介绍应用SoC芯片中的DMA技术对振动的高速采集和存储功能的实现方法,并给出了钻井环境中测试的结果。 1 方法的提出 传统的数据采集方法采用CPU直接控制的方式进行数据采集,数据传送需要经过CPU的中转才能存入存储器,传送速度慢且采集速率受到CPU的限制,极大影响了系统的采样频率,不能满足对振动信号高速采集的要求。而在DMA传送方式下,数据传送不经过CPU,由DMA
[单片机]
基于C8051F060<font color='red'>单片机</font>和K9F2808UOC存储器实现数据采集系统的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved