树莓派外设直接编程驱动
目前树莓派python版本的硬件驱动库只能使用GPIO,SPI等,很多外设的功能都没办法用.可以使用mmap映射物理地址,直接操作外设的寄存器,这样树莓派的整个硬件资源就可以打通了.下面是通过操作GPIO寄存器控制一个引脚的例子,其他的外设也可以参照操作.
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h> // 文件打开、加锁等操作
#include <unistd.h> // unistd.h 是 C 和 C++ 程序设计语言中提供对 POSIX 操作系统 API 的访问功能的头文件的名称。是Unix Standard的缩写。
#include <errno.h> // errno.h是C语言C标准库里的头文件,定义了通过错误码来回报错误信息的宏:
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h> // 内存管理,包括POSIX 共享内存 (进程间通信)与内存映射文件
#define PERIPH_BASE_RPI2 0x3F000000
#define GPIO_OFFSET 0x00200000
typedef struct
{
uint32_t fsel; // GPIO Function Select
uint32_t resvd_0x18;
uint32_t set; // GPIO Pin Output Set
uint32_t resvd_0x24;
uint32_t clr; // GPIO Pin Output Clear
uint32_t resvd_0x30;
uint32_t lev; // GPIO Pin Level
uint32_t resvd_0x3c;
uint32_t eds; // GPIO Pin Event Detect Status
uint32_t resvd_0x48;
uint32_t ren; // GPIO Pin Rising Edge Detect Enable
uint32_t resvd_0x54;
uint32_t fen; // GPIO Pin Falling Edge Detect Enable
uint32_t resvd_0x60;
uint32_t hen; // GPIO Pin High Detect Enable
uint32_t resvd_0x6c;
uint32_t len; // GPIO Pin Low Detect Enable
uint32_t resvd_0x78;
uint32_t aren; // GPIO Pin Async Rising Edge Detect
uint32_t resvd_0x84;
uint32_t afen; // GPIO Pin Async Falling Edge Detect
uint32_t resvd_0x90;
uint32_t pud; // GPIO Pin Pull up/down Enable
uint32_t pudclk; // GPIO Pin Pull up/down Enable Clock
uint32_t resvd_0xa0;
uint32_t test;
} __attribute__((packed, aligned(4))) gpio_t;
volatile gpio_t * gpio;
void GPIO_WriteHigh(gpio_t * gpio, int pin)
{
if (pin > 53)
return;
int reg = pin >> 5;
int offset = (pin & 0x1F);
gpio->set |= (1 << offset);
}
void GPIO_WriteLow(gpio_t * gpio, int pin)
{
if (pin > 53)
return;
int reg = pin / 32;
int offset = pin % 32;
gpio->clr |= (1 << offset);
}
typedef enum
{
GPIO_Function_Input = 0,
GPIO_Function_Output = 1,
GPIO_Function_Alternate0 = 2,
GPIO_Function_Alternate1 = 3,
GPIO_Function_Alternate2 = 4,
GPIO_Function_Alternate3 = 5,
GPIO_Function_Alternate4 = 6,
GPIO_Function_Alternate5 = 7
}GPIO_FUNCTION_SEL;
void GPIO_SetMode(gpio_t * gpio, int pin, GPIO_FUNCTION_SEL sel)
{
if (pin > 53)
return;
int reg = pin / 10;
int offset = (pin % 10) * 3;
gpio->fsel &= ~(0x00000007 << offset);
gpio->fsel |= (sel << offset);
}
int main(int argc, char * argv[])
{
int mem_fd;
mem_fd = open("/dev/mem", O_RDWR);
if (mem_fd == -1)
{
perror("mem");
exit(0);
}
gpio = mmap(0, sizeof(gpio_t), PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, (PERIPH_BASE_RPI2 + GPIO_OFFSET));
if (gpio == MAP_FAILED)
{
perror("mmap");
exit(0);
}
GPIO_SetMode(gpio, 18, GPIO_Function_Output);
while (true)
{
GPIO_WriteHigh(gpio, 18);
sleep(1);
GPIO_WriteLow(gpio, 18);
sleep(1);
}
return 0;
} 不错,这样的话,其它端口就也可以使用了 four_zhg 发表于 2016-12-1 15:56
不错,这样的话,其它端口就也可以使用了
还可以通过DMA+PWM的方式直接驱动ws2812b,
Github上有一个项目https://github.com/jgarff/rpi_ws281x Python也可以{:lol:}{:lol:}
哈,终于有人聊树莓派了 这个消息真是太好了,可以直接调试外设。 几年前就用mmap操作linux下硬件,不知道树莓的寄存器手册是否详细?一直没玩 不错,支持一下。我的PI3快长灰了。 好,空闲时候玩玩 mmap方式,很多人都这样搞! XIVN1987 发表于 2016-12-1 16:52
Python也可以
这个还真没了解过,python功能挺强大的呀. python类库很多
页:
[1]