泰凌微TLSR825X开发二 GPIO常用配置与中断休眠唤醒

前言

TLSR825X系列的IO配置与常用MCU相差无几,应用到低功耗设计的话差异比较大,825X系列的停止模式下功耗相对较高(suspend模式),要做到较低功耗需要类似于ST单片机进入待机Standby模式(deepsleep模式),仅通过wakeup引脚或时钟来唤醒,唤醒后系统重新通过启动文件来跳转到main入口
本章讲下GPIO的常用配置与IO中断、IO唤醒功能,如有异议,欢迎留言指正

功能简介

  • 8258系列共有5组36个GPIO,PA0-PA7、PB0-PB7、PC0-PC7、PD0-PD7、PE0-PE3
  • PA0~PD7可以用作通用IO口,其中上下拉寄存器为模拟寄存器控制,该寄存器可以在deepsleep模式中保持
  • PA7默认用作SWS功能(调试下载),必须内部上拉
  • PE0~PE3被用于内部flash的SPI读写通信引脚,用户不允许使用
  • PA5~PA6可复用DM和DP用作USB功能

不同的型号封装和IO管脚不同,以实际型号为准
具体引脚复用表可查看数据手册第7章7.1GPIO章节

在这里插入图片描述

寄存器配置

寄存器

  • GPIO寄存器偏移地址为0x580~0x59c,对应PA0~PE3中的输入、输出、上下拉、强弱输出、中断等配置
#define reg_gpio_pa_in			 REG_ADDR8(0x580)
#define reg_gpio_pa_ie			 REG_ADDR8(0x581)
#define reg_gpio_pa_oen			 REG_ADDR8(0x582)
#define reg_gpio_pa_out			 REG_ADDR8(0x583)
#define reg_gpio_pa_pol			 REG_ADDR8(0x584)
#define reg_gpio_pa_ds			 REG_ADDR8(0x585)
#define reg_gpio_pa_gpio		 REG_ADDR8(0x586)
#define reg_gpio_pa_irq_en		 REG_ADDR8(0x587)
- - - - - - - - - 

常用接口

  • 功能配置:主要是配置成普通IO还是复用高级功能(uart、spi、iic等)
void gpio_set_func(GPIO_PinTypeDef pin, GPIO_FuncTypeDef func);
  • 输入使能
void gpio_set_input_en(GPIO_PinTypeDef pin, unsigned int value);
  • 读取管脚电平
 unsigned int gpio_read(GPIO_PinTypeDef pin);
  • 输出使能
int gpio_is_output_en(GPIO_PinTypeDef pin);
  • 设置管脚输出电平
void gpio_write(GPIO_PinTypeDef pin, unsigned int value)
  • 设置上下拉
void gpio_setup_up_down_resistor(GPIO_PinTypeDef gpio, GPIO_PullTypeDef up_down)
输出实例
gpio_set_func(GPIO_PA4, AS_GPIO); // 数字gpio
gpio_set_output_en(GPIO_PA4, 1);//使能输出
gpio_set_input_en(GPIO_PA4, 0); //禁用输入
gpio_write(GPIO_PA4, 0); //输出低
gpio_write(GPIO_PA4, 1); //输出高
输入实例
gpio_set_func(GPIO_PA4, AS_GPIO); // 数字gpio
gpio_set_output_en(GPIO_PA4, 0);//禁用输出
gpio_set_input_en(GPIO_PA4, 1); //使能输入
gpio_setup_up_down_resistor(GPIO_PA4, PM_PIN_PULLUP_10K);  //上拉10K
if(gpio_read(GPIO_PA4)){ //读取电平 H
    ;
}else{//L
    ;
}

IO中断

中断响应会映射到统一入口,通过中断标志来判断是哪个中断源;
IO中断源获取到后,如果单组中断源存在多个IO使能的中断,可以进一步判断IO电平来决定是哪个IO触发了中断

  • IO中断最大支持三组,分别对应IRQ_GPIOIRQ_GPIO_RISC0IRQ_GPIO_RISC1,实际需要根据应用来合理分配,建议一组设置一个IO中断(相互独立),如果同组使能多个GPIO需要在入口中断中进行判断

