单片机模拟串口通讯注意事项
波特率计算公式:方式1,3的波特率=1/32或1/16*计时器2的溢出率
波特率=1/16或1/32*(晶振的频率/12*(256-TH1))
串口工作在方式1时,分别采用T/C1和T/C2常用波特率初值表如下
有关模拟串口波特率设置方法:
9600b/s -> 104us——>定时计数器工作方式2时,为了达到104us的延时间——>即在12MHZ的频率下计数104次
——>单片机采用+1方式计数,设置初值为(256-104)——>由于函数运行需要消耗一定的时间,所以设置初值
为(256-99)降低误差
51单片机定时计数器的4中工作方式:
工作方式 | 特点 |
0 | 定时器/计数器T0工作在方式0时,16位计数器只用了13位,即TH0的高8位和TL0的低5位,组成一个13位定时器/计数器。 |
1 | 定时器T0工作方式1与工作方式0类同,差别在于其中的计数器的位数。工作方式0以13位计数器参与计数,工作方式1则以16位计数器参与计数。 |
2 |
定时器T0在工作方式2时,16位的计数器分成了两个独立的8位计数器TH0和TL0。 |
3 | 工作方式3仅对定时器T0有效。当定时器T0工作在方式3时,将16位的计数器分为两个独立的8位计数器TH0和TL0。 |
串口相关寄存器:
串口通讯时序图:
输出时序图:
输入时序图:
用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当RI=0,且SM2=0(或接收到的停止位为1)时,将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU请求中断。
————————————————
版权声明:本文为CSDN博主「To_dreams」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/to_dreams/java/article/details/7716678
单片机的中断信号方式:
INT0 | 外部中断0请求,低电平有效。通过P3.2引脚输入。 |
INT1 | 外部中断1请求,低电平有效。通过P3.3引脚输入 |
T0 | 定时器/计数器0溢出中断请求。 |
T1 | 定时器/计数器1溢出中断请求 |
TXD/RXD | 串行口中断请求。当串行口完成一帧数据的发送或接收时,便请求中断。 |
有关51单片机中断的形式和C语言编程格式
void INT0() interrupt 0 using 1 { } interrupt 0 指明外部中断0 interrupt 1 指明定时器中断0 . . . . using 0 是第0组寄存器 using 1 是第1组寄存器
举例说明:
/* 外部中断程序 */ void ISR_Key(void) interrupt 0 using 1 { P1=~P1; //s3 按下触发一次, P1取反一次 } /* 串口中断程序 */ void UART_SER (void) interrupt 4 // 串行中断服务程序 { unsigned char Temp; // 定义临时变量 if(RI) // 判断是接收中断产生 { RI=0; // 标志位清零 Temp=SBUF; // 读入缓冲区的值 P1=Temp; // 把值输出到 P1口,用于观察 SBUF=Temp; // 把接收到的值再发回电脑端 } if(TI) // 如果是发送标志位,清零 TI=0; }
单片机模拟串口通讯代码:
#include"reg52.h" //定义数据的收发引脚与最大接收字节数 //#include "stdio.h" //sbit RXD=P3^0; //#define TXD P3^1 #define RECEIVE_MAX_BYTES 16 #define TIMER_ENABLE() {TL0=TH0;TR0=1;fTimeouts=0;}//使能T/C #define TIMER_DISABLE() {TR0=0;fTimeouts=0;}//禁止T/C #define TIMER_WAIT() {while(!fTimeouts)fTimeouts=0;}//等待T/C超时 unsigned char fTimeouts=0;//T/C超时溢出标志位 unsigned char RecvBuf[16];//数据接收缓冲区 unsigned char RecvCount=0;//接收数据计数器 //发送字节 void SendByte(unsigned char b) { unsigned char i=8; TXD = 0; TIMER_ENABLE(); TIMER_WAIT(); while(i--) { if(b&1) TXD=1; else TXD=0; TIMER_WAIT(); b>>=1; } TIMER_ENABLE(); TIMER_DISABLE(); } //接收字节 unsigned char RecvByte(void) { unsigned char i; unsigned char b=0; TIMER_ENABLE(); TIMER_WAIT(); for(i=0;i<8;i++) { if(RXD) b|=(1<<i); TIMER_WAIT(); } TIMER_WAIT();//等待结束位 TIMER_DISABLE(); return b; } // 打印字符串 void PrintfStr(char *pstr) { while(pstr && *pstr) { SendByte(*pstr++); } } //T/C初始化 void TimerInit(void) { TMOD=0X02; TR0=0; TF0=0; TH0=(256-99); TL0=TH0; ET0=1; EA=1; } //是否有起始位到达 unsigned char StartBitCome(void) { return (RXD==0); } //主函数 void main (void) { unsigned char i; TimerInit(); //printf("hello 80c52\r\n"); while(1) { if(StartBitCome()) { RecvBuf[RecvCount++] = RecvByte(); if(RecvCount >= RECEIVE_MAX_BYTES) { RecvCount=0; for(i=0;i<RECEIVE_MAX_BYTES;i++) { SendByte(RecvBuf[i]); } } } } } //定时器中断服务函数 void Timer0IRQ(void) interrupt 1 using 0 { fTimeouts=1; }
实验现象:
由于波特率原因一直显示乱码不推荐使用模拟串口