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

【正點(diǎn)原子STM32連載】第三十二章 DMA實(shí)驗(yàn) 摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南

這篇具有很好參考價(jià)值的文章主要介紹了【正點(diǎn)原子STM32連載】第三十二章 DMA實(shí)驗(yàn) 摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1)實(shí)驗(yàn)平臺(tái):正點(diǎn)原子APM32E103最小系統(tǒng)板
2)平臺(tái)購(gòu)買地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套實(shí)驗(yàn)源碼+手冊(cè)+視頻下載地址: http://www.openedv.com/docs/boards/xiaoxitongban

第三十二章 DMA實(shí)驗(yàn)

本章介紹APM32E103直接存儲(chǔ)訪問(DMA)的使用,DMA能夠在無CPU干預(yù)的情況下,實(shí)現(xiàn)外設(shè)與存儲(chǔ)器或存儲(chǔ)器與存儲(chǔ)器之間數(shù)據(jù)的高速傳輸,從而節(jié)省CPU資源來做其他操作。通過本章的學(xué)習(xí),讀者將學(xué)習(xí)到DMA的使用。
本章分為如下幾個(gè)小節(jié):
32.1 硬件設(shè)計(jì)
32.2 程序設(shè)計(jì)
32.3 下載驗(yàn)證

32.1 硬件設(shè)計(jì)
32.1.1 例程功能

  1. 按下KEY0按鍵,USART1以DMA方式發(fā)送數(shù)據(jù),同時(shí)在LCD上顯示DMA傳輸?shù)倪M(jìn)度
  2. LED0閃爍,指示程序正在運(yùn)行
    32.1.2 硬件資源
  3. LED
    LED0 - PB5
  4. 按鍵
    KEY0 - PE4
  5. 正點(diǎn)原子 2.8/3.5/4.3/7/10寸TFTLCD模塊(僅限MCU屏,16位8080并口驅(qū)動(dòng))
  6. USART1(PA9、PA10連接至板載USB轉(zhuǎn)串口芯片上)
  7. DMA(DMA1通道4)
    32.1.3 原理圖
    本章實(shí)驗(yàn)使用的DMA為APM32E103的片上資源,因此沒有對(duì)應(yīng)的連接原理圖。
    32.2 程序設(shè)計(jì)
    32.2.1 Geehy標(biāo)準(zhǔn)庫(kù)的DMA驅(qū)動(dòng)
    在使用DMA之前,需要先根據(jù)需求對(duì)DMA的通道進(jìn)行配置,例如本章實(shí)驗(yàn)要使用DMA進(jìn)行串口數(shù)據(jù)的發(fā)送,因此應(yīng)將DMA的通道配置為存儲(chǔ)器到外設(shè)的模式等等。使用DMA的具體步驟如下:
    ①:根據(jù)需求配置DMA通道
    ②:使能DMA通道進(jìn)行數(shù)據(jù)傳輸
    ③:讀DMA通道的狀態(tài)標(biāo)志判斷傳輸是否完成
    ④:傳輸完成后清除DMA通道的傳輸完成標(biāo)志
    在Geehy標(biāo)準(zhǔn)庫(kù)中對(duì)應(yīng)的驅(qū)動(dòng)函數(shù)如下:
    ①:配置DMA通道
    該函數(shù)用于配置DMA通道的各項(xiàng)參數(shù),其函數(shù)原型如下所示:
    void DMA_Config(DMA_Channel_T* channel, DMA_Config_T* dmaConfig)
    該函數(shù)的形參描述,如下表所示:
    形參 描述
    channel 指定的DMA通道
    例如:DMA1_channelx,其中x可以從1到7或DMA2_channely,同樣的y可以從1至5(在apm32e10x.h文件中有定義)
    dmaConfig 指向DMA通道配置結(jié)構(gòu)體的指針
    需自行定義,并根據(jù)DMA通道的配置參數(shù)填充結(jié)構(gòu)體中的成員變量
    表32.2.1.1 函數(shù)DMA_Config()形參描述
    該函數(shù)的返回值描述,如下表所示:
    返回值 描述
    無 無
    表32.2.1.2 函數(shù)DMA_Config()返回值描述
    該函數(shù)使用DMA_Config_T類型的結(jié)構(gòu)體變量傳入DMA通道的配置參數(shù),該結(jié)構(gòu)體的定義如下所示:
