STM32-第十節-DMA直接存儲器存取

一、DMA:

1.簡介:

DMA,直接存儲區存取

DMA可以提供外設和存儲器或存儲器與存儲器見的高速數據傳輸,無需CPU干預。

12個通道:DMA1(7個通道),DMA2(5個通道)

每個通道支持軟件觸發,和特定硬件觸發(每個外設有固定通道)。

本芯片只有DMA1。

2.存儲器映像:

3.功能圖:

外設寄存器Flash和SRAM(存儲器)為兩大數據存儲地點。

轉運數據由兩個結構體決定,每個包含三個參數:
起始地址,數據寬度,地址是否自增(一次轉運完成后,指針是否挪到下個地址)。
(ps:這兩個結構體其實是完全相同的,并非外設結構體只能放外設地址等等)

傳輸計數器:觸發后,進行數據轉運的次數,在傳輸完成后,兩個結構體的指針回到初始地址。

自動重裝器:決定了是否循環傳輸,在傳輸完成后,傳輸寄存器恢復到自動重裝器的值,配合上面結構體指針回到初始地址,可以做到對對同一塊地址數據循環傳輸。

M2M:決定觸發邏輯,為1則軟件觸發,為0硬件觸發(MtoM名稱意義為存儲器到存儲器)

軟件觸發:與前面不同的是,并非由一個函數觸發,而是不斷連續觸發DMA,直到將傳輸計數器清零,完成傳輸,即使能DMA就自動開始轉運。(軟件觸發和循環模式不能同時使用)

硬件觸發:就是外設給出信號觸發

開關控制:給DMA使能,寫傳輸計數器時,需要將DMA關閉。

4.ADC與DMA:

前文介紹了ADC的功能,ADC有一個掃描模式,可以同時轉換多個通道的值,但在規則組中,卻只有一個寄存器存放結果,就需要DMA,在一次轉換完成后,就將寄存器的數據轉運到存儲器中,這樣就不會被下一個通道的結果覆蓋而丟失。

二、實戰:DMA數據轉運

DMA.c

#include "stm32f10x.h"                  // Device headeruint16_t MyDMA_Size;					//定義全局變量,用于記住Init函數的Size,供Transfer函數使用/*** 函    數:DMA初始化* 參    數:AddrA 原數組的首地址* 參    數:AddrB 目的數組的首地址* 參    數:Size 轉運的數據大小(轉運次數),1代表字節* 返 回 值:無*/
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{MyDMA_Size = Size;					//將Size寫入到全局變量,記住參數Size/*開啟時鐘*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);						//開啟DMA的時鐘/*DMA初始化*/DMA_InitTypeDef DMA_InitStructure;										//定義結構體變量DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;						//外設基地址,給定形參AddrADMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	//外設數據寬度,選擇字節DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;			//外設地址自增,選擇使能DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;							//存儲器基地址,給定形參AddrBDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;			//存儲器數據寬度,選擇字節DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					//存儲器地址自增,選擇使能DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;						//數據傳輸方向,選擇由外設到存儲器(此處名稱的意思是,外設作為數據源)DMA_InitStructure.DMA_BufferSize = Size;								//轉運的數據大小(轉運次數)DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;							//模式,選擇正常模式DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;								//存儲器到存儲器,選擇使能DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;					//優先級,選擇中等DMA_Init(DMA1_Channel1, &DMA_InitStructure);							//將結構體變量交給DMA_Init,配置DMA1的通道1(軟件無所謂,硬件要查手冊,看是通道幾)/*DMA使能*/DMA_Cmd(DMA1_Channel1, DISABLE);	//這里先不給使能,初始化后不會立刻工作,等后續調用Transfer后,再開始
}/*** 函    數:啟動DMA數據轉運* 參    數:無* 返 回 值:無*/
void MyDMA_Transfer(void)
{DMA_Cmd(DMA1_Channel1, DISABLE);					//DMA失能,在寫入傳輸計數器之前,需要DMA暫停工作DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);	//寫入傳輸計數器,指定將要轉運的次數DMA_Cmd(DMA1_Channel1, ENABLE);						//DMA使能,開始工作while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);	//等待DMA工作完成DMA_ClearFlag(DMA1_FLAG_TC1);						//清除工作完成標志位
}

三、實戰:DMA+AD多通道

問:如何訪問外設寄存器?

答:無需具體地址,可通過結構體來訪問,如想訪問ADC1的DR寄存器,直接ADC1->DR即可。

新AD.c

