实现自己的RPi.GPIO(三)-Python C API

Python C 的扩展按照模板来就行了,其实就4步:参数传递,返回值传递,函数注册,初始化。

直接上代码:

  1 /*
  2  * PyGPIO.h
  3  *
  4  *  Created on: 2015年5月19日
  5  *      Author: jugg
  6  */
  7
  8 #ifndef SRC_PYGPIO_H_
  9 #define SRC_PYGPIO_H_
 10
 11 #include <errno.h>
 12 #include <string.h>
 13 #include <stdio.h>
 14 #include <stdlib.h>
 15 #include <unistd.h>
 16 #include <fcntl.h>
 17 #include <sys/mman.h>
 18 #include <sys/ioctl.h>
 19 #include <sys/stat.h>
 20
 21 // Ti DM8168/DM8148 GPIO Reg base addr
 22 #define TI81XX_GPIO0_BASE    0x48032000
 23 #define TI81XX_GPIO1_BASE    0x4804C000
 24
 25 // Pin mux reg base addr
 26 #define PIN_CTRL_AE28        0x481409A8
 27
 28 #define GPIO_SYSCONFIG        0x10
 29 #define GPIO_SYSSTATUS        0x114
 30 #define GPIO_CTRL        0x130
 31 #define GPIO_OE            0x134
 32 #define GPIO_DATAIN        0x138
 33 #define GPIO_DATAOUT        0x13C
 34
 35 // GPIO Reg size
 36 #define GPIO_REG_ADDR_4KB    0x1000
 37
 38 #define GPIO_P0            0x00000001
 39 #define GPIO_P1            0x00000002
 40 #define GPIO_P2            0x00000004
 41 #define GPIO_P3            0x00000008
 42 #define GPIO_P4            0x00000010
 43 #define GPIO_P5            0x00000020
 44 #define GPIO_P6            0x00000040
 45 #define GPIO_P7            0x00000080
 46 #define GPIO_P8            0x00000100
 47 #define GPIO_P9            0x00000200
 48 #define GPIO_P10        0x00000400
 49 #define GPIO_P11        0x00000800
 50 #define GPIO_P12        0x00001000
 51 #define GPIO_P13        0x00002000
 52 #define GPIO_P14        0x00004000
 53 #define GPIO_P15        0x00008000
 54 #define GPIO_P16        0x00010000
 55 #define GPIO_P17        0x00020000
 56 #define GPIO_P18        0x00040000
 57 #define GPIO_P19        0x00080000
 58 #define GPIO_P20        0x00100000
 59 #define GPIO_P21        0x00200000
 60 #define GPIO_P22        0x00400000
 61 #define GPIO_P23        0x00800000
 62 #define GPIO_P24        0x01000000
 63 #define GPIO_P25        0x02000000
 64 #define GPIO_P26        0x04000000
 65 #define GPIO_P27        0x08000000
 66 #define GPIO_P28        0x10000000
 67 #define GPIO_P29        0x20000000
 68 #define GPIO_P30        0x40000000
 69 #define GPIO_P31        0x80000000
 70
 71
 72 typedef union {
 73     struct {
 74       unsigned int P0 : 1;
 75       unsigned int P1 : 1;
 76       unsigned int P2 : 1;
 77       unsigned int P3 : 1;
 78       unsigned int P4 : 1;
 79       unsigned int P5 : 1;
 80       unsigned int P6 : 1;
 81       unsigned int P7 : 1;
 82       unsigned int P8 : 1;
 83       unsigned int P9 : 1;
 84       unsigned int P10 : 1;
 85       unsigned int P11 : 1;
 86       unsigned int P12 : 1;
 87       unsigned int P13 : 1;
 88       unsigned int P14 : 1;
 89       unsigned int P15 : 1;
 90       unsigned int P16 : 1;
 91       unsigned int P17 : 1;
 92       unsigned int P18 : 1;
 93       unsigned int P19 : 1;
 94       unsigned int P20 : 1;
 95       unsigned int P21 : 1;
 96       unsigned int P22 : 1;
 97       unsigned int P23 : 1;
 98       unsigned int P24 : 1;
 99       unsigned int P25 : 1;
100       unsigned int P26 : 1;
101       unsigned int P27 : 1;
102       unsigned int P28 : 1;
103       unsigned int P29 : 1;
104       unsigned int P30 : 1;
105       unsigned int P31 : 1;
106     } port;
107     unsigned int port_val;
108 } GPIO_PORT;
109
110 typedef enum {
111     GPIO_PORT0,
112     GPIO_PORT1
113 } GPIO_NUM;
114
115
116 typedef enum {
117     GPIO_WRITE,    //GPIO output
118     GPIO_READ    //GPIO input
119 } GPIO_MODE;
120
121 typedef enum {
122     GPIO_VAL_LOW,
123     GPIO_VAL_HIGH
124 } GPIO_VAL;
125
126 int GPIO_init(GPIO_NUM gpio, unsigned int gpio_port, GPIO_MODE gpio_mode);
127 int GPIO_write(GPIO_NUM gpio, unsigned int gpio_port, GPIO_VAL gpio_val);
128
129 #endif /* SRC_PYGPIO_H_ */