typedef enum
{
    DMA_DIR_PERIPHERAL_SRC,
    DMA_DIR_PERIPHERAL_DST
} DMA_DIR_T;

typedef enum
{
    DMA_PERIPHERAL_INC_DISABLE,						/* 禁止外設(shè)增量模式 */
    DMA_PERIPHERAL_INC_ENABLE						/* 使能外設(shè)增量模式 */
} DMA_PERIPHERAL_INC_T;

typedef enum
{
    DMA_MEMORY_INC_DISABLE,							/* 禁用存儲(chǔ)器遞增模式 */
    DMA_MEMORY_INC_ENABLE							/* 使能存儲(chǔ)器遞增模式 */
} DMA_MEMORY_INC_T;

typedef enum
{
    DMA_PERIPHERAL_DATA_SIZE_BYTE,					/* 外設(shè)數(shù)據(jù)大小為字節(jié) */
    DMA_PERIPHERAL_DATA_SIZE_HALFWORD,				/* 外設(shè)數(shù)據(jù)大小為半字 */
    DMA_PERIPHERAL_DATA_SIZE_WORD					/* 外設(shè)數(shù)據(jù)大小為字 */
} DMA_PERIPHERAL_DATA_SIZE_T;

typedef enum
{
    DMA_MODE_NORMAL,								/* 禁用循環(huán)模式 */
    DMA_MODE_CIRCULAR								/* 使能循環(huán)模式 */
} DMA_LOOP_MODE_T;

typedef enum
{
    DMA_PRIORITY_LOW,								/* 優(yōu)先級(jí)低 */
    DMA_PRIORITY_MEDIUM,							/* 優(yōu)先級(jí)中 */
    DMA_PRIORITY_HIGH,								/* 優(yōu)先級(jí)高 */
    DMA_PRIORITY_VERYHIGH							/* 優(yōu)先級(jí)非常高 */
} DMA_PRIORITY_T;

typedef struct
{
    uint32_t					peripheralBaseAddr;	/* 外設(shè)基地址 */
    uint32_t					memoryBaseAddr;		/* 存儲(chǔ)器基地址 */
    DMA_DIR_T					dir;				/* 數(shù)據(jù)傳輸方向 */
    uint32_t					bufferSize;			/* 傳輸?shù)臄?shù)據(jù)項(xiàng)數(shù)目 */
    DMA_PERIPHERAL_INC_T		peripheralInc;		/* 外設(shè)增量模式 */
    DMA_MEMORY_INC_T			memoryInc;			/* 存儲(chǔ)器遞增模式 */
    DMA_PERIPHERAL_DATA_SIZE_T	peripheralDataSize;	/* 外設(shè)數(shù)據(jù)大小 */
    DMA_MEMORY_DATA_SIZE_T		memoryDataSize;		/* 存儲(chǔ)器數(shù)據(jù)大小 */
    DMA_LOOP_MODE_T				loopMode;			/* 循環(huán)模式 */
DMA_PRIORITY_T				priority;			/* 優(yōu)先級(jí) */
DMA_M2MEN_T                M2M;
} DMA_Config_T;
該函數(shù)的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_dma.h"

static uint8_t membuf[256];

void example_fun(void)
{
    DMA_Config_T dma_init_struct;
    
    /* 配置DMA1通道0通道0 */
    dma_init_struct.channel				= DMA_CHANNEL_0;
    dma_init_struct.peripheralBaseAddr	= (uint32_t)&USART1->DATA;
    dma_init_struct.memoryBaseAddr		= (uint32_t)&membuf[0];
    dma_init_struct.dir					= DMA_DIR_MEMORYTOPERIPHERAL;
    dma_init_struct.bufferSize			= sizeof(membuf) / sizeof(membuf[0]);
    dma_init_struct.peripheralInc		= DMA_PERIPHERAL_INC_DISABLE;
    dma_init_struct.memoryInc			= DMA_MEMORY_INC_ENABLE;
    dma_init_struct.peripheralDataSize	= DMA_PERIPHERAL_DATA_SIZE_BYTE;
    dma_init_struct.memoryDataSize		= DMA_MEMORY_DATA_SIZE_BYTE;
    dma_init_struct.loopMode			= DMA_MODE_NORMAL;
    dma_init_struct.priority			= DMA_PRIORITY_MEDIUM;
    dma_init_struct.fifoMode			= DMA_FIFOMODE_DISABLE;
    dma_init_struct.fifoThreshold		= DMA_FIFOTHRESHOLD_FULL;
    dma_init_struct.memoryBurst			= DMA_MEMORYBURST_SINGLE;
    dma_init_struct.peripheralBurst	= DMA_PERIPHERALBURST_SINGLE;
    DMA_Config(DMA1_Stream0, &dma_init_struct);
}

