本文介紹STM8L051F3的DMA相關(guān)知識。內(nèi)容分為以下幾部分:
- DMA簡介
- DMA傳輸ADC數(shù)據(jù)
DMA(Direct memory access):直接內(nèi)存存儲。DMA可以提高外設(shè)和內(nèi)存以及內(nèi)存到內(nèi)存直接的傳輸速率,數(shù)據(jù)能不經(jīng)過CPU任何的參與快速地移動,這樣可以節(jié)省CPU去處理其他事情。以STM8L051F3為例,它的DMA控制器一共有4個人通道,每個通道專門用于從一個或多個外設(shè)內(nèi)存訪問請求,它也能仲裁DMA請求的優(yōu)先級。DMA的主要特點如下:
- 4個通道在多個外設(shè)之間共享
- 數(shù)據(jù)傳輸可以從外設(shè)到內(nèi)存、內(nèi)存到外設(shè)、內(nèi)存到內(nèi)存
- 硬件/軟件可以根據(jù)每個通道的優(yōu)先級進行仲裁
- 可編程傳輸數(shù)據(jù)量:最多達255個數(shù)據(jù)塊(字節(jié)或字)
- 遞增和遞減尋址模式
- 可硬件和軟件編程通道優(yōu)先級
- 在半發(fā)送和發(fā)送結(jié)束可選擇中斷
- 可軟件編程發(fā)送數(shù)據(jù)大?。?位或16位
- 通道請求直接的優(yōu)先級:可軟件編程(非常高、高、中、低)或在相同的情況下硬件可編程
- 軟件觸發(fā)器也支持內(nèi)存通道,取決于硬件配置
- 兩個標(biāo)志位(DMA半傳輸,DMA傳輸完成)對每個通道的單個中斷請求進行邏輯上的或
- 循環(huán)緩沖區(qū)管理(自動裝載模式)
- 掛起和重新開始DMA發(fā)送能力
- 運行在低功耗模式能力(WFI或WFE)
DMA模塊的框圖如下:
DMA傳輸。一個事件之后,外設(shè)發(fā)送一個請求信號到DMA控制器,DMA控制器根據(jù)通道的優(yōu)先級來對請求進行處理,一旦DMA控制器訪問外設(shè),DMA控制器就會發(fā)送一個應(yīng)答給外設(shè),如果外設(shè)沒有其他等待的請求,得到DMA控制器的應(yīng)答后就會釋放它的請求信號。
DMA通道。4個通道:3個普通通道(通道0、通道1、通道2)和一個內(nèi)存通道(通道3)。普通通道處理位于固定地址的外設(shè)寄存器和一個自動遞增/遞減指針指向的內(nèi)存地址范圍之間的數(shù)據(jù)傳輸。內(nèi)存通道也是一個普通通道,但是它可以處理兩個內(nèi)存指針指向的內(nèi)存地址之間的數(shù)據(jù)傳輸。
可編程的數(shù)據(jù)大小。發(fā)送的數(shù)據(jù)大小(8位或16位)可以通過DMA_CXSPR寄存器的TSIZE位來控制(當(dāng)運行在16位模式是,系統(tǒng)處理字節(jié)存儲地址在遞增或遞減模式,目標(biāo)和源指針必須包含MSB地址)。配置成16位模式,傳輸由4個連續(xù)的8位讀寫操作:
- 從源數(shù)據(jù)的偶地址讀取MSB
- 從源數(shù)據(jù)的奇地址讀取LSB
- 往目標(biāo)的偶地址寫入MSB數(shù)據(jù)
- 往目標(biāo)的奇地址寫入LSB數(shù)據(jù)
為了保證數(shù)據(jù)的連貫性,兩個讀操作和兩個寫操作是不可分割的。
指針增量。在內(nèi)存到外設(shè)或外設(shè)到內(nèi)存?zhèn)鬏斊陂g,每次傳輸后內(nèi)存指針會自動地遞增或遞減,這取決于DMA_CXCR寄存器的MINCDEC位,而外設(shè)的地址是固定的。
通道配置步驟??筛鶕?jù)以下步驟配置DMA的通道x(x為通道號):
1)在DMA_CXPARL/H寄存器設(shè)置外設(shè)寄存器地址
2)在DMA_CXPARH/L和DMA_CXM0ARH/L寄存器設(shè)置內(nèi)存地址
3)在DMA_CXNDTR寄存器配置發(fā)送數(shù)據(jù)的數(shù)量
4)在DMA_CXSPR寄存器的PL[1:0]位配置通道優(yōu)先級
5)在DMA_CXCR寄存器配置數(shù)據(jù)傳輸方向、循環(huán)模式、內(nèi)存遞增/遞減模式、發(fā)送數(shù)據(jù)大小、在半傳輸或傳輸完成中斷等
6)在DMA_CXCR寄存器設(shè)置EN位激活通道
7)在所有通道配置完成后,配置DMA_GCSR寄存器GEN位使能DMA
其他的循環(huán)模式、內(nèi)存到內(nèi)存模式、DMA傳輸暫停、等相關(guān)的詳細說明可以參考官方手冊RM0031的第13章內(nèi)容。DMA1(STM8L051F3的DMA外設(shè)是DMA1)通道請求映射如下:
2、 DMA傳輸ADC數(shù)據(jù)
2.1 DMA配置
本小節(jié)介紹通過ADC采集電壓數(shù)據(jù),通過DMA把數(shù)據(jù)轉(zhuǎn)送到內(nèi)存,然后設(shè)置TIM3_CH1(接的是PB1,也就是LED1)為PWM1模式,再通過DMA把內(nèi)存中ADC的數(shù)據(jù)傳送到TIM3的CCR1寄存器上,實現(xiàn)根據(jù)ADC采集電壓的變化來控制LED1的亮度。
實驗的過程可以理解為:外設(shè)--DMA--內(nèi)存--DMA--外設(shè)。實驗使用三個外設(shè)功能:
- ADC1--配置ADC1_CH22,連續(xù)轉(zhuǎn)換模式,12位分辨率,使用DMA通道1(外設(shè)到內(nèi)存)
- TIM3--配置TIM3_CH1為PWM1模式,使用通道0(內(nèi)存到外設(shè))
- DMA--配置通道0與通道1的模式、參數(shù)以及使能
使用的例程:STM8L051F3_12_DMA,ADC的配置步驟如下:
1)使能ADC1外設(shè)時鐘
2)初始化ADC1通道22(PD0)IO口為浮空輸入模式
3)初始化ADC1:連續(xù)轉(zhuǎn)換模式,12位分辨率,ADC時鐘2分頻
4)配置ADC低速通道,采樣周期384
5)使能ADC1
6)使能ADC1通道22
DMA的配置步驟如下(包括ADC-->內(nèi)存與內(nèi)存-->TIM3):
1)使能DMA1外設(shè)時鐘
2)映射ADC1到DMA通道1
3)DMA初始化:通道1、內(nèi)存地址BUFFER_ADDRESS、外設(shè)地址ADC1_DR_ADDRESS、數(shù)據(jù)大小BUFFER_SIZE、傳輸方向外設(shè)到內(nèi)存、DMA模式循環(huán)、內(nèi)存增長模式增長、DMA優(yōu)先級高、內(nèi)存數(shù)據(jù)大小半字
4)DMA初始化:通道0、內(nèi)存地址BUFFER_ADDRESS、外設(shè)地址TIM3_CCR1_ADDRESS、數(shù)據(jù)大小BUFFER_SIZE、傳輸方向內(nèi)存到外設(shè)、DMA模式循環(huán)、內(nèi)存增長模式增長、DMA優(yōu)先級高、內(nèi)存數(shù)據(jù)大小半字
5)使能DMA1通道1
6)使能DMA1通道0
7)使能DMA1
TIM3配置(配置TIM3_CH1為PWM輸出)步驟如下:
1)使TIM3外設(shè)時鐘
2)TIM3基本配置:時鐘分頻1、向上計數(shù)、周期0xFFF
3)配置TIM3的通道1作為PWM輸出
4)使能TIM3
5)配置TIM3_CH1(PB1)的GPIO
6)使能TIM3通道1的PWM輸出
2.2 例程介紹
所有的函數(shù)實現(xiàn)都在main.c文件中,ADC配置函數(shù)如下:
static void ADC_Config ( void**)**
{
/* 使能 ADC1 時鐘 */
CLK_PeripheralClockConfig ( CLK_Peripheral_ADC1**,** ENABLE**);**
//配置ADC1通道22的IO口為浮空輸入模式
GPIO_Init ( GPIOD**,** GPIO_Pin_0**,** GPIO_Mode_In_FL_No_IT**);**
/* 初始化 ADC1 連續(xù)轉(zhuǎn)換,12位分辨率, ADC時鐘分頻2 */
ADC_Init ( ADC1**,** ADC_ConversionMode_Continuous**,** ADC_Resolution_12Bit**,** ADC_Prescaler_2**);**
/* 配置ADC1 低速通道, 采樣周期384 */
ADC_SamplingTimeConfig ( ADC1**,** ADC_Group_SlowChannels**,** ADC_SamplingTime_384Cycles**);**
/* 使能 ADC1 */
ADC_Cmd ( ADC1**,** ENABLE**);**
/* 使能ADC1通道22 */
ADC_ChannelCmd ( ADC1**,** ADC_Channel_22**,** ENABLE**);** /* connected to potentiometer */
}
TIM3的配置函數(shù)如下:
static void TIM3_Config ( void**)**
{
/* 使能 TIM3 時鐘 */
CLK_PeripheralClockConfig ( CLK_Peripheral_TIM3**,** ENABLE**);**
/* TIM3基本配置:時鐘分頻:1,向上計數(shù),周期:0xfff */
TIM3_TimeBaseInit ( TIM3_Prescaler_1**,** TIM3_CounterMode_Up**,** 0xFFF**);**
/* 配置TIM3_CH1作為PWM輸出 */
TIM3_OC1Init ( TIM3_OCMode_PWM1**,** TIM3_OutputState_Enable**,**
0x7FF**,** TIM3_OCPolarity_Low**,** TIM3_OCIdleState_Set**);**
/* 使能 TIM3 */
TIM3_Cmd ( ENABLE**);**
/* 配置TIM3_CH1的GPIO (PD2)*/
GPIO_Init ( GPIOB**,** GPIO_Pin_1 , GPIO_Mode_Out_PP_Low_Fast**);**
/* 使能TIM3的PWM輸出*/
TIM3_CtrlPWMOutputs ( ENABLE**);**
}
DMA配置函數(shù)如下:
static void DMA_Config ( void**)**
{
/* 使能 DMA1 時鐘 */
CLK_PeripheralClockConfig ( CLK_Peripheral_DMA1**,** ENABLE**);**
/* 連接ADC1到DMA1通道1 */
SYSCFG_REMAPDMAChannelConfig ( REMAP_DMA1Channel_ADC1ToChannel1**);**
//*初始化DMA1通道1, 內(nèi)存地址:BUFFER_ADDRESS,外設(shè)地址:ADC1_DR_ADDRESS,
//數(shù)據(jù)大小:BUFFER_SIZE,傳輸方向:外設(shè)到內(nèi)存,DMA模式:循環(huán),內(nèi)存地址模式:增長,
//DMA優(yōu)先級:高,內(nèi)存數(shù)據(jù)大?。喊胱?/p>
DMA_Init ( DMA1_Channel1**,** BUFFER_ADDRESS**,** ADC1_DR_ADDRESS**,** BUFFER_SIZE**,** DMA_DIR_PeripheralToMemory**,**
DMA_Mode_Circular**,** DMA_MemoryIncMode_Inc**,** DMA_Priority_High**,** DMA_MemoryDataSize_HalfWord**);**
// 初始化DMA1通道0, 內(nèi)存地址:BUFFER_ADDRESS,外設(shè)地址:ADC1_DR_ADDRESS,
//數(shù)據(jù)大小:BUFFER_SIZE,傳輸方向:內(nèi)存到外設(shè),DMA模式:循環(huán),內(nèi)存地址模式:增長,
//DMA優(yōu)先級:高,內(nèi)存數(shù)據(jù)大?。喊胱?/p>
DMA_Init ( DMA1_Channel0**,** BUFFER_ADDRESS**,** TIM3_CCR1_ADDRESS**,** BUFFER_SIZE**,** DMA_DIR_MemoryToPeripheral**,**
DMA_Mode_Circular**,** DMA_MemoryIncMode_Inc**,** DMA_Priority_High**,** DMA_MemoryDataSize_HalfWord**);**
/* 使能DMA1通道1 */
DMA_Cmd ( DMA1_Channel1**,** ENABLE**);**
/* 使能DMA1通道0 */
DMA_Cmd ( DMA1_Channel0**,** ENABLE**);**
/* DMA1 使能 */
DMA_GlobalCmd ( ENABLE**);**
}
DMA配置相關(guān)的地址定義如下:
//定義內(nèi)存與外設(shè)的地址,用于DMA傳輸
#define ADC1_DR_ADDRESS ((uint16_t)(ADC1_BASE + 0x04))
#define TIM3_CCR1_ADDRESS ((uint16_t)(TIM3_BASE + 0x11))
#define BUFFER_SIZE ((uint8_t) 0x01)
#define BUFFER_ADDRESS ((uint16_t)(&Buffer))
uint16_t Buffer = 0**;** //定義變量保存DMA數(shù)據(jù),作為DMA傳輸內(nèi)存地址
主函數(shù)如下:
void main ( void**)**
{
ADC_Config**();** //ADC配置
DMA_Config**();** //DMA配置
TIM3_Config (); //TIM3配置
/* 使能 ADC1 DMA 請求*/
ADC_DMACmd ( ADC1**,** ENABLE**);**
/* 使能 TIM1 DMA 請求*/
TIM3_DMACmd ( TIM3_DMASource_Update**,** ENABLE**);**
/* 起始ADC1轉(zhuǎn)換*/
ADC_SoftwareStartConv ( ADC1**);**
while ( 1**)**
{
;
}
}
使用ST-LINK把程序下載到開發(fā)板,ADC1_CH22(PD0)采樣電壓越高LED1越亮,檢測的測試方法:把PD0口接板子的GND,LED1滅;接板子的VCC,LED1亮(如果把PD0接電位器,那么LED1的亮度可以由電位器調(diào)節(jié))。
-
cpu
+關(guān)注
關(guān)注
68文章
10804瀏覽量
210828 -
dma
+關(guān)注
關(guān)注
3文章
556瀏覽量
100344 -
stm8l051f3
+關(guān)注
關(guān)注
0文章
4瀏覽量
2241
發(fā)布評論請先 登錄
相關(guān)推薦
評論