关于一部分坑爹的51单片机来说,压根就米有串口啊!!特别是用来做小东西的利器:STC15F100系列的,坑爹到串口都米有的境地。当然,咱们能够运用软件来模仿串口。惋惜,软件模仿的串口速度那个慢(12T单片机),误码率比硬件串口那个高……可是总比没有的好。这个玩意不像硬件相同能支撑全双工(12T的。1T的能够,究竟12T的定时器中止频率快了主程序直接会被堵塞了……)。
别的STC的手册上面说的8位主动重载定时器居然TMOD等于6!导致我搞了一下午都调不通,没想到老妖写错了……定时器重载形式应该是=2.我现在想把TMOD寄存器的O去掉,再用这个词问好他们全家!!
趁便说一句,1T的51单片机满足在定时器里完成全双工,这便是为什么老妖说实在波特率要/3的原因。有RCNT=3这个句子在,所以能够完成一起接纳发送……老妖写程序不写注释是出了名的……可是至于一般的12T单片机。假如也用老妖得的程序,要注意定时器形式没有16位主动重装形式。假如/3的话,9600就成3200的波特率了……仍是非标准的,这个程序在89C52上最高波特率只能到9600,持续往上加就严峻误码……所以模仿串口仍是用1T单片机或许12T降3倍速吧,(可是速度能卡的可怕,我感觉9600都卡)。要不然误码率能搞死人。
对了,趁便阐明一下,这个程序在keil c51上通不过,由于Keil内置putchar……会提示重复界说。能过keil的程序请参阅http://www.51hei.com/mcu/1541.html,并且好像keil的printf函数有毛病……
#include#include #include void WaitTF0(){while(!TF0);TF0=0;}void WByte(BYTE out){//发送启始位BYTE i=8;BYTE tmp=out;TR0=1;//开定时器TX1=0;WaitTF0();//发送8位数据位while(i--){TX1=(tmp&0x01); //先传低位tmp=tmp>>1;WaitTF0();}//发送校验位(无)//发送结束位TX1=1;WaitTF0();TR0=0;} void putchar(char ch){WByte(ch);}BYTE RByte(){BYTE in=0;BYTE cnt;while(RX1==1);//等候RXD变低,发动定时器,这个是堵塞形式TR0=1;//同步开定时器WaitTF0();//比及周期曩昔for(cnt=0;cnt<8;cnt++){in=in >>1;//从高移到低if(RX1==1) in = in | 0x80;//假如RXD=1,则最高置位WaitTF0();//等候一位曩昔}//等候中止位//WaitTF0();TR0=0;//封闭定时器return in;}void Init_VSer(){//指令周期=(1000000/Baud)/(12/SysClock)//定时器值=0x100-指令周期TMOD |=0x02; //计数器0,方法2TH0=0xa0; TL0=0xa0; TR0=0; //中止计数//TF0=0; //ET0=0; //T1中止关//EA=0; //总中止关}void main(){BYTE a;Init_VSer();printf("Hello,world!");while(1){a=RByte();//堵塞形式putchar(a);}}
趁便附上老妖的减掉三倍速的1T单片机模仿串口程序。安稳得多,当然功率也低的多。那个是靠定时器中止完成的。不过至少不会象在12T上到主程序简直跑不动的境地。强烈要求老妖出有串口的C版别!
/*----------------------------------------------------*//* --- STC MCU International Limited -----------------*//* --- 演示STC 15 系列单片机运用定时器1完成模仿串口功用-----*//* --- Mobile: (86)13922809991 -----------------------*//* --- Fax: 86-755-82905966 --------------------------*//* --- Tel: 86-755-82948412 --------------------------*//* --- Web: www.STCMCU.com ---------------------------*//* 假如要在程序中运用或在文章中引证该程序, -----------------*//* 请在程序中或文章中注明运用了STC的资料及程序 -------------*//*----------------------------------------------------*/#include "reg51.h"//define baudrate const//BAUD = 256 - SYSclk/3/BAUDRATE/M (1T:M=1; 12T:M=12)//NOTE: (SYSclk/3/BAUDRATE) must be greater than 98, (RECOMMEND GREATER THAN 110)//开端一向看不懂为什么要除三//#define BAUD 0xF400 // 1200bps @ 11.0592MHz//#define BAUD 0xFA00 // 2400bps @ 11.0592MHz//#define BAUD 0xFD00 // 4800bps @ 11.0592MHz//#define BAUD 0xFE80 // 9600bps @ 11.0592MHz//#define BAUD 0xFF40 //19200bps @ 11.0592MHz//#define BAUD 0xFFA0 //38400bps @ 11.0592MHz//#define BAUD 0xEC00 // 1200bps @ 18.432MHz//#define BAUD 0xF600 // 2400bps @ 18.432MHz//#define BAUD 0xFB00 // 4800bps @ 18.432MHz//#define BAUD 0xFD80 // 9600bps @ 18.432MHz//#define BAUD 0xFEC0 //19200bps @ 18.432MHz#define BAUD 0xFF60 //38400bps @ 18.432MHz//#define BAUD 0xE800 // 1200bps @ 22.1184MHz//#define BAUD 0xF400 // 2400bps @ 22.1184MHz//#define BAUD 0xFA00 // 4800bps @ 22.1184MHz//#define BAUD 0xFD00 // 9600bps @ 22.1184MHz//#define BAUD 0xFE80 //19200bps @ 22.1184MHz//#define BAUD 0xFF40 //38400bps @ 22.1184MHz//#define BAUD 0xFF80 //57600bps @ 22.1184MHz//define UART TX/RX porttypedef bit BOOL;typedef unsigned char BYTE;typedef unsigned int WORD;BYTE TBUF,RBUF;BYTE TDAT,RDAT;BYTE TCNT,RCNT;BYTE TBIT,RBIT;BOOL TING,RING;BOOL TEND,REND;void UART_INIT();BYTE t, r;BYTE buf[16];void main(){TMOD = 0x00;//timer1 in 16-bit auto reload modeAUXR = 0x40;//timer1 working at 1T modeTL1 = BAUD;//initial timer1 and set reload valueTH1 = BAUD>>8;TR1 = 1;//timer1 start running[原文有过错],感觉这个代码不像老妖写的。注释都英文……ET1 = 1;//enable timer1 interruptPT1 = 1;//improve timer1 interrupt priorityEA = 1;//open global interrupt switchUART_INIT();while (1){//users functionif (REND){REND = 0;buf[r++ & 0x0f] = RBUF;}if (TEND){if (t != r){TEND = 0;TBUF = buf[t++ & 0x0f];TING = 1;}}}}