②:使能DMA通道
該函數(shù)用于使能DMA通道進(jìn)行數(shù)據(jù)傳輸,其函數(shù)原型如下所示:
void DMA_Enable(DMA_Channel_T *channel);
該函數(shù)的形參描述,如下表所示:
形參 描述
channel 指定的DMA通道
表32.2.1.3 函數(shù)DMA_Enable()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無 無
表32.2.1.4 函數(shù)DMA_Enable()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_dma.h"

void example_fun(DMA_Channel_T *dma_chx)
{
    /* 使能DMA通道 */
    DMA_Enable(dma_chx);
}

③:讀取DMA通道的狀態(tài)標(biāo)志
該函數(shù)用于讀取DMA通道的指定狀態(tài)標(biāo)志,其函數(shù)原型如下所示:
uint8_t DMA_ReadStatusFlag(DMA_FLAG_T flag);
該函數(shù)的形參描述,如下表所示:
形參 描述
flag 指定DMA通道的狀態(tài)標(biāo)志
例如:DMA1_FLAG_GINT1、DMA1_FLAG_TC1等(在apm32e10x_dma.h文件中有定義)
表32.1.2.5 函數(shù)DMA_ReadStatusFlag()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
SET 事件標(biāo)志發(fā)生
RESET 事件標(biāo)志未發(fā)生
表32.1.2.6 函數(shù)DMA_ReadStatusFlag()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_dma.h"

void example_fun(void)
{
    uint8_t flag;
    
    /* 讀取DMA1通道4的數(shù)據(jù)傳輸完成標(biāo)志 */
    flag = DMA_ReadStatusFlag(DMA1_FLAG_TC4);
    if (flag == SET)
    {
    		/* Do something. */
    }
    else
    {
    		/* Do something. */
    }
}

④:清除DMA通道狀態(tài)標(biāo)志
該函數(shù)用于清除DMA通道的狀態(tài)標(biāo)志,其函數(shù)原型如下所示:
void DMA_ClearStatusFlag(uint32_t flag);
該函數(shù)的形參描述,如下表所示:
形參 描述
flag 清除指定DMA通道的標(biāo)志
例如:DMA1_FLAG_GINT1、DMA1_FLAG_TC1等(在apm32e10x_dma.h文件中有定義)
表32.2.1.7 函數(shù)DMA_ClearStatusFlag()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無 無
表32.2.1.8 函數(shù)DMA_ClearStatusFlag()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_dma.h"

void example_fun(void)
{
    /* 清除DMA1通道1的傳輸完成標(biāo)志 */
    DMA_ClearStatusFlag(DMA1_FLAG_TC1);
}

32.2.2 DMA驅(qū)動(dòng)
本章實(shí)驗(yàn)的DMA驅(qū)動(dòng)主要負(fù)責(zé)向應(yīng)用層提供DMA的初始化和開啟傳輸?shù)暮瘮?shù)。本章實(shí)驗(yàn)中,DMA的驅(qū)動(dòng)代碼包括dma.c和dma.h兩個(gè)文件。
DMA驅(qū)動(dòng)中,DMA的初始化函數(shù),如下所示:

/**
 * @brief       初始化DMA
 * @param       dma_chx   : DMA通道
 * @param       par       : 外設(shè)地址
 * @param       mar       : 存儲(chǔ)器0地址
 * @param       ndtr      : 傳輸?shù)臄?shù)據(jù)項(xiàng)數(shù)目
 * @retval      無
 */
