针对RT_Thread中rt_pin_mode()函数的分析

文章目录

  • 前言
  • 一、流水灯代码
  • 二、分析void rt_pin_mode(rt_base_t pin, rt_base_t mode)函数
    • 1.查看其函数原型
    • 2.pin_mode函数原型分析
  • 总结

前言

最近学习RT_Thread系统,和以往学单片机一样,依旧是以流水灯做为第一份学习案例;学硬件的基本都有个习惯,看代码喜欢扣到底层,例程中的流水灯IO口配置是用的封装好的函数,所以我就想看看函数底层是如何实现配置GPIO模式以及执行控制IO操作的。


提示:以下是本篇文章正文内容,下面案例可供参考

一、流水灯代码

该应用代码来自于RT-Thread,此代码只有应用层的程序,底层的驱动程序可以在RT-Thread网站下载完整的发布版本RT-Thread完整版,感谢前辈们的开源资料

整体思路很容易理解:
1.配置LED_PIN的GPIO模式为推挽输出模式

2.在for循环中,设置LED_PIN的输出电平,使IO输出 电压在高低电平间进行切换,从而实现流水灯的视觉效果。
其中用了rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT)以及rt_pin_write(LED_PIN, PIN_LOW)俩个封装好的函数,后面会对这两个函数原理进行分析。

int led(void)
{rt_uint8_t count;rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);  for(count = 0 ; count < 10 ;count++){       rt_pin_write(LED_PIN, PIN_HIGH);rt_kprintf("led on, count : %d\r\n", count);rt_thread_mdelay(500);rt_pin_write(LED_PIN, PIN_LOW);rt_kprintf("led off\r\n");rt_thread_mdelay(500);}return 0;
}

二、分析void rt_pin_mode(rt_base_t pin, rt_base_t mode)函数

1.查看其函数原型

代码如下(示例):

void rt_pin_mode(rt_base_t pin, rt_base_t mode)
{RT_ASSERT(_hw_pin.ops != RT_NULL);_hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode);
}

其中RT_ASSERT是很个有用的报错函数,当该处出现错误时会把出错的函数,行数这些信息打出来,便于调试bug。

_hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode);
可以猜到该行代码就是用来配置GPIO的模式,根据传下来的pin,mode进行相应的配置;接下来我们看下pin_mode这个接口是如何实现的。

2.pin_mode函数原型分析

代码如下:

static void pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode)
{if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC)){LOG_E("pin:%d value wrongful", pin);return;}gpio_set_func(pin_index[pin].pin_port, pin_index[pin].pin, mode);
}
int gpio_set_func(enum gpio_port port, enum gpio_pin pin, rt_uint8_t func)
{rt_uint32_t addr;rt_uint32_t offset;rt_uint32_t data;RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));if (func & 0x8){LOG_W("[line]:%d There is a warning with parameter input", __LINE__);return RT_EINVAL;}addr = GPIOn_CFG_ADDR(port) + (pin / 8) * 4;offset = (pin % 8) * 4;data = readl(addr);data &= ~(0x7 << offset);data |= func << offset;writel(data, addr);LOG_D("[line]:%d offset:%d addr:%08x data:%08x", __LINE__, offset, addr, *((rt_uint32_t *)addr));return RT_EOK;
}

可以看出是通过gpio_set_func()函数,根据传入的pin口和mode参数对寄存器赋相应的值,从而实现相应的GPIO的模式配置


## 3.rt_pin_write函数原型分析 代码如下:

void rt_pin_write(rt_base_t pin, rt_base_t value)
{RT_ASSERT(_hw_pin.ops != RT_NULL);_hw_pin.ops->pin_write(&_hw_pin.parent, pin, value);
}static void pin_write(struct rt_device *dev, rt_base_t pin, rt_base_t value)
{if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC)){LOG_E("pin:%d value wrongful", pin);return;}gpio_set_value(pin_index[pin].pin_port, pin_index[pin].pin, value);
}
int gpio_set_value(enum gpio_port port, enum gpio_pin pin, rt_uint8_t value)
{rt_uint32_t addr;rt_uint32_t offset;rt_uint32_t data;RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));if (value & 0xE){LOG_W("[line]:%d There is a warning with parameter input", __LINE__);return RT_EINVAL;}addr = GPIOn_DATA_ADDR(port);offset = pin;data = readl(addr);data &= ~(0x1 << offset);data |= value << offset;writel(data, addr);LOG_D("[line]:%d offset:%d addr:%08x data:%08x", __LINE__, offset, addr, *((rt_uint32_t *)addr));return RT_EOK;
}

