4472 views|3 replies

530

Posts

4

Resources
The OP
 

[GD32E231 DIY Contest] 06. Automatic fish feeding robot: ADC/DMA/TIMER0/serial port [Copy link]

[GD32E231 DIY Contest] 06. Automatic Fish Feeding Robot - ADC/DMA/TIMER0/Serial Port
Here, a photoresistor is used to monitor the light intensity around the fish tank.
Acquired from the internal ADC, the comparison event 0 of timer 0 triggers the ADC conversion, and the result of the ADC conversion will change with the change of the analog value input.
The conversion result is transferred to SRAM by DMA, and finally it is determined whether the AD value is greater than a certain value. The specific procedure is as follows: First, the following functions and variables are involved:
  1. __IO uint16_t ad_value[220]; //day: ad_value <1500; night: ad_value>2500 void adc_rcu_config(void); void adc_gpio_config(void); void adc_dma_config(void); void adc_timer_config(void); void adc_config(void); void display_adc_ value(void);
复制代码
  1. /*! \brief RCU configuration function for ADC \param[in] none \param[out] none \retval none */ void adc_rcu_config(void) { /* enable the GPIO clock */ //rcu_periph_clock_enable(RCU_GPIOA); //rcu_periph_clock_enable(RCU_GPIOB); //rcu_periph_clock_enable(RCU_ GPIOC); // rcu_periph_clock_enable(RCU_GPIOF); /* ADCCLK = PCLK2/6 */ rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6); /* enable DMA clock */ rcu_periph_clock_enable(RCU_DMA); /* enable ADC clock */ rcu_periph_clock_enable(RCU_ADC); /* enable TIMER0 clock */ _clock_enable(RCU_TIMER0); } /*! \brief GPIO configuration function for ADC \param[in] none \param[out] none \retval none */ void adc_gpio_config(void) { /* configure PA2(ADC channel2) as analog input */ gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2); } /*! \brief DMA configuration function for ADC \param[in] none \param[out] none \retval none */ void adc_dma_config(void) { dma_parameter_struct dma_init_struct; /* initialize DMA channel0 */ dma_deinit(DMA_CH0); dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory _addr = (uint32_t)ad_value; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_init_struct.number = 220; dma_init_struct.periph_addr = (uint32_t)&(ADC_RD ATA); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA_CH0, &dma_init_struct); /* configure DMA mode */ _circulation_enable(DMA_CH0); dma_memory_to_memory_disable(DMA_CH0); /* enable DMA channel0 */ dma_channel_enable(DMA_CH0); } /*! \brief TIMER configuration function for ADC \param[in] none \param[out] none \retval none */ void adc_timer_config(void) { timer_oc_parameter_struct timer_ocintpara ; timer_parameter_struct timer_initpara; timer_deinit(TIMER0); /* TIMER0 configuration */ timer_initpara.prescaler = 5; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 399; timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
  2.     timer_initpara.repetitioncounter = 0;
  3.     timer_init(TIMER0, &timer_initpara);
  4.     /* CH0 configuration in PWM mode1 */
  5.     timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_LOW;
  6.     timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  7.     timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara);
  8.     timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 100);
  9.     timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1);
  10.     timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
  11.     /* auto-reload preload enable */
  12.     timer_auto_reload_shadow_enable(TIMER0);
  13.     timer_primary_output_config(TIMER0, ENABLE);
  14. }
  15. /*!
  16.     \brief      ADC configuration function
  17.     \param[in]  none
  18.     \param[out] none
  19.     \retval     none
  20. */
  21. void adc_config(void)
  22. {
  23.     /* ADC channel length config */
  24.     adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
  25.     /* ADC regular channel config */
  26.     adc_regular_channel_config(0, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
  27.     /* ADC external trigger enable */
  28.     adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
  29.     /* ADC external trigger source config */
  30.     adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0);
  31.     /* ADC data alignment config */
  32.     adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
  33.     /* enable ADC interface */
  34.     adc_enable();
  35.     /* ADC calibration and reset calibration */
  36.     adc_calibration_enable();
  37.     /* ADC DMA function enable */
  38.     adc_dma_mode_enable();
  39. }
  40. void display_adc_value(void)
  41. {
  42.           printf("\r\n%d\r\n",ad_value[0]);
  43. }
复制代码


ad转换我只用了第一个值,其实DMA传输会不停的循环传输。
主函数中这样用:
  1. gd_eval_com_init(EVAL_COM1,115200);
  2.   adc_rcu_config();
  3.     adc_gpio_config();
  4.           adc_dma_config();
  5.     adc_timer_config();
  6.     adc_config();
  7.          /* TIMER0 counter enable for ADC */
  8.     timer_enable(TIMER0);
  9.                 /* test on channel0 transfer complete flag */
  10.                 while( !dma_flag_get(DMA_CH0, DMA_FLAG_FTF));
  11.                 display_adc_value();
复制代码
然后在while(1) 中执行display_adc_value(); 就能把值实时打印到串口。

DMA配置完会不断循环写入到buffer中,配置完成后CPU不需要参与,我们在循环中,可以直接读取AD值,这些值在配置DMA时是循环覆盖写入的。

printf是采用串口显示,
具体方法如下,在keil的魔术棒option里,Target中,勾选Use MicroLIB, 然后添加如下子程序,重新映射串口,
  1. /* retarget the C library printf function to the USART */
  2. int fputc(int ch, FILE *f)
  3. {
  4.     usart_data_transmit(EVAL_COM1, (uint8_t)ch);
  5.     while(RESET == usart_flag_get(EVAL_COM1, USART_FLAG_TBE));
  6.     return ch;
  7. }
