#include "gd32f30x.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
void RCU_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_USART0);
rcu_periph_clock_enable(RCU_DMA0);
}
void NVIC_config(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
nvic_irq_enable(USART0_IRQn,1,0);
}
void GPIO_config(void)
{
//PA9 USART0_Tx
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
//PA10 USART0_Rx
gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
}
#define USART0_DMA_TXBUF_SIZE 100
#define USART0_DMA_RXBUF_SIZE 100
uint8_t USART0_DMA_txbuf[USART0_DMA_TXBUF_SIZE];
uint8_t USART0_DMA_rxbuf[USART0_DMA_RXBUF_SIZE];
void USART0_config(void)
{
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200U);
//--接收超时设置
usart_receiver_timeout_threshold_config(USART0,100);
usart_interrupt_enable(USART0,USART_INT_RT);
usart_receiver_timeout_enable(USART0);
//=====配置USART使用的DMA通道======
//USART0_TX:DMA0_CH3
dma_parameter_struct dma_init_struct; //DMA初始化结构体
dma_deinit(DMA0, DMA_CH3); //复位DMA通道为默认配置
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; //传输方向
dma_init_struct.memory_addr = (uint32_t)USART0_DMA_txbuf; //存储器基地址
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; //增量式存储器地址生成模式
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; //存储器单个数据宽度
dma_init_struct.number = 0; //传输长度
dma_init_struct.periph_addr = (uint32_t)&(USART_DATA(USART0)); //外设基地址(寄存器地址)
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; //增量式外设地址生成模式
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; //外设单个数据宽度
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; //通道的优先级
dma_init(DMA0, DMA_CH3, &dma_init_struct); //进行配置
dma_circulation_disable(DMA0, DMA_CH3); //配置循环传输模式(单次模式和循环模式)
//dma_interrupt_enable(DMA0,DMA_CH3,DMA_INT_FTF); //DMA中断使能
//dma_channel_enable(DMA0, DMA_CH3); //使能DMA通道
//USART0_RX:DMA0_CH4
dma_deinit(DMA0, DMA_CH4); //复位DMA通道为默认配置
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; //传输方向
dma_init_struct.memory_addr = (uint32_t)USART0_DMA_rxbuf; //存储器基地址
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; //增量式存储器地址生成模式
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; //存储器单个数据宽度
dma_init_struct.number = USART0_DMA_RXBUF_SIZE; //传输长度
dma_init_struct.periph_addr = (uint32_t)&(USART_DATA(USART0)); //外设基地址(寄存器地址)
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; //增量式外设地址生成模式
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; //外设单个数据宽度
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; //通道的优先级
dma_init(DMA0, DMA_CH4, &dma_init_struct); //进行配置
dma_circulation_enable(DMA0, DMA_CH4); //配置循环传输模式(单次模式和循环模式)
//dma_interrupt_enable(DMA0,DMA_CH4,DMA_INT_FTF); //DMA中断使能
dma_channel_enable(DMA0, DMA_CH4); //使能DMA通道
//=====使能串口的DMA发送和接收=====
usart_dma_transmit_config(USART0, USART_DENT_ENABLE); //使能串口的DMA发送
usart_dma_receive_config(USART0,USART_DENR_ENABLE); //使能串口的DMA接收
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
void USART0_printf(const char*format , ...)
{
int tx_len;
va_list args;
//如果dma传输通道是使能的,且传输没完成
while((DMA_CHCTL(DMA0,DMA_CH3)&0x01) && (!dma_flag_get(DMA0,DMA_CH3,DMA_FLAG_FTF))); //等待DMA传输完成
dma_flag_clear(DMA0,DMA_CH3,DMA_FLAG_FTF); //清除传输完成标志
va_start(args,format);
tx_len = vsnprintf((char*)USART0_DMA_txbuf,USART0_DMA_TXBUF_SIZE,format,args);
va_end(args);
if(tx_len>0)
{
dma_channel_disable(DMA0,DMA_CH3); //关闭DMA通道,这样才能设置传输长度
dma_transfer_number_config(DMA0,DMA_CH3,tx_len); //设置本次DMA传输长度
dma_channel_enable(DMA0,DMA_CH3); //使能USART0_TX使用的DMA通道,开始DMA传输
}
}
volatile uint32_t USART0_get_msg=0;
volatile uint32_t USART0_rear=0;
volatile uint32_t USART0_front=0;
int main(void)
{
RCU_config();
NVIC_config();
GPIO_config();
USART0_config();
while(1)
{
if(USART0_get_msg)
{
USART0_get_msg=0;
uint32_t len = (USART0_DMA_RXBUF_SIZE - USART0_front + USART0_rear)%USART0_DMA_RXBUF_SIZE;//本次消息长度
USART0_printf("\nlen=%u:",len);
//打印出收到的字符
for(uint32_t i=0;i<len;i++)
{
USART0_printf("[%u]%c ",i,USART0_DMA_rxbuf[USART0_front]); //处理第i个字节
USART0_front = (USART0_front+1)%USART0_DMA_RXBUF_SIZE; //更新front指针
}
}
}
}
void USART0_IRQHandler(void)
{
//接收超时中断(也可以使用IDLE中断实现)
if(usart_interrupt_flag_get(USART0,USART_INT_FLAG_RT))
{
//清除中断标志
usart_interrupt_flag_clear(USART0,USART_INT_FLAG_RT);
//计算rear的值
USART0_rear = USART0_DMA_RXBUF_SIZE - dma_transfer_number_get(DMA0,DMA_CH4);
//通知main收到了一包数据
USART0_get_msg=1;
}
}