串口通信筆記

1.同步
說話雙方按照同一步調,同一個標準,
2.異步
兩個人不用一個同步信號,發送方發送的時候,接收方是不知道的,發送方和接收方事先沒有約定好,
發送完全是隨機的,但是發送速度是事先知道的
3. UART
發明很早的通信協議。
異步、串行、全雙工、短距離(1.5米內)、完備通信機制。
現在看來速率太慢,要淘汰了,幾百K的速率,現在都用USB,網絡等高速協議
在雙方可以接收的前提下,儘量提高通信速率。
現在一般用在低速率,近距離,調試,
調試奇偶校驗一般不要,調試沒有那麼嚴格,偶爾出個錯沒關係。早期的應用比較嚴格,
(3)
    3根線(GND、RXD、TXD)不能做完備的通信機制
    9根線(DB9)可以做完備的通信機制,比如速度適配。
(4)
    發送方有發送移位寄存器,接收方有接收移位寄存器。爲什麼要做移位寄存器,是因爲我們的
    數據在通信線上是以位單位傳送的,也就是說我們的串行通信的最小單元是一個bit位,一次只能
    傳一個bit位,字節轉成位,位轉成字節。
(5)數據在發送方和接收方的CPU中都是以字節爲單位整字節處理。其實計算機誕生初期是以bit爲單位處理的
    後來覺得這樣做太複雜,就改爲以字節爲單位處理了。CPU比較忙,所以我們在CPU內部內置了一個移位寄存器,
    讓其自動的把字節轉成bit,把bit轉成字節。CPU就只要處理一個整字節就可以了。但是在通信線上還是一個bit一個bit的傳。
(6)串行通信的主要概念
        起始位、數據位、奇偶校驗位、停止位  這些組合起來就叫一幀,所有的幀都是由這四部分構成的,但是每一部分有多少
        位是不一定的,需要通信雙方協商好,一般情況數據位一般是8位,ASCII碼一個符號就是用8位(一個字節表示),但是數據位
        也可能有6位的7位的不等,起始位也可以是0位、1位、2位不等,奇偶校驗位可以是奇校驗,也可以是偶校驗,也可以是沒有校驗位,
        停止位可以是一位停止位,2位停止位,由雙方自己協商。只要發送方和接收方設置爲一樣就行。
        波特率:通信速率,多長時間發一個位,多長時間表示一個位。一秒鐘之內傳輸多少個位,
                比如波特率:9600,表示一秒鐘之內傳輸9600個bit位
                只要記住:發送方和接收方波特率設爲一樣就行。波特率越小代表我們的傳輸速度越慢,抗干擾能力就越強,就更不容易出錯,
                波特率越大代表我們的傳輸速度越快,抗干擾能力就越差,就更容易出錯
        流控:流控就是數據協商,就是發送方怎麼知道接收方接收多快,接收方怎麼知道發送方有多快呢,但是這種機制現在已經沒有用了,所以在軟件設置
        的時候遇到流控要禁用掉,以前完備通信需要,現在非完備通信已經不需要了,現在流控已經被時代淘汰掉了。
4. 單片機的串行通信
    CPU是由控制器和運算器組成,並沒有通信功能,早年CPU與串行通信模塊是分離的,即在CPU外面擴展一個串行通信IC,後來看到串行通信用的比較頻繁,後來才集成到SOC裏面。各種soc芯片的串行通信
    大同小異,
    例如:STC90C51系列單片機內部集成有一個功能很強大的全雙工串行通信口,與傳統
    的8051單片機的串口完全兼容。設有2個相互獨立的接收、發送緩衝器,可以同時發送
    和接收數據。發送緩衝器只能寫入而不能讀出,接收緩衝器只能讀出而不能寫入,因而兩個緩衝器可以共用一個地址
    碼(99H)。兩個緩衝器統稱爲串行通信特殊功能寄存器SBUF。
    串行通信設有4種工作方式,其中兩種方式的波特率是可變的,另兩種是固定的,以供不同的
    應用場合選用。波特率由內部定時器/計數器產生,用軟件設置不同的波特率和選擇不同的工作方式。
    主機可以通過查詢或中斷的方式對接收/發送進行程序處理,使用十分靈活。
    一般發送都是用查詢方式,接收用中斷方式。爲什麼用中斷方式接收,串行通信是異步的,接收方不知道發送方什麼時候發送,
    用查詢方式消耗大量CPU資源,用中斷方式,當發送方給接收方發送數據後,就會觸發中斷。
    其實按鍵也是用中斷方式來處理的,
    按鍵、串行通信都是異步的。
