• GPIO与外部中断


    今天看了看RT1052的GPIO,感觉这玩意比STM32复杂多了,今天我们来尝试了解一下它先从LED点灯开始。

    <ignore_js_op>

    <ignore_js_op>


    可以看出飞凌底板上的LED是连接的GPIO1_IO02脚。 首先放出例程的配置方式(删除了注释)

      IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09,  0U);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09,  0x10B0u);                              

    其中
    #define IOMUXC_GPIO_AD_B0_09_GPIO1_IO09
     0x401F80E0U0x5U, 0, 0, 0x401F82D0U

    这红色的字体就是这次配置的关键了。首先看IOMUXC_SetPinMux函数
    static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
                                        uint32_t muxMode,
                                        uint32_t inputRegister,
                                        uint32_t inputDaisy,
                                        uint32_t configRegister,
                                        uint32_t inputOnfield)
    {
        *((volatile uint32_t *)muxRegister) =
            IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);

        if (inputRegister)
        {
            *((volatile uint32_t *)inputRegister) = inputDaisy;
        }
    }

    #define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_MASK      (0x7U)
    #define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_SHIFT     (0U)
    #define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(x)        (((uint32_t)(((uint32_t)(x)) << IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_SHIFT)) & IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_MASK)
    #define IOMUXC_SW_MUX_CTL_PAD_SION_MASK          (0x10U)
    #define IOMUXC_SW_MUX_CTL_PAD_SION_SHIFT         (4U)
    #define IOMUXC_SW_MUX_CTL_PAD_SION(x)            (((uint32_t)(((uint32_t)(x)) << IOMUXC_SW_MUX_CTL_PAD_SION_SHIFT)) & IOMUXC_SW_MUX_CTL_PAD_SION_MASK)
    可以看出,我们配置了0x401F80E0U的第0—2位为0x5U,第4位为0

    我们来看一下这个0x401F80E0U到底是个什么地址
    <ignore_js_op>
    可以看出来,第4位为0时可以设置功能复用,而0—2位设置的是功能复用,这里设置为GPIO1功能

    然后是IOMUXC_SetPinConfig函数
    static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
                                           uint32_t muxMode,
                                           uint32_t inputRegister,
                                           uint32_t inputDaisy,
                                           uint32_t configRegister,
                                           uint32_t configValue)
    {
        if (configRegister)
        {
            *((volatile uint32_t *)configRegister) = configValue;
        }
    }
    可以看出是配置0x401F82D0U0x10B0u
    我们来看一下0x401F82D0U是什么
    <ignore_js_op>
    <ignore_js_op>
    可以看出来这里是对引脚功能的设置,这里的0x10B0u就是设置为 转化速率慢,驱动强度为R0/6,速度100MHz,关闭开漏,开启拉/保持器,选择为保持,100K下拉(无用),关闭滞回。
    感觉写这么一个数不好理解,我改写了一下这个函数

    //转换速率       0 慢     1 快
    //驱动强度       0 无     1 R0     2 R0/2   3 R0/3    4 R0/4    5 R0/5    6 R0/6    7 R0/7
    //输出速度       0 50MHz  1 100MHz   2 100MHz   3 200MHz
    //开漏输出       0 关闭   1 开启
    //拉/保持器      0 关闭   1 开启
    //拉/保持器设置  0 保持    1 拉
    //上下拉电阻     0 100K下拉   1 47K上拉   2 100K上拉   3 22K上拉
    //滞回器设置     0 关闭       1开启
    IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, IOMUXC_SW_PAD_CTL_PAD_SRE(0)    //转换速率慢
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_DSE(6)    //驱动强度R0/6
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_SPEED(2)  //速度100MHz
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_ODE(0)    //关闭开漏
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_PKE(1)    //拉/保持器开启
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_PUE(0)    //选择为保持
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_PUS(0)    //100K下拉(没用到)
                                                                                            |IOMUXC_SW_PAD_CTL_PAD_HYS(0));  //关闭滞回
    感觉这样更容易理解,更容易操作一点。

    接下来就是配置GPIO了,下面只放出关键程序

    gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; //设为输出 默认输出0 无中断
    GPIO_PinInit(GPIO1, 2, &led_config);

    这两句很好理解,首先设置led_config

    typedef struct _gpio_pin_config
    {
        gpio_pin_direction_t direction;                 //设置输出方向
        uint8_t outputLogic;                               //设置初始电平
        gpio_interrupt_mode_t interruptMode;     //设置中断模式
    } gpio_pin_config_t;

    里面有这三个成员 取值如下

    typedef enum _gpio_pin_direction
    {
        kGPIO_DigitalInput = 0U,  //输入
        kGPIO_DigitalOutput = 1U, //输出
    } gpio_pin_direction_t;

    typedef enum _gpio_interrupt_mode
    {
        kGPIO_NoIntmode = 0U,                 //无中断
        kGPIO_IntLowLevel = 1U,                //低电平中断
        kGPIO_IntHighLevel = 2U,               //高电平中断
        kGPIO_IntRisingEdge = 3U,              //上升沿中断
        kGPIO_IntFallingEdge = 4U,             //下降沿中断
        kGPIO_IntRisingOrFallingEdge = 5U, //上升下降沿中断
    } gpio_interrupt_mode_t;

    就是把GPIO1_2配置为输出模式,默认输出1,无中断。(这里的寄存器也没啥好分析的,接下来就不讨论了寄存器了)

    GPIO_PinWrite(GPIO1, 2, 0U);//点亮LED
    delay(10);
    GPIO_PinWrite(GPIO1, 2, 1U);//熄灭LED
    delay(10);

    相当简单的程序 运行结果就是灯一闪一闪的,效果见视频附件

    接下来是GPIO输入 参考原理图



    <ignore_js_op>
    <ignore_js_op>

    嗯,这GPIO5_0就是我们要的。对他进行配置



    IOMUXC_SetPinMux(IOMUXC_SNVS_WAKEUP_GPIO5_IO00, 0U);         //复用为GPIO
    IOMUXC_SetPinConfig(IOMUXC_SNVS_WAKEUP_GPIO5_IO00,   IOMUXC_SW_PAD_CTL_PAD_SRE(0)    //转换速率慢
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_DSE(0)    //无驱动强度
    (没用到)
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_SPEED(2)  //速度100MHz
    (没用到)
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_ODE(0)    //关闭开漏(没用到)
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_PKE(1)    //拉/保持器开启
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_PUE(1)    //选择为拉
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_PUS(3)    //22K上拉
                                                                                              |IOMUXC_SW_PAD_CTL_PAD_HYS(0));  //关闭滞回

    这里我们把它设为了22K上拉(这里只能配置为,拉/保持器开启,选择为拉。具体原因应该是RT1052把使能上下拉设为了输入专用了。而输出使用的是配置开漏,和配置驱动能力)。下面是main里程序(省略很多)


    gpio_pin_config_t key_config = {kGPIO_DigitalInput, 0, kGPIO_NoIntmode};  //设为输入 默认输出0 无中断
    GPIO_PinInit(GPIO5, 0, &key_interrupt_config);
    while(1)
    {
            GPIO_PinWrite(GPIO1, 2, GPIO_PinReadPadStatus(GPIO5,0));
    }

    补充一句,如果设置为输入模式那么默认输出电平就不起作用
    这里的GPIO_PinReadPadStatus是一个读取引脚电平的函数,运行结果是按住按键灯亮,松开灭。


    接下来是配置外部中断。参考MIMXRT1052.h


    <ignore_js_op>

    可以发现包含GPIO5_0的中断是GPIO5_Combined_0_15_IRQn,中断回调函数是GPIO5_Combined_0_15_IRQHandler(MIMXRT1052.s有定义)
    还是和刚才一样配置引脚模式,下面是main里程序(省略很多)

            gpio_pin_config_t key_interrupt_config = {kGPIO_DigitalInput, 1, kGPIO_IntFallingEdge};  //设为输入 默认输出0 下降沿中断

            EnableIRQ(GPIO5_Combined_0_15_IRQn);//使能中断
            GPIO_PinInit(GPIO5, 0, &key_interrupt_config);
            GPIO_PortEnableInterrupts(GPIO5, 1U << 0); //使能特定引脚中断

    中断回调函数

    void GPIO5_Combined_0_15_IRQHandler(void)
    {
            delay(1);          //消除抖动
        if(GPIO_PinReadPadStatus(GPIO5, 0) == 0)  //二次判断
                    GPIO_PortToggle(GPIO1,1<<2);      //灯取反
            GPIO_PortClearInterruptFlags(GPIO5, 1 << 0);  //清除中断标志位
        __DSB();
    }


    这里的代码和普通的代码差不多,就不分析了。
    比较有意思的是这个__DSB();它的作用是只有CPU把这句话之前的代码全部执行完毕后才能继续向下执行。
    最后的效果是按下按键后灯转换状态补充一点如果不需要go to什么的,可以把output里的两个输出去掉,大大加快了编译速度
    <ignore_js_op>
    最后不得不吐槽一句底板的绿灯有点太亮了。。。。。晚上拍的视频看着特别显眼。
  • 相关阅读:
    python框架之Django(2)-简单的CRUD
    python框架之Django(1)-第一个Django项目
    实习进度13
    实习进度12
    实习进度11
    实习进度10
    学习进度08
    毕设进度07
    毕设进度06
    毕设进度05
  • 原文地址:https://www.cnblogs.com/zhugeanran/p/16101922.html
Copyright © 2020-2023  润新知