[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:- __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);
复制代码- /*! \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;
- timer_initpara.repetitioncounter = 0;
- timer_init(TIMER0, &timer_initpara);
- /* CH0 configuration in PWM mode1 */
- timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_LOW;
- timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
- timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocintpara);
- timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 100);
- timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1);
- timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
- /* auto-reload preload enable */
- timer_auto_reload_shadow_enable(TIMER0);
- timer_primary_output_config(TIMER0, ENABLE);
- }
- /*!
- \brief ADC configuration function
- \param[in] none
- \param[out] none
- \retval none
- */
- void adc_config(void)
- {
- /* ADC channel length config */
- adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
- /* ADC regular channel config */
- adc_regular_channel_config(0, ADC_CHANNEL_2, ADC_SAMPLETIME_55POINT5);
- /* ADC external trigger enable */
- adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
- /* ADC external trigger source config */
- adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0);
- /* ADC data alignment config */
- adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
- /* enable ADC interface */
- adc_enable();
- /* ADC calibration and reset calibration */
- adc_calibration_enable();
- /* ADC DMA function enable */
- adc_dma_mode_enable();
- }
- void display_adc_value(void)
- {
- printf("\r\n%d\r\n",ad_value[0]);
- }
复制代码
ad转换我只用了第一个值,其实DMA传输会不停的循环传输。
主函数中这样用:- gd_eval_com_init(EVAL_COM1,115200);
- adc_rcu_config();
- adc_gpio_config();
- adc_dma_config();
- adc_timer_config();
- adc_config();
- /* TIMER0 counter enable for ADC */
- timer_enable(TIMER0);
- /* test on channel0 transfer complete flag */
- while( !dma_flag_get(DMA_CH0, DMA_FLAG_FTF));
- display_adc_value();
复制代码 然后在while(1) 中执行display_adc_value(); 就能把值实时打印到串口。
DMA配置完会不断循环写入到buffer中,配置完成后CPU不需要参与,我们在循环中,可以直接读取AD值,这些值在配置DMA时是循环覆盖写入的。
printf是采用串口显示,
具体方法如下,在keil的魔术棒option里,Target中,勾选Use MicroLIB, 然后添加如下子程序,重新映射串口,- /* retarget the C library printf function to the USART */
- int fputc(int ch, FILE *f)
- {
- usart_data_transmit(EVAL_COM1, (uint8_t)ch);
- while(RESET == usart_flag_get(EVAL_COM1, USART_FLAG_TBE));
- return ch;
- }
复制代码
关于串口初始化:gd_eval_com_init(EVAL_COM1,115200);
其是在gd32e231c_start.c、gd32e231c_start.h中定义的:
gd32e231c_start.h- //-----------------added by user--------------------------//
- /* eval board low layer COM */
- #define COMn 1U //定义数组大小
- /* definition for COM0,connected to USART0 */
- #define EVAL_COM1 USART0
- #define EVAL_COM1_CLK RCU_USART0
- #define EVAL_COM1_TX_PIN GPIO_PIN_9
- #define EVAL_COM1_RX_PIN GPIO_PIN_10
- #define EVAL_COM_GPIO_PORT GPIOA
- #define EVAL_COM_GPIO_CLK RCU_GPIOA
- #define EVAL_COM_AF GPIO_AF_1
- /* configure COM port */
- void gd_eval_com_init(uint32_t com, uint32_t baud);
复制代码
gd32e231c_start.c- static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM1_CLK};
- static uint32_t COM_TX_PIN[COMn] = {EVAL_COM1_TX_PIN};
- static uint32_t COM_RX_PIN[COMn] = {EVAL_COM1_RX_PIN};
复制代码
- void gd_eval_com_init(uint32_t com, uint32_t baud)
- {
- uint32_t COM_ID;
-
- if(EVAL_COM1 == com){
- COM_ID = 0U;
- }else{
- }
- /* enable COM GPIO clock */
- rcu_periph_clock_enable(EVAL_COM_GPIO_CLK);
- /* enable USART clock */
- rcu_periph_clock_enable(COM_CLK[COM_ID]);
- /* connect port to USARTx_Tx */
- gpio_af_set(EVAL_COM_GPIO_PORT, EVAL_COM_AF, 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);
- }
复制代码
注意串口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。
-------------------------------------------
|