PyGPIO.h

  1 /*
  2  * PyGPIO.c
  3  *
  4  *  Created on: 2015年5月19日
  5  *      Author: jugg
  6  */
  7 #include <python2.6/Python.h>
  8
  9 #include "PyGPIO.h"
 10
 11
 12 int GPIO_init(GPIO_NUM gpio, unsigned int gpio_port, GPIO_MODE gpio_mode)
 13 {
 14   int file;
 15   unsigned int TI81XX_GPIO_BASE;
 16   unsigned int *mem_viraddr = NULL;
 17   file = open("/dev/mem", O_RDWR|O_SYNC);
 18   if(file < 0){
 19       printf(" ERROR: /dev/mem open failed !!!\n");
 20       return -1;
 21   }
 22
 23   TI81XX_GPIO_BASE = gpio ? TI81XX_GPIO1_BASE:TI81XX_GPIO0_BASE;
 24   mem_viraddr = mmap(NULL, GPIO_REG_ADDR_4KB, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, file, TI81XX_GPIO_BASE);
 25
 26   mem_viraddr[GPIO_SYSCONFIG >> 2] = 0x10;    // No idle
 27   mem_viraddr[GPIO_OE >> 2] = gpio_mode ? gpio_port:~gpio_port;     // GPIO mode setting
 28   munmap((void *)mem_viraddr, GPIO_REG_ADDR_4KB);
 29
 30
 31
 32   close(file);
 33
 34   return 0;
 35 }
 36
 37 int GPIO_write(GPIO_NUM gpio, unsigned int gpio_port, GPIO_VAL gpio_val)
 38 {
 39   int file;
 40   unsigned int TI81XX_GPIO_BASE;
 41   unsigned int *mem_viraddr = NULL;
 42   file = open("/dev/mem", O_RDWR|O_SYNC);
 43   if(file < 0){
 44       printf(" ERROR : /dev/mem open failed write!!!\n");
 45       return -1;
 46   }
 47
 48   TI81XX_GPIO_BASE = gpio ? TI81XX_GPIO1_BASE:TI81XX_GPIO0_BASE;
 49   mem_viraddr = mmap(NULL, GPIO_REG_ADDR_4KB, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, file, TI81XX_GPIO_BASE);
 50
 51   mem_viraddr[GPIO_DATAOUT >> 2] = gpio_val ? gpio_port:~gpio_port;
 52
 53   munmap((void *)mem_viraddr, GPIO_REG_ADDR_4KB);
 54   close(file);
 55
 56   return 0;
 57 }
 58
 59 static PyObject *pyGPIO_init(PyObject *self, PyObject *args)
 60 {
 61   int gpio,gpio_port,gpio_mode;
 62   int temp;
 63   PyObject *return_val;
 64
 65   temp = PyArg_ParseTuple(args, "iii", &gpio,&gpio_port,&gpio_mode);
 66   if(!temp){
 67       return NULL;
 68   }
 69
 70   temp = GPIO_init(gpio,gpio_port,gpio_mode);
 71   return_val = (PyObject *)Py_BuildValue("i", temp);
 72   return return_val;
 73 }
 74
 75 static PyObject *pyGPIO_write(PyObject *self, PyObject *args)
 76 {
 77   int gpio,gpio_port,gpio_val;
 78   int temp;
 79   PyObject *return_val;
 80
 81   temp = PyArg_ParseTuple(args, "iii", &gpio,&gpio_port,&gpio_val);
 82   if(!temp){
 83       return NULL;
 84   }
 85
 86   temp = GPIO_write(gpio, gpio_port, gpio_val);
 87   return_val = (PyObject *)Py_BuildValue("i", temp);
 88   return return_val;
 89 }
 90
 91 static PyMethodDef pyGPIOMethods[] = {
 92     {"GPIO_init", pyGPIO_init, METH_VARARGS},
 93     {"GPIO_write", pyGPIO_write, METH_VARARGS},
 94     {NULL,NULL}
 95 };
 96
 97 void initPyGPIO(void)
 98 {
 99   Py_InitModule("PyGPIO", pyGPIOMethods);
100 }

