mars4zhu · 2022年11月25日 · 广东

【GD32F427开发板试用】+ GD32F427V-START例程学习笔记

1. GD32F427V-START例程学习笔记

1.1. Demo-01\_GPIO-Running-LED

该例程实现对板载LED连接的IO引脚(PC6)设置高/低电平,实现LED的亮灭闪烁。

1.1.1. 打开项目

使用Keil打开项目文件,初次运行会提示未知设备GD32F427,可以在Keil的Pack Installer里安装对应的DFP文件包。(实际测试发现,不安装也能编译,但是下载算法需要将DFP包中的GD32F4xx\_3MB.FLM文件复制到Keil安装目录的ARMFlash下,这样才能顺利下载)

../_images/Demo-01_GPIO-Running-LED_project-files.png

1.1.2. 代码分析

分析main函数代码运行过程,首先设置systick,然后使能LED对应的GPIO的时钟,最后设置PC6为推挽输出,并初始化为低电平。

然后在无限循环中,每隔1000ms设置PC6引脚为高/底电平,实现LED的亮灭。

int main(void)
    {
        /* configure systick */
        systick_config();
    
        /* enable the LEDs GPIO clock */
        rcu_periph_clock_enable(RCU_GPIOC);
    
        /* configure LED2 GPIO port */
        gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
        gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
        /* reset LED2 GPIO pin */
        gpio_bit_reset(GPIOC, GPIO_PIN_6);
    
        while(1) {
            /* turn on LED2 */
            gpio_bit_set(GPIOC, GPIO_PIN_6);
            delay_1ms(1000);
    
            /* turn off LED2 */
            gpio_bit_reset(GPIOC, GPIO_PIN_6);
            delay_1ms(1000);
        }
    }

1.1.3. 运行效果

编译后,下载到开发板,运行效果如下:

../_images/Demo-01_GPIO-Running-LED_effect.gif

1.2. Demo-02\_GPIO-Key-polling-mode

1.2.1. 代码分析

本例程代码在前一个例程GPIO-Running-LED的基础上,

  1. 对连接在User Key按键上的IO引脚(PA0)设置为输入模式,
  2. 然后在无限循环中,检测该按键的电平,
  3. 当按键按下时,设置LED翻转,然后等待按键释放,如此循环往复。
 int main(void)
    {
        /* configure systick */
        systick_config();
    
        /* enable the LED2 clock */
        rcu_periph_clock_enable(RCU_GPIOC);
        /* configure LED2 GPIO port */
        gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
        gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    
        /* reset LED2 GPIO pin */
        gpio_bit_reset(GPIOC, GPIO_PIN_6);
    
        /* enable the User Key GPIO clock */
        rcu_periph_clock_enable(RCU_GPIOA);
    
        /* configure key pin as input */
        gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
    
        while(1) {
            /* check whether the key is pressed */
            if(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) {
                delay_1ms(100);
    
                /* check whether the key is pressed */
                if(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) {
                    gpio_bit_write(GPIOC, GPIO_PIN_6, (bit_status)(1 - gpio_input_bit_get(GPIOC, GPIO_PIN_6)));
                }
    
                while(RESET == gpio_input_bit_get(GPIOA, GPIO_PIN_0)) {
                }
            }
        }
    }

1.2.2. 运行效果

编译后,下载到开发板,运行效果如下:

../_images/Demo-02_GPIO-Key-Polling-mode_effect.gif

1.3. Demo-03\_EXTI-Key-Interrupt\_mode

本例程将按键设置为中断模式,并在中断响应函数中,闪烁LED。

1.3.1. 代码分析

1. main函数

  • 设置systick、LED的GPIO,同前;
  • PA0对应的GPIO的设置;
  • EXTI\_0对应的NVIC中断相关的设置
 int main(void)
         {
             /* configure systick */
             systick_config();
         
            /* enable the LEDs GPIO clock */
             rcu_periph_clock_enable(RCU_GPIOC);
         
             /* configure LED2 GPIO port */
            gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
             gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
             /* reset LED2 GPIO pin */
             gpio_bit_reset(GPIOC, GPIO_PIN_6);
         
             /* flash the LED for test */
             led_flash(1);
        
             /* enable the key clock */
             rcu_periph_clock_enable(RCU_GPIOA);
             rcu_periph_clock_enable(RCU_SYSCFG);
         
             /* configure key pin as input */
             gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
         
             /* enable and set key EXTI interrupt to the lowest priority */
             nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
         
             /* connect key EXTI line to key GPIO pin */
             syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN0);
         
             /* configure key EXTI line */
             exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
             exti_interrupt_flag_clear(EXTI_0);
         
             while(1) {
             }
        }

2. 在中断处理函数EXTI0\_IRQHandler中

  • 首先确认是EXTI\_0的中断标志,
  • 然后翻转PC6的电平,
  • 最后清除EXTI\_0的中断标志。
 void EXTI0_IRQHandler(void)
    {
         if(RESET != exti_interrupt_flag_get(EXTI_0)) {
            gpio_bit_toggle(GPIOC, GPIO_PIN_6);
             exti_interrupt_flag_clear(EXTI_0);
         }
     }

