//DMA --- Directional Memory Access, direct memory access is used to provide high-speed data transfer between peripherals and memory or between memory and memory. Without CPU intervention, data can be moved quickly through DMA, which saves CPU resources for other operations
// serial port initialization
void USART1_Init(u32 baud)
{
GPIO_InitTypeDef GPIO_Initstructure;
USART_InitTypeDef USART_Initstructure;
NVIC_InitTypeDef NVIC_Initstructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); //Enable the clock of PA and USART1
//USART1_TX PA9
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP; //Push-pull multiplexing output
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_9; //PA9
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz; //50MHz
GPIO_Init(GPIOA, &GPIO_Initstructure); //Initialization
//USART1_RX PA10
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //Floating input
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz; //50MHz
GPIO_Init(GPIOA, &GPIO_Initstructure);
USART_DeInit (USART1);
NVIC_Initstructure.NVIC_IRQChannel = USART1_IRQn; //串口1
NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority = 3; //Preempt priority 3
NVIC_Initstructure.NVIC_IRQChannelSubPriority = 0; //Sub priority 3
NVIC_Initstructure.NVIC_IRQChannelCmd = ENABLE; //Enable interrupt
NVIC_Init(&NVIC_Initstructure);
USART_Initstructure.USART_BaudRate = baud; //Baud rate
USART_Initstructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //No hardware data flow control
USART_Initstructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // Development model
USART_Initstructure.USART_Parity = USART_Parity_No; //No parity bit
USART_Initstructure.USART_StopBits = USART_StopBits_1; //One stop bit
USART_Initstructure.USART_WordLength = USART_WordLength_8b; //8 data bits
USART_Init(USART1, &USART_Initstructure); //Initialization
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA1_Channel4_UseForUSART1_Config();
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //Open serial port to accept interrupt
USART_Cmd(USART1, ENABLE); //Enable serial port 1
}
void DMA1_Channel4_UseForUSART1_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
DMA_DeInit(DMA1_Channel4); //Reset DMA channel register to default value
DMA_InitStructure.DMA_BufferSize = 0; //The DMA buffer size is temporarily set to 6 bytes
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //Peripheral as destination
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Not set to memory to memory
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff; //The memory address is temporarily set to 0, and the specific location is specified when the transfer is started
DMA_InitStructure.DMA_MemoryDataSize = SENDBUFF_SIZE;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //The memory address is incremented
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //Normal mode does not cycle
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; //Peripheral address
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //Peripheral size is one byte
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //The peripheral address does not increase automatically
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //High priority
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); //Enable transfer completion interrupt
}
//Send data to serial port via DMA
FlagStatus FlagStatus_DMA1_Channel4_Busy; //DMA1_Channel4 busy flag
ErrorStatus USART1_SendDataByDMA(u32 memoryaddr, u16 buffersize)
{
if(FlagStatus_DMA1_Channel4_Busy != SET) //Channel is idle
{
LED_TX_Onepulse();
FlagStatus_DMA1_Channel4_Busy = SET; //Set the channel busy flag
DMA_Cmd(DMA1_Channel4, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel4, buffersize); //Buffer size
DMA1_Channel4->CMAR = memoryaddr; //memory address
DMA_Cmd(DMA1_Channel4, ENABLE); //Start transmission
return SUCCESS;
}
else //The channel is busy
{
return ERROR;
}
}
//Channel 4 interrupt function, used to clear the busy flag
void DMA1_Channel4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_GL4) != RESET)
{
if(DMA_GetITStatus(DMA1_IT_TC4) != RESET)
{
FlagStatus_DMA1_Channel4_Busy = RESET; //Clear the busy flag
DMA_ClearITPendingBit(DMA1_IT_TC4);
}
DMA_ClearITPendingBit(DMA1_IT_GL4);
}
}