<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > stm32F407之USART6的DMA工作方式

stm32F407之USART6的DMA工作方式

作者: 時(shí)間:2016-11-10 來(lái)源:網(wǎng)絡(luò ) 收藏
昨天調試了USART6DMA工作模式,今天補發(fā)上這篇筆記。

力求簡(jiǎn)潔,stm32的DMA就不介紹了,不了解的可以搜索一下。這里重點(diǎn)介紹一下DMA的外設地址如何確定,這個(gè)是網(wǎng)上很少涉及但是很重要的一塊,如果不清楚如何確定外設寄存器地址就無(wú)法進(jìn)行DMA功能,這里以stm32F407的USART6為例介紹,參考手冊為“RM0090 Reference manual”。

本文引用地址:http://dyxdggzs.com/article/201611/317475.htm

在進(jìn)行DMA參數配置時(shí)有這樣一項 DMA_InitStructure.DMA_PeripheralBaseAddr = ?;這句是要確定Memory與Peripheral數據傳輸時(shí)的外設數據地址,因為這里我們用到的是USART6從Memory的數組中取出數據并發(fā)送給上位機,所以這里用到的外設地址其實(shí)是USART6的數據寄存器地址 USART6_DR,關(guān)鍵是確定他的地址。好了我們現在打開(kāi)參考手冊,找到“Memory Map”一項,

打開(kāi)可以看到USART6的基地址為0x4001 1400,好了,接著(zhù)點(diǎn)擊后面的藍色連接

看到USART_DR的OFFSET地址為0x04,則USART6的真實(shí)地址為 0x4001 1400+0x04 = 0x4001 1404;這樣便確定了USART6_DR的地址。其他的就好說(shuō)了,代碼如下

/************************************************************
Copyright (C), 2012-2022, yin.
FileName: main.c
Author: ycw Version : 1.0 Date: 2012.04.27
Description: USART6 DMA SendData
Version: V3.0
Function List:USART6 DMA SendData
History: V1.0

#include

/*定義USART6的數據寄存器地址,DMA功能要用到外設的數據地址
*USART6的數據地址為外設基地址+偏移地址,基地址在RM0090 Reference
*manual(參考手冊)的地址映射表里(P50),為0x40011400,USART_DR
*偏移地址在P657,為0x04,故實(shí)際地址為0x40011400+0x04 = 0x40011404 */
#define USART6_DR_Addr 0x40011404
/*定義一個(gè)數組,DMA工作時(shí)從內存取數組的數據傳給USART6 */
uint8_t Buffer[] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
uint8_t Buffer2[] = {0x99,0x6f};
void GPIO_Config(void);
void USART_Config(void);
void USART6_Puts(char * str);
void DMA_Config(void);
void NVIC_Config(void);
void Delay(uint32_t nCount);

main()
{
/*在主函數main之前通過(guò)調用啟動(dòng)代碼運行了SystemInit函數,而這個(gè)函數位于system_stm32f4xx.c”。
程序運行起始于啟動(dòng)文件的第175行(LDR R0, =SystemInit)。sys時(shí)鐘為HSE頻率/PLL_M*PLL_N/PLL_P,
定義HSE為25M,則sys時(shí)鐘頻率為168M */

GPIO_Config();
USART_Config();
DMA_Config();
NVIC_Config();
GPIO_SetBits(GPIOG, GPIO_Pin_6); //關(guān)閉LED
while (1)
{
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE); //使能USART6的發(fā)送數據DMA請求,至此USART6與DMA開(kāi)始工作
/*因為DMA工作是獨立于CPU之外的,所以在DMA工作的同時(shí)CPU可以做其他事
*我們等到DMA傳輸完畢后產(chǎn)生一個(gè)狀態(tài)指示,即點(diǎn)亮一個(gè)LED */
/*查詢(xún)模式
while (DMA_GetFlagStatus(DMA2_Stream6, DMA_FLAG_TCIF6) == RESET)
{
GPIO_ResetBits(GPIOG,GPIO_Pin_6); //點(diǎn)亮LED
}
*/
//DMA_Cmd(DMA2_Stream6, DISABLE); //DMA傳輸完畢后會(huì )自動(dòng)關(guān)閉通道,這句可以不寫(xiě)
}
}

/*************************************************
Function: void GPIO_Config(void)
Description: GPIO配置函數
Input: 無(wú)
Output:無(wú)
Return:無(wú)
*************************************************/
void GPIO_Config(void)
{
/*定義了一個(gè)GPIO_InitStructure的結構體,方便一下使用 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 初始化GPIOG時(shí)鐘*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG , ENABLE);//使能GPIOG時(shí)鐘(時(shí)鐘結構參見(jiàn)“stm32圖解.pdf”)
/*僅設置結構體中的部分成員:這種情況下,用戶(hù)應當首先調用函數PPP_SturcInit(..)
*來(lái)初始化變量PPP_InitStructure,然后再修改其中需要修改的成員。這樣可以保證其他
*成員的值(多為缺省值)被正確填入。
*/
GPIO_StructInit(&GPIO_InitStructure);
/* 初始化GPIOG的Pin_6為推挽輸出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //指定第六引腳
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //模式為輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //頻率為快速
GPIO_Init(GPIOG, &GPIO_InitStructure); //調用IO初始化函數
}

/*************************************************
Function: void USART_Config(void)
Description: USART配置函數
Input: 無(wú)
Output:無(wú)
Return:無(wú)
*************************************************/
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); //開(kāi)啟USART6時(shí)鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //開(kāi)啟GPIOC時(shí)鐘
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);//這相當于M3的開(kāi)啟復用時(shí)鐘?只配置復用的引腳,
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);//
/*配置GPIOC*/
GPIO_StructInit(&GPIO_InitStructure); //缺省值填入