void dma_init(	DMA_Channel_T *dma_chx,
				uint32_t par, 
				uint32_t mar,
			    uint16_t ndtr)
{
    DMA_Config_T dma_init_struct;
    
    RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);          /* 使能DMA時(shí)鐘 */
    DMA_Reset(dma_chx);                                     /* 復(fù)位DMA */
    
    /* 配置DMA */
    dma_init_struct.peripheralBaseAddr = par;               /* 外設(shè)基地址 */
    dma_init_struct.memoryBaseAddr = mar;                   /* DMA內(nèi)存基地址 */
    dma_init_struct.dir = DMA_DIR_PERIPHERAL_DST;           /* 數(shù)據(jù)傳輸方向 */
dma_init_struct.bufferSize = ndtr;                      /* 傳輸?shù)臄?shù)據(jù)項(xiàng)數(shù)目 */
/* 外設(shè)增量模式 */
    dma_init_struct.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
dma_init_struct.memoryInc = DMA_MEMORY_INC_ENABLE;      /* 存儲(chǔ)器遞增模式 */
/* 外設(shè)數(shù)據(jù)大小 */
dma_init_struct.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE; 
/* 存儲(chǔ)器數(shù)據(jù)大小 */
    dma_init_struct.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE;         
    dma_init_struct.loopMode = DMA_MODE_NORMAL;             /* 正常工作模式 */
dma_init_struct.priority = DMA_PRIORITY_MEDIUM;         /* 優(yōu)先級(jí) */
/* DMA通道x沒有設(shè)置為內(nèi)存到內(nèi)存?zhèn)鬏?*/
    dma_init_struct.M2M = DMA_M2MEN_DISABLE;
    DMA_Config(dma_chx, &dma_init_struct);                  /* 配置DMA通道 */
   
    DMA_Enable(dma_chx);                                    /* 使能DMA通道 */
}

從上面的代碼中可以看到,DMA的初始化函數(shù)提供了DMA通道、外設(shè)基地址、存儲(chǔ)器基地址、傳輸數(shù)據(jù)項(xiàng)數(shù)據(jù)的配置參數(shù),結(jié)合這些傳入的參數(shù),通過DMA通道配置函數(shù)DMA_Config()配置了指定的DMA通道。
DMA驅(qū)動(dòng)中,開啟DMA傳輸?shù)暮瘮?shù),如下所示:

/**
 * @brief       開啟一次DMA傳輸
 * @param       dma_chx   : DMA通道
 * @param       ndtr      : 傳輸?shù)臄?shù)據(jù)項(xiàng)數(shù)目
 * @retval      無
 */
void dma_enable(DMA_Channel_T *dma_chx, uint16_t ndtr)
{
    DMA_Disable(dma_chx);                    /* 關(guān)閉USART1 TX DMA1 所指示的通道 */
    DMA_ConfigDataNumber(dma_chx, ndtr);     /* 配置傳輸?shù)臄?shù)據(jù)項(xiàng)數(shù)目 */
    DMA_Enable(dma_chx);                     /* 使能USART1 TX DMA1 所指示的通道 */
}

從上面的代碼中可以看到,開啟DMA數(shù)據(jù)傳輸實(shí)際上就是調(diào)用函數(shù)DMA_Enable()使能DMA通道,但考慮到每次傳輸?shù)臄?shù)據(jù)量可能不同,因此在使能DMA通道前,還配置了DMA通道傳輸數(shù)據(jù)項(xiàng)目的數(shù)量。
32.2.3 實(shí)驗(yàn)應(yīng)用代碼
本實(shí)驗(yàn)的應(yīng)用代碼,如下所示:
/* 要循環(huán)發(fā)送的字符串 */

const uint8_t text_to_send[] = {"正點(diǎn)原子 APM32E103最小系統(tǒng)板 DMA實(shí)驗(yàn)\r\n"};
#define SEND_BUF_SIZE (sizeof(text_to_send) * 200)  /* 發(fā)送數(shù)據(jù)長(zhǎng)度 */
uint8_t g_sendbuf[SEND_BUF_SIZE];                   /* 發(fā)送數(shù)據(jù)緩沖區(qū) */

int main(void)
{
    uint8_t key;
    uint16_t i;
    uint16_t len;
    uint16_t pro;
    
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4);/* 設(shè)置中斷優(yōu)先級(jí)分組為組4 */
    sys_apm32_clock_init(15);                       /* 配置系統(tǒng)時(shí)鐘 */
    delay_init(120);                                /* 初始化延時(shí)功能 */
    usart_init(115200);                             /* 初始化串口 */
    led_init();                                     /* 初始化LED */
    lcd_init();                                     /* 初始化LCD */
