51微控制器的串列埠通訊(一)
串列埠通訊好東西,但我沒用過。
下面照著普中科技的ppt搬運下。
隨著多微機系統的廣泛應用和計算機網路技術的普及,計算機的通訊功能愈來愈顯得重要。計算機通訊是指計算機與外部裝置或計算機與計算機之間的資訊交換。
通訊方式
有並行通訊和序列通訊兩種。
並行通訊通常是將資料位元組的各位用多條資料線同時進行傳送 。
序列通訊是將資料位元組分成一位一位的形式在。
序列通訊的傳輸方向
單工是指資料傳輸僅能沿一個方向,不能實現反向傳輸。
半雙工是指資料傳輸可以沿兩個方向,但需要分時進行。
全雙工是指資料可以同時進行雙向傳輸。
序列通訊常見的錯誤校驗
奇偶校驗、迴圈冗餘校驗
傳輸速率(位元率):
位元率是每秒鐘傳輸二進位制程式碼的位數,單位是:位/秒(bps)。
80C51序列口的結構
有兩個物理上獨立的接收、傳送緩衝器SBUF,
序列口的控制暫存器(SCON)(有點複雜,沒咋整明白,以後用的時候再說)
用以設定序列口的工作方式、接收/傳送控制以及設定狀態標誌:
SM0和SM1為工作方式選擇位,可選擇四種工作方式:
SM2,多機通訊控制位,主要用於方式2和方式3。當接收機的SM2=1時可以利用收到的RB8來控制是否啟用RI(RB8=0時不啟用RI,收到的資訊丟棄;RB8=1時收到的資料進入SBUF,並激活RI,進而在中斷服務中將資料從SBUF讀走)。當SM2=0時,不論收到的RB8為0和1,均可以使收到的資料進入SBUF,並激活RI(即此時RB8不具有控制RI啟用的功能)。通過控制SM2,可以實現多機通訊。在方式0時,SM2必須是0。在方式1時,如果SM2=1,則只有接收到有效停止位時,RI才置1。
REN,允許序列接收位。由軟體置REN=1,則啟動序列口接收資料;若軟體置REN=0,則禁止接收。
TB8,在方式2或方式3中,是傳送資料的第九位,可以用軟體規定其作用。可以用作資料的奇偶校驗位,或在多機通訊中,作為地址幀/資料幀的標誌位。在方式0和方式1中,該位未用。
RB8,在方式2或方式3中,是接收到資料的第九位,作為奇偶校驗位或地址幀/資料幀的標誌位。在方式1時,若SM2=0,則RB8是接收到的停止位。
TI,傳送中斷標誌位。在方式0時,當序列傳送第8位資料結束時,或在其它方式,序列傳送停止位的開始時,由內部硬體使TI置1,向CPU發中斷申請。在中斷服務程式中,必須用軟體將其清0,取消此中斷申請。
RI,接收中斷標誌位。在方式0時,當序列接收第8位資料結束時,或在其它方式,序列接收停止位的中間時,由內部硬體使RI置1,向CPU發中斷申請。也必須在中斷服務程式中,用軟體將其清0,取消此中斷申請。
PCON中只有一位SMOD與序列口工作有關 :
SMOD(PCON.7) 波特率倍增位。在序列口方式1、方式2、方式3時,波特率與SMOD有關,當SMOD=1時,波特率提高一倍。復位時,SMOD=0。
波特率的計算(用波特率計算器)
方式0的波特率 = fosc/12
方式2的波特率 =(2SMOD/64)· fosc
方式1的波特率 =(2SMOD/32)·(T1溢位率)
方式3的波特率 =(2SMOD/32)·(T1溢位率)
T1 溢位率 = fosc /{12×[256 -(TH1)]}
在微控制器的應用中,常用的晶振頻率為:12MHz和11.0592MHz。所以,選用的波特率也相對固定。常用的序列口波特率以及各引數的關係如表所示。
串列埠如何使用
確定序列口控制(程式設計SCON暫存器);
確定T1的工作方式(程式設計TMOD暫存器);
計算T1的初值,裝載TH1、TL1;
啟動T1(程式設計TCON中的TR1位);
PC和微控制器通訊:
#include<reg52.h>
typedef unsigned char uchar;
void Serial_comInit()
{
SCON=0X50; //設定為工作方式1 ,既然是方式一,自然要確定波特率,設定定時器1
TMOD=0X20;//8位重灌載
PCON=0X80;
TH1=0xF3;//波特率4800
TL1=0XF3;
ES=1; //開啟通訊中斷
EA=1; //開啟總中斷
TR1=1; //開啟計數器
}
void main(void)
{
Serial_comInit();
while(1);
}
void communication() interrupt 4
{
uchar receiveData;
receiveData=SBUF;//出去,接,收到的資料
RI = 0;//清除接收中斷標誌位
SBUF=receiveData;//將接收到的資料放入到傳送暫存器
while(!TI); //等待發送資料完成
TI=0; //清除傳送完成標誌位
}
電腦傳送資料到微控制器:
(來源:https://blog.csdn.net/u014453898/article/details/57123007)
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar buf;
#define led P2
void main(void)
{
SCON=0x50;//設定串列埠工作方式0101 0000
PCON=0x00;
TMOD=0x20;
EA=1;
ES=1;
TL1=0xfd;//波特率9600
TH1=0xfd;
TR1=1;
while(1);
}
//序列中斷服務函式
void serial() interrupt 4
{
ES=0; //暫時關閉串列埠中斷
RI=0;
buf=SBUF; //把收到的資訊從SBUF放到buf中。
switch(buf)
{
case 0x31: led=0xfe;break; //二進位制 0011 0001 十進位制 49 控制字元 1 16進位制 0X31
case 0x32: led=0xfd;break; //1111 1101
case 0x33: led=0xfb;break;
case 0x34: led=0xf7;break;
case 0x35: led=0xef;break;
case 0x36: led=0xdf;break;
case 0x37: led=0xbf;break;
case 0x38: led=0x7f;break;
}
ES=1; //重新開啟串列埠中斷
SBUF=buf;
while(!TI);
TI=0;
}
我的串列埠助手有點智障,不過程式應該沒有啥大問題。
參考文章:
一條傳輸線上逐個地傳送。