顺便说一句,这个程序也有另外一个用途,在晶振不准的时候仍然可以和电脑以标准波特率通讯。方法就是规定好帧格式,然后上位机不停换波特率找到没有误码率的波特率,然后根据下位机的应答计算出下位机的时钟频率,这个是受了老妖ISP的启发才想到的~大家可以参考我发布的另2篇文章:模拟串口自动测量波特率的单片机程序http://www.51hei.com/mcu/1537.html ,下面这个网页是用11.0592兆的晶振模拟串口接收发发送的已经通过本人测试http://www.51hei.com/mcu/1418.html
上代码:
/* * 自适应波特率模拟串口程序, * 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 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); printf("Could you please test another baudrate? "); printf("But I think that I couldn't to do..... "); } }
完整的源代码下载:http://www.51hei.com/f/molic.rar
转自:万致远的博客http://www.rwzy.co.cc
顺便说一下,根据重载值计算波特率的公式是:
R=重载值
Clock=系统时钟(HZ)
B=波特率
Clock=12(256-R)*B
上一篇:数码管电子钟
下一篇:模拟串口自动测量波特率的单片机程序
推荐阅读最新更新时间:2024-03-16 14:25