GD32L23X USART+DMA空闲中断收发数据

DMA+USART1收发数据

空闲中断函数以及宏定义

#define USART1_RDATA_ADDRESS (&USART_RDATA(USART1))
#define USART1_TDATA_ADDRESS (&USART_TDATA(USART1))
#define ARRAYNUM(arr_nanme) (uint32_t)(sizeof(arr_nanme) / sizeof(*(arr_nanme)))
#define USART_TX_RX_BUFF_LEN 256
#define USART_DMA_IDLE 0
#define USART_DMA_BUSY 1

#pragma pack(1)
typedef struct
{
    uint8_t dma_tx_buf[USART_TX_RX_BUFF_LEN];
    uint8_t dma_rx_buf[USART_TX_RX_BUFF_LEN];
    uint16_t dma_rev_cnt;
} USART_DataInfo;
USART_DataInfo usart_DataInfo;

static void com_usart_init(uint32_t baudrate);
static void dma_usart_init(void);

static dma_parameter_struct dma_init_struct;
uint8_t rxdata[USART_TX_RX_BUFF_LEN];

void USART1_Init(uint32_t baudrate)
{
    // initialize the com
    com_usart_init(baudrate);
    // configure DMA ch0 and ch1
    dma_usart_init();
}
void USART1_IRQHandler(void)
{
    if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE))
    {
        // clear flag
        usart_interrupt_flag_clear(USART1, USART_INT_FLAG_IDLE);
        // disable channel
        dma_channel_disable(DMA_CH1);

        // read
        usart_DataInfo.dma_rev_cnt = sizeof(usart_DataInfo.dma_rx_buf) - dma_transfer_number_get(DMA_CH1);
        memcpy(rxdata, usart_DataInfo.dma_rx_buf, usart_DataInfo.dma_rev_cnt);
        memset(usart_DataInfo.dma_rx_buf, 0, sizeof(usart_DataInfo.dma_rx_buf));

        // reset DMA configure
        dma_channel_enable(DMA_CH1);
    }
}

USART1

配置 8N1 LSB 中断IRQ优先级0,无硬件流控制

硬件流控概念理解(需要多加两条线)

硬件流控制常用的有RTS/CTS流控制和DTR/DSR(数据终端就绪/数据设置就绪)流控制。
RTS (Require ToSend,发送请求)为输出信号,用于指示本设备准备好可接收数据,低电平有效,低电平说明本设备可以接收数据。
CTS (Clear ToSend,发送允许)为输入信号,用于判断是否可以向对方发送数据,低电平有效,低电平说明本设备可以向对方发送数据。

static void com_usart_init(uint32_t baudrate)
{
    /* enable USART clock */
    rcu_periph_clock_enable(RCU_USART1);

    /* enable COM GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);

    /* connect port to USART TX */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_2);

    /* connect port to USART RX */
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_3);

    /* configure USART TX as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_2);

    /* configure USART RX as alternate function push-pull */
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_3);

    /* USART configure */
    usart_deinit(USART1);
    usart_baudrate_set(USART1, baudrate);
    usart_word_length_set(USART1, USART_WL_8BIT);
    usart_parity_config(USART1, USART_PM_NONE);
    usart_stop_bit_set(USART1, USART_STB_1BIT);
    usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);
    usart_data_first_config(USART1, USART_MSBF_LSB);
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
    /*USART enable*/
    usart_interrupt_enable(USART1, USART_INT_IDLE);
    nvic_irq_enable(USART1_IRQn, 0);
    usart_enable(USART1);
}

DMA

DMA直接存储器访问控制器

能够让外设与存储器之间直接进行数据传输,而不需要CPU的参与,在串口检测到有数据输入的时候,让DMA直接往我们定义好的存储器中搬收到的UART数据,在这个过程中,CPU还是在处理自己的事,最后,在一帧数据传输完成后,通过中断告诉主任务一帧数据已经传输完毕,主任务再对接收到的数据进行相应的处理。整个过程下来,程序代码只会触发一次中断,就是DMA搬移完数据后通知CPU的那一次中断,对比前一种方法,每接收到一个字节就需要进中断把数据读到自定的的FIFO中,第二种方法不论一帧数据的数据量有多大,我们都只会触发一次中断。

DMAMUX 基本功能

第一块,DMA请求路由器【Request Multiplexer】, 它的核心功能就是实现DMA请求的路由转发。其组成单元是DMA请求路由通道,请求路由器由多个请求路由通道组成。
第二块,DMA请求生成器【RequestGenerator】,它的核心功能,就是生成DMA请求。
相比于其他单片机GD32L23X有DMAMUX功能后,DMA不在与外设绑定

static void dma_usart_init(void)
{
    dma_parameter_struct dma_init_struct;
    /* initialize DMA channel 2 */
    rcu_periph_clock_enable(RCU_DMA);
    dma_deinit(DMA_CH2);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.request = DMA_REQUEST_USART1_TX;
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_addr = NULL;
    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)USART1_TDATA_ADDRESS;
    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(DMA_CH2, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_disable(DMA_CH2);
    dma_memory_to_memory_disable(DMA_CH2);

    /* disable the DMAMUX_MUXCH2 synchronization mode */
    dmamux_synchronization_disable(DMAMUX_MUXCH2);

    /* USART DMA enable for transmission and reception */
    usart_dma_transmit_config(USART1, USART_TRANSMIT_DMA_ENABLE);

    /* initialize DMA channel 1 */
    dma_deinit(DMA_CH1);
    dma_struct_para_init(&dma_init_struct);
    dma_init_struct.request = DMA_REQUEST_USART1_RX;
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_addr = (uint32_t)&usart_DataInfo.dma_rx_buf[0];
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = ARRAYNUM(usart_DataInfo.dma_rx_buf);
    dma_init_struct.periph_addr = (uint32_t)USART1_RDATA_ADDRESS;
    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(DMA_CH1, &dma_init_struct);

    /* configure DMA mode */
    dma_circulation_disable(DMA_CH1);
    dma_memory_to_memory_disable(DMA_CH1);
    /* disable the DMAMUX_MUXCH1 synchronization mode */
    dmamux_synchronization_disable(DMAMUX_MUXCH1);
    /* USART DMA enable for reception */
    usart_dma_receive_config(USART1, USART_RECEIVE_DMA_ENABLE);
}

printf 重定义

在Xcom里换行尾部加 \ r\ n

/* retarget the C library printf function to the USART */
int fputc(int ch, FILE* f)
{
    usart_data_transmit(USART1, (uint8_t)ch);
    while(RESET == usart_flag_get(USART1, USART_FLAG_TBE))
        ;
    return ch;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值