国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼)

這篇具有很好參考價值的文章主要介紹了HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

最近想做一個控制電機的項目,其中會用到Pytho與單片機STM32之間的互同,最近也在看一些關(guān)于數(shù)據(jù)通信和拆包的相關(guān)知識,所以記錄一下這段時間里對兩者之間的互通所做的事情和發(fā)現(xiàn)的問題,以供自己和大家參考。

單片機的串口是我們常用的與電腦通信的外設(shè),本次與Python互通就采用的串口實現(xiàn)上位機與下位機的通訊。

本章先講解串口外設(shè)的使用,下一章講解在Python中接收單片機發(fā)送的數(shù)據(jù)。

我采用的單片機型號是STM32F103ZET6,使用usart1進行數(shù)據(jù)的收發(fā),所使用的引腳是PA9、PA10。使用STM32Cube打開串口進行初始化。

第一步,設(shè)置時鐘源,在未設(shè)置的情況下,我們的單片機默認的系統(tǒng)時鐘是8MHz,如下圖所示。

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

所以,要想系統(tǒng)時鐘達到最大就要使用外部晶振,不過,值得注意的是,F(xiàn)1系列的板子使用外部晶振作為時鐘源時,系統(tǒng)時鐘可超過72MHz,但是為了單片機的穩(wěn)定性,我們對系統(tǒng)時鐘的設(shè)置不能超過官方的限制。

下面,將打開外部時鐘源

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

選擇高速時鐘源,然后選擇72MHz,讓系統(tǒng)自己設(shè)置。

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

第二步,在SYS里面的Debug選擇 Serial write,非常重要的一步,否則會造成第一次燒錄程序后續(xù)無法識別調(diào)試器

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

第三步打開串口USART1,在USART1中的Mode選擇?Asynchronous?異步通信

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

波特率為?115200 Bits/s。傳輸數(shù)據(jù)長度為?8 Bit。奇偶檢驗?None,停止位?1?,接收和發(fā)送都使能。

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

?開啟中斷

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

并且采用DMA進行數(shù)據(jù)傳輸,采用DMA 好處是不需要占用CPU的資源即可完成數(shù)據(jù)的接收和發(fā)送,極大的節(jié)約了CPU 的占用。對于DMA 的原理這里不重點解釋,我們只需要知道他的功能和如何使用即可,下面將USART1的DMA開啟。

選擇DMA Settings點擊Add,添加USART1_RXUSART1_TX

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

選擇MDK-ARMCode Generator 中的 Generate peripheral initialization as a pair of '.c/.h' files per peripheral

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

?最后生成文件

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

生成的代碼如下,這里說一個小技巧,我們可以在

/* USER CODE BEGIN 1 */

? /* USER CODE END 1 */

中間寫函數(shù),例如

/* USER CODE BEGIN 1 */

? ? ? interesting();

? /* USER CODE END 1 */

這樣,如果向開其他外設(shè)的時候直接在Cube里面打開,再生成即可,如果不卸載里面的話,我們自己寫的代碼將會在生成后被刪除,會很麻煩。?

main.c?

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

usart.c

UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;

/* USART1 init function */

void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA1_Channel5;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);

    /* USART1_TX Init */
    hdma_usart1_tx.Instance = DMA1_Channel4;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);

  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 DMA DeInit */
    HAL_DMA_DeInit(uartHandle->hdmarx);
    HAL_DMA_DeInit(uartHandle->hdmatx);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

串口使能中斷函數(shù)

void usart_dma_int()
{
	
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中斷

	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//開啟DMA接收
}

DMA發(fā)送函數(shù)

HAL_UART_Transmit_DMA(&huart1, buf,len)

重定向printf函數(shù)

int fputc(int ch,FILE *stream)
{
HAL_UART_Transmit(&huart1,( uint8_t *)&ch,1,0xFFFF);
return ch;
}

我們的接收數(shù)據(jù)采用DMA接收方式,使用DMA+IDLE空閑中斷,這樣的好處是,當接收到一串數(shù)據(jù)時,串口不會發(fā)生中斷,而是將接收到的數(shù)據(jù)通過DMA存到緩存區(qū)中,當數(shù)據(jù)傳輸完成后,IDLE產(chǎn)生中斷標志位,進而產(chǎn)生一次中斷,我們就可以在這次中斷中做一些我們想要實現(xiàn)的功能,這種DMA+IDLE接收的方式,很符合數(shù)據(jù)傳輸通訊的形式,代碼如下

