SYD8821 GPIO模块使用说明

SYD8821是具有全球领先低功耗(RX 2.4mA @-94.5dBm灵敏度,TX 4.3mA @0dBm输出功率)的蓝牙低功耗SOC芯片,在极低电流下实现了优异的射频性能,搭配176kB SRAM,512kB flash,非常适合中高阶可穿戴、智能家居、物联网等低功耗应用具体可咨询:http://www.syd-tek.com/

 

SYD8821 GPIO模块使用说明

手册中提及GPIO的相关功能如下:

6.9 GPIO
     SYD8821QN-GH offer 31 GPIOs. GPIO could be set with internal Pulled-up(GPIO0~GPIO23,GPIO25,GPIO31,GPIO34) or Pulled-Low
(GPIO26~GPIO29). Max driving current of each GPIO is 2mA.

   注意:这里GPIO26~GPIO29是下拉的.

   注意:gpio的GPIOINT_POL寄存器只是对中断有效,能够用来实现上升沿和下降沿中断,对于MCU读取电平状态是无效的,也就是说外部管脚是低电平,不管设不设置GPIOINT_POL寄存器,MCU读到的都是0.另外GPIOINT_POL设置为1的时候是下降沿中断,设置为0是上升沿中断。
     并且有GPIO的功能列表:

SYD8821 GPIO模块使用说明

在“\SYD8821\SYD8821_SDK\Documentation”的《SYD8821_EVB.pdf》原理图文件可以看到LED和KEY的相关电路如下:

SYD8821 GPIO模块使用说明

这里GPIO07~GPIO10作为控制LED的输出,GPIO04~GPIO06作为读取按键值得输入,其中GPIO06(key3)作为中断输入,剩下作为普通输入!

在程序中的《SYD8821_SDK\Source Code\Include\led_key.h》定义相应的LED和KEY管脚如下:

#define KEY1 GPIO_4
#define KEY2 GPIO_5
#define KEY3 GPIO_6


#define LED4 GPIO_7
#define LED5 GPIO_8
#define LED6 GPIO_9
#define LED7 GPIO_10

其中的GPIO_0~GPIO_31是在"ARMCM0.h"中定义的从0~31的枚举!

 

打开“\SYD8821_SDK\Source Code\SYD8821\gpio\Keil”目录下的《Module_samples.uvprojx》工程,可看到SYD8821的GPIO的主函数如下:

/*
GPIO例程main.c


作者:北京盛源达科技有限公司
日期:2018/3/8
*/
#include "ARMCM0.h"
#include "gpio.h"
#include "pad_mux_ctrl.h"
#include "delay.h"
#include "led_key.h"


int main()
{
__disable_irq();
//GPO
pad_mux_write(LED4, 0);
pad_mux_write(LED5, 0);
pad_mux_write(LED6, 0);
pad_mux_write(LED7, 0);
gpo_config(LED4,1);
gpo_config(LED5,1);
gpo_config(LED6,1);
  gpo_config(LED7,1);

//GPI
pad_mux_write(KEY1, 0);
pad_mux_write(KEY2, 0);
pad_mux_write(KEY3, 0);
gpi_config(KEY1, PULL_UP);
gpi_config(KEY2, PULL_UP);
gpi_config(KEY3, PULL_UP);

gpi_enable_int(KEY3, EDGE_TRIGGER, POL_FALLING_LOW);
gpi_irq_set_cb(key_handler);

__enable_irq();
while(1)
{
    gpo_toggle(LED4);
if(!gpi_get_val(KEY1)){
    gpo_toggle(LED5);
}
if(!gpi_get_val(KEY2)){
    gpo_toggle(LED6);
}
delay_ms(100);
}
}

    配置GPIO有三个步骤:

1.设置相应管脚(也称为pad_mux)为gpio的功能,函数为pad_mux_write

2.设置相应管脚的方向已经上拉功能等,如gpi_config和gp0_config函数

3.如果要使能某个管脚的中断功能还要调用管脚的中断使能函数,这里还要传入回调函数,比如gpi_enable_int和gpi_irq_set_cb函数

 

    这里一共涉及到GPIO的三个功能:GPIO的输出功能,GPIO的输入功能,GPIO的中断功能,下面将分三个部分来说明:

    GPIO的输出功能:

    首先设置管脚为GPIO功能,如pad_mux_write(LED4, 0);

    然后设置管脚的方向为输出,并且输出默认值为1,比如gpo_config(LED4,1);配置工作就完成了。

    这里在主循环中每100ms翻转一次LED4的状态,调用的是  gpo_toggle函数,如  gpo_toggle(LED4);

    GPIO的输入功能:

    gpio的输入功能的配置工作第一步是和gpio输出的配置工作一样的,唯一有差别的是第一位,比如:gpi_config(KEY1, PULL_UP);

    这里配置KEY1这个管脚为输入功能,并且带有上拉的功能。

    在主循环中通过判断按键是否被按下来翻转对应LED的变换,比如:

               if(!gpi_get_val(KEY1)){
    gpo_toggle(LED5);
}

    当发现KEY1被按下的时候就每隔100ms翻转LED5的状态,就可以看到按下KEY1,LED5就会闪烁!

    GPIO的中断功能:

    gpio的中断功能相对于gpio的输入又多了一步使能中断的操作,比如:gpi_enable_int(KEY3, EDGE_TRIGGER, POL_FALLING_LOW);

    这里设置KEY3的中断功能,其中第二个参数EDGE_TRIGGER代表该管脚的中断触发类型为边缘触发,第三个参数POL_FALLING_LOW代表设置改管脚的边沿触发类型为下降沿,因为管脚按下的时候是低电平。

    然后这里还要设置一个回调函数,以方便驱动程序调用应用层的钩子代码,比如:gpi_irq_set_cb(key_handler);

   其中key_handler就是用户设置的钩子函数。当外设模块检测到正确的中断条件的时候,就会触发gpio中断,然后MCU执行GPIO_IRQHandler函数,在该函数中将回调用户设置的回调函数。该函数可以通过读取相应管脚的状态来判断是哪个管脚发生了中断,以执行相应的代码,如下:

void key_handler(GPIO_BANK_TYPE type, uint32_t bitmask)
{
//    if(!gpi_get_val(KEY3))
//    {
// delay_ms(20);
// if(!gpi_get_val(KEY3)) gpo_toggle(LED7);
//    }

if(type==GPIO_BANK_0)  // GPIO  0 ~ 31
{
    if(bitmask==U32BIT(KEY3))
{
delay_ms(20);
if(!gpi_get_val(KEY3)) gpo_toggle(LED7);
}
}else{   // GPIO 32 ~ 38

}
}

    这里有两种方式来判断按下的是哪个按键,一种是直接读取相应的管脚状态,比如上面函数中被注释了的部分;另外一种办法就是使用驱动函数传回的参数来判断,请看上面的代码。

     注意:当使用中断功能的时候,在main函数里进入while(1)主循环之前必须开启M0内核的总中断开关,就是上面main函数代码中的:__enable_irq();

     最后总结一下gpio例程的测试现象:

1.LED4始终会以200的频率闪烁

2.按下key1,LED5会以200的频率闪烁

3.按下key2,LED6会以200的频率闪烁

4.按下key3,LED7会翻转一次状态

 

     这里上传本章节的测试源代码,该源代码属于SDK的“Source Code”子集(SDK介绍请看:http://blog.****.net/chengdong1314/article/details/79599299),打开相应的工程即可:https://download.****.net/download/chengdong1314/10293702