5. 四種工作模式
    模式0:同步移位寄存器
    模式1:8位UART,波特率可變    最重要的應用
    模式2: 9位UART,波特率固定
    模式3: 9位UART,波特率可變
6.串口發送時的軟硬件協作方式
(1)查詢方式
    硬件在發送完一幀數據後會將一個標誌位置位(標誌位本來是0),軟件需要不斷讀取這個標誌位的值來判斷硬件是否完成了發送(如果讀出來
    是0就表示硬件還在發還沒完還在忙,所以我們就不能認爲硬件發完了,所以就不能給硬件安排下一幀數據的發送;如果讀出來的是1則說明硬件已經發完了上
    一幀數據,這時候軟件就應該給硬件再給一幀數據去發送)。因爲串口發送完這個事件對CPU來說是個異步事件(即CPU不知道這個事件什麼時候發生),所以這裏
    查詢方式來處理和之前講過的查詢方式處理按鍵是非常類似的。
(2)中斷方式。查詢方式處理的劣勢是CPU必須一直守着串口發送,在串口發送完所有字節之前CPU不能離開去做別的事情,這對CPU來說是極大的浪費(因爲CPU的
速度比串口發送的速度快多了)。因此用中斷的方式來處理串口發送是非常合適的,可以提升CPU的使用率。
(3)常見情況下:串口發送會使用查詢方式,而串口接收會使用中斷方式。
7.串口轉USB芯片
CH340、PL2303、FT2303
8.串口設置
(1)現在數據位都是8位,停止位1位,奇偶校驗NO,流控無
9.代碼
(1)串口初始化
注意:寫代碼要先把框架搭起來,越是複雜的項目越是這樣,邊寫邊編譯
不要到寫完了再來編譯,後面再來填充這個框架。

//聲明函數,先聲明後調用
void uart_init(void);
void uart_send_byte(unsigned char c);
void delay(void);
void uart_send_string(unsigned char *str);


void main()
{
    //第一步:初始化好串口到正確狀態
    uart_init();
    //第二步:通過串口發送信息出去
/*
    while(1)
    {
        uart_send_byte('A');
        delay();
    }
*/
    //測試發送字符串
/*
    while(1)
    {
        uart_send_string("abcdefg");  //通過""引起來的字符串,編譯器會在末尾追加字符串
        uart_send_string("中文測試軟件");  //也可以發送中文,一箇中文對應兩個字節
        //串口只管傳輸,像快遞員,管你們送的是中文還是英文
        delay();
    }
    
*/
    uart_send_string("串口迴環測試\r\n"); 
    while(1);
    
}

