51串口发送字符串
谢谢这位同学首先做的笔记,让我明白了很多:http://www.cnblogs.com/freesblog/p/5040474.html
刚开始也是一直乱码,直到昨天我才解决了乱码的问题,原来这一切都是晶振频率惹的祸,今天开始不会乱码了。可以发送单个字符了。但是又出现了一个新的问题,一个很长的字符串怎么办?
很多人想,那好办啊,下面这个程序就可以:
/*发送一个字符串*/ void send_string(uchar *p){ while(*p!= '\0'){ send_byte(*p); p++; } }
这样不就可以实现字符串的发送了吗?是的,没错,但是在send_byte()这个函数里面该怎么写?其实这个函数写不好很容易和中断函数冲突。
当然,你可以这样写:
/*发送一个字符*/ void send_byte(uchar by){ SBUF = by; while(!TI);//等待发送完毕 TI = 0; }
如果你这样写了,那么你要么不要打开串口中断,要么就在串口中断里面什么都不写(如果你只是发送,不接收的话),这里只是讲发送,接收是一个道理的。如果你在中断函数里面写了下面这样的程序:
void uart_interrupt() interrupt 4{ if(RI==1)RI = 0; if(TI==1)TI = 0; }
那么,恭喜你,你不会在电脑端收到任何数据的(不对,你能收到字符串的第一个字符)。原因很简单:
当一个字符发送/接收完毕的时候 ,发送/接收标志位TI/RI会自动置1,如果你在初始化里面打开了串口中断的话,程序一定进入中断函数里面去执行:if(TI==1)TI = 0;而不是先执行while(!TI);//等待发送完毕
,所以,在中断里面TI又置了0,然后回到while(!TI);这样,就陷入了一个死循环。你的程序就卡在这里了。
总结:
当你发现无法发送字符串的 时候,首先检查自己的比特率是否对,就是检查能不能发送单个字符,如果单个字符发送没有问题,那么一定能发送字符串。
接下来检查你的初始化程序中有没有打开 串口中断。如果打开,看中断函数 有没有和单个字符发送函数冲突。
当然,当你只是发送数据的话,不接受,不打开串口中断也是可以的,就是自己手动清零中断标志。
下面附上源程序(亲测可用):
#include "reg52.h" #include "stdio.h" #define uchar unsigned char #define uint unsigned int void uart_cfg(); void send_byte(uchar by); void send_string(uchar *p); void delayms(uchar i); uchar str[] = "yes,you aer good!"; void main(){ uart_cfg(); //波特率4800 ,0xf9 while(1){ send_string(str); delayms(100); } } void uart_cfg(){ SCON = 0X50;//MODE 1 TMOD&= 0X0F;//清除T1的控制位 TMOD|= 0X20;//T1的工作模式2 PCON|= 0X80;//倍频 TH1 = 0xf3; //4800 TL1 = TH1; ET1 = 0;//禁止T1中断 // EA = 1; TR1 = 1; // ES = 1;//使能串口中断 ,无论是TI/RI出现,只要中断打开,单片机就进入中断函数。 } /*中断处理函数*/,如上面所说,写不写都一样。这里我屏蔽掉了 // void uart_interrupt() interrupt 4{ // // if(RI==1)RI = 0; // // if(TI==1); // //TI = 0; // } /*发送一个 字符*/ void send_byte(uchar by){ SBUF = by; while(!TI);//当写下这句的时候,就不要在中断函数里面在写TI = 0;这句了,不然进入中断函数将TI清零之后,程序就会一直卡在这里 TI = 0; //在这里将TI清零 } /*发送一个字符串*/ void send_string(uchar *p){ while(*p!= '\0'){ send_byte(*p); p++; } } /*简单延时*/ void delayms(uchar i) { uint j; while(i--) { for(j = 0; j < 150; j++); } }
发送成功:
虽千万里,吾往矣。