之前写了GD32F103调试小记(二)之USART(接收中断、接收空闲中断+DMA、发送DMA)一文。这次我们来看看GD32F303的USART是如何配置的,结合这两篇文章,相信大家GD32的USART配置流程会十分熟悉。
能大大减轻CPU负荷,数据的搬运工,建议场景合适的情况下,都去配置DMA功能。
一种串行通信协议,网上资料很多,这里不多说。
在配置前,请确保你已经有一个GD32F303包含其对应标准库的Keil工程。
1、时钟配置
void SystemClock_Reconfig(void)
{
/* Enable all peripherals clocks you need*/
rcu_periph_clock_enable(RCU_AF);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_DMA0);
rcu_periph_clock_enable(RCU_USART2);
}
// USART port and pins definition
#define USART2_PORT GPIOC
#define USART2_TX_PIN GPIO_PIN_10
#define USART2_RX_PIN GPIO_PIN_11
void GPIO_Init(void)
{
/* 使用SW下载,不使用JTAG下载,管脚用作其它功能 */
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
/* demo board USARTx I/O */
gpio_pin_remap_config(GPIO_USART2_PARTIAL_REMAP, ENABLE);
gpio_init(USART2_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,USART2_TX_PIN);
gpio_init(USART2_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,USART2_RX_PIN);
}
/* USARTx Receiving Mode */
#define USARTx_RX_BY_IDLE_DMA 1 //1:使用接收空闲中断+DMA 0:仅使用接收中断
/* USARTx ADrawbuffer definition */
#define USART2_TX_SIZE 20
#define USART2_RX_SIZE 20
uint8_t USART2TX_Buffer[USART2_TX_SIZE] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18};
uint8_t USART2RX_Buffer[USART2_RX_SIZE] = {0};
void DMA_Init(void)
{
dma_parameter_struct dma_init_Usart2_TX = {0};
dma_parameter_struct dma_init_Usart2_RX = {0};
/* deinitialize DMA channel */
dma_deinit(DMA0, DMA_CH1); //USART2_TX
dma_deinit(DMA0, DMA_CH2); //USART2_RX
/* initialize DMA0 channel1(Usart2_TX) */
dma_init_Usart2_TX.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_Usart2_TX.memory_addr = (uint32_t)USART2TX_Buffer;
dma_init_Usart2_TX.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_Usart2_TX.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_Usart2_TX.number = (uint32_t)USART2_TX_SIZE;
dma_init_Usart2_TX.periph_addr = (uint32_t)(&USART_DATA(USART2));
dma_init_Usart2_TX.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_Usart2_TX.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_Usart2_TX.priority = DMA_PRIORITY_LOW;
dma_init(DMA0, DMA_CH1, &dma_init_Usart2_TX);
dma_circulation_disable(DMA0, DMA_CH1);
/* initialize DMA0 channel2(Usart2_RX) */
dma_init_Usart2_RX.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_Usart2_RX.memory_addr = (uint32_t)USART2RX_Buffer;
dma_init_Usart2_RX.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_Usart2_RX.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_Usart2_RX.number = (uint32_t)USART2_RX_SIZE;
dma_init_Usart2_RX.periph_addr = (uint32_t)(&USART_DATA(USART2));
dma_init_Usart2_RX.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_Usart2_RX.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_Usart2_RX.priority = DMA_PRIORITY_LOW;
dma_init(DMA0, DMA_CH2, &dma_init_Usart2_RX);
dma_circulation_disable(DMA0, DMA_CH2);
dma_memory_to_memory_disable(DMA0,DMA_CH1); //USART2_TX
dma_memory_to_memory_disable(DMA0,DMA_CH2); //USART2_RX
/* enable all DMA channels you need */
dma_channel_disable(DMA0,DMA_CH1); //USART2_TX
dma_channel_enable(DMA0,DMA_CH2); //USART2_RX
}
4、配置USART2
void USARTx_Init(void)
{
/* USART2 configure */
usart_deinit(USART2);
usart_baudrate_set(USART2, 38400U);
usart_word_length_set(USART2, USART_WL_8BIT);
usart_stop_bit_set(USART2, USART_STB_1BIT);
usart_parity_config(USART2, USART_PM_NONE);
usart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE);
usart_receive_config(USART2, USART_RECEIVE_ENABLE);
usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);
usart_enable(USART2);
/* config USARTx_TX transmit by DMA */
usart_dma_transmit_config(USART2,USART_DENT_ENABLE);
#if USARTx_RX_BY_IDLE_DMA
usart_dma_receive_config(USART2,USART_DENR_ENABLE);
#endif
}
5、配置中断优先级组与USART2中断
void NVIC_Init(void)
{
/* USART2 IRQ set */
nvic_irq_enable(USART2_IRQn, 2, 0);
#if USARTx_RX_BY_IDLE_DMA
usart_interrupt_enable(USART2, USART_INT_IDLE);
#else
usart_interrupt_enable(USART2, USART_INT_RBNE);
#endif
}
void USART2_IRQHandler(void)
{
#if USARTx_RX_BY_IDLE_DMA
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE))
{
Module.USART2_RX_OK=1;
/* clear USART_INT_FLAG_IDLE */
usart_data_receive(USART2);
/* disable USART2_RX DMA_Channel */
dma_channel_disable(DMA0, DMA_CH2);
/* reset DMA_Channel CNT */
dma_transfer_number_config(DMA0, DMA_CH2, USART2_RX_SIZE);
/* enable USART2_RX DMA_Channel */
dma_channel_enable(DMA0, DMA_CH2);
}
#else
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE))
{
usart_interrupt_flag_clear(USART2,USART_INT_FLAG_RBNE);
Module.USART2_RX_OK=1;
USART2RX_Buffer[0] = usart_data_receive(USART2);
}
#endif
}
void Usartx_Transmit_DMA(uint32_t usart_periph,uint8_t* data_buffer,uint8_t length)
{
if(usart_periph==USART2)
{
/* Channel disable */
dma_channel_disable(DMA0, DMA_CH1);
dma_memory_address_config(DMA0, DMA_CH1,(uint32_t)data_buffer);
dma_transfer_number_config(DMA0,DMA_CH1,length);
/* enable DMA channel to start send */
dma_channel_enable(DMA0, DMA_CH1);
}
}
7、主函数部分
int main(void)
{
SystemTick_Init();
SystemClock_Reconfig();
GPIO_Init();
DMA_Init();
USARTx_Init();
NVIC_Init();
while(1)
{
// Usartx_Transmit_DMA(USART2,USART2TX_Buffer,USART2_RX_SIZE);
Usartx_Transmit_DMA(USART2,(uint8*)"hello,MCU World!",20);
delay_ms(1000);
}
}
while(1)
{
if(Module.USART2_RX_OK)
{
Module.USART2_RX_OK = 0;
Usartx_Transmit_DMA(USART2,USART2RX_Buffer,USART2_RX_SIZE);
}
}
!!!本文为欢喜6666在CSDN原创发布,复制或转载请注明出处 :)!!!