复制代码

关于串口初始化:gd_eval_com_init(EVAL_COM1,115200);
其是在gd32e231c_start.c、gd32e231c_start.h中定义的:
gd32e231c_start.h
  1. //-----------------added by user--------------------------//
  2. /* eval board low layer COM */
  3. #define COMn                             1U   //定义数组大小
  4. /* definition for COM0,connected to USART0 */
  5. #define EVAL_COM1                        USART0
  6. #define EVAL_COM1_CLK                    RCU_USART0
  7. #define EVAL_COM1_TX_PIN                 GPIO_PIN_9
  8. #define EVAL_COM1_RX_PIN                 GPIO_PIN_10
  9. #define EVAL_COM_GPIO_PORT               GPIOA
  10. #define EVAL_COM_GPIO_CLK                RCU_GPIOA
  11. #define EVAL_COM_AF                      GPIO_AF_1
  12. /* configure COM port */
  13. void gd_eval_com_init(uint32_t com, uint32_t baud);
复制代码



gd32e231c_start.c
  1. static rcu_periph_enum COM_CLK[COMn]  = {EVAL_COM1_CLK};
  2. static uint32_t COM_TX_PIN[COMn]      = {EVAL_COM1_TX_PIN};
  3. static uint32_t COM_RX_PIN[COMn]      = {EVAL_COM1_RX_PIN};
复制代码

  1. void gd_eval_com_init(uint32_t com, uint32_t baud)
  2. {
  3.     uint32_t COM_ID;
  4.   
  5.     if(EVAL_COM1 == com){
  6.         COM_ID = 0U;
  7.     }else{
  8.     }
  9.     /* enable COM GPIO clock */
  10.     rcu_periph_clock_enable(EVAL_COM_GPIO_CLK);
  11.     /* enable USART clock */
  12.     rcu_periph_clock_enable(COM_CLK[COM_ID]);
  13.     /* connect port to USARTx_Tx */
  14.     gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, COM_TX_PIN[COM_ID]);
  15.     /* connect port to USARTx_Rx */
  16.     gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, COM_RX_PIN[COM_ID]);
  17.     /* configure USART Tx as alternate function push-pull */
  18.     gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_TX_PIN[COM_ID]);
  19.     gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_TX_PIN[COM_ID]);
  20.     /* configure USART Rx as alternate function push-pull */
  21.     gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_RX_PIN[COM_ID]);
  22.     gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_RX_PIN[COM_ID]);
  23.     /* USART configure */
  24.     usart_deinit(com);
  25.    // usart_baudrate_set(com, 115200U);
  26.           usart_baudrate_set(com, baud);
  27.     usart_receive_config(com, USART_RECEIVE_ENABLE);
  28.     usart_transmit_config(com, USART_TRANSMIT_ENABLE);
  29.     usart_enable(com);
  30. }
复制代码


注意串口0还是1。
-------------------------------------------COM_TX_PIN[COM_ID]);

    /* connect port to USARTx_Rx */
    gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, COM_RX_PIN[COM_ID]);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_TX_PIN[COM_ID]);
    gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_TX_PIN[COM_ID]);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_RX_PIN[COM_ID]);
    gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_RX_PIN[COM_ID]);

    /* USART configure */
    usart_deinit(com);
   // usart_baudrate_set(com, 115200U);
          usart_baudrate_set(com, baud);
    usart_receive_config(com, USART_RECEIVE_ENABLE);
    usart_transmit_config(com, USART_TRANSMIT_ENABLE);

    usart_enable(com);
}[/code]


注意串口0还是1。
-------------------------------------------COM_TX_PIN[COM_ID]);

    /* connect port to USARTx_Rx */
    gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, COM_RX_PIN[COM_ID]);

    /* configure USART Tx as alternate function push-pull */
    gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_TX_PIN[COM_ID]);
    gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_TX_PIN[COM_ID]);

    /* configure USART Rx as alternate function push-pull */
    gpio_mode_set(EVAL_COM_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, COM_RX_PIN[COM_ID]);
    gpio_output_options_set(EVAL_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, COM_RX_PIN[COM_ID]);

    /* USART configure */
    usart_deinit(com);
   // usart_baudrate_set(com, 115200U);
          usart_baudrate_set(com, baud);
    usart_receive_config(com, USART_RECEIVE_ENABLE);
    usart_transmit_config(com, USART_TRANSMIT_ENABLE);

    usart_enable(com);
}[/code]


注意串口0还是1。
-------------------------------------------



This post is from GD32 MCU

Latest reply

Thanks for sharing   Details Published on 2021-4-22 17:31

赞赏

1

查看全部赞赏

 

121

Posts

1

Resources
2
 

The timer triggers AD once, AD samples once, and after completing one sampling, DMA is triggered, and DMA fills the cache ad_value[220] once.

The timer triggers AD 220 times. When ad_value[220] is full, DMA will automatically refill it starting from ad_value[0].

I don't know if this is the right understanding.

This post is from GD32 MCU
 
 
 

1942

Posts

2

Resources
3
 

Isn’t Shandong going to hold a robot design competition recently?

This post is from GD32 MCU
 
 
 

661

Posts

0

Resources
4
 

Thanks for sharing

This post is from GD32 MCU
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list