搜索
bottom↓
回复: 11

树莓派外设直接编程驱动

[复制链接]

出0入0汤圆

发表于 2016-12-1 15:04:07 | 显示全部楼层 |阅读模式
  目前树莓派python版本的硬件驱动库只能使用GPIO,SPI等,很多外设的功能都没办法用.
可以使用mmap映射物理地址,直接操作外设的寄存器,这样树莓派的整个硬件资源就可以打通了.下面是通过操作GPIO寄存器控制一个引脚的例子,其他的外设也可以参照操作.


  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>

  5. #include <fcntl.h>                // 文件打开、加锁等操作
  6. #include <unistd.h>                // unistd.h 是 C 和 C++ 程序设计语言中提供对 POSIX 操作系统 API 的访问功能的头文件的名称。是Unix Standard的缩写。
  7. #include <errno.h>                // errno.h是C语言C标准库里的头文件,定义了通过错误码来回报错误信息的宏:

  8. #include <sys/ioctl.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <sys/mman.h>        // 内存管理,包括POSIX 共享内存 (进程间通信)与内存映射文件

  12. #define PERIPH_BASE_RPI2        0x3F000000
  13. #define GPIO_OFFSET                        0x00200000

  14. typedef struct
  15. {
  16.         uint32_t fsel[6];                            // GPIO Function Select
  17.         uint32_t resvd_0x18;
  18.         uint32_t set[2];                             // GPIO Pin Output Set
  19.         uint32_t resvd_0x24;
  20.         uint32_t clr[2];                             // GPIO Pin Output Clear
  21.         uint32_t resvd_0x30;
  22.         uint32_t lev[2];                             // GPIO Pin Level
  23.         uint32_t resvd_0x3c;
  24.         uint32_t eds[2];                             // GPIO Pin Event Detect Status
  25.         uint32_t resvd_0x48;
  26.         uint32_t ren[2];                             // GPIO Pin Rising Edge Detect Enable
  27.         uint32_t resvd_0x54;
  28.         uint32_t fen[2];                             // GPIO Pin Falling Edge Detect Enable
  29.         uint32_t resvd_0x60;
  30.         uint32_t hen[2];                             // GPIO Pin High Detect Enable
  31.         uint32_t resvd_0x6c;
  32.         uint32_t len[2];                             // GPIO Pin Low Detect Enable
  33.         uint32_t resvd_0x78;
  34.         uint32_t aren[2];                            // GPIO Pin Async Rising Edge Detect
  35.         uint32_t resvd_0x84;
  36.         uint32_t afen[2];                            // GPIO Pin Async Falling Edge Detect
  37.         uint32_t resvd_0x90;
  38.         uint32_t pud;                                // GPIO Pin Pull up/down Enable
  39.         uint32_t pudclk[2];                          // GPIO Pin Pull up/down Enable Clock
  40.         uint32_t resvd_0xa0[4];
  41.         uint32_t test;
  42. } __attribute__((packed, aligned(4))) gpio_t;

  43. volatile gpio_t * gpio;

  44. void GPIO_WriteHigh(gpio_t * gpio, int pin)
  45. {
  46.         if (pin > 53)
  47.                 return;
  48.         int reg = pin >> 5;
  49.         int offset = (pin & 0x1F);
  50.         gpio->set[reg] |= (1 << offset);
  51. }

  52. void GPIO_WriteLow(gpio_t * gpio, int pin)
  53. {
  54.         if (pin > 53)
  55.                 return;
  56.         int reg = pin / 32;
  57.         int offset = pin % 32;
  58.         gpio->clr[reg] |= (1 << offset);
  59. }

  60. typedef enum
  61. {
  62.         GPIO_Function_Input = 0,
  63.         GPIO_Function_Output = 1,
  64.         GPIO_Function_Alternate0 = 2,
  65.         GPIO_Function_Alternate1 = 3,
  66.         GPIO_Function_Alternate2 = 4,
  67.         GPIO_Function_Alternate3 = 5,
  68.         GPIO_Function_Alternate4 = 6,
  69.         GPIO_Function_Alternate5 = 7
  70. }GPIO_FUNCTION_SEL;

  71. void GPIO_SetMode(gpio_t * gpio, int pin, GPIO_FUNCTION_SEL sel)
  72. {
  73.         if (pin > 53)
  74.                 return;
  75.         int reg = pin / 10;
  76.         int offset = (pin % 10) * 3;
  77.         gpio->fsel[reg] &= ~(0x00000007 << offset);
  78.         gpio->fsel[reg] |= (sel << offset);
  79. }


  80. int main(int argc, char * argv[])
  81. {
  82.         int mem_fd;

  83.         mem_fd = open("/dev/mem", O_RDWR);
  84.         if (mem_fd == -1)
  85.         {
  86.                 perror("mem");
  87.                 exit(0);
  88.         }

  89.         gpio = mmap(0, sizeof(gpio_t), PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, (PERIPH_BASE_RPI2 + GPIO_OFFSET));
  90.         if (gpio == MAP_FAILED)
  91.         {
  92.                 perror("mmap");
  93.                 exit(0);
  94.         }

  95.         GPIO_SetMode(gpio, 18, GPIO_Function_Output);

  96.         while (true)
  97.         {
  98.                 GPIO_WriteHigh(gpio, 18);
  99.                 sleep(1);
  100.                 GPIO_WriteLow(gpio, 18);
  101.                 sleep(1);
  102.         }

  103.         return 0;
  104. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2016-12-1 15:56:38 | 显示全部楼层
不错,这样的话,其它端口就也可以使用了

出0入0汤圆

 楼主| 发表于 2016-12-1 16:26:36 | 显示全部楼层
four_zhg 发表于 2016-12-1 15:56
不错,这样的话,其它端口就也可以使用了

还可以通过DMA+PWM的方式直接驱动ws2812b,
Github上有一个项目https://github.com/jgarff/rpi_ws281x

出0入25汤圆

发表于 2016-12-1 16:52:59 | 显示全部楼层
Python也可以

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-12-1 17:53:52 来自手机 | 显示全部楼层
哈,终于有人聊树莓派了

出0入0汤圆

发表于 2016-12-1 18:27:38 | 显示全部楼层
这个消息真是太好了,可以直接调试外设。

出0入0汤圆

发表于 2016-12-1 19:02:46 | 显示全部楼层
几年前就用mmap操作linux下硬件,不知道树莓的寄存器手册是否详细?一直没玩

出0入0汤圆

发表于 2016-12-1 19:50:21 | 显示全部楼层
不错,支持一下。我的PI3快长灰了。

出0入0汤圆

发表于 2016-12-1 20:04:13 来自手机 | 显示全部楼层
好,空闲时候玩玩

出100入101汤圆

发表于 2016-12-1 20:49:58 | 显示全部楼层
mmap方式,很多人都这样搞!

出0入0汤圆

 楼主| 发表于 2016-12-2 08:53:22 | 显示全部楼层

这个还真没了解过,python功能挺强大的呀.

出0入0汤圆

发表于 2016-12-3 07:14:27 来自手机 | 显示全部楼层
python类库很多
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 13:47

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表