1、现在能找到的寄存器是控制输出值的寄存器,直接对寄存器赋值最快接近2Mhz频率
2、例如开发板上的led是属于416组号的,所以输入命令
cat /sys/class/gpio/gpiochip416/label 得到3022000.gpio 0x3022000是这个组gpio的基址
3、经过测试更改这个地址的值,相应的gpio值也会变,440是led的GPIO编号 例如
写1就这个地址 或一下 0x01<<(440-416)
写0为赋值 ~(0x01<<(440-416))
4、对gpio初始化还是用原来的 两条命令
echo 440 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio440/direction
5、操作寄存器代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define PAGE_SIZE (0x1000)
static int gpio_fd=0;
static int page_ailgned =0;
static char *gpio_address = NULL;
int main()
{
int GPIO_BASE_ADDRESS;
int lishi;
GPIO_BASE_ADDRESS=0x3022000;//这个组gpio的基址
gpio_fd=open("/dev/mem",O_RDWR);
if(gpio_fd < 0)
{
printf("open /dev/mem failed\r\n");
}
else
{
page_ailgned = (GPIO_BASE_ADDRESS & (~(PAGE_SIZE - 1)));
gpio_address = (char *)mmap(NULL,PAGE_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,gpio_fd,page_ailgned);
if((void *)-1 == gpio_address)
{
printf("mmap gpio address failed\r\n");
}
}
while(1)
{
*((int *)(gpio_address + (GPIO_BASE_ADDRESS-page_ailgned))) |= 0x01<<(440-416);//赋值高电平
usleep(100000);
*((int *)(gpio_address + (GPIO_BASE_ADDRESS-page_ailgned))) &= ~(0x01<<(440-416));//赋值低电平
usleep(100000);
}
return 0;
}
6、只需要改代码里的440和416和0x3022000,分别是gpio编号、gpio linux组号、这个组号的基址,其他gpio也可以操作。
7、补充:
1. 属于GPIOA下的 为 linux组号为480,基址为0x3020000,gpio编号为 linux组号+GPIOA后面的数字
2.属于GPIOC下的 为 linux组号为416,基址为0x3022000,gpio编号为 linux组号+GPIOC后面的数字
3.属于GPIO下的 为 linux组号为352,基址为0x5021000,gpio编号为 linux组号+GPIO后面的数字
8、方便对寄存器 读写调试程序 代码如下
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define PAGE_SIZE (0x1000)
static int gpio_fd=0;
static int page_ailgned =0;
static char *gpio_address = NULL;
int main(int argc,char* argv[])
{
int GPIO_BASE_ADDRESS;
int lishi;
sscanf(argv[2],"%x",&GPIO_BASE_ADDRESS); //读取命令行的第三个字符串
gpio_fd=open("/dev/mem",O_RDWR);//打开文件
if(gpio_fd < 0)
{
printf("open /dev/mem failed\r\n");
}
else
{
page_ailgned = (GPIO_BASE_ADDRESS & (~(PAGE_SIZE - 1)));
gpio_address = (char *)mmap(NULL,PAGE_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,gpio_fd,page_ailgned);
if((void *)-1 == gpio_address)
{
printf("mmap gpio address failed\r\n");
}
}
if(argv[1][0] == 'r')
{
printf("内容:0x%x\r\n",*((int *)(gpio_address + (GPIO_BASE_ADDRESS-page_ailgned))));
}
else if (argv[1][0] == 'w')
{
sscanf(argv[3],"%x",&lishi);
*((int *)(gpio_address + (GPIO_BASE_ADDRESS-page_ailgned))) = lishi;
}
else
{
printf("输入错误,请从新运行!\r\n");
}
return 0;
}
1.编译代码,下载到开发板。
2.例如编译出的文件叫main,那么运行命令为 ./main (w或r) (地址) (如果填的是w就需要)
3. (w)为写,(r)为读。第三个参数为写入的数据
4.例如 我要读一个内存命令为 : ./main r 0x3020000
5.例如 我要写一个内存命令为 :./main w 0x3020000 0x00aa
6.地址和写入的值只可以为 0x 开头十六进制,打印出来的值也是十六进制
寄存器补充:
下面的寄存器都是一个gpio只有寄存器的一个比特
1、基址+0x04为 设置 out或in 寄存器 ········out为1
2、基址+0x50为 如果gpio设置为in,gpio的值在这个寄存器
3、例如 基址+0x04需要赋值给 上面代码的GPIO_BASE_ADDRESS
示例 led的gpio------440为编号,416为组号
基址+0x04 |= 0x01 << (440-416) 将gpio设置为out
基址+0x04 &= ~(0x01 << (440-416)) 将gpio设置为in
读 基址+0x50 的第440-416位为值