娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

STM32F103串口DMA+空閑中斷+多級緩沖實現(xiàn)不定長接收

發(fā)布者:TranquilSoul最新更新時間:2025-03-11 來源: jianshu關(guān)鍵字:STM32F103  串口DMA  空閑中斷  不定長接收 手機看文章 掃描二維碼
隨時隨地手機看文章

文本提供的代碼是基于STM32CubeMX生成的HAL庫的。

STM32串口接收大體分為3種方式:

1、阻塞接收---HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);

2、中斷接收---HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

3、DMA接收---HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

本文只談?wù)揇MA接收方式,同時增加空閑中斷和多級緩沖。單純的DMA接收適合固定長度的數(shù)據(jù)接收,局限性太大,很難適用實際項目需要。增加空閑中斷,可以做到不定長接收。多級緩沖在一定程度上可以緩解裸機代碼實時性差的問題。

具體步驟如下:

1.STM32CubeMX生成工程,這里介紹串口部分的設(shè)置:

image


2.新建usart_ex.c文件,主要關(guān)注兩個函數(shù):void HW_UART_Modem_IRQHandler(UART_HandleTypeDef *huart)和void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)。


/**


  ******************************************************************************

  * @file    : usart_ex.c

  * @author  : xEndLess

  * @version : V1.0.0

  * @date    : 2018-4-3

  * @brief  : 本文件是對usart.c的擴展,避免每次用Cube建立工程時,需要對usart.c做出修改.

  *            串口發(fā)送函數(shù),回調(diào)函數(shù),DMA接收完成函數(shù),都放在這里。

  *

  ******************************************************************************

  */> /* Includes ------------------------------------------------------------------*/#include 'bsp.h'#include 'stdarg.h'/* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*/Usart1_BufTypeDef Usart1Buf;Usart2_BufTypeDef Usart2Buf;Usart3_BufTypeDef Usart3Buf;Usart4_BufTypeDef Usart4Buf;Usart5_BufTypeDef Usart5Buf;/* 以下4個變量是在uasrt.c中定義的 ,Cube自動生成 */extern DMA_HandleTypeDef hdma_uart4_rx;extern DMA_HandleTypeDef hdma_usart1_rx;extern DMA_HandleTypeDef hdma_usart2_rx;extern DMA_HandleTypeDef hdma_usart3_rx;/* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*//****************** UART CallBack *******************//**

  * @brief  Rx Transfer completed callback

  * @param  UartHandle: UART handle

  * @note  This example shows a simple way to report end of DMA Rx transfer, and

  *        you can add your own implementation.

  * @retval None

  */void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){

  if (huart->Instance == USART1)

  {

    Usart1Buf.RxEndFlag[Usart1Buf.RxDimension] = SET;

    Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] = USART1_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);

    Usart1Buf.RxDimension++;

    Usart1Buf.RxDimension %= USART1_BUF_DIMENSION;

    HAL_UART_DMAStop(huart);

    HAL_UART_Receive_DMA(huart, Usart1Buf.RxBuffer[Usart1Buf.RxDimension], USART1_BUF_LENGTH);

  }

  else if (huart->Instance == USART2)

  {

    Usart2Buf.RxEndFlag[Usart2Buf.RxDimension] = SET;

    Usart2Buf.RxEndIndex[Usart2Buf.RxDimension] = USART2_BUF_LENGTH -   

 __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);

    Usart2Buf.RxDimension++;

    Usart2Buf.RxDimension %= USART2_BUF_DIMENSION;

    HAL_UART_DMAStop(huart);

    HAL_UART_Receive_DMA(huart, Usart2Buf.RxBuffer[Usart2Buf.RxDimension], USART2_BUF_LENGTH);

  }

  else if (huart->Instance == USART3)

  {

    Usart3Buf.RxEndFlag[Usart3Buf.RxDimension] = SET;

    Usart3Buf.RxEndIndex[Usart3Buf.RxDimension] = USART3_BUF_LENGTH - 

 __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);

    Usart3Buf.RxDimension++;

    Usart3Buf.RxDimension %= USART3_BUF_DIMENSION;

    HAL_UART_DMAStop(huart);

    HAL_UART_Receive_DMA(huart, Usart3Buf.RxBuffer[Usart3Buf.RxDimension], USART3_BUF_LENGTH);

  }

  else if (huart->Instance == UART4)

  {

    Usart4Buf.RxEndIndex[Usart4Buf.RxDimension] = USART4_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);

    Usart4Buf.RxEndFlag[Usart4Buf.RxDimension] = SET;

    Usart4Buf.RxDimension++;

    Usart4Buf.RxDimension %= USART4_BUF_DIMENSION;

    HAL_UART_DMAStop(huart);

    HAL_UART_Receive_DMA(huart, Usart4Buf.RxBuffer[Usart4Buf.RxDimension], USART4_BUF_LENGTH);

  }

  else if (huart->Instance == UART5)

  {

    Usart5Buf.RxEndIndex[Usart5Buf.RxDimension] = USART5_BUF_LENGTH;

    Usart5Buf.RxEndFlag[Usart5Buf.RxDimension] = SET;

    Usart5Buf.RxDimension++;

    Usart5Buf.RxDimension %= USART5_BUF_DIMENSION;

    HAL_UART_Receive_IT(huart, Usart5Buf.RxBuffer[Usart5Buf.RxDimension], USART5_BUF_LENGTH);

  }}/**

  * @brief DMA IDLE接收串口數(shù)據(jù),該函數(shù)剛到串口中斷中

  * @param handle to the UART

  * @retval void

  **/void HW_UART_Modem_IRQHandler(UART_HandleTypeDef *huart){

  uint32_t tmp_flag = 0, tmp_it_source = 0;


  if (huart->Instance == USART1)

  {

    tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);

    tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE); 

    /* UART parity error interrupt occurred ------------------------------------*/

    if ((tmp_flag != RESET) && (tmp_it_source != RESET))

    {

      Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] = USART1_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);

      /* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */

      if (Usart1Buf.RxEndIndex[Usart1Buf.RxDimension] != 0)

      {

        Usart1Buf.RxEndFlag[Usart1Buf.RxDimension] = SET;

        Usart1Buf.RxDimension++;

        Usart1Buf.RxDimension %= USART1_BUF_DIMENSION;

        HAL_UART_DMAStop(huart);

        HAL_UART_Receive_DMA(huart, Usart1Buf.RxBuffer[Usart1Buf.RxDimension], USART1_BUF_LENGTH);

      }

    }

    __HAL_UART_CLEAR_IDLEFLAG(huart);

  }

  else if (huart->Instance == USART2)

  {

    tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);

    tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE); 

    /* UART parity error interrupt occurred ------------------------------------*/

    if ((tmp_flag != RESET) && (tmp_it_source != RESET))

    {

      Usart2Buf.RxEndIndex[Usart2Buf.RxDimension] = USART2_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);

      /* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */

      if (Usart2Buf.RxEndIndex[Usart2Buf.RxDimension] != 0)

      {

        Usart2Buf.RxEndFlag[Usart2Buf.RxDimension] = SET;

        Usart2Buf.RxDimension++;

        Usart2Buf.RxDimension %= USART2_BUF_DIMENSION;

        HAL_UART_DMAStop(huart);

        HAL_UART_Receive_DMA(huart, Usart2Buf.RxBuffer[Usart2Buf.RxDimension], USART2_BUF_LENGTH);

      }

    }

    __HAL_UART_CLEAR_IDLEFLAG(huart);

  }

  else if (huart->Instance == USART3)

  {

    tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);

    tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE); 


    /* UART parity error interrupt occurred ------------------------------------*/

    if ((tmp_flag != RESET) && (tmp_it_source != RESET))

    {

      Usart3Buf.RxEndIndex[Usart3Buf.RxDimension] = USART3_BUF_LENGTH - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);

      /* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */

      if (Usart3Buf.RxEndIndex[Usart3Buf.RxDimension] != 0)

      {

        Usart3Buf.RxEndFlag[Usart3Buf.RxDimension] = SET;

        Usart3Buf.RxDimension++;

        Usart3Buf.RxDimension %= USART3_BUF_DIMENSION;

        HAL_UART_DMAStop(huart);

        HAL_UART_Receive_DMA(huart, Usart3Buf.RxBuffer[Usart3Buf.RxDimension], USART3_BUF_LENGTH);

      }

    }

    __HAL_UART_CLEAR_IDLEFLAG(huart);

  }

  else if (huart->Instance == UART4)

  {

    tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);

    tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE); 

    /* UART parity error interrupt occurred ------------------------------------*/

    if ((tmp_flag != RESET) && (tmp_it_source != RESET))

    {

      Usart4Buf.RxEndIndex[Usart4Buf.RxDimension] = USART4_BUF_LENGTH - 

 __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);

      /* 在485通信時,有時會出現(xiàn)未接收到數(shù)據(jù),空閑中斷響應(yīng)的情況 */

      if (Usart4Buf.RxEndIndex[Usart4Buf.RxDimension] != 0)

      {

        Usart4Buf.RxEndFlag[Usart4Buf.RxDimension] = SET;

        Usart4Buf.RxDimension++;

        Usart4Buf.RxDimension %= USART4_BUF_DIMENSION;

        HAL_UART_DMAStop(huart);

        HAL_UART_Receive_DMA(huart, Usart4Buf.RxBuffer[Usart4Buf.RxDimension], USART4_BUF_LENGTH);

      }

    }

    __HAL_UART_CLEAR_IDLEFLAG(huart);

  }

  else if (huart->Instance == UART5)

  {

    tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);

    tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE); 


    /* UART parity error interrupt occurred ------------------------------------*/

    if ((tmp_flag != RESET) && (tmp_it_source != RESET))

    {

      Usart5Buf.RxEndIndex[Usart5Buf.RxDimension] = USART5_BUF_LENGTH - huart5.RxXferCount;

[1] [2]
關(guān)鍵字:STM32F103  串口DMA  空閑中斷  不定長接收 引用地址:STM32F103串口DMA+空閑中斷+多級緩沖實現(xiàn)不定長接收

上一篇:在stm32f407上移植openharmony遇到的問題
下一篇:意法半導(dǎo)體推出STM32U3微控制器,面向遠程、智能和可持續(xù)應(yīng)用,拓展超低功耗系列創(chuàng)新技術(shù)

推薦閱讀最新更新時間:2025-04-02 12:13

STM32 | 串口空閑中斷接收定長數(shù)據(jù)(DMA方式)
在使用STM32的串口接收數(shù)據(jù)的時候,我們常常會使用接收中斷的方式來接收數(shù)據(jù),常用的是RXNE。這里分享另一種接收數(shù)據(jù)的方式——IDLE中斷(PS:本文的例子運行在STM32F103ZET6上)。 一、IDLE中斷什么時候發(fā)生? IDLE就是串口收到一幀數(shù)據(jù)后,發(fā)生的中斷。什么是一幀數(shù)據(jù)呢?比如說給單片機一次發(fā)來1個字節(jié),或者一次發(fā)來8個字節(jié),這些一次發(fā)來的數(shù)據(jù),就稱為一幀數(shù)據(jù),也可以叫做一包數(shù)據(jù)。 二、RXNE中斷和IDLE中斷的區(qū)別? 當接收到1個字節(jié),就會產(chǎn)生RXNE中斷,當接收到一幀數(shù)據(jù),就會產(chǎn)生IDLE中斷。比如給單片機一次性發(fā)送了8個字節(jié),就會產(chǎn)生8次RXNE中斷,1次IDLE中斷。 三、IDLE中斷如何配
[單片機]
STM32 | <font color='red'>串口</font><font color='red'>空閑</font><font color='red'>中斷</font><font color='red'>接收</font>不<font color='red'>定長</font>數(shù)據(jù)(<font color='red'>DMA</font>方式)
STM32CubeMX之串口定長數(shù)據(jù)接收接收中斷+空閑中斷
環(huán)境: 開發(fā)板:STM32F4探索者(正點原子) 一. 空閑(IDLE)中斷 1. 空閑幀 什么是空閑幀?在 STM32的中文參考手冊 中,你會發(fā)現(xiàn)如下解釋: 空閑幀可理解為整個幀周期內(nèi)電平均為“1”(停止位的電平也是“1”),該幀后是下一個數(shù)據(jù)幀的起始位。如下圖所示: 其實按使用的情況來看,應(yīng)是數(shù)據(jù)幀接收之后,從停止位開始一直為高電平,一直持續(xù)一幀的時間(包含停止位)為高電平,那時就會產(chǎn)生空閑中斷。 二. 空閑中斷相關(guān)的宏 使能 IDLE 中斷 __HAL_UART_ENABLE_IT(__HANDLE__, UART_IT_IDLE) //使能idle中斷 獲取 IDLE 中斷標志位 __HAL_UA
[單片機]
STM32CubeMX之<font color='red'>串口</font>不<font color='red'>定長</font>數(shù)據(jù)<font color='red'>接收</font>(<font color='red'>接收</font><font color='red'>中斷</font>+<font color='red'>空閑</font><font color='red'>中斷</font>)
解決串口開啟DMA接受卻只能接收到第一個字節(jié)的問題
設(shè)備: 單片機:STM32G070 MDK:V5.25 問題描述: 發(fā)現(xiàn)串口接受不到數(shù)據(jù),只能接受到第一個字節(jié)。 MX_USART4_UART_Init(); HAL_Delay(200); HAL_UART_Receive_DMA(&huart4, UART_DMA_RXBuf, UART_RX_BUF_SIZE); 原因分析: 在單片機執(zhí)行完串口初始化之后,并沒有立馬開啟DMA接收,在這個時間差之內(nèi)如果有數(shù)據(jù)發(fā)過來就會導(dǎo)致這個問題 解決方案: 在完成串口初始化之后,立馬開啟DMA接收,中間不能有較大的空擋時間差即可。 MX_USART4_UART_Init(); // HAL_Delay(200);
[單片機]
STM32的串口采用DMA方式接收數(shù)據(jù)測試
環(huán)境: 主機:WINXP 開發(fā)環(huán)境:MDK4.23 MCU:STM32F103CBT6 說明: 串口可以配置成用DMA的方式接收數(shù)據(jù),不過DMA需要定長才能產(chǎn)生接收中斷,如何接收可變長度的數(shù)據(jù)呢? 方法有以下3種: 1.將RX腳與一路時鐘外部引腳相連,當串口一幀發(fā)完,即可利用此定時器產(chǎn)生超時中斷.這個實時性較高,可以做到1個字節(jié)實時監(jiān)測. 2.不改變硬件,開啟一個定時器監(jiān)控DMA接收,如果超時則產(chǎn)生中斷.這個實時性不高,因為超時時間必須要大于需要接收幀的時間,精度不好控制. 3.STM32單片機有的串口可以監(jiān)測總線是否處于空閑,如果空閑則產(chǎn)生中斷.可以用它來監(jiān)測DMA接收是否完畢.這種方式實時性很高. 本文采用
[單片機]
STM32的<font color='red'>串口</font>采用<font color='red'>DMA</font>方式<font color='red'>接收</font>數(shù)據(jù)測試
stm32f103 flash模擬eeprom
STM32F103是意法半導(dǎo)體(STMicroelectronics)推出的一款32位單片機系列,該系列芯片具有高性能和豐富的外設(shè)接口,廣泛應(yīng)用于工業(yè)控制、消費電子、汽車電子等領(lǐng)域。其中,STM32F103的Flash存儲器可以模擬EEPROM的功能,在本文中我們將詳細介紹如何使用STM32F103的Flash存儲器來實現(xiàn)EEPROM。 概述 EEPROM(Electrically Erasable Programmable Read-Only Memory)是一種可擦寫的非易失性存儲器,可以在不使用外部電壓的情況下對其進行擦除和編程。它不同于Flash存儲器的主要特點是可以對單個字節(jié)進行隨機讀寫操作。而STM32F103的Fl
[單片機]
使用STM32F103C8和SIM800C GSM模塊發(fā)送/接收短信
GSM 模塊經(jīng)常用于物聯(lián)網(wǎng)項目,因為它能夠遠程發(fā)送和接收數(shù)據(jù)。GSM 模塊沒有像 Wi-Fi 模塊那樣的依賴項。雖然其他無線模塊如Wi-Fi或Zigbee具有短距離和成本等缺點,但 GSM 模塊具有可靠性、長距離,因為有效計劃只需要一張 SIM 卡。盡管 GSM 模塊無法發(fā)送傳感器生成的大量數(shù)據(jù),但它非常適合需要發(fā)送少量合理數(shù)據(jù)的應(yīng)用。 在本教程中,此類GSM 模塊將與 STM32F103C8 ARM 微控制器連接,以從程序中配置的蜂窩移動號碼發(fā)送和接收文本消息 (SMS)。為了顯示接收和發(fā)送的消息,一個16x2 LCD將與兩個按鈕一起使用,這兩個按鈕將在按下相關(guān)按鈕后啟動文本消息的發(fā)送和接收。 所需組件 STM32F10
[單片機]
使用<font color='red'>STM32F103</font>C8和SIM800C GSM模塊發(fā)送/<font color='red'>接收</font>短信
基于STM32F103RB和CC1101的無線數(shù)傳模塊設(shè)計
本文設(shè)計了一種可工作在433.00-434.79MHz,中心頻率為433.00MHz,輸出功率可調(diào)的無線數(shù)傳模塊。模塊采用STM32F103RB單片機和射頻芯片CC1101設(shè)計,利用EDA軟件ADS2008仿真優(yōu)化了射頻電路的輸出匹配網(wǎng)絡(luò)。最后對無線模塊輸出功率,通信距離等參數(shù)進行了測試和驗證。 0 引言 隨著近些年無線通信技術(shù)的發(fā)展,越來越多的無線技術(shù)開始涌現(xiàn),GSM/GPRS、Wlan、Zigbee等,為了更方便人們生產(chǎn)生活,以及改變現(xiàn)有的無線頻道變得越來越擁擠的現(xiàn)狀,不同國家相繼開通了一些用于免費的ISM頻段,其中430M~510M的頻段在中國最為常用。 本文選用ST公司生產(chǎn)的STM32F103RB作為主控芯片,T
[單片機]
基于<font color='red'>STM32F103</font>RB和CC1101的無線數(shù)傳模塊設(shè)計
stm32f103系列引腳定義-功能圖
  器件功能和配置(STM32F103xx增強型)   STM32F103xx增強型模塊框架圖   STM32F103xx增強型VFQFPN36管腳圖   STM32F103xx增強型LQFP100管腳圖   STM32F103xx增強型LQFP64管腳圖   STM32F103xx增強型LQFP48管腳圖   STM32F103xx增強型BGA100管腳圖   STM32F103xx系列各個管腳名稱定義、功能:
[單片機]
<font color='red'>stm32f103</font>系列引腳定義-功能圖
小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 六枝特区| 阜南县| 淳安县| 泰顺县| 当阳市| 永吉县| 康平县| 乐业县| 神农架林区| 莎车县| 阿城市| 富民县| 太保市| 旬邑县| 平罗县| 原阳县| 尼勒克县| 闵行区| 西平县| 莎车县| 根河市| 汝州市| 斗六市| 广平县| 红原县| 卫辉市| 永济市| 罗定市| 荥阳市| 饶河县| 正宁县| 合水县| 嘉峪关市| 阜新市| 南城县| 大足县| 阿荣旗| 凉城县| 原平市| 阿尔山市| 微山县|