代码实例

  • 参考app_gpio_irq.c的例程代码,分别配置了三组独立的GPIO中断
#define GPIO_TEST_PIN1				GPIO_PD0
#define GPIO_TEST_PIN2				GPIO_PD1
#define GPIO_TEST_PIN3				GPIO_PD2
void app_gpio_irq_test_init(void)
{
    //IRQ_GPIO  下降沿触发
    /***step1. 配置为输入*/
    gpio_set_func(GPIO_TEST_PIN1, AS_GPIO);           //enable GPIO func
    gpio_set_input_en(GPIO_TEST_PIN1, 1);             //enable input
    gpio_set_output_en(GPIO_TEST_PIN1, 0);            //disable output
    /***step2.      上拉 下降沿中断 ***/
    gpio_setup_up_down_resistor(GPIO_TEST_PIN1, PM_PIN_PULLUP_10K);  //上拉10K open pull up resistor
    gpio_set_interrupt_pol(GPIO_TEST_PIN1, pol_falling);    //下降沿 falling edge
    /***step3.     设置IRQ中断  ***/
    reg_irq_src = FLD_IRQ_GPIO_EN; //清中断标志
    reg_irq_mask |= FLD_IRQ_GPIO_EN;//使能irq中断
    gpio_en_interrupt(GPIO_TEST_PIN1, 1);
     
    //IRQ_GPIO_RISC0 下降沿触发
    /***step1. 配置为输入********/
    gpio_set_func(GPIO_TEST_PIN2, AS_GPIO);           //enable GPIO func
    gpio_set_input_en(GPIO_TEST_PIN2, 1);             //enable input
    gpio_set_output_en(GPIO_TEST_PIN2, 0);            //disable output  
      /***step2.      上拉 下降沿中断 ***/
    gpio_setup_up_down_resistor(GPIO_TEST_PIN2, PM_PIN_PULLUP_10K);  //上拉10K open pull up resistor
    gpio_set_interrupt_pol(GPIO_TEST_PIN2, pol_falling);    //下降沿 falling edge
    /***step3.     设置IRQ中断  ***/
    reg_irq_src = FLD_IRQ_GPIO_RISC0_EN; //清中断标志
    reg_irq_mask |= FLD_IRQ_GPIO_RISC0_EN;//使能irq_risc0中断
    gpio_en_interrupt_risc0(GPIO_TEST_PIN2, 1);
    
    //IRQ_GPIO_RISC1 上升沿触发
      /***step1. 配置为输入********/
    gpio_set_func(GPIO_TEST_PIN3, AS_GPIO);           //enable GPIO func
    gpio_set_input_en(GPIO_TEST_PIN3, 1);             //enable input
    gpio_set_output_en(GPIO_TEST_PIN3, 0);            //disable output
    /***step2.      set the polarity and open pullup ***/
    gpio_setup_up_down_resistor(GPIO_TEST_PIN3, PM_PIN_PULLDOWN_100K);  //下拉100K open pull down resistor
    gpio_set_interrupt_pol(GPIO_TEST_PIN3, pol_rising); //上升沿 rising edge
    //***step3.     设置IRQ中断  ***/
    reg_irq_src = FLD_IRQ_GPIO_RISC1_EN; //清中断标志
    reg_irq_mask |= FLD_IRQ_GPIO_RISC1_EN;//使能irq_risc1中断
    gpio_en_interrupt_risc1(GPIO_TEST_PIN3, 1);
    irq_enable();  //开启总中断
}
  • 函数irq_handler为中断入口,通过判断中断标志来进行相对应处理