交叉编译为动态链接库,拷贝到Python库路径下面即可。

下面是一个LED闪烁的Python Demo:

‘‘‘
This a PyGPIO module test.
PyGPIO module is written in C, used to deal with GPIO hardware directly by python.
‘‘‘
import PyGPIO
import time
gpio1 = 1                   # GPIO_1
gpio_port = 0x00002000      # GPIO_1.13
gpio_mode = 0               # Output
gpio_val = 1                # Output high level
# Init GPIO1
PyGPIO.GPIO_init(gpio1,gpio_port,gpio_mode)
# Write output value
while(True):
    PyGPIO.GPIO_write(gpio1,gpio_port,0)
    time.sleep(1)
    PyGPIO.GPIO_write(gpio1,gpio_port,1)
    time.sleep(1)

自此,自己实现的RPi.GPIO模块就完成了。当然还有一些问题,比如如何在Python里面使用C里面的枚举类型,这样点亮LED就可以直接GPIO.ON而不是数字1,还有每次写GPIO都需要mmap再munmap,开销很大,可以 init 的时候mmap,不再操作GPIO uninit的时候munmap等。

时间: 2024-07-31 06:29:53

实现自己的RPi.GPIO(三)-Python C API的相关文章

实现自己的RPi.GPIO(一)-Python C Extension

树莓派有个RPi.GPIO的Python模块,import之后就可以直接用Python操作ARM芯片的GPIO硬件模块.觉得这个很有意思,于是查资料想在自己画的DM8148平台上面也实现这样的一个模块. DM8148是TI推出的一款达芬奇系列数字图像处理芯片,比DM8168性能略差,但是功耗更低.之前公司的很多图像处理都是用的DM8168,但是散热和功耗问题一直很让人头疼,于是就让我预研更低功耗的DM8148.DM8148可以理解为ARM+DSP的异构核心,我们要用到的就是它的一颗Cortex

【玩转开源】BananaPi R2——移植RPi.GPIO 到 R2

1. 首先给大家介绍一下什么是RPi.GPIO. 简单去讲,RPi.GPIO就是一个运行在树莓派开发板上可以通过Python去控制GPIO的一个中间件. 现在我这边做了一个基础功能的移植,接下来大家可以跟着我去学习一下RPi.GPIO是如何通过Python去实现控制开发板上的GPIO的. 2. 看一下效果图: 2.1 硬件实物运行效果 2.2 执行Python脚本打印的log 3. 那么RPi.GPIO在R2上是如何使用的呢? 3.1 首先在R2上面运行一个Ubuntu镜像,然后下载代码:git

