浏览 15899 次
锁定老帖子 主题:51系列单片机之串口通信
精华帖 (0) :: 良好帖 (0) :: 新手帖 (10) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-05
最后修改:2009-04-06
单片机的中断系统中第4个中断就是串口中断,要进行串口通信首先就要打开CPU总中断EA,还要打开串口通信中断ES,这是串口通信的前堤,而串口通信也跟计时器一样有很多的模式,因此我们还要设置SCON寄存器来指定采用哪一种方式进行通信,而在通信的过程中,我们还要设定通信的波特率,不然的话,单片机是没办法进行采样的,这样也不会得到正确的结果了.我在实验过程中用到的是1号定时器来设定的波特率,用到了计时器方式2,也就是8位自动重装,这样可以简化编程,她的实现思想就是将常数放入TH,而TL中则是初始化参数,当溢出时,单片机会自动将TH中的常数装入TL中. 再来说说波特率,我们为什么要设定波特率,因为单片机会以16倍波特率的速度进行采样,而在实验中我们用的是10位异步收发方式,因此要将SM0置0,SM1置1.而其中的10位有8位数据位,第一位和最后一位是发送数据的起始与结束.采用高的皮特率就不会出错啦.而波特率是有一个公式的: 方式0的波特率 = fosc/12 方式2的波特率 =(2SMOD/64)· fosc 方式1的波特率 =(2SMOD/32)·(T1溢出率) 方式3的波特率 =(2SMOD/32)·(T1溢出率) T1 溢出率 = fosc /{12×[256 -(TH1)]} 根据公式我们很容易就算出当晶振为110592HZ时,要达到9600的波特率,我们只需要将TL1置FDH即可,如下图: 除此之外,你还要将SCON中的REN位置1,不然的话,单片机是不会接收数据的. 还有不要忘了选择定时器的工作方式,设置TMOD为0x20既是工作方式2,8位自动重装定时器. 这样一来,初始批工作算是差不多了.而串口通信分为中断方式,和查询方式,如果你想用查询方式你也不用设置IE寄存器了. 在串口通信中,还有一个很重要的寄存器SBUF,其实也不是一个,是两个,只是它们共用同一个地址,再热气表达式的不同,单片机会自动选择使用哪一个SBUF. 下面是我写的一个例子程序,产生的效果是:向单片机发送任一个0~255之间的数,将会被显示到数码管上.并且单片机还会自动把刚才传过去的数又发送回来 ,实验过程中用到了几个工具如下: 串口调试助手V2.1.exe,51串口波特率计算器.exe(我已打包在附件中)还有一些必用的就不说了. #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit sda = P1^0; sbit clk = P1^1; sbit dig1 = P1^2; sbit dig2 = P1^3; sbit dig3 = P1^4; sbit dig4 = P1^5; uchar r,flag; uchar code table[]={0x7e,0x0c,0xb6,0x9e, 0xcc,0xda,0xfa,0x0e, 0xfe,0xde,0xef,0xf9, 0x72,0xb8,0xf2,0xe2}; void init(); void write(uchar); void display(uchar); void delay(uchar); void main() { init(); while(1) { //查询方式通信 //if(RI==1) //RI为1表示收到一字节数据 //{ // RI = 0;//此步必不可少,因为硬件不能将其置0 // r = SBUF; //} display(r); //中断方式通信 delay(10); if(flag==1) { flag = 0; ES = 0; SBUF = r; //放送数据 while(!TI); TI = 0; ES = 1; } } } /** 串口中断 **/ void ser() interrupt 4 { RI = 0; r = SBUF; flag = 1; } /** 延迟函数 **/ void delay(uchar t) { uchar x,y; for(x=t;x>0;x--) for(y=101;y>0;y--); } /** 初始化 **/ void init() { dig1 = 1; dig2 = 1; dig3 = 1; dig4 = 1; r = 0xff; TMOD = 0x20; TH1 = 0xfd; TL1 = 0xfd; TR1 = 1; //启动定时器1,从而设定了串口通信的波特率 SM0 = 0; SM1 = 1; //设定串口通信方式为十位异步收发器 REN = 1; //打开串口通信 EA = 1; ES = 1; } /** 向数据码管写入一个字节数据 **/ void write(uchar u) { uchar i; for(i=0;i<8;i++) { clk = 1; sda = u&0x80; clk = 0; u = u<<1; } } /** 显示一个3位的整数 **/ void display(uchar num) { uchar bai,shi,ge; bai = num/100; shi = num%100/10; ge = num%10; /* 显示个位 */ dig4 = 0; write(table[ge]); delay(10); dig4 = 1; /* 显示百位 */ if(bai!=0) { dig2 = 0; write(table[bai]); delay(10); dig2 = 1; /* 显示十位 */ dig3 = 0; write(table[shi]); delay(10); dig3 = 1; } else { if(shi==0) { dig3 = 1; //delay(10); } else { /* 显示十位 */ dig3 = 0; write(table[shi]); delay(10); dig3 = 1; } } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-04-05
单片机=51...一个很奇特的现象.
|
|
返回顶楼 | |
发表时间:2009-04-06
恩那,同楼上,单片机有千万种,发贴请注明类型和芯片名称。
|
|
返回顶楼 | |
发表时间:2009-04-06
agurick 写道 恩那,同楼上,单片机有千万种,发贴请注明类型和芯片名称。
是有这个问题,马上改 |
|
返回顶楼 | |