STM32:DMA例項之串列埠(USART)通訊
阿新 • • 發佈:2019-02-15
硬體平臺:stm32f10xZET6
開發環境:keil MDK uVision v4.10
開發語言:C、ST_lib_3.5韌體庫
開發環境:keil MDK uVision v4.10
開發語言:C、ST_lib_3.5韌體庫
/* 程式碼演示 main.c */ #include "stm32f10x.h" #include "bsp_usart1.h" #include "bsp_led.h" extern uint8_t SendBuff[SENDBUFF_SIZE]; static void Delay(__IO u32 nCount); /** * @brief 主函式 */ int main(void) { /* USART1 config 115200 8-N-1 */ USART1_Config(); USART1_DMA_Config(); LED_GPIO_Config(); printf ("\r\n usart1 DMA TX test... \r\n"); { uint16_t i; /*填充將要傳送的資料*/ for(i=0;i<SENDBUFF_SIZE;i++) { SendBuff[i] = 'a'; // 打字母a僅做演示 } } /* USART1 向 DMA發出TX請求 */ USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); /* 此時CPU是空閒的,可以幹其他的事情 */ //例如同時控制LED for(;;) { LED1(ON); Delay(0xFFFFF); LED1(OFF); Delay(0xFFFFF); } } static void Delay(__IO uint32_t nCount) //簡單的延時函式 { for(; nCount != 0; nCount--); }
/* 中斷處理函式 stm32f10x_it.c line:157 */
void DMA1_Channel4_IRQHandler(void)
{
//判斷是否為 DMA 傳送完成中斷
if (DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET)
{
//LED 關閉
LED1(OFF);
DMA_ClearFlag(DMA1_FLAG_TC4);
}
}
/* 程式碼演示 bsp_usart1模組 */ #ifndef __USART1_H #define __USART1_H #include "stm32f10x.h" #include <stdio.h> #define USART1_DR_Base 0x40013804 // 0x40013800 + 0x04 = 0x40013804 #define SENDBUFF_SIZE 5000 void USART1_Config(void); void USART1_DMA_Config(void); #endif /* __USART1_H */ // ------------------------------------------------------ #include "bsp_usart1.h" uint8_t SendBuff[SENDBUFF_SIZE]; /** * @brief USART1 GPIO 配置,工作模式配置。115200 8-N-1 * @param 無 * @retval 無 */ void USART1_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /* config USART1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); /* USART1 GPIO config */ /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* USART1 mode config */ 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(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } /** * @brief USART1 TX DMA 配置,記憶體到外設(USART1->DR) * @param 無 * @retval 無 */ void USART1_DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; /*開啟DMA時鐘*/ RCC_AHBPeriphClockCmd (RCC_AHBPeriph_DMA1, ENABLE); /*傳輸大小DMA_BufferSize=SENDBUFF_SIZE*/ DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE; // 此處是傳送的buffer的配置 /*方向:從記憶體到外設*/ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; /*禁止記憶體到記憶體的傳輸 */ DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /*記憶體地址(要傳輸的變數的指標)*/ DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff; /*記憶體資料單位 8bit*/ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /*記憶體地址自增*/ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*DMA模式:不斷迴圈*/ DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; /* 設定DMA源:串列埠資料暫存器地址 */ DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base; /* 外設資料單位:位元組 */ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; /* 外設地址不增 */ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /*優先順序:中*/ DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; /*配置DMA1的4通道*/ DMA_Init(DMA1_Channel4, &DMA_InitStructure); /*使能DMA*/ DMA_Cmd (DMA1_Channel4,ENABLE); //DMA_ITConfig(DMA1_Channel4, DMA_IT_TC,ENABLE); // 配置DMA傳送完成後產生中斷 } /// 重定向c庫函式printf到USART1 int fputc(int ch, FILE *f) { /* 傳送一個位元組資料到USART1 */ USART_SendData(USART1, (uint8_t) ch); /* 等待發送完畢 */ while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); return (ch); } /// 重定向c庫函式scanf到USART1 int fgetc(FILE *f) { /* 等待串列埠1輸入資料 */ while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(USART1); }
*注:LED燈的管腳Pin根據開發板的不同,實際去調整即可。/* 程式碼演示 bsp_led模組 */ #ifndef __LED_H #define __LED_H #include "stm32f10x.h" /** the macro definition to trigger the led on or off * 1 - off *0 - on */ #define ON 0 #define OFF 1 /* 帶參巨集,可以像行內函數一樣使用 */ #define LED1(a) if (a) \ GPIO_SetBits(GPIOB,GPIO_Pin_0);\ else \ GPIO_ResetBits(GPIOB,GPIO_Pin_0) #define LED2(a) if (a) \ GPIO_SetBits(GPIOF,GPIO_Pin_7);\ else \ GPIO_ResetBits(GPIOF,GPIO_Pin_7) #define LED3(a) if (a) \ GPIO_SetBits(GPIOF,GPIO_Pin_8);\ else \ GPIO_ResetBits(GPIOF,GPIO_Pin_8) void LED_GPIO_Config(void); #endif /* __LED_H */ //--------------------------------------------------------- #include "bsp_led.h" /** * @brief 初始化控制LED的IO * @param 無 * @retval 無 */ void LED_GPIO_Config(void) { /*定義一個GPIO_InitTypeDef型別的結構體*/ GPIO_InitTypeDef GPIO_InitStructure; /*開啟GPIOB和GPIOF的外設時鐘*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE); /*選擇要控制的GPIOB引腳*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; /*設定引腳模式為通用推輓輸出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*設定引腳速率為50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*呼叫庫函式,初始化GPIOB0*/ GPIO_Init(GPIOB, &GPIO_InitStructure); /*選擇要控制的GPIOF引腳*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; /*呼叫庫函式,初始化GPIOF7*/ GPIO_Init(GPIOF, &GPIO_InitStructure); /*選擇要控制的GPIOF引腳*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; /*呼叫庫函式,初始化GPIOF7*/ GPIO_Init(GPIOF, &GPIO_InitStructure); /* 關閉所有led燈 */ GPIO_SetBits(GPIOB, GPIO_Pin_0); /* 關閉所有led燈 */ GPIO_SetBits(GPIOF, GPIO_Pin_7|GPIO_Pin_8); }