/*配置GPIOC_Pin6為T(mén)X輸出*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //設置為復用,必須為AF,OUT不行
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);

/*配置GPIOC_Pin7為RX輸入*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //這也必須為復用,與M3不同!
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);

/*IO引腳復用功能設置,與之前版本不同*/
/*配置USART6*/
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate =115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_ClockStructInit(&USART_ClockInitStruct); //之前沒(méi)有填入缺省值,是不行的
USART_ClockInit(USART6, &USART_ClockInitStruct);

USART_ITConfig(USART6, USART_IT_RXNE, ENABLE); //使能 USART6中斷
USART_Cmd(USART6, ENABLE); //使能 USART6
//USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE); //使能USART6的發(fā)送數據DMA請求,至此USART6與DMA開(kāi)始工作,可以寫(xiě)在主函數里隨時(shí)工作
}

void NVIC_Config()
{
/*USART6中斷配置*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //嵌套優(yōu)先級分組為 1
NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn; //嵌套通道為USART6_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占優(yōu)先級為 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應優(yōu)先級為 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中斷使能
NVIC_Init(&NVIC_InitStructure);

/*DMA中斷配置*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //嵌套優(yōu)先級分組為 1
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream6_IRQn; //嵌套通道為DMA2_Stream6_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //搶占優(yōu)先級為 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應優(yōu)先級為 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中斷使能
NVIC_Init(&NVIC_InitStructure);

}

/*************************************************
Function: void USART6_Puts(char * str)
Description: USART6發(fā)送數據
Input: 待發(fā)送數據指針
Output:無(wú)
Return:無(wú)
*************************************************/
void USART6_Puts(char * str)
{
while (*str)
{
USART_SendData(USART6, *str++);
/* Loop until the end of transmission */
while (USART_GetFlagStatus(USART6, USART_FLAG_TXE) == RESET); //詳見(jiàn)英文參考的521頁(yè),當TXE被置起時(shí),一幀數據傳輸完成
}
}

/*************************************************
Function: void DMA_Config(void)
Description: DMA配置函數
Input: 延時(shí)的時(shí)間
Output:無(wú)
Return:無(wú)
*************************************************/
void DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
/*首先開(kāi)DMA2時(shí)鐘,由407參考手冊-RM0090-Reference manual
165頁(yè)可知,UASRT6與DMA2映射,而且DMA2掛載在A(yíng)HB1時(shí)鐘總線(xiàn)上*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*由RM0090-Reference manual第165頁(yè)映射表可知,USART6映射在
Channel_5的Stream6和Stream7上,在這里可以選擇Stream6 */
DMA_DeInit(DMA2_Stream6);
DMA_StructInit( &DMA_InitStructure);
DMA_InitStructure.DMA_Channel = DMA_Channel_5; //選擇Channel_5
DMA_InitStructure.DMA_PeripheralBaseAddr = USART6_DR_Addr; //數據傳輸的外設首地址,詳解見(jiàn)上
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer; //自己定義待發(fā)送數組的首地址,要強制轉換為32位
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //數據傳輸方向選擇為內存->外設
DMA_InitStructure.DMA_BufferSize = 8; //傳輸數據大小為8,單位由以下確定,大小要配合定義的數組類(lèi)型和外設數據類(lèi)型
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址寄存器自動(dòng)增加禁止,因為這里只用到了DR數據寄存器
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址自增允許,因為要讀取一個(gè)數組
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外設的數據大小,因為USART6_DR數據寄存器為8為,故選Byte
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //這里也選Byte
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA傳輸模式為Normal,如果為Circular,將會(huì )循環(huán)傳輸
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //優(yōu)先級為High
/*雙緩沖模式,在DMA_Init之前調用在Circular模式有效,會(huì )強制Circular,
*不支持Memory toMemory,(uint32_t)Buffer2為DMA_Memory_1,DMA先將Buffer
*中的數據發(fā)送完畢后在發(fā)送Buffer2的數據,當然順序可以改變
DMA_DoubleBufferModeConfig(DMA2_Stream6, (uint32_t)Buffer2, DMA_Memory_0);
DMA_DoubleBufferModeCmd(DMA2_Stream6, ENABLE);
*/
DMA_Init(DMA2_Stream6, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream6, ENABLE);//使能DMA2_Stream6通道
/*DMA中斷開(kāi)*/
DMA_ITConfig(DMA2_Stream6, DMA_IT_TC, ENABLE);
}

/*************************************************
Function: void Delay(uint32_t nCount)
Description: 延時(shí)函數
Input: 延時(shí)的時(shí)間
Output:無(wú)
Return:無(wú)
*************************************************/
void Delay(uint32_t nCount)
{
while (nCount--);
}

中斷服務(wù)函數:

/**名稱(chēng):DMA中斷服務(wù)程序
*作用:DMA數據完全完成后產(chǎn)生中斷,并點(diǎn)亮LED
*/
void DMA2_Stream6_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_Stream6, DMA_IT_TCIF6) != RESET) //判斷為接收中斷
{
DMA_ClearITPendingBit(DMA2_Stream6, DMA_IT_TCIF6);
GPIO_ResetBits(GPIOG, GPIO_Pin_6); //點(diǎn)亮LED,起到中斷指示作用
}
}

調試結果如下:



關(guān)鍵詞: stm32F407USART6DMA工作方

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>