//所有中断入口
_attribute_ram_code_ void irq_handler(void)
{
    irq_blt_sdk_handler (); //ble中断处理

    /************ test1 irq  ***************/
    if(reg_irq_src & FLD_IRQ_GPIO_EN)
    {
        reg_irq_src = FLD_IRQ_GPIO_EN;        // clear irq_gpio irq flag
        printf("test1 irq !\n");
    }
    
    /************* test2 irq risc0 *************/
    if(reg_irq_src & FLD_IRQ_GPIO_RISC0_EN)
    {
        reg_irq_src = FLD_IRQ_GPIO_RISC0_EN;        // clear irq_gpio irq flag
        printf("test2 irq risc0 !\n");
    }

    /************* test3 irq risc1 *************/
    if(reg_irq_src & FLD_IRQ_GPIO_RISC1_EN)
    {
        reg_irq_src = FLD_IRQ_GPIO_RISC1_EN;        // clear irq_gpio irq flag
        printf("test3 irq risc1!\n");
    }
}

IO唤醒

系统休眠状态下是无法直接通过IO中断唤醒的,唤醒机制仅支持Timer与PAD;休眠前可通过配置使能PAD的唤醒电平来触发

代码实例

参考test_low_power.c文件代码,实际开发可同时使能多个IO进行指定的电平唤醒;

DEEPSLEEP模式
  • 调用cpu_sleep_wakeup进入深度休眠后,管脚PB6产生低电平脉冲系统会立即重启
    gpio_setup_up_down_resistor(GPIO_PB6, PM_PIN_PULLUP_10K); //上拉10K
    cpu_set_gpio_wakeup(GPIO_PB6, Level_Low,1); //低电平唤醒
    while(1)
    {
        cpu_sleep_wakeup(DEEPSLEEP_MODE, PM_WAKEUP_PAD, 0);  //进入deepsleep,开启PAD唤醒
    }
SUSPEND模式
  • 调用cpu_sleep_wakeup进入停止模式后,管脚PB6产生低电平脉,系统唤醒并执行打印
    gpio_setup_up_down_resistor(GPIO_PB6, PM_PIN_PULLUP_10K); //上拉10K
    cpu_set_gpio_wakeup(GPIO_PB6, Level_Low,1); //低电平唤醒
    while(1)
    {
        cpu_sleep_wakeup(SUSPEND_MODE, PM_WAKEUP_PAD, 0);  //进入suspend,开启PAD唤醒
        printf("suspend mode wakeup\n");
        break;
    }

IO唤醒常见问题

  • 休眠前如果唤醒管脚电平处于有效状态,调用cpu_sleep_wakeup进入DEEPSLEEP_MODE会立即重启; 而配置进入SUSPEND_MODEDEEPSLEEP_RETENTION_MODE并立即返回错误结果状态
  • deepsleep深度休眠模式下为了保持IO的输出能力,需要通过上下拉来实现,但是上拉1M的电平会比VCC(3.3V)略低,建议配置为10K
  • 上拉10K的控制中不要使用PC0~PC7,在deepsleep retention wakeup时会有短时间的抖动,产生毛刺

版权声明:本文为CSDN博主「玉怀一捧雪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/libin55/article/details/118675870

生成海报
点赞 0

玉怀一捧雪

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

RT-Thread Studio移植LAN8720A驱动

RTT网络协议栈驱动移植(霸天虎) 1、新建工程 ​ 工程路径不含中文路径名,工程名用纯英文不含任何符号。 2、用CubeMx配置板子外设 2.1、配置时钟 ​ 按照自己板子配置相应时钟。

ESP8266 无限重启踩坑

最近做了一个电子墨水屏万年历,在移植屏幕代码时遇到了esp8266无限软复位的问题,如果你的串口打印是以下图片所示,那么恭喜你问题解决了。 造成软复位的原因是因为,程序里有死循环&#xf

Renode应用:在RISC-V核上运行FreeRTOS

本篇记录通过Renode在RISC-V核上运行FreeRTOS demo的情况。本来不准备写这一篇,但是发现近期工作学习密度实在太大,上周工作的中间结果这周竟然完全想不起来了,不得不又花了一些时间从头摸

Lin总线通信在STM32作为主机代码以及从机程序

距离上次做资料准备已经过去六天了。最近在学车,上周末就没有开电脑。这周开始进行了Lin通信的代码整理,目前是可以正常通信的了,采用的是增强型校验方式。后期再进一步跟进研究。。。更新一博,留