3. systick相关函数

  • 内核定时器的初始化配置函数systick\_config中,将其主频的1/1000,即每1ms中断一次,
  • 中断处理函数SysTick\_Handler中,调用delay\_decrement,
  • delay\_decremen函数中,变量delay,果非零则减1,从而实现精确的毫秒定时。
    void systick_config(void)
     {
         /* setup systick timer for 1000Hz interrupts */
         if(SysTick_Config(SystemCoreClock / 1000U)) {
             /* capture error */
             while(1) {
             }
         }
         /* configure the systick handler priority */
         NVIC_SetPriority(SysTick_IRQn, 0x00U);
      }
     
     void SysTick_Handler(void)
     {
         delay_decrement();
     }
     
     void delay_decrement(void)
     {
         if(0U != delay) {
             delay--;
         }
     }

1.3.2. 运行效果

编译后,下载到开发板,运行效果同Demo-02,不再重复。

1.4. Demo-04\_Timer-Key-EXTI

本例程在前一个例程的基础上,添加了Timer输出到PA6,然后PA6通过杜邦线连接到PA4,PA4也跟PA0同样设置为EXTI中断,在中断响应函数中闪烁LED.

1.4.1. 代码分析

1. main函数

  • main函数完成key、led、systick等设置同前。
  • 然后闪烁一次LED;
  • 分别调用exti、gpio、timer的设置函数。
  • 进入无限循环。
    int main(void)
     {
         /* initialize KEY and LED, configure SysTick */
         gd_eval_key_init(KEY_USER, KEY_MODE_EXTI);
         led_config();
         systick_config();
     
         /* flash the LED for test */
         led_flash(1);
     
         /* configure EXTI, TIMER */
         exti_config();
         gpio_config();
         timer_config();
     
         while(1){
         }
     }

2.PA6设置为TIMER2\_CH0的输出

void gpio_config(void)
   {
         rcu_periph_clock_enable(RCU_GPIOA);
     
         /*Configure PA6(TIMER2_CH0) as alternate function*/
        gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);        gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
    
         gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_6);
     }
  1. PA4设置为EXTI\_4,并在中断响应函数EXTI4\_IRQHandler中翻转LED。
  void exti_config(void)
     {
         /* enable the clock */
         rcu_periph_clock_enable(RCU_GPIOA);
     
         /* enable and set EXTI interrupt */
         nvic_irq_enable(EXTI4_IRQn, 1U, 0U);
     
         /* configure EXTI line */
         exti_init(EXTI_4, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
          exti_interrupt_flag_clear(EXTI_4);
     }
      
     void EXTI4_IRQHandler(void)
     {
         if(RESET != exti_interrupt_flag_get(EXTI_4)){
             gd_eval_led_toggle(LED2);
         }
     
         exti_interrupt_flag_clear(EXTI_4);
     }
  1. Timer2设置为时钟100KHz,计数到25000/50000,在CH0分别输出高低电平。
    void timer_config(void)
     {
         /* -----------------------------------------------------------------------
         TIMER2CLK is 100KHz
         TIMER2 channel0 duty cycle = (25000/ 50000)* 100  = 50%
         ----------------------------------------------------------------------- */
         timer_oc_parameter_struct timer_ocintpara;
         timer_parameter_struct timer_initpara;
     
          rcu_periph_clock_enable(RCU_TIMER2);
     
         timer_deinit(TIMER2);
         /* TIMER configuration */
         timer_initpara.prescaler         = 999;
         timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
         timer_initpara.counterdirection  = TIMER_COUNTER_UP;
         timer_initpara.period            = 49999;
         timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
         timer_initpara.repetitioncounter = 0;
         timer_init(TIMER2,&timer_initpara);
     
         /* configurate CH0 in PWM mode0 */
         timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
         timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
        timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara);
     
         timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 24999);
         timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0);
         timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
     
         /* auto-reload preload enable */
         timer_auto_reload_shadow_enable(TIMER2);
         /* auto-reload preload enable */
         timer_enable(TIMER2);
     }

1.4.2. 运行效果

将PA6通过杜邦线连接到PA4,并接上示波器观察Timer2\_CH0输出波形,如下:

../_images/Demo-04_Timer-Key-EXTI_effect.gif

1.5. Demo-05\_USB-MSC-Device

本例程实现一个USB大容量存储设备,使用MCU的USB-FS或者USB-HS模块作为USB接口,实现标准的MSC类,使用内部RAM作为存储空间,可以在PC上对存储空间进行格式化、文件读写等操作。

在编译时会出现“cannot find cortex-m4f.h”错误,原因在于CMSIS没有自动包含在编译头文件目录中,在Keil的options选项卡设置,如图:

../_images/usb-msc-udisk_options-include-path_cmsis.png

1.5.1. 运行效果

用另一个USB线连接USB-FS/USB-HS对应的USB接口到PC,就可以弹出新移动存储设备的窗口,格式化后,文件的复制、读写、删除等操作,与普通U盘一致。

../_images/usb-msc-udisk_format.png ../_images/usb-msc-udisk_file-save.png

推荐阅读
关注数
10708
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息