可以看出是对GPIO进行写操作是经过pin_write()调用gpio_set_value()函数,从而实现对底层的操作寄存器进行赋值,使GPIO按照预期输出高低电平,从而驱动led的亮和灭,达到流水灯的效果

总结

由于个人水平有限,如有疏漏请大家指出。

针对RT_Thread中rt_pin_mode()函数的分析相关推荐

  1. linux中request_region()函数的分析

    linux中request_region()函数的分析 struct resource ioport_resource = { .name = "PCI IO", .start = ...

  2. caffe中loss函数代码分析--caffe学习(16)

    接上篇:caffe中样本的label一定要从序号0开始标注吗?–caffe学习(15) A: 1:数学上来说,损失函数loss值和label从0开始还是从1或者100开始是没有直接联系的,以欧式距离损 ...

  3. php的filter input,php中filter_input函数用法分析

    本文实例分析了php中filter_input函数用法.分享给大家供大家参考.具体分析如下: 在 php5.2 中,内置了filter 模块,用于变量的验证和过滤,过滤变量等操作,这里我们看下如何直接 ...

  4. php explode用法,php中explode函数用法分析

    本文实例分析了php中explode函数用法.分享给大家供大家参考.具体如下: explode(string separator,string string [,int limit]) separat ...

  5. linux 内核flush,armv8(aarch64)linux内核中flush_dcache_all函数详细分析

    /* *  __flush_dcache_all() *  Flush the wholeD-cache. * Corrupted registers: x0-x7, x9-x11 */ ENTRY( ...

  6. php simplexml 函数,PHP中SimpleXML函数用法分析

    本文实例讲述了关于php中SimpleXML 函数的用法,此函数是允许您把 XML 转换为对象,分享给大家供大家参考.具体分析如下: SimpleXML 函数允许您把 XML 转换为对象,通过普通的属 ...

  7. php中 param,php中bind_param()函数用法分析

    本文实例讲述了php中bind_param()函数用法.分享给大家供大家参考,具体如下: 从字面上不难理解,绑定的参数:下面我通过一个绑定参数的例子讲一下: for example: bind_par ...

  8. python中exp函数_Python3中exp()函数用法分析

    python中虚数函数exp怎么表示 复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型 虚数函数exp用math是不行的要用cmat ...

  9. mysql中lead_SqlServer2012中LEAD函数简单分析_MySQL

    LEAD函数简单点说,就是把下一行的某列数据提取到当前行来显示,看示例更能解释清楚,先看测试用脚本 DECLARE @TestData TABLE( ID INT IDENTITY(1,1), Dep ...

最新文章

  1. linux文件自动删除,自动删除文件脚本(Linux shell脚本)
  2. SpringBoot 上传多个文件
  3. leaflet加载离线地图教程以及下载离线地图瓦片工具
  4. apache 静态编译和动态编译参考
  5. Shell应用:批量将文件编码由gbk转utf-8
  6. java读c二进制文件_如何使用JAVA读取C / Matlab创建的二进制文件
  7. 无监督学习 | DBSCAN 原理及Sklearn实现
  8. java静态注解处理器_深入理解Java:注解(Annotation)--注解处理器
  9. linux下mysql中文乱码_linux下mysql中文乱码
  10. ios调用restful接口_iPhone中调用RESTFUL Service
  11. [算法题] 安排会议室——贪心算法的应用
  12. 大学计算机基础总结与复习
  13. leetcode547 朋友圈
  14. 使用Linux常见问题及其解决办法
  15. flex 调用 flash影片剪辑
  16. java编写这个通讯录管理系统_Java如何实现通讯录管理系统
  17. 第56章 SQL UCASE() 函数教程
  18. 关于VMware虚拟机安装失败的解决办法,报错(29142)或者安装系统后无法启动
  19. GPU状态显示和部分指标含义
  20. 优化算法选择:SGD、SGDM、NAG、Adam、AdaGrad、RMSProp、Nadam

热门文章

  1. net framework4.0安装未成功,错误代码为0x800c006
  2. vivo手机哪款性价比高质量好 2022
  3. 关于es的一些默认限制解除
  4. 同一栋办公楼连接的计算机网络是,在同一栋办公楼连接的计算机网络是(  )...
  5. CAD展点+更改点样式
  6. JavaScript笔记6(数组,foreach(),slice(),splice(),数组的剩余方法,函数的方法call和apply ,arguments,Date对象,Math,字符串的相关方法)
  7. jar文件加密方法之xjar使用教程
  8. C#读取EXCEL列数据,并画折线图(刚开始入门小白自己整理的,方便自己以后看)
  9. mysql事务数 每秒_TPS(每秒处理事务数)和TPMC(每分钟处理交易量)
  10. 网站应该如何制定关键词策略