• GD32学习2——流水灯


    开发环境

    MDK:keil 5.37

    MCU: GD32F450IK

    2.1GPIO工作原理

    要想实现流水灯,首先必须了解GPIO的工作原理。

    2.1.1 GPIO的基本结构如下图所示。

    2.1.2 GD32 的 I/O 口可以由32位控制寄存器(GPIOx_CTL)配置为GPIO输入,GPIO输出,AF功能,模拟模式

    当端口配置为输出 时,可以通过 GPIO 输出模式寄存器 (GPIOx_OMODE)配置为推挽或开漏模式。
    输出端口的最大速度可以通过 GPIO 输出速度寄存 器 (GPIOx_OSPD) 配置。
    每个端口可以通过 GPIO / 下拉寄存器 (GPIOx_PUD) 配置为浮空 (无上拉或下拉 ) ,上拉或下拉功能。
    分类CTLyOMyPUDy
    GPIO输入X浮空00X00
    上拉01
    下拉10
    GPIO输出推挽浮空01000
    上拉01
    下拉10
    开漏浮空100
    上拉01
    下拉10
    AFIO输入X浮空10X00
    上拉01
    下拉10
    AFIO输出推挽浮空000
    上拉01
    下拉10
    开漏浮空100
    上拉01
    下拉10
    模拟XX11XXX

     输入模式


     浮空输入:浮空(floating)就是逻辑器件的输入引脚即不接高电平,也不接低电平。由于逻辑器件的内部结构,当它输入引脚悬空时,相当于该引脚接了高电平。一般实际运用时,引脚不建议悬空,易受干扰。 通俗讲就是让管脚什么都不接,浮空着。信号进入芯片内部后,既没有接上拉电阻也没有接下拉电阻,经由触发器输入。配置成这个模式后,用电压变量引脚电压为1点几伏,这是个不确定值。由于其输入阻抗比较大,一般把这种模式用于标准的通讯协议,比如IIC、USART的等。该模式是GD32复位之后的默认模式。

    在这里插入图片描述

     上拉输入:上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻嵌位在高电平,电阻同时起限流作用,弱强只是上拉电阻的阻值不同,没有什么严格区分。上拉输入就是信号进入芯片后加了一个上拉电阻,再经过施密特触发器转换成0、1信号,读取此时的引脚电平为高电平;

    在这里插入图片描述

     下拉输入:就是把电压拉低,拉到GND。与上拉原理相似。下拉输入就是信号进入芯片后加了一个下拉电阻,再经过施密特触发器转换成0、1信号,读取此时的引脚电平为低电平;

    在这里插入图片描述

     模拟输入:信号进入后不经过上拉电阻或者下拉电阻,关闭施密特触发器,经由另一线路把电压信号传送到片上外设模块。模拟输入是指传统方式的输入,数字输入是输入PCM数字信号,即0、1的二进制数字信号,通过数模转换,转换成模拟信号,经前级放大进入功率放大器,功率放大器还是模拟的。比如传送给ADC模块,由ADC采集电压信号。所以可以理解为模拟输入的信号是未经处理的信号,是原汁原味的信号。

    在这里插入图片描述

     输出模式

     开漏输出:一般用在电平不匹配的场合,如需要输出5V的高电平。输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行。适合于做电流型的驱动,其吸收电流的能力相对强(一般20mA以内)。

    在这里插入图片描述

     

     复用开漏输出:可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)。端口必须配置成复用开漏功能输出模式。

    在这里插入图片描述

     

     推挽式输出:可以输出高、低电平,连接数字器件;推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由IC的电源决定。推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。

    在这里插入图片描述

     

     推挽式复用输出

    在这里插入图片描述

     

     备用功能(AF)——为了适应不同的器件封装,GPIO 端口支持软件配置将一些备用功能应用到其他引脚上。

     

    2.2 I/O复用和重映射

    2.2.1 I/O复用

    GD32 有很多的内置外设,这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。当I/O端口被配置为复用功能时:

    2.3 GPIO流水灯硬件电路分析

    发光二极管是属于二极管的一种,具有二级管单向导电特性,即只有在正向电压(二极管的正极接正,负极接负)下才能导通发光。PF6引脚接发光二极管(LED1)的正极,所以PF6引脚输出高电平LED1亮,PF6引脚输出低电平LED1熄灭,其他LED同理。

     

    2.4 GPIO流水灯寄存器分析

    要想真正掌握一款单片机,分析寄存器是必不可少,但是对于GD32来再说,GD已经将寄存器操作封装成库函数,开发者只需要调用库函数即可.

    每个GPIO端口都有两个32位配置寄存器(GPIO_CTL0 ,GPIO_CTL1) ,两个16位数据寄存器 (GPIO_ISTAT和GPIO_OCTL),一个32位置位寄存器(GPIO_BOP),一个16位复位寄存器(GPIO_BC),一个16位锁定寄存器(GPIO_LOCK)。每个I/O端口位可以自由编程。

    点亮LED,基本步骤是:配置寄存器;控制寄存器。库开发只是将传统的配置方式编程函数,使单片机开发变得简单方便快捷。

    2.5 GPIO 流水灯实现流程

    在上文已经分析了GPIO的原理及操作步骤,现在我们就来写代码吧。

    GPIO是开发GD32最基本的配置,所以掌握GPIO的配置显得尤为重要。要实现流水灯,一般步骤可以总结为如下:

    1)GPIO 时钟使能;
    2)GPIO 端口模式设置;
    3)初始化IO口;
    4)编写处理函数;

    2.6 GPIO 流水灯实现

    2.6.1 GPIO库函数

    GPIO库函数相关的库函数如下:
     gpio_deinit 复位外设GPIO
     gpio_afio_deinit 复位AFIO
     gpio_init GPIO参数初始化
     gpio_bit_set 置位引脚值
     gpio_bit_reset 复位引脚值
     gpio_bit_write 将特定的值写入引脚
     gpio_port_write 将特定的值写入一组端口
     gpio_input_bit_get 获取引脚的输入值
     gpio_input_port_get 获取一组端口的输入值
     gpio_output_bit_get 获取引脚的输出值
     gpio_output_port_get 获取一组端口的输出值
     gpio_pin_remap_config 配置GPIO引脚重映射
     gpio_pin_remap1_config 配置GPIO引脚重映射1
     gpio_exti_source_select 选择哪个引脚作为EXTI源
     gpio_ethernet_phy_select 以太网MII或RMII PHY选择
     gpio_event_output_config 配置事件输出
     gpio_event_output_enable 事件输出使能
     gpio_event_output_disable 事件输出禁能
     gpio_pin_lock 相应的引脚配置被锁定

    2.6.2流水灯代码实现
    核心代码如下:

    1. #include "gd32f4xx.h"
    2. /*!
    3. \brief configure led GPIO
    4. \param[in] lednum: specify the Led to be configured
    5. \arg LED1
    6. \arg LED2
    7. \arg LED3
    8. \param[out] none
    9. \retval none
    10. */
    11. void gd_eval_led_init (led_typedef_enum lednum)
    12. {
    13. /* enable the led clock */
    14. rcu_periph_clock_enable(GPIO_CLK[lednum]);
    15. /* configure led GPIO port */
    16. gpio_mode_set(GPIO_PORT[lednum], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,GPIO_PIN[lednum]);
    17. gpio_output_options_set(GPIO_PORT[lednum], GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]);
    18. GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
    19. }
    20. /*!
    21. \brief configure systick
    22. \param[in] none
    23. \param[out] none
    24. \retval none
    25. */
    26. void systick_config(void)
    27. {
    28. /* setup systick timer for 1000Hz interrupts */
    29. if (SysTick_Config(SystemCoreClock / 1000U)){
    30. /* capture error */
    31. while (1){
    32. }
    33. }
    34. /* configure the systick handler priority */
    35. NVIC_SetPriority(SysTick_IRQn, 0x00U);
    36. }
    37. /*!
    38. \brief turn on selected led
    39. \param[in] lednum: specify the Led to be turned on
    40. \arg LED1
    41. \arg LED2
    42. \arg LED3
    43. \param[out] none
    44. \retval none
    45. */
    46. void gd_eval_led_on(led_typedef_enum lednum)
    47. {
    48. GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
    49. }
    50. /*!
    51. \brief turn off selected led
    52. \param[in] lednum: specify the Led to be turned off
    53. \arg LED1
    54. \arg LED2
    55. \arg LED3
    56. \param[out] none
    57. \retval none
    58. */
    59. void gd_eval_led_off(led_typedef_enum lednum)
    60. {
    61. GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
    62. }
    63. /*!
    64. \brief delay a time in milliseconds
    65. \param[in] count: count in milliseconds
    66. \param[out] none
    67. \retval none
    68. */
    69. void delay_1ms(uint32_t count)
    70. {
    71. delay = count;
    72. while(0U != delay){
    73. }
    74. }
    75. int main(void)
    76. {
    77. gd_eval_led_init(LED1);
    78. gd_eval_led_init(LED2);
    79. gd_eval_led_init(LED3);
    80. systick_config();
    81. while(1){
    82. /* turn on LED1 */
    83. gd_eval_led_on(LED1);
    84. /* insert 200 ms delay */
    85. delay_1ms(200);
    86. /* turn on LED2 */
    87. gd_eval_led_on(LED2);
    88. /* insert 200 ms delay */
    89. delay_1ms(200);
    90. /* turn on LED3 */
    91. gd_eval_led_on(LED3);
    92. /* insert 200 ms delay */
    93. delay_1ms(200);
    94. /* turn off LEDs */
    95. gd_eval_led_off(LED1);
    96. gd_eval_led_off(LED2);
    97. gd_eval_led_off(LED3);
    98. /* insert 200 ms delay */
    99. delay_1ms(200);
    100. }
    101. }


     


     

  • 相关阅读:
    springboot+vue学生综合测评系统(java项目源码+文档)
    Spring Cloud微服务:Loadbalancer 实战
    TCP的管理机制(3)
    Tomcat多实例部署
    Python面向对象特性——多继承(概念、语法、代码演练、使用注意事项)
    STM32的hex文件格式的分析
    记一次 .NET 某工控软件 内存泄露分析
    唧唧down怎么下载安装-唧唧down使用操作内容讲解
    一款好的软件,软件测试必不可少...
    Elasticsearch 面试题
  • 原文地址:https://blog.csdn.net/weixin_42849105/article/details/126008769