难的东西学不会是因为简单的知识没学好
基础不牢,地动山摇
1.0通信
1.0.1通信的关键:
(1)事先约定
(2)基本信息单元
(3)有效信息编码,传输和解码
1.0.2通信的几个专业性概念
(1)同步和异步
(2)双工 半双工,单工
(3)并行通信和串行通信
(4)电平信号和差分信号
1.1串行通信
(1)串口通信
(2)一种特定的通信协议,一般叫串口通信,串行通信,UART USART等都指串口通信。
(3)这种通信的特点:异步,串行,全双工
1.1.1串行通信的工作方式:
(1)3根线(GND TXD RXD )或者9根线(DB9)
(2)发送方有发送移位寄存器,接收方有接收移位寄存器
(3)数据在发送方和接收方都是以字节为单位进行整字节处理的
(4)数据在通信线上是以位为单位进行传输的。
1.1.2串行通信的主要概念:
(1)起始位、数据位、奇偶校验位、停止位(一帧数据)
(2)波特率:通信的速率,每秒钟发送的bit位的个数,比如波特率9600就代表1秒钟发送9600个bit的二进制位。
(3)流控:速率协商,完备通信需要流控,现在基本不需要流控了
1.2 51单片机的串行通信
(1)寄存器
(2)查询方式与中断方式。一般接收用中断方式,查询方式用于发送。
1.3STC51单片机串行通信相关寄存器
(1)SCON 串行口控制寄存器
(2)PCON波特率选择特殊寄存器(感觉这个稍微有点坑)
(3)TMOD定时器模式选择寄存器(为设置波特率而设置的)
看数据手册中写的这个鬼玩意。。SMOD=1,串口通信方式123波特率加倍,后边有来一句SMOD=0,各种方式波特率加倍。复位时SMOD=0.
那是不是默认情况下就是加倍呢?不是的,复位情况下是不加倍的。或者我拿的数据手册有错误,或者,我理解错了。。
我说几点:
(1)我们一般都用8位数据位模式,基本都使用方式1.所以我目前就管的方式1的情况。也实验的是方式1的情况。
(2)实验了。波特率加倍是SMOD=1. 波特率不加倍SMOD=0;
(3)计算波特率要注意:(不要觉得加倍了,我要4800的波特率就那2400来算,这样就错了。直接带公式算)
例如:我们要4800的波特率。晶振是11.0592MHZ,工作在12T模式下
如果波特率加倍:
我要4800的波特率就把4800带进去算。不要想着加倍了,那拿2400算除了就是4800。。。。。因为我之前搞错了
波特率不加倍:
说白了加倍不加倍只是给TH1 与TL1中装载的计数值不同而已。
1.3代码实战
#include <reg51.h>
// P3^0 RXD
// P3^1 TXD
void delay(unsigned char t);
void UartSendByte(unsigned char c);
void UartInit(void);
void SendString(unsigned char *str);
void main(void)
{
UartInit();
while(1)
{
//UartSendByte('A');
// SendString("专业技能要强硬\r\n"); //发送中文是没有问题的。
//我们发送中文,单片机发送的是啥它是不管的。最终编译器都会
//转化成bit位依次进行发送的.只不过一个英文字符占1个字节,也就是
//8bit,而一个汉字占2字节,16bit的区别而已。
delay(40);
}
}
void UartInit(void)
{
//我们这里要用串口通信的方式1.对应的SM0 SM1分别为0 1.
//我们要配置成1位起始位 8位数据位 无奇偶校验位 1为停止位 波特率4800
//SCON 寄存器的8个位分别是:B7-B0依次为:SM0/FE SM1 SM2 REN TB8 RB8 TI RI
// SM0/FE SM1 SM2 REN TB8 RB8 TI RI
// 0 1 0 1 0 0 0 0
//SM0 SM1 共同控制串口的工作方式。设置为方式1,8位UART波特率可变。为 0 1
//但是要注意。SM1要与PCON的第六位有点关系。要注意
// SM2 是允许方式2或者方式3多级通信的控制位,这里not care 那就为0吧
// REN 允许或禁止串行接收控制位。我们需要串口接收。REN= 1表示打开。
//TB8 RB8 都是设置方式2与方式3的。这里统统设置为0
//TI 发送中断请求位,我们发送一般都用查询方式,所以为0就ok.
//
//RI 串口接收完一帧数据后,由内部硬件置位,必须又软件复位。
SCON = 0x50; //串行口控制寄存器
PCON = 0x80; //波特率选择特殊功能寄存器, 我们选择波特率加倍
//这里的意思就是我们要4800的波特率,那么按2400算就可以了。
TMOD = 0x20; //定时器8为自动重装载定时器
//我们要设置波特率,工作在12T模式下, 定时器1的溢出率为 晶振频率/12/(256-TH1)
//波特率为:2^SMOD /32 * 晶振频率/12/(256-TH1)
TH1 = 244;
TL1 = 244;
// TH1 = 250;
// TL1 = 250;
//定时器1是不是要打开呢?
TR1 = 1;
//我们要串口中断接收,那么就要打开串口中断
ES = 1; //串口中断开关
EA= 1; //总中断开关
}
void UartSendByte(unsigned char c)
{
//我们要发送,要把要发送的数据放入发送移位寄存器中,即SBUF 。
//但是我们发送前需要检查串口这个时候有么有在忙,是不是正在发呢?要等上一次发
//完我们才能开始下一次发送。
SBUF = c;
while(!TI); //一次发送结束时,硬件就自动置位了。
TI = 0; //软件复位
}
void delay(unsigned char t)
{
unsigned char i,j,k;
for(i=0; i<200; i++)
//for(j=0; j<100; j++)
for(k=0; k<t;k++);
}
//发送字符串函数。
void SendString(unsigned char *str) //参数是指针
{
while(*str !='\0' ) //字符串是以\0结尾的
{
UartSendByte(*str);
str++; //地址加1.依次发送
}
}
//串口接收到PC机发给它东西,他就回传,又发给PC机
void UartIsr(void) interrupt 4
{
unsigned char temp;//临时变量用于存放读出的寄存器SBUF中的值。
//还是检测串口接收中断标志位。默认情况下为0,如果有数据来了,硬件就置位了
if(RI)
{
temp = SBUF;
UartSendByte(temp);
RI = 0; //清中断标志
}
}
//代码看着可能有些乱,因为好几个功能在同一个工程里实验的。用完一个用下一个就把一个屏蔽掉了。函数都是可用的。还有就是记得软件清除标志位。