/*
本代码基于STM32F030F4P6，用例为DMA控制串口发送，需要注意以下几点
1、注意串口IO配置，包括IO配置和复用功能选择
2、STM32F030系列的DMA不支持外设到外设，STM32F030只有DMA1，没有DMA2
3、注意不同外设对应不同DMA通道，而且不同芯片的通道也不一定相同，注意看数据手册
直接代码如下：
*/
//#include "stm32_lib/inc/stm32f0xx_rcc.h"
//#include "stm32_lib/inc/stm32f0xx_gpio.h"
//#include "stm32_lib/inc/stm32f0xx_usart.h"
//#include "stm32_lib/inc/stm32f0xx_dma.h"
#include "uarts.h"

//以下两种地址写法都可以
#define USART1_TDR_Address	((uint32_t)(USART1_BASE+0x28))
//#define USART1_TDR_Address	(uint32_t)(&USART1->TDR)

unsigned char hellStr[] = {'H', 'E', 'L', 'L', 'O'};

void RCC_Config ( void );
void GPIO_Config ( void );
void USART_Config ( void );
void DMA_Config ( void );

int main ( void )
{

    SystemInit();

    RCC_Config();
    GPIO_Config();
    USART_Config();
    DMA_Config();

    //使能DMA通道2，意味着开始传输
    DMA_Cmd ( DMA1_Channel2, ENABLE );

    while ( 1 )
    {

    }
}

void RCC_Config ( void )
{
    //时钟配置
    RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_GPIOA, ENABLE );
    RCC_APB2PeriphClockCmd ( RCC_APB2Periph_USART1, ENABLE );
    RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_DMA1, ENABLE );
}
void GPIO_Config ( void )
{
    //选择引脚
    //针对F030F4P6，TX有PA2和PA9可选，RX有PA3和PA10可选，特别注意查看文档是AF多少
    //GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_1);
    //GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_1);
    GPIO_PinAFConfig ( GPIOA, GPIO_PinSource9, GPIO_AF_1 );
    GPIO_PinAFConfig ( GPIOA, GPIO_PinSource10, GPIO_AF_1 );
    //引脚设置
    GPIO_InitTypeDef PORT_UART1_TX; //定义TX脚,PORT_UART1_TX是自定义名称，可以任意
    PORT_UART1_TX.GPIO_Pin = GPIO_Pin_9; //此参数根据上面选择的引脚来定
    PORT_UART1_TX.GPIO_Speed = GPIO_Speed_10MHz;
    PORT_UART1_TX.GPIO_Mode = GPIO_Mode_AF;
    PORT_UART1_TX.GPIO_PuPd = GPIO_PuPd_NOPULL;
    //IO初始化
    GPIO_Init ( GPIOA, &PORT_UART1_TX );

    GPIO_InitTypeDef PORT_UART1_RX; //定义RX脚
    PORT_UART1_RX.GPIO_Pin = GPIO_Pin_10; //此参数根据上面选择的引脚来定
    PORT_UART1_RX.GPIO_Speed = GPIO_Speed_10MHz;
    PORT_UART1_RX.GPIO_Mode = GPIO_Mode_AF;
    PORT_UART1_RX.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init ( GPIOA, &PORT_UART1_RX );
}

void USART_Config ( void )
{
    //串口参数配置
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 115200; //设置波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置数据长度
    USART_InitStructure.USART_Parity = USART_Parity_No; //设置奇偶校验
    USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置停止位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //设置流控制
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //设置模式
    USART_Init ( USART1, &USART_InitStructure );
    //使能DMA发送
    USART_DMACmd ( USART1, USART_DMAReq_Tx, ENABLE ); //串口1发射 DMA使能
    //使能
    USART_Cmd ( USART1, ENABLE );
}

void DMA_Config ( void )
{
    //特别注意，对于STM32F030F4P6，USART1_TX对应通道2，注意看数据手册
    DMA_DeInit ( DMA1_Channel2 );
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_TDR_Address;
    DMA_InitStructure.DMA_MemoryBaseAddr = ( uint32_t ) hellStr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = 5;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init ( DMA1_Channel2, &DMA_InitStructure );
}