|
[GD32E231 DIY大赛] 06. 自动喂鱼机器人之ADC/DMA/TIMER0/串口篇
[复制链接]
[GD32E231 DIY大赛] 06. 自动喂鱼机器人之ADC/DMA/TIMER0/串口篇
这里用到了光敏电阻来监测鱼缸周围的光照度。
从内部ADC采集,定时器0的比较事件0触发ADC转换,ADC转换的结果将随着模拟值输入的改变而改变。
转换结果由DMA 搬运到SRAM 中,最后判断AD的值是否大于一定数值。
具体程序如下:
首先涉及以下函数和变量:
- __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 */
- rcu_periph_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_RDATA);
- 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 */
- dma_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。
-------------------------------------------
|
赞赏
-
1
查看全部赞赏
-
|