#include "stm32f10x.h"                  // Device headeruint16_t AD_Value[4];					//定義用于存放AD轉換結果的全局數組/*** 函    數:AD初始化* 參    數:無* 返 回 值:無*/
void AD_Init(void)
{/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//開啟ADC1的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//開啟GPIOA的時鐘RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);		//開啟DMA1的時鐘/*設置ADC時鐘*/RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//選擇時鐘6分頻,ADCCLK = 72MHz / 6 = 12MHz/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);					//將PA0、PA1、PA2和PA3引腳初始化為模擬輸入/*規則組通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);	//規則組序列1的位置,配置為通道0ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);	//規則組序列2的位置,配置為通道1ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);	//規則組序列3的位置,配置為通道2ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);	//規則組序列4的位置,配置為通道3/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure;											//定義結構體變量ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;							//模式,選擇獨立模式,即單獨使用ADC1ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;						//數據對齊,選擇右對齊ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;			//外部觸發,使用軟件觸發,不需要外部觸發ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;							//連續轉換,使能,每轉換一次規則組序列后立刻開始下一次轉換ADC_InitStructure.ADC_ScanConvMode = ENABLE;								//掃描模式,使能,掃描規則組的序列,掃描數量由ADC_NbrOfChannel確定ADC_InitStructure.ADC_NbrOfChannel = 4;										//通道數,為4,掃描規則組的前4個通道ADC_Init(ADC1, &ADC_InitStructure);											//將結構體變量交給ADC_Init,配置ADC1/*DMA初始化*/DMA_InitTypeDef DMA_InitStructure;											//定義結構體變量DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;				//外設基地址,給定形參AddrADMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	//外設數據寬度,選擇半字,對應16為的ADC數據寄存器DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;			//外設地址自增,選擇失能,始終以ADC數據寄存器為源DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;					//存儲器基地址,給定存放AD轉換結果的全局數組AD_ValueDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;			//存儲器數據寬度,選擇半字,與源數據寬度對應DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;						//存儲器地址自增,選擇使能,每次轉運后,數組移到下一個位置DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;							//數據傳輸方向,選擇由外設到存儲器,ADC數據寄存器轉到數組DMA_InitStructure.DMA_BufferSize = 4;										//轉運的數據大小(轉運次數),與ADC通道數一致DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;								//模式,選擇循環模式,與ADC的連續轉換一致DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;								//存儲器到存儲器,選擇失能,數據由ADC外設觸發轉運到存儲器DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;						//優先級,選擇中等DMA_Init(DMA1_Channel1, &DMA_InitStructure);								//將結構體變量交給DMA_Init,配置DMA1的通道1(只能是通道1)/*DMA和ADC使能*/DMA_Cmd(DMA1_Channel1, ENABLE);							//DMA1的通道1使能ADC_DMACmd(ADC1, ENABLE);								//ADC1觸發DMA1的信號使能ADC_Cmd(ADC1, ENABLE);									//ADC1使能/*ADC校準*/ADC_ResetCalibration(ADC1);								//固定流程,內部有電路會自動執行校準while (ADC_GetResetCalibrationStatus(ADC1) == SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) == SET);/*ADC觸發*/ADC_SoftwareStartConvCmd(ADC1, ENABLE);	//軟件觸發ADC開始工作,由于ADC處于連續轉換模式,故觸發一次后ADC就可以一直連續不斷地工作
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915689.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915689.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

服務器設置國外IP無法訪問對防御攻擊有用嗎?

將服務器設置為僅允許國外 IP 訪問,限制國內 IP 訪問,確實可以在某些特定場景下提高服務器的抗攻擊能力,但這并不能完全防御攻擊。以下是對這種方法的分析、優缺點以及其他防御攻擊的補充措施。1. 僅允許國外 IP 訪問是否有用?1.1…

八大作業票(一) 動火安全作業證

動火安全作業證 執行標準:GB30871 GSDH——2200001 申報單位 申請人 作業申請時間 年 月 日 時 分 動火內容 動火方式 動火地點 動火類別 特級動火□ 一級動火□ 二級動火□ 作業負責人 監護人 動火…

NumPy庫使用教學,簡單詳細。

NumPy 使用教學NumPy 是 Python 中用于科學計算的基礎庫,它提供了高性能的多維數組對象以及用于處理這些數組的工具。下面將結合多個代碼文件,詳細介紹 NumPy 的各種用法。1. 創建數組1.1 從列表創建數組import numpy as np# 一維數組 list1 [1,2,3,4,5…

vue3:十八、內容管理-實現行內圖片的預覽、審核功能

一、實現效果 實現圖片的顯示,大圖預覽;審核部分的待審核的審核功能 二、圖片預覽實現 1、參考官網 官網-圖片預覽 2、圖片預覽插槽設置 {row,index} 插槽中獲取row行信息、index索引信息(指定行圖片預覽需要用到) style 設置基本樣式寬width高height src 設置圖片的路徑…

Go后端配置文件教程

注:本文為博主,首次接觸項目時的入門級配置實操在 Go 后端中,使用配置文件管理參數(如數據庫連接、服務端口等)是必備技能。Viper 是 Go 生態中最流行的配置管理庫。支持多種配置文件、環境變量、命令行參數等&#xf…

ubuntu24.04安裝CUDA、VLLM、Pytorch等并部署Qwen3-8B-AWQ【50系顯卡通用】

1. 系統更新與依賴安裝 sudo apt update && sudo apt upgrade -y sudo apt install -y python3-pip python3-venv build-essential git nvidia-driver-575注:RTX 5070 Ti 推薦驅動 ≥550 版本 我是直接官網安裝最新的驅動了,反正向上兼容,驅動安裝教程可以參考我以…

Azure可靠性架構指南:構建云時代的高可用系統

隨著企業加速擁抱數字化轉型,云服務的可靠性已成為業務連續性的核心命題。Microsoft Azure憑借其"可靠性即核心"的設計理念,為企業技術決策者與架構師提供了一個可信賴的數字化底座。本文將系統解析Azure如何通過技術架構、工具鏈與方法論&…

linux 驅動 - v4l2 驅動框架

文章目錄一、/dev/videoX1. 查詢設備能力2. 獲取當前視頻格式3. 設置視頻格式4. 申請緩沖區1) mmap 方式2) user 分配5. 查詢緩沖區信息6. 將緩沖區放入隊1) fill_vb2_buffer2) buf_prepare3) get_userptr4) buf_init5) attach_dmabuf 和 map_dmabuf6) start_streaming7) 總結7…