树莓派瞎玩~7~RPi.GPIOのWIKI文档

树莓派瞎玩~7~RPi.GPIOのWIKI文档 RPiGPIO Python Module RPiGPIO module basics Importing the module Pin numbering Warnings Setup up a channel Setup more than one channel Input Output Output to several channels Cleanup RPi Board Information and RPiGPIO version I

三.python高级

三.python高级 1.元类 1.1 Python 中类方法.类实例方法.静态方法有何区别? 类方法:是类对象的方法,在定义时需要在上方使用@classmethod进行装饰,形参为cls,表示类对象,类对象和实例对象都可调用: 类实例方法:是类实例化对象的方法,只有实例对象可以调用,形参为 self,指代对象本身: 静态方法:是一个任意函数,在其上方使用@staticmethod进行装饰,可以用对象直接调用, 静态方法实际上跟该类没有太大关系 2.内存管理与垃圾回收机制 2.1 Python

Python C API 引用计数器(三)

简介 Python的内存管理是通过对象的引用计数器来实现的,对象的创建会将引用计数器加1,被引用一次则引用计数器就会加1,反之解除引用时,则引用计数器就会减1,当Python对象的引用计数器为0的时候,则这个对象就会被回收和释放. 这种内存管理的方式是有一定的弊端的,一是它需要额外的空间维护引用计数,二是它不能解决对象的"循环引用"的问题,因此,也有很多语言比如Java并没有采用该算法做来垃圾的回收机制. Python代码实例 import sys def test_refcount(

Coreseek:第三步调用api搜索php版

有三个步骤 1.讲searchd进程写成一个服务,不然每次调用都要打开这个进程很麻烦. g:\service\coreseek\bin\searchd --install --config g:/service/coreseek/etc/csft_mysql.conf --servicename Coreseek 同样的万变不离其宗还是跟配置文件有关系 一个参数是你searchd的路径 ,第二个固定是--install,第三个是指后面跟配置文件--config,第三个是配置文件路径 后面是定义服

漫谈可视化Prefuse(三)---Prefuse API数据结构阅读有感

前篇回顾:上篇<漫谈可视化Prefuse(二)---一分钟学会Prefuse>主要通过一个Prefuse的具体实例了解了构建一个Prefuse application的具体步骤.一个Prefuse Application需要经过数据导入(文本数据.数据库)->Prefuse数据结构接收数据->注册各种效果的Actions->渲染Renderer->交互展现Display的流程. 摸清了Prefuse那些看似眼花缭乱的框架结构,剩下的就是抽丝剥茧,顺藤摸瓜,结合Manua

HBase概念学习(三)Java API之扫描和过滤器

HBase基本的CRUD操作就不多介绍了,无非就是Put,Get,Delete三个类的运用. 本文相当于是阅读HBase权威指南的总结. 一.扫描(Scan) 现在看一下扫描技术,这种技术类似于关系型数据库的游标(cursor),并利用到了HBase底层顺序存储的特性. 使用扫描的一般步骤是: 1.创建Scan实例 2.为Scan实例增加扫描的限制条件 3.调用HTable的getScanner()方法获取ResultScanner对象 4.迭代ResultScanner对象中的Result对象

Python DB API的异常

我们在昨天预告了一下Python DB API的异常,今天我们来细讲一下: 1.所有异常的超类:StandardError; 2.waring:属于StandardError超类,发生非致命问题所以发的异常: 3.Error:属于StandardError超类,所有错误条件的超类: 4.InterfaceError:属于Error超类,发生与接口(非数据库)相关的错误所引发的异常: 5.DatabaseError:属于Error超类,发生与数据库相关的错误的超类: 6.DataError:属于D