dma_init( DMA1_Channel4, 
		  (uint32_t) & USART1->DATA, 
  		  (uint32_t)g_sendbuf, 
              SEND_BUF_SIZE);                       /* 初始化DMA */
    
    lcd_show_string(30, 50, 200, 16, 16, "APM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "DMA TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "KEY0:Start", RED);
    
    len = sizeof(text_to_send);                                                             /* 填充發(fā)送數(shù)據(jù)緩沖區(qū) */
    
    for (i = 0; i < SEND_BUF_SIZE; i++)
    {
        g_sendbuf[i] = text_to_send[i % len];
    }
    i = 0;
    
    while (1)
    {
        key = key_scan(0);
        
        if (key == KEY0_PRES)
        {
            lcd_show_string(30, 130, 200, 16, 16, "Start Transimit....", BLUE);
            lcd_show_string(30, 150, 200, 16, 16, "   %", BLUE);
            
            USART_EnableDMA(USART_UX, USART_DMA_TX);                                        /* 使能USART的DMA發(fā)送 */
            dma_enable(DMA1_Channel4, SEND_BUF_SIZE);                                       /* 開啟一次DMA傳輸 */
            
            /* 等待DMA傳輸完成
             * 實(shí)際應(yīng)用中,在等待DMA傳輸完成期間,可以執(zhí)行另外的任務(wù)
             */
            while (1)
            {   /* 判斷通道4傳輸完成 */
                if (DMA_ReadStatusFlag(DMA1_FLAG_TC4) != RESET)
                {   /* 清除通道4傳輸完成標(biāo)志 */
                    DMA_ClearStatusFlag(DMA1_FLAG_TC4);
                    break;
                }
                
                pro = DMA_ReadDataNumber(DMA1_Channel4);                                    /* 得到當(dāng)前還剩余多少個(gè)數(shù)據(jù)  */
                pro = ((SEND_BUF_SIZE - pro) * 100) / SEND_BUF_SIZE;                        /* 獲得百分比 */
                lcd_show_num(30, 150, pro, 3, 16, BLUE);                                    /* LCD顯示DMA傳輸進(jìn)度 */
            }
            
            pro = DMA_ReadDataNumber(DMA1_Channel4);
            pro = ((SEND_BUF_SIZE - pro) * 100) / SEND_BUF_SIZE;
            lcd_show_num(30, 150, pro, 3, 16, BLUE);
            lcd_show_string(30, 130, 200, 16, 16, "Transimit Finished!", BLUE);             /* LCD顯示傳送完成 */
        }
        
        i++;
        
        if ((i % 20) == 0)
        {
            i = 0;
            LED0_TOGGLE();                                                                  
        }
        delay_ms(10);
    }
}

從上面的代碼中可以看到,在DMA的初始化中,初始化了DMA1通道4,這是因?yàn)閁SART1的發(fā)送就對(duì)應(yīng)了DMA1通道4,完成初始化工作后,就不斷地掃描按鍵,若掃描到KEY0按鍵,并使用DMA進(jìn)行USART1發(fā)送數(shù)據(jù),在DMA進(jìn)行數(shù)據(jù)傳輸?shù)拇似陂g,LCD上不斷刷新顯示DMA傳輸?shù)倪M(jìn)度,直至DMA傳輸完畢。
32.3 下載驗(yàn)證
在完成編譯和燒錄操作后,可以看到LCD上顯示了本實(shí)驗(yàn)的實(shí)驗(yàn)信息,此時(shí)若按下KEY0按鍵,可以看到串口調(diào)試助手不斷打印“正點(diǎn)原子 APM32E103最小系統(tǒng)板 DMA實(shí)驗(yàn)\r\n”(200次),在此期間也能看到LCD上不斷地實(shí)時(shí)刷新串口打印的進(jìn)度。文章來源地址http://www.zghlxwxcb.cn/news/detail-837153.html

到了這里,關(guān)于【正點(diǎn)原子STM32連載】第三十二章 DMA實(shí)驗(yàn) 摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包