• mmap操作荔枝派gpio v3s Linux


    1.预备知识

    https://baike.baidu.com/item/mmap/1322217?fr=aladdin 大家直接看百度百科,比较清楚了。

    2.代码

    gpio.c

    #include "gpio.h"
    
    unsigned int fd;
    PIO_Map *PIO = NULL;
    unsigned int *gpio_map;
    unsigned int addr_start, addr_offset;
    unsigned int PageSize, PageMask;
    void GPIO_Init(void)
    {
    
        if ((fd = open("/dev/mem", O_RDWR)) == -1)
        {
            printf("open error
    ");
            return;
        }
    
        PageSize = sysconf(_SC_PAGESIZE); //使用sysconf查询系统页面大小
        PageMask = (~(PageSize - 1));     //页掩码
        printf("PageSize:%d,PageMask:0x%.8X
    ", PageSize, PageMask);
    
        addr_start = PIO_BASE_ADDRESS & PageMask;   //0x01C20800 & 0xfffff000 =  0x1C20000
        addr_offset = PIO_BASE_ADDRESS & ~PageMask; //0x01C20800 & 0x00000100 = 0x800
        printf("addr_start:%.8X,addr_offset:0x%.8X
    ", addr_start, addr_offset);
        //mmap(系统自动分配内存地址,映射区长度“内存页的整数倍”,选择可读可写,MAP_SHARED=与其他所有映射到这个对象的进程共享空间,文件句柄,被映射内容的起点)
        //offest 映射物理内存的话,必须页对其!!!   所以这个起始地址应该是0x1000的整数倍,那么明显0x01C20800需要减去0x800才是整数倍!
        if ((gpio_map = mmap(NULL, PageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start)) == NULL)
        {
            printf("mmap error
    ");
            close(fd);
            return;
        }
        printf("gpio_map:%.8X
    ", gpio_map);
        //这里已经将0x1c20000的地址映射到了内存中,但是我们需要的地址是0x01C20800,所以要再加上地址偏移量~
        PIO = (PIO_Map *)((unsigned int)gpio_map + addr_offset);
        printf("PIO:0x%.8X
    ", PIO);
    
        close(fd); //映射好之后就可以关闭文件?
    }
    
    void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode)
    {
        if (gpio_map == NULL)
            return;
        PIO->Pn[port].CFG[pin / 8] &= ~((unsigned int)0x07 << pin % 8 * 4);
        PIO->Pn[port].CFG[pin / 8] |= ((unsigned int)mode << pin % 8 * 4);
        printf("struct PIO_Struct size : %d",sizeof(PIO->Pn[port]));
    }
    
    void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level)
    {
        if (gpio_map == NULL)
            return;
        if (level)
            PIO->Pn[port].DAT |= (1 << pin);
        else
            PIO->Pn[port].DAT &= ~(1 << pin);
    }
    
    int GPIO_Free(void)
    {
        if ((munmap(gpio_map, PageSize * 2)) == 0)//取消映射
        {
            printf("unmap success!
    ");
        }
        else
        {
            printf("unmap failed!
    ");
        }
        return 0;
    }

    gpio.h

    #ifndef __GPIO_H__
    #define __GPIO_H__
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #define PIO_BASE_ADDRESS 0x01C20800
    
    
    //unsigned int 4字节 一个PIO_Struct占36字节,对应十六进制就是0x24,正好是一个offset值。
    typedef struct
    {
        unsigned int CFG[4];
        unsigned int DAT;
        unsigned int DRV0;
        unsigned int DRV1;
        unsigned int PUL0;
        unsigned int PUL1;
    } PIO_Struct;
    
    typedef struct
    {
        PIO_Struct Pn[7];
    } PIO_Map;
    
    typedef enum {
        PA = 0,
        PB = 1,
        PC = 2,
        PD = 3,
        PE = 4,
        PF = 5,
        PG = 6,
    } PORT;
    
    typedef enum {
        IN = 0x00,
        OUT = 0x01,
        AUX = 0x02,
        INT = 0x06,
        DISABLE = 0x07,
    } PIN_MODE;
    
    extern PIO_Map *PIO;
    
    void GPIO_Init(void);
    void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode);
    void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level);
    unsigned int GPIO_GetPin(PORT port, unsigned int pin);
    int GPIO_Free(void);
    #endif

    main.c

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include "gpio.h"
    #include <stdbool.h>
    int main()
    {
        int a=0,b=-1,i;
        GPIO_Init();
        GPIO_ConfigPin(PB,4,OUT);
        GPIO_ConfigPin(PB,5,OUT);
        for(i=0;i<20;i++)
        {
            GPIO_SetPin(PB,4,a=~a);//!!-1的取反是0 1的取反是-2....
            GPIO_SetPin(PB,5,b=~b);
            //usleep(100000);
            sleep(1);
        }
        GPIO_Free();
    }

    makefile

    TARGET        = myGPIO    #可执行文件名称
    
    ########################编译参数############################
    CC            = arm-linux-gnueabihf-gcc 
    CXX           = arm-linux-gnueabihf-g++ 
    DEFINES       = 
    CFLAGS        = -pipe -g -Wall -W -fPIE $(DEFINES)
    CXXFLAGS      = -pipe -g -Wall -W -fPIE $(DEFINES)
    INCPATH       = -I. 
    
    
    ########################编译文件############################
    SOURCES       = ./main.c ./gpio.c
    OBJECTS       = main.o gpio.o
    
    $(TARGET) : $(OBJECTS)
            $(CC) -o $(TARGET) $(OBJECTS)
    main.o : main.c gpio.h
            $(CC) $(include) $(CFLAGS) -c main.c 
    gpio.o : gpio.c gpio.h 
            $(CC) $(include) $(CFLAGS) -c gpio.c 
    clean :
            rm  $(OBJECTS) $(TARGET)

    3.运行

    将程序编译出来放到v3s上运行,那么pb4 pb5 会交替高低电平。

  • 相关阅读:
    Falsy Bouncer(算法)
    Check for Palindromes(算法)
    ecshop 修改模板可输出php代码
    ecshop显示所有分类树栏目
    ecshop首页调用评论及图片
    ECSHOP 商品评论条件修改——购买过该商品且只能评价一次(购买多少次能评价多少次)
    PS4破解
    Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
    Java中类方法与实例方法的区别
    Java中类及方法的加载顺序
  • 原文地址:https://www.cnblogs.com/ZQQH/p/8547822.html
Copyright © 2020-2023  润新知