void USART1_IRQHandler(void)
{
        uint32_t flag = 0;
	    uint32_t num;//DMA沒有傳輸?shù)膫€數(shù)
	    flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //獲取IDLE標志位
	if((tmp_flag != RESET))//IDE產(chǎn)生中斷
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除標志位
		HAL_UART_DMAStop(&huart1); //停止DMA傳輸
		num = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 獲取DMA中未傳輸?shù)臄?shù)據(jù)個數(shù)   
		rx_num =  BUFFER_SIZE - temp; //BUFFER_SIZE(接收數(shù)據(jù)緩存的最大個數(shù))-num(剩余的個數(shù))=當前接收的數(shù)據(jù)個數(shù)
		flag= 1;	// 接受完成標志位置1	
	}
  /* USER CODE END USART1_IRQn 0 */
   HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

主函數(shù)

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  usart_dma_int();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
     printf("實驗\r\n");
     HAL_Delay(300);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

實驗結(jié)果

HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼),單片機,stm32,嵌入式硬件,python,c語言

?本次先講解串口收發(fā)的使用,下一章介紹在Python中接收單片機發(fā)送的數(shù)據(jù)并解析。

跳轉(zhuǎn)連接:https://blog.csdn.net/m0_73816319/article/details/135667240?spm=1001.2014.3001.5502文章來源地址http://www.zghlxwxcb.cn/news/detail-814070.html

