GD32上升沿采样_定时器捕获外部上升沿信号,DMA读取GPIO口数据的问题
时间: 2024-01-21 16:18:56 浏览: 97
在 GD32 上采集外部上升沿信号,可以使用定时器捕获模式。具体步骤如下:
1. 初始化 GPIO 口为输入模式。
2. 初始化定时器为捕获模式,并设置触发源为外部上升沿。
3. 在定时器触发后,通过 DMA 读取 GPIO 口数据。
下面是示例代码:
```c
#include "gd32f30x.h"
#define BUFFER_SIZE 100
uint16_t g_data_buffer[BUFFER_SIZE];
uint8_t g_dma_transfer_complete = 0;
void gpio_init(void)
{
/* Enable the GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* Configure PB13 as input */
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
}
void timer_init(void)
{
/* Enable the TIMER1 clock */
rcu_periph_clock_enable(RCU_TIMER1);
/* Configure TIMER1 channel 1 as input capture */
timer_ic_parameter_struct timer_icinitpara;
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING;
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
timer_icinitpara.icfilter = 0;
timer_input_capture_config(TIMER1, TIMER_CH_1, &timer_icinitpara);
/* Configure TIMER1 as up counter with a period of 0xFFFF and a frequency of 72 MHz */
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = 0;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 0xFFFF;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(TIMER1, &timer_initpara);
/* Enable TIMER1 */
timer_enable(TIMER1);
}
void dma_init(void)
{
/* Enable the DMA clock */
rcu_periph_clock_enable(RCU_DMA);
/* Configure DMA channel 1 */
dma_parameter_struct dma_initpara;
dma_initpara.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_initpara.peripheral_addr = (uint32_t)&GPIO_BOP(GPIOB);
dma_initpara.memory_addr = (uint32_t)g_data_buffer;
dma_initpara.number = BUFFER_SIZE;
dma_initpara.peripheral_burst = DMA_BURST_SINGLE;
dma_initpara.memory_burst = DMA_BURST_SINGLE;
dma_initpara.peripheral_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_initpara.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_initpara.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_initpara.m2m = DMA_M2M_DISABLE;
dma_init(DMA1, DMA_CH1, &dma_initpara);
/* Enable DMA channel 1 transfer complete interrupt */
dma_interrupt_enable(DMA1, DMA_CH1, DMA_INT_FTF);
/* Enable DMA channel 1 */
dma_channel_enable(DMA1, DMA_CH1);
}
void dma1_channel1_isr(void)
{
if (dma_interrupt_flag_get(DMA1, DMA_CH1, DMA_INT_FLAG_FTF)) {
g_dma_transfer_complete = 1;
dma_interrupt_flag_clear(DMA1, DMA_CH1, DMA_INT_FLAG_FTF);
}
}
int main(void)
{
/* Initialize GPIO, TIMER and DMA */
gpio_init();
timer_init();
dma_init();
/* Enable DMA channel 1 interrupt */
eclic_irq_enable(DMA1_Channel1_IRQn, 1, 0);
while (1) {
/* Wait for DMA transfer complete */
while (!g_dma_transfer_complete);
/* Reset DMA transfer complete flag */
g_dma_transfer_complete = 0;
/* Process data */
for (int i = 0; i < BUFFER_SIZE; i++) {
if (g_data_buffer[i] & GPIO_PIN_13) {
/* GPIO pin 13 is high */
} else {
/* GPIO pin 13 is low */
}
}
}
}
```
注意,在使用 DMA 读取 GPIO 口数据时,需要将 GPIO 口的地址作为 DMA 的外设地址。这里使用 `GPIO_BOP(GPIOB)` 获取 GPIOB 的输出寄存器地址。另外,DMA 传输完成后需要清除 DMA 传输完成标志,并在 DMA 中断中设置传输完成标志。在主函数中等待传输完成标志,然后处理数据即可。
阅读全文