当前位置:首页 > 嵌入式 > 嵌入式云IOT技术圈
[导读]通过A64手册可以看出,共有两个普通gpio控制器……

微信公众号:morixinguan
关注可了解更多的教程。问题或建议,请公众号留言;
[如果你觉得Md2All对你有帮助,欢迎交流讨论]
如需本平台推广以及其它合作,请加微信:morixinguan

通过A64手册可以看出共有两个普通gpio控制器: 
 

gpio控制器是由厂商负责驱动好的,在设备树里关于gpio控制器的描述:

pio: pinctrl@01c20800 {
   compatible = "allwinner,sun50i-pinctrl";
   reg = <0x0 0x01c20800 0x0 0x400>;
   interrupts = <0 11 4>,
         <0 17 4>,
         <0 21 4>;
   device_type = "pio";
   clocks = <&clk_pio>;
   gpio-controller;
   interrupt-controller;
   #interrupt-cells = <2>;
   #size-cells = <0>;
   #gpio-cells = <6>;   

r_pio: pinctrl@01f02c00 {
   compatible = "allwinner,sun50i-r-pinctrl";
   reg = <0x0 0x01f02c00 0x0 0x400>;
   interrupts = <0 45 4>;
   clocks = <&clk_cpurpio>;
   device_type = "r_pio";

   gpio-controller;
   interrupt-controller;
   #interrupt-cells = <2>;
   #size-cells = <0>;
   #gpio-cells = <6>;

关于设备树设置GPIO的文档描述:

其中“ #gpio-cells = <6>”表示在设备树里描述使用一个gpio口需要提供6个指定的参数.
通过文档,可以得知6个参数的分别作用:
gpio = <&pio   1   1   1   1   1  0>;
    |      |    |   |   |   |   |  |-------------------表示有效电平
    |      |    |   |   |   |   |----------------------上下拉, 0关闭功能, 1上拉, 2下拉, 3保留
    |
      |    |   |   |   |-------------------------驱动力,电流等级(0 - 3),级别越高,输出电流越大
    |
      |    |   |   |----------------------------gpio功能类型,0输入, 1输出, 6和外部中断,7关闭功能(具体查手册)
    |      |    |   |------------------------------pin bank 内偏移(即组内第几个io口).
    |      |    |---------------------------------哪组gpio, PA(0),PB(1),PC(2),PD(3),PE(4),PF(5),PG(6),PH(7),PI(8),PJ(9),PK(10),PL(11)
    |
      |--------------------------------------指向哪个gpio控制器,  pio / r_pio(PL组)
    |
-----------------------------------------------------属性名字(随便命名)

那么在Linux驱动里如何获取设备树里设备节点的gpio口信息呢?

#include 

//只需一个函数即可
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
    int index, enum of_gpio_flags *flags)
;

//返回值为int类型的gpio口.
//np为设备或设备子节点对象, propname为指定的属性名字, index表示获取属性里的第几个值
// 其中flags一定得注意,按文档里的说明应就是一个int类型的值,但根本就不能为int参数(会导致kernel panic),
// 通过阅读内核里的代码得出, flags的参数应为struct gpio_config类型. 定义在下面文件:
"include/linux/sys_config.h"
struct gpio_config {
     u32 gpio;       /* gpio global index, must be unique */
     u32     mul_sel;    /* multi sel val: 0 - input, 1 - output... */
     u32     pull;       /* pull val: 0 - pull up/down disable, 1 - pull up... */
     u32     drv_level;  /* driver level val: 0 - level 0, 1 - level 1... */
     u32 data;       /* data val: 0 - low, 1 - high, only vaild when mul_sel is input/output */
 };

获取到int类型的gpio口后,就可以使用linux/gpio.h里的gpio口操作函数:

#include  //里面声明io口的操作函数

int gpio_request(unsigned gpio, const char *label);//每个io只能被请求一次,可防止多个驱动来控制同一个IO口
void gpio_free(unsigned gpio)//释放已请求的io口

int gpio_direction_input(unsigned gpio)//把指定的IO口作输入功能, gpio用于指定具体哪个io口
int gpio_direction_output(unsigned gpio, int value)//作输出功能,并根据value的值输出高低电平

int gpio_get_value(unsigned gpio)//获取指定IO口的电平
void gpio_set_value(unsigned gpio, int value)//设置IO口的电平为value(0/1)

int gpio_to_irq(unsigned gpio);  //根据io口,获取到它对应的中断号(io口大都有外部中断功能)

应用例子,如图板上有两个led,和一个蜂鸣器: 

设备树里添加对这两个LED和蜂鸣器的描述:

jkbuzzer {
   compatible = "jk,buzzer";
   gpios = <&pio 3 24 1 1 1 1>
 };

 jkleds {
   compatible = "jk,leds";
   gpios = <&r_pio 11 10 1 1 1 1><&r_pio 11 12 1 1 1 1>;
 };

在Linux驱动中编写蜂鸣器的测试代码 如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int myprobe(struct platform_device *pdev)
{
    struct device_node *nd = pdev->dev.of_node;
    int gpio;   
    struct gpio_config config;


    printk("gpio count:%d\n", of_gpio_named_count(nd, "gpios"));
    gpio = of_get_named_gpio_flags(nd, "gpios"0, (enum of_gpio_flags *)&config);
    if (!gpio_is_valid(gpio))
        printk("gpio isn't valid\n");
    if (gpio_request(gpio, pdev->name) < 0)
            printk("gpio request failed %d\n", gpio);

    gpio_direction_output(gpio, 1);
    msleep(3000);
    gpio_direction_input(gpio);
    gpio_free(gpio);
    return 0;
}

int myremove(struct platform_device *pdev)
{
    printk("in myremove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "jk,buzzer"},
    {},
};

struct platform_driver mydrv = {
    .probe = myprobe,
    .remove = myremove,

    .driver = {
        .owner = THIS_MODULE,
        .name = "mydrv" ,

        .of_match_table = ids,
    },
};

module_platform_driver(mydrv);
MODULE_LICENSE("GPL");

在Linux驱动中编写两个LED的驱动测试代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int myprobe(struct platform_device *pdev)
{
    struct device_node *nd = pdev->dev.of_node;
    int gpio, n, i; 
    struct gpio_config config;


    n = of_gpio_named_count(nd, "gpios");
    for (i = 0; i < n ; i++)
    {
        gpio = of_get_named_gpio_flags(nd, "gpios", i, (enum of_gpio_flags *)&config);
        if (!gpio_is_valid(gpio))
            printk("gpio isn't valid\n");
        if (gpio_request(gpio, pdev->name) < 0)
            printk("gpio request failed %d\n", gpio);

        gpio_direction_output(gpio, 1);
        msleep(3000);
        gpio_direction_input(gpio);
        gpio_free(gpio);
    }
    return 0;
}

int myremove(struct platform_device *pdev)
{
    printk("in myremove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "jk,leds"},
    {},
};

struct platform_driver mydrv = {
    .probe = myprobe,
    .remove = myremove,

    .driver = {
        .owner = THIS_MODULE,
        .name = "mydrv" ,

        .of_match_table = ids,
    },
};


免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