到了這里,關(guān)于HAL庫 STM32運用DMA與IDLE中斷實現(xiàn)高效串口通信 (附代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • GD32實現(xiàn)串口空閑(IDLE)中斷 + DMA機制接收數(shù)據(jù)

    GD32實現(xiàn)串口空閑(IDLE)中斷 + DMA機制接收數(shù)據(jù)

    前言 串口功能在單片機開發(fā)中,是比較常用的外設(shè),熟練使用串口功能也是驅(qū)動開發(fā)必備的技能之一。 DMA 是一種CPU輔助手段,可以在CPU不參與的情況下,是做一些輔助CPU的事情,如通常的數(shù)據(jù)搬運。 在沒有DMA之前,數(shù)據(jù)讀取時,需要CPU的處理,在多任務(wù)處理時,增加資源緊

    2023年04月13日
    瀏覽(24)
  • STM32—HAL庫中斷/DMA控制和完成串口通信

    STM32—HAL庫中斷/DMA控制和完成串口通信

    目錄 一、解決的問題 二、串口通訊協(xié)議和RS-232的介紹以及USB/TTL轉(zhuǎn)232模塊的工作原理? ?1、?串口協(xié)議和RS-232標準: ?(1)串口協(xié)議: (2)RS-232 標準:? ?2、RS232電平與TTL電平的區(qū)別? ?3、USB/TTL轉(zhuǎn)232“模塊(CH340芯片為例)? (1)基本原理:? (2)CH340模塊介紹: ?三、搭

    2024年02月02日
    瀏覽(30)
  • (stm32之HAL庫)UART工作在DMA模式要打開串口中斷嗎?

    (stm32之HAL庫)UART工作在DMA模式要打開串口中斷嗎?

    最近學(xué)習(xí)了stm32(F4xx)的串口在DMA模式下的使用,期間以ST官方提供的例程進行參考學(xué)習(xí),發(fā)現(xiàn)其初始化過程中是打開了UART的中斷的,而且HAL庫中stm32f4xx_hal_uart.c文件中的DMA模式使用說明里也有這么一句話: 即在非循環(huán)模式下(也就是發(fā)完一次數(shù)據(jù)就停止的常用模式)需要配置

    2024年02月12日
    瀏覽(30)
  • STM32-HAL庫串口DMA空閑中斷的正確使用方式+解析SBUS信號

    STM32-HAL庫串口DMA空閑中斷的正確使用方式+解析SBUS信號

    能夠點進這篇文章的小伙伴肯定是對STM32串口DMA空閑中斷接收數(shù)據(jù)感興趣的啦,今天用這一功能實現(xiàn)串口解析航模遙控器sbus信號時,查閱了很多網(wǎng)友發(fā)布的文章(勤勞的搬運工~),包括自己之前寫過一篇博客 STM32_HAL庫_CubeMx串口DMA通信(DMA發(fā)送+DMA空閑接收不定長數(shù)據(jù))。本文

    2024年02月09日
    瀏覽(25)
  • 【STM32】CUBEMX之串口:串口三種模式(輪詢模式、中斷模式、DMA模式)的配置與使用示例 + 串口重定向 + 使用HAL擴展函數(shù)實現(xiàn)不定長數(shù)據(jù)接收

    【STM32】CUBEMX之串口:串口三種模式(輪詢模式、中斷模式、DMA模式)的配置與使用示例 + 串口重定向 + 使用HAL擴展函數(shù)實現(xiàn)不定長數(shù)據(jù)接收

    目錄 ? 總覽 使用CUBEMX創(chuàng)建工程的基本配置 CUBEMX中的配置 Keil中的配置 實物連接 串口輪詢模式 輪詢模式HAL庫函數(shù) 特點 實驗一:發(fā)送數(shù)據(jù)給單片機并讓其返回相同值 串口重定向 串口中斷模式 在CUBEMX中打開串口中斷 中斷模式HAL庫函數(shù) 特點 實驗二:使用中斷回調(diào)完成實驗一

    2024年04月10日
    瀏覽(44)
  • STM32F4_HAL庫_串口阻塞/中斷/DMA三種方式發(fā)送數(shù)據(jù)的配置

    串口阻塞發(fā)送的意思就是,發(fā)送一段數(shù)據(jù),在沒有發(fā)送完所有數(shù)據(jù)之前,一直停留在此發(fā)送函數(shù)(可設(shè)定阻塞時間),這個過程中會阻塞別的程序運行; HAL庫的配置分為兩個層次,一個是HAL庫內(nèi)部調(diào)用的、與MCU硬件相關(guān)的初始化xxx_MspInit,一個是我們外部調(diào)用的初始化xxx_In

    2023年04月25日
    瀏覽(32)
  • GD32或STM32:DMA循環(huán)模式與普通模式(串口IDLE)

    USART+DMA+循環(huán)隊列接收不定長數(shù)據(jù)-CSDN博客 STM32 DMA 循環(huán)模式DMA_Mode_Circular詳解-CSDN博客 推薦以上兩個鏈接。 Normal(普通)模式的DMA+串口IDLE中斷,流程如下: 1、初始化時:開啟串口IDLE中斷;dma_circulation_disable,失能DMA的循環(huán); 2、在串口IDLE中斷里面: (1) 清除idle的flag;dma_c

    2024年02月21日
    瀏覽(26)
  • STM32 F4串口空閑中斷 + DMA實現(xiàn)數(shù)據(jù)發(fā)送

    最近在做 STM32 + ROS車的項目,STM32與ROS之間通信由于數(shù)據(jù)量大,所以在 STM32端 使用 空閑中斷 + DMA 的方案來減輕 CPU 的壓力。 一、空閑中斷 空閑中斷 顧名思義為空了,閑了,沒事了進的中斷,在 沒有數(shù)據(jù)流 的時候會進入進行讀取。 在我們串口進行發(fā)送時實則為連續(xù)發(fā)送,兩

    2024年02月16日
    瀏覽(27)
  • STM32 UART串口通信IDLE空閑中斷的使用步驟

    參考了各路大神的資料,蒙蔽了半天,終于學(xué)會了,記錄一下,以后忘了可以回來復(fù)習(xí)參考。 一、首先在stm32cube中配置打開對應(yīng)uart串口的中斷 二、工程main函數(shù)調(diào)用 __HAL_UART_ENABLE_IT(huart1,UART_IT_IDLE);//hal庫宏定義,使能串口空閑中斷 ?? ?HAL_UART_Receive_DMA(huart1,data,sizeof(data));//使

    2024年02月12日
    瀏覽(15)
  • STM32使用三種方式(阻塞、中斷、DMA)實現(xiàn)串口發(fā)送和接收數(shù)據(jù)

    STM32使用三種方式(阻塞、中斷、DMA)實現(xiàn)串口發(fā)送和接收數(shù)據(jù)

    記錄下學(xué)習(xí)STM32開發(fā)板的心得的和遇見的問題。 板卡型號:STM32F405RGT6 軟件:STM32CubeMX、IAR STM32串口外設(shè)提供了3種接收和發(fā)送方式:阻塞、中斷、DMA,主要給大家分享中斷方式接收不定長數(shù)據(jù)和DMA使用空閑中斷接收不定長數(shù)據(jù)。 阻塞發(fā)送: 阻塞接收: 兩個函數(shù)需要注意的就

    2024年02月03日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包