1. 程式人生 > >STM32:DMA例項之串列埠(USART)通訊

STM32:DMA例項之串列埠(USART)通訊

硬體平臺:stm32f10xZET6
開發環境: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);
}
/* 程式碼演示 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);	 
}
*注:LED燈的管腳Pin根據開發板的不同,實際去調整即可。