//串口初始化函數
//預設一個串口條件及我們初始化的目標:8位數據位、1位停止位、0校驗位、波特率4800
//初始化的相關工作就是去設置相關的寄存器
void uart_init(void)
{
//SCON:      SM0/FE   SM1   SM2    REN     TB8     RB8    TI     RI
//           0      1     0     1/0     0        0     0      0       0x40/0x50     REN爲0接收使能,爲0接收不使能

    SCON = 0X50;   //工作在模式一(8位數據),而且允許接收
//PCON:     SMOD      SMOD0
//            1/0        0         0x80/0x00   0x80爲波特率加倍,0x00爲波特率不加倍
    PCON = 0X80;  //波特率加倍,意思是本來需要波特率4800,等下計算時按2400計算就可以了
//現在串口的發送用查詢方式,中斷寄存器IE、IPH、IP可以先不管
//SADEN(Slave Address Mask)、SADDR(Slave Address)無關緊要,不用設置。

//通信波特率設置
//SM0     SM
//  0      1       方式1    8位UART波特率可變      ((2^SMOD)/32)*(定時器1的溢出率)
//當單片機工作在12T模式時,定時器1的溢出率=SYSclk/12(256-TH1)
//d當單片機工作在6T模式時,定時器1的溢出率=SYSclk/6(256-TH1)
//計算
//上面我們把SMOD設置爲1,即波特率加倍
//波特率=(2/32)*(定時器1的溢出率)
//SYSclk=12MHz=12000000
//即(2*12000000)/(32*12*(256-TH1))=4800
//求TH1=256-13.02取整 TH1=256-13=243
//定時器/計數器1具有4種工作方式,而常選用定時器/計數器1的工作方式2(8位自動重裝)作爲波特率的
//溢出率,對應模式寄存器位TMOD
//TMOD     GATE     C/T     M1      M0     GATE     C/T      M1     M0
            0        0      1       0      0       0        0      0               0X20
    TMOD = 0X20;   //設置定時器1爲模式2
    TH1 = 243;
    TL1 = 243;     //爲什麼TL1也是243?因爲自動重裝的意思是TH1用完了之後下一個週期TL1會自動重裝到TH1中
    TR1 = 1;  開啓定時器1讓它工作
    
    ES = 1;   //使能串口中斷
    EA = 1;   //使能總中斷
}
//通過串口發送一個字節出去
void uart_send_byte(unsigned char c)
{
// 第一步,發送一個字節
//串口忙不忙只要差一個標誌位就可以知道TI
//TI爲發送請求中斷標誌位。在方式0,當串行發送數據第8位結束時,由內部硬件自動置位,即TI=1
//,向主機請求中斷,響應中斷後必須用軟件復位,即TI=0。如果是0說明硬件在忙
    SBUF = c;  //直接把數據丟到Serial Buffer裏面去
    while(!TI);   //如果是忙狀態,進入死循環
// 第二步,確認串口發送部分沒有在忙
// 注意:嵌入式裏面都是先檢測後發送
// 第三步,軟件復位TI標誌位
    TI = 0;
    
}

void uart_send_string(unsigned char *str)
{
    while(*str != '\0')   //'\0'位字符串結尾的標誌符,如果沒有檢測到'\0'就繼續
    {
        uart_send_byte(*str);  //發送一個字符
        str++;  //指針指向下一個字符
    }
}
//延遲函數
void delay(void)
{
    unsigned char i,j;
    for(i=0;i<100;i++)
        for(j=0;j<100;j++)
}


//uart的中斷編號爲4
void uart_isr(void) interrupt 4 using 1
{
    unsigned char tmp;
    if (RI)
    {
        tmp = SBUF;   //讀取SBUF,其實就是讀出了串口接收到的1個字節
        RI = 0;
    }
    //至此已經讀到了PC發給單片機的1個字節,但是單片機是麼沒有顯示器沒有顯示給人看
    //我們這裏用一個最簡單的方法來測試,就是直接回發到PC
    uart_send_byte(tmp);
}
(2)波特率計算
(3)串口發送字符
10. RS485介紹
(1)UART的缺點:傳輸距離受限
(2)理論上RS232不超過15米
(3)理論上TTL電平通信距離更短1米內
(4)波特率越高通信距離越近,波特率與通信距離是一對矛盾,一般講通信距離是多少米要指定波特率是在多少的前提下。
遠距離傳輸怎麼辦?距離越長,電壓在通信線上有衰減,越長衰減越嚴重,
(1)提高電壓標準,一味提高電壓,功耗成平方增加P=(U^2)/R,不是辦法。
(2)提升通信線抗干擾能力,降低阻抗。一般可以通過通信線外加屏蔽層;銅線的阻抗比鋁線阻抗低,銀線阻抗比銅線低,但是阻抗越低價錢越貴。
(3)使用差分信號,先天就可以抵抗共摸干擾
通信距離:
(1)最大通信距離1200多米,最快通信速率10Mbps,距離和速度成反比
(2)差分信號負邏輯
(3)更遠距離可以加中繼器
(4)半雙工,只有兩根線,要實現全雙工,需要四根線
    
    
    
    
    
    
    
    
    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章