乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      GD32實戰(zhàn)6__串口讀寫

       印度阿三17 2019-06-13

      目的

      ? 串口通信是非常非常常見的一種通信方式,必須掌握的??梢詮娜缦聨讉€方面掌握串口通信:

      1. 串口通信原理,此處我們只研究異步串口
      2. GD32常見的幾種串口通信配置

      異步串口通信原理

      1. 配置

      ? 在了解原理之前,我們先看看串口要如何使用,如下圖,只要選擇正確的串口號,把收發(fā)雙方的波特率、校驗位、數(shù)據(jù)位、停止位配置成一致,這么就可以實現(xiàn)雙方通信。

      在這里插入圖片描述

      那么配置的這些參數(shù)分別代表什么意思呢?

      串口號:唯一標(biāo)識一個串口,當(dāng)設(shè)備存在多個串口時,可以用其標(biāo)識每個串口。

      波特率:每秒鐘傳輸?shù)臄?shù)據(jù)位數(shù)。表示數(shù)據(jù)傳輸?shù)乃俾?,單位bps(位每秒)。比如115200bps就表示1s可以傳輸115200bits的數(shù)據(jù)。

      校驗位:

      ? even 每個字節(jié)傳送整個過程中bit為1的個數(shù)是偶數(shù)個(校驗位調(diào)整個數(shù))
      ? odd 每個字節(jié)穿送整個過程中bit為1的個數(shù)是奇數(shù)個(校驗位調(diào)整個數(shù))
      ? none 沒有校驗位
      ? space 校驗位總為0
      ? mark 校驗位總為1

      數(shù)據(jù)位:5678共4個選擇,這是歷史原因,如下

      ? 5:用于電報機(jī)傳26個英文字母,5位足以

      ? 6:用于電報機(jī),識別大小寫字母,增加一個大小寫位

      ? 7:用于電腦,ASCII碼7位

      ? 8:用于電腦,DBCS碼用于兼容ASCII和支持中文雙字節(jié)

      停止位:

      ? 停止位是按長度來算的。串行異步通信從計時開始,以單位時間為間隔(一個單位時間就是波特率的倒數(shù)),依次接受所規(guī)定的數(shù)據(jù)位和奇偶校驗位,并拼裝成一個字符的并行字節(jié);此后應(yīng)接收到規(guī)定長度的停止位“1”。所以說,停止位都是“1”,1.5是它的長度,即停止位的高電平保持1.5個單位時間長度。一般來講,停止位有1,1.5,2個單位時間三種長度。

      2. 幀格式

      ? 下面我們看下串行協(xié)議的幀格式,如圖

      在這里插入圖片描述

      一個幀由4部分組成,起始位 數(shù)據(jù)位 校驗位 停止位,正好跟上面的配置一一對應(yīng),其中,起始位必須是低電平,停止位必須是高電平。

      至此,也大致明白串口是怎么回事了。

      3. 常見的串口電平標(biāo)準(zhǔn)

      ? 下面幾種都是串口,只是電平標(biāo)準(zhǔn)不同,導(dǎo)致其應(yīng)用場景存在差異,通信協(xié)議和配置都是相同的,通信原理是相同的,軟件實現(xiàn)相同,硬件電路存在差異。

      TTL:

      1. 接線方式如圖

      2. 高電平表示邏輯1, 低電平表示邏輯零

         ![1536645105294](assets/1536739271596.png)
        

      RS232和RS485對比

      1. 抗干擾性:RS485 接口是采用平衡驅(qū)動器和差分接收器的組合,抗噪聲干擾性好。RS232 接口使用一根信號線和一根信號返回線而構(gòu)成共地的傳輸形式,這種共地傳輸容易產(chǎn)生共模干擾。
      2. 傳輸距離:RS485 接口的最大傳輸距離標(biāo)準(zhǔn)值為 1200 米(9600bps 時),實際上可達(dá) 3000 米。RS232 傳輸距離有限,最大傳輸距離標(biāo)準(zhǔn)值為 50 米,實際上也只能用在 15 米左右。
      3. 通信能力:RS-485 接口在總線上是允許連接多達(dá)128個收發(fā)器,用戶可以利用單一的 RS-485 接口方便地建立起設(shè)備網(wǎng)絡(luò)。RS-232只允許一對一通信。
      4. 傳輸速率:RS-232傳輸速率較低,在異步傳輸時,波特率為 20Kbps。RS-485 的數(shù)據(jù)最高傳輸速率為 10Mbps 。
      5. 信號線:RS485 接口組成的半雙工網(wǎng)絡(luò),一般只需二根信號線。RS-232 口一般只使用 RXD、TXD、GND 三條線 。
      6. 電氣電平值:RS-485的邏輯"1"以兩線間的電壓差為 (2-6) V 表示;邏輯"0"以兩線間的電壓差為-(2-6)V 表 示 。在 RS-232-C 中任何一條信號線的電壓均為負(fù)邏輯關(guān)系。即:邏輯"1",-5- -15V;邏輯"0 " 5- 15V 。

      4. 芯片如何實現(xiàn)串口功能

      ? 在這里插入圖片描述

      ? 我們知道串口的作用是為CPU和其它設(shè)備之間提供通信,本質(zhì)上是把數(shù)據(jù)從其他設(shè)備搬移到自身MCU的內(nèi)存中去,如上圖,MCU為實現(xiàn)串口功能會做如上的模塊劃分。

      1. GPIO

        串口總線狀態(tài),默認(rèn)是高電平,所以Tx應(yīng)該是上拉輸出,Rx應(yīng)該是浮空輸入。

      2. 移位器

        我們知道串口是一位位傳輸?shù)?,所以移位器即可以實現(xiàn)串口的收發(fā)。

      3. 數(shù)據(jù)寄存器

        用于存儲將要發(fā)送和接收的數(shù)據(jù),其實只要收發(fā)共用一個字節(jié)就足以。

      4. 時鐘

        上述的運(yùn)行過程都需要在固定時鐘下才能正確運(yùn)行,例如波特率。

      5. 數(shù)據(jù)由寄存器搬移到內(nèi)存

        1. CPU方式,由CPU控制數(shù)據(jù)如何在數(shù)據(jù)寄存器和內(nèi)存之間進(jìn)行轉(zhuǎn)移,例如當(dāng)數(shù)據(jù)寄存器空時,將內(nèi)存轉(zhuǎn)移到數(shù)據(jù)寄存器中,即發(fā)送過程
        2. DMA方式,過程同CPU,那為什么還有有DMA呢?因為數(shù)據(jù)搬移省去CPU的參與,也就意味著CPU可以去忙其它事情,效率自然就高了。
      6. 狀態(tài)寄存器

        1. 我們粗略的思考下,在整個串口的傳輸過程中,肯定會有各式各樣的狀態(tài),例如,收到數(shù)據(jù),數(shù)據(jù)異常,幀錯誤,數(shù)據(jù)發(fā)送完畢,數(shù)據(jù)寄存器空了等等,這些都需要狀態(tài)寄存器存儲。
        2. 再深入思考下,當(dāng)我們需要及時的處理上述狀態(tài)時,靠CPU輪詢顯然太慢了,所以肯定需要中斷,再增加一組中斷狀態(tài)寄存器。
      7. 配置寄存器

        ? 上述情況那么多,代表不同的配置,肯定需要幾組配置寄存器。例如,中斷的使能控制等

      功能設(shè)計

      ? 如果明白了原理,那么自然就知道該如何配置一個串口了,無非就是從芯片手冊中找到相應(yīng)的寄存器進(jìn)行配置而已。

      ? 在”串口發(fā)送“例子中,已經(jīng)接觸了串口的發(fā)送功能,現(xiàn)在我們把這個例子再度深入,實現(xiàn)串口的接收功能。實現(xiàn)一個回顯功能,即PC通過串口向GD32寫入數(shù)據(jù),然后GD32把數(shù)據(jù)原封不動返回給PC。

      輪詢方式
      VOID DRV_UART1_PollTest(VOID)
      {
          U8 ch = 0;
          
          while (1)
          {
              if (USART_GetBitState(USART1, USART_FLAG_RBNE) != RESET)
              {
                  ch = (U8)USART_DataReceive(USART1);
                  UART1_SendChar(ch);
              }
          }
      }
      
      VOID DRV_UART1_PollInit(VOID)
      {
          UART1_GpioInit();
          UART1_Config();
          USART_Enable(USART1, ENABLE);
      }
      

      效果如圖

      在這里插入圖片描述

      中斷方式

      注:中斷優(yōu)先級部分,我會抽單獨(dú)章節(jié)分析。

      必須注意下面這兩個函數(shù)的區(qū)別,

      USART_GetBitState(USART1, USART_FLAG_RBNE); /* 非中斷使用 */
      USART_GetIntBitState(USART1, USART_INT_RBNE);/* 中斷內(nèi)使用 */
      

      中斷方式處理代碼如下:

      VOID USART1_IRQHandler(VOID)
      {
          if (USART_GetIntBitState(USART1, USART_INT_RBNE) != RESET)
          {
              if (gUart1RxCount >= DRV_UART1_BUFLEN)
              {
                  memset(gUart1RxBuf, 0, sizeof(gUart1RxBuf));
                  gUart1RxCount = 0;
              }
              gUart1RxBuf[gUart1RxCount] = (U8)USART_DataReceive(USART1);
              gUart1RxCount  ;
          }
      
          if (USART_GetIntBitState(USART1, USART_INT_IDLEF) != RESET)
          {
              gUart1RxBufFlag  ;
          }
      }
      
      VOID DRV_UART1_InterruptTest(VOID)
      {
          U8 rxCount = 0;
      
          while (1)
          {
              if (gUart1RxBufFlag > 0)
              {
                  for (rxCount = 0; rxCount < gUart1RxCount; rxCount  )
                  {
                      UART1_SendChar(gUart1RxBuf[rxCount]);
                  }
                  memset(gUart1RxBuf, 0, sizeof(gUart1RxBuf));
                  gUart1RxCount = 0;
                  gUart1RxBufFlag = 0;
              }
          }
      }
      
      VOID DRV_UART1_InterruptInit(VOID)
      {
          UART1_GpioInit();
          UART1_Config();
          UART1_NvicConfiguration();
          USART_Enable(USART1, ENABLE);
          USART_INT_Set(USART1, USART_INT_RBNE, ENABLE);
          USART_INT_Set(USART1, USART_INT_IDLEF, ENABLE);
      }
      
      DMA方式

      ? 注:DMA細(xì)節(jié)我會抽單獨(dú)章節(jié)分析,此處只寫一個DMA輪詢方式的例子。

      static VOID UART1_DmaRxConfig(IN U8 *buf, IN U32 len)
      {
          DMA_InitPara DMA_InitStructure;
          
          DMA_Enable(DMA1_CHANNEL5, DISABLE);
          
          /* USART1 RX DMA1 Channel (triggered by USART1 Rx event) Config */
          DMA_DeInit(DMA1_CHANNEL5);
          DMA_InitStructure.DMA_PeripheralBaseAddr = (U32) &(USART1->DR);
          DMA_InitStructure.DMA_MemoryBaseAddr = (U32)buf;
          DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALSRC;
          DMA_InitStructure.DMA_BufferSize = len;
          DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
          DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
          DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE;
          DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
          DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
          DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
          DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
          DMA_Init(DMA1_CHANNEL5, &DMA_InitStructure);
          DMA_Enable(DMA1_CHANNEL5, ENABLE);
      }
      
      VOID DRV_UART1_DmaInit(VOID)
      {
          UART1_GpioInit();
          UART1_Config();
          RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_DMA1, ENABLE);
          UART1_DmaRxConfig(gUart1RxBuf, DRV_UART1_BUFLEN);
          USART_Enable(USART1, ENABLE);
          USART_DMA_Enable(USART1, (USART_DMAREQ_TX | USART_DMAREQ_RX), ENABLE);
      }
      
      static VOID UART1_DmaSend(IN U8 *buf, IN U32 len)
      {
          DMA_InitPara DMA_InitStructure;
      
          DMA_Enable(DMA1_CHANNEL4, DISABLE);
      
          /* USART1_Tx_DMA_Channel (triggered by USART1 Tx event) Config */
          DMA_DeInit(DMA1_CHANNEL4);
          DMA_InitStructure.DMA_PeripheralBaseAddr = (U32) &(USART1->DR);
          DMA_InitStructure.DMA_MemoryBaseAddr = (U32)buf;
          DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALDST;
          DMA_InitStructure.DMA_BufferSize = len;
          DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
          DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
          DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE;
          DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
          DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
          DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
          DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
          DMA_Init(DMA1_CHANNEL4, &DMA_InitStructure);
          
          DMA_Enable(DMA1_CHANNEL4, ENABLE);
          while (DMA_GetBitState(DMA1_FLAG_TC4) == RESET)
          {
          }
      }
      
      VOID DRV_UART1_DmaTest(VOID)
      {
          while (1)
          {
              if (USART_GetBitState(USART1, USART_FLAG_IDLEF) != RESET)
              {
                  UART1_DmaSend(gUart1RxBuf, DRV_UART1_BUFLEN);
                  memset(gUart1RxBuf, 0, DRV_UART1_BUFLEN);
                  UART1_DmaRxConfig(gUart1RxBuf, DRV_UART1_BUFLEN);
                  USART_DataReceive(USART1); /* 清除USART_FLAG_IDLEF */
              }
          }
      }
      

      總結(jié)

      ? 串口是一種非常常見的通信總線,必須掌握。如果上面的原理和例子理解了,我相信用GPIO口虛擬一個窗口并不是什么難事。

      代碼路徑

      https://github.com/YaFood/GD32F103/tree/master/TestUART

      來源:http://www./content-4-246651.html

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多