windows內核研究(驅動開發-0環與3環的通信)

驅動開發0環與3環的通信 設備對象 在之前開發窗口程序時,消息都是被封裝成一個結構體(MSG),在內核開發時,消息被封裝成另外一個結構體:IRP(I/O Request Package) 在窗口程序中&#…

ASP.NET Core Web API 內存緩存(IMemoryCache)入門指南

在 Web API 開發中,頻繁訪問數據庫或第三方服務可能會帶來性能瓶頸。為了提升接口響應速度并減輕后端壓力,使用緩存是非常有效的優化手段。本文將帶你快速上手 ASP.NET Core 提供的內存緩存(IMemoryCache),無需安裝額外…

Axios Token 設置示例

以下是一個完整的 Axios Token 設置示例,涵蓋全局配置、請求攔截器和單次請求設置三種方式:1. 基礎配置(推薦方案)javascript復制代碼import axios from axios;// 創建 Axios 實例 const apiClient axios.create({baseURL: https…

Excel數據合并工具:零門檻快速整理

軟件介紹 在數據處理工作中,合并Excel同類數據是一項常見但繁瑣的任務。今天為大家推薦一款專為簡化此類操作設計的工具,它能快速完成工作表內多行同類數據的合并整理,大幅提升數據處理效率。 零門檻操作體驗 相比Excel自帶的數據透視…

深度學習 -- 梯度計算及上下文控制

深度學習 – 梯度計算及上下文控制 文章目錄深度學習 -- 梯度計算及上下文控制一,自動微分1.1 基礎概念1.2 計算梯度1.2.1 計算標量梯度1.2.2 計算向量梯度1.2.3 多標量梯度計算1.2.4 多向量梯度計算二,梯度上下文控制2.1 控制梯度計算2.2 累計梯度2.3 梯…

Redisson RLocalCachedMap 核心參數詳解

🧑 博主簡介:CSDN博客專家,歷代文學網(PC端可以訪問:https://literature.sinhy.com/#/?__c1000,移動端可微信小程序搜索“歷代文學”)總架構師,15年工作經驗,精通Java編…

【Unity3D實例-功能-移動】角色移動-通過WSAD(Rigidbody方式)

你是否曾夢想在虛擬世界中自由翱翔,像海豚一樣在海洋自由穿梭,或者像宇航員一樣在宇宙中盡情探索?今天,我們就來聊聊如何在Unity中使用Rigidbody來實現角色移動。 廢話不多說,走,讓我們馬上來一探究竟&…

Vue接口平臺學習十一——業務流測試

效果圖及簡單說明 與之前的用例列表相似布局,也分左右,左邊用于顯示測試流程的名稱,右邊用于顯示流程相關信息。 左側點擊添加,直接增加一個新的業務流。 右側是點擊的業務流詳情,展示名稱,名稱的編輯保存&…

碳化硅缺陷分類與原因

01一、碳化硅晶體材料中的缺陷到底是什么?碳化硅晶體材料中的缺陷是指在晶體生長、加工或使用過程中出現的不完美結構。這些缺陷可能表現為晶體內部的裂紋、表面的凹坑、原子排列的錯誤等。雖然缺陷看起來微不足道,但它們卻可能對晶體的電學、熱學和機械…

Jenkins 實現項目的構建和發布

作者:小凱 沉淀、分享、成長,讓自己和他人都能有所收獲! 本文的宗旨在于通過簡單干凈實踐的方式教會讀者,如何在 Docker 中部署 Jenkins,并通過 Jenkins 完成對項目的打包構建并在 Docker 容器中部署。 Jenkins 的主要…

Django接口自動化平臺實現(三)

3.2 后臺 admin 添加數據 1)注冊模型類到 admin: 1 from django.contrib import admin2 from . import models3 4 5 class ProjectAdmin(admin.ModelAdmin):6 list_display ("id", "name", "proj_owner", "tes…

CentOS 7 配置環境變量常見的4種方式

?博客主頁: https://blog.csdn.net/m0_63815035?typeblog 💗《博客內容》:.NET、Java.測試開發、Python、Android、Go、Node、Android前端小程序等相關領域知識 📢博客專欄: https://blog.csdn.net/m0_63815035/cat…