您尚未登录。

#2 计算机图形/GUI/RTOS/FileSystem/OpenGL/DirectX/SDL2 » 【lvgl疑问】程序无法读取event事件,evdev_read()未被调用 » 2022-11-29 17:02:57

SwordofMorning
回复: 1

我尝试使用lvgl来实现一个图形界面的程序,现在UI可以显示在屏幕上,但是触摸屏没有反应。

我用的触摸芯片是GT911,我使用evtest或者ts_print都能读取到触摸屏的信息,但是lvgl应用却似乎没有调用evdev_read()。下面是我用evtest的输出:

No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:	rk805 pwrkey
/dev/input/event1:	goodix-ts
/dev/input/event2:	adc-keys
/dev/input/event3:	Rmoncam A2 1080P: RMONCAM A2 10
Select the device event number [0-3]: 1
Input driver version is 1.0.1
Input device ID: bus 0x18 vendor 0xdead product 0xbeef version 0x28bb
Input device name: "goodix-ts"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 330 (BTN_TOUCH)
  Event type 3 (EV_ABS)
    Event code 48 (ABS_MT_TOUCH_MAJOR)
      Value      0
      Min        0
      Max      255
    Event code 50 (ABS_MT_WIDTH_MAJOR)
      Value      0
      Min        0
      Max      255
    Event code 53 (ABS_MT_POSITION_X)
      Value      0
      Min        0
      Max      800
    Event code 54 (ABS_MT_POSITION_Y)
      Value      0
      Min        0
      Max     1280
    Event code 57 (ABS_MT_TRACKING_ID)
      Value      0
      Min        0
      Max      255
Properties:
  Property type 1 (INPUT_PROP_DIRECT)
Testing ... (interrupt to exit)
Event: time 1501847472.953342, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1501847472.953342, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 195
Event: time 1501847472.953342, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 92
Event: time 1501847472.953342, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 26
Event: time 1501847472.953342, type 3 (EV_ABS), code 50 (ABS_MT_WIDTH_MAJOR), value 26
Event: time 1501847472.953342, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 0
Event: time 1501847472.953342, ++++++++++++++ SYN_MT_REPORT ++++++++++++
Event: time 1501847472.953342, -------------- SYN_REPORT ------------
Event: time 1501847472.964185, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 195
Event: time 1501847472.964185, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 92
Event: time 1501847472.964185, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 26
Event: time 1501847472.964185, type 3 (EV_ABS), code 50 (ABS_MT_WIDTH_MAJOR), value 26
Event: time 1501847472.964185, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 0
Event: time 1501847472.964185, ++++++++++++++ SYN_MT_REPORT ++++++++++++
Event: time 1501847472.964185, -------------- SYN_REPORT ------------
Event: time 1501847472.974098, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 195
Event: time 1501847472.974098, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 92
Event: time 1501847472.974098, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 26
Event: time 1501847472.974098, type 3 (EV_ABS), code 50 (ABS_MT_WIDTH_MAJOR), value 26
Event: time 1501847472.974098, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 0
Event: time 1501847472.974098, ++++++++++++++ SYN_MT_REPORT ++++++++++++
Event: time 1501847472.974098, -------------- SYN_REPORT ------------
Event: time 1501847472.984269, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 195
Event: time 1501847472.984269, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 92
Event: time 1501847472.984269, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 26
Event: time 1501847472.984269, type 3 (EV_ABS), code 50 (ABS_MT_WIDTH_MAJOR), value 26
Event: time 1501847472.984269, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 0
Event: time 1501847472.984269, ++++++++++++++ SYN_MT_REPORT ++++++++++++
Event: time 1501847472.984269, -------------- SYN_REPORT ------------
Event: time 1501847472.994804, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1501847472.994804, -------------- SYN_REPORT ------------

对于lvgl程序,我在lv_drv_conf.h中启用了如下内容:

#  define USE_EVDEV           1
#  define EVDEV_NAME   "/dev/input/event1"

下面是我的主函数,以及evdev_read()函数。

int main(void)
{

    // DRM_Init();

	// pthread_t pth_capt;

	// pthread_create(&pth_capt, NULL, (void*)V4L2_SP_Streaming, NULL);

#if 1
/* ================ */
/* ===== LVGL ===== */
/* ================ */

    /*LittlevGL init*/
    lv_init();

    /*Linux frame buffer device init*/
    drm_init();

    /*A small buffer for LittlevGL to draw the screen's content*/
    static lv_color_t buf[DISP_BUF_SIZE], buf1[DISP_BUF_SIZE];

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;
    // lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);
    lv_disp_draw_buf_init(&disp_buf, buf, buf1, DISP_BUF_SIZE);

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb   = drm_flush;
    disp_drv.hor_res    = 800;
    disp_drv.ver_res    = 1280;
    // disp_drv.screen_transp = 1;
    lv_disp_drv_register(&disp_drv);

#if 1
    // trans background
    lv_style_t style_scr_act;
    lv_style_init(&style_scr_act);
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_TRANSP);
    lv_obj_add_style(lv_scr_act(), &style_scr_act, 0);
    // lv_disp_set_bg_opa(lv_scr_act(), LV_OPA_TRANSP);
#endif

#if 1
    evdev_init();
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    /*This function will be called periodically (by the library) to get the mouse position and state*/
    indev_drv_1.read_cb = evdev_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);    
    // debug
    if (mouse_indev)
    {
        printf("register success.\n");
    }
    else
    {
        printf("register fail.\n");
    }
#endif

#if 1
    /*Set a cursor for the mouse*/
    LV_IMG_DECLARE(mouse_cursor_icon)
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/
#endif
    
    mystart();
 
    printf("Start handler\n");

    /*Handle LitlevGL tasks (tickless mode)*/
    while(1) {
        lv_timer_handler();
        usleep(5000);
    }

#endif

    // pthread_exit(NULL);

    return 0;
}

void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
    struct input_event in;

    printf("[DEBUG] Entered evdev_read() function...\n");

    while(read(evdev_fd, &in, sizeof(struct input_event)) > 0) {
        if(in.type == EV_REL) {
            printf("[DEBUG] in.type == EV_REL\n");
            if(in.code == REL_X)
				#if EVDEV_SWAP_AXES
					evdev_root_y += in.value;
				#else
					evdev_root_x += in.value;
				#endif
            else if(in.code == REL_Y)
				#if EVDEV_SWAP_AXES
					evdev_root_x += in.value;
				#else
					evdev_root_y += in.value;
				#endif
        } else if(in.type == EV_ABS) {
            printf("[DEBUG] in.type == EV_ABS\n");
            if(in.code == ABS_X)
				#if EVDEV_SWAP_AXES
					evdev_root_y = in.value;
				#else
					evdev_root_x = in.value;
				#endif
            else if(in.code == ABS_Y)
				#if EVDEV_SWAP_AXES
					evdev_root_x = in.value;
				#else
					evdev_root_y = in.value;
				#endif
            else if(in.code == ABS_MT_POSITION_X)
                                #if EVDEV_SWAP_AXES
                                        evdev_root_y = in.value;
                                #else
                                        evdev_root_x = in.value;
                                #endif
            else if(in.code == ABS_MT_POSITION_Y)
                                #if EVDEV_SWAP_AXES
                                        evdev_root_x = in.value;
                                #else
                                        evdev_root_y = in.value;
                                #endif
            else if(in.code == ABS_MT_TRACKING_ID) {
                                if(in.value == -1)
                                    evdev_button = LV_INDEV_STATE_REL;
                                else if(in.value == 0)
                                    evdev_button = LV_INDEV_STATE_PR;
            }
        } else if(in.type == EV_KEY) {
            printf("[DEBUG] in.type == EV_KEY\n");
            if(in.code == BTN_MOUSE || in.code == BTN_TOUCH) {
                if(in.value == 0)
                    evdev_button = LV_INDEV_STATE_REL;
                else if(in.value == 1)
                    evdev_button = LV_INDEV_STATE_PR;
            } else if(drv->type == LV_INDEV_TYPE_KEYPAD) {
#if USE_XKB
                data->key = xkb_process_key(in.code, in.value != 0);
#else
                switch(in.code) {
                    case KEY_BACKSPACE:
                        data->key = LV_KEY_BACKSPACE;
                        break;
                    case KEY_ENTER:
                        data->key = LV_KEY_ENTER;
                        break;
                    case KEY_PREVIOUS:
                        data->key = LV_KEY_PREV;
                        break;
                    case KEY_NEXT:
                        data->key = LV_KEY_NEXT;
                        break;
                    case KEY_UP:
                        data->key = LV_KEY_UP;
                        break;
                    case KEY_LEFT:
                        data->key = LV_KEY_LEFT;
                        break;
                    case KEY_RIGHT:
                        data->key = LV_KEY_RIGHT;
                        break;
                    case KEY_DOWN:
                        data->key = LV_KEY_DOWN;
                        break;
                    case KEY_TAB:
                        data->key = LV_KEY_NEXT;
                        break;
                    default:
                        data->key = 0;
                        break;
                }
#endif /* USE_XKB */
                if (data->key != 0) {
                    /* Only record button state when actual output is produced to prevent widgets from refreshing */
                    data->state = (in.value) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
                }
                evdev_key_val = data->key;
                evdev_button = data->state;
                return;
            }
        }
    }

    if(drv->type == LV_INDEV_TYPE_KEYPAD) {
        /* No data retrieved */
        data->key = evdev_key_val;
        data->state = evdev_button;
        return;
    }
    if(drv->type != LV_INDEV_TYPE_POINTER)
        return ;
    /*Store the collected data*/

#if EVDEV_CALIBRATE
    data->point.x = map(evdev_root_x, EVDEV_HOR_MIN, EVDEV_HOR_MAX, 0, drv->disp->driver->hor_res);
    data->point.y = map(evdev_root_y, EVDEV_VER_MIN, EVDEV_VER_MAX, 0, drv->disp->driver->ver_res);
#else
    data->point.x = evdev_root_x;
    data->point.y = evdev_root_y;
#endif

    // debug
    printf("[DEBUG] evdev_root_x: %d\n", evdev_root_x);
    printf("[DEBUG] evdev_root_y: %d\n", evdev_root_y);
    printf("[DEBUG] evdev_button: %d\n", evdev_button);

    data->state = evdev_button;

    if(data->point.x < 0)
      data->point.x = 0;
    if(data->point.y < 0)
      data->point.y = 0;
    if(data->point.x >= drv->disp->driver->hor_res)
      data->point.x = drv->disp->driver->hor_res - 1;
    if(data->point.y >= drv->disp->driver->ver_res)
      data->point.y = drv->disp->driver->ver_res - 1;

    printf("[DEBUG] Leaving evdev_read() function...\n");

    return ;
}

通过打印信息可以确定,程序进入了handler循环,并且没有挂掉。但是evdev_read()函数中的调试信息没有被打印,我尝试了触摸屏和鼠标,均不能使其被调用。我参考了github上的一个问题,该用户使用了/dev/input/touchscreen0替换/event2,并且解决了该问题。但是我这边只有如下的设备:

by-id  by-path	event0	event1	event2	event3	mice

我使用的kernel版本是4.19,lvgl版本为8.3。我不确定是否时程序对evdev的初始化出现了问题。

感谢您的回复。

#3 Re: 全志 SOC » 【I2C】当ADC输入大于1v时读取错误 » 2022-07-05 10:38:09

可以看到D14的数据本来应该拉高的,但是Nano这边却在将SDA拉低。
libi2c.png
但是除了这一位和低八位的数据,接收的其他数据确是正常的。之后我又使用gpiod库来手动模拟了i2c,但是该问题仍然存在:
gpiod.png
可以看到,除了config八位的数据是正常的,data的数据均没有被拉起来。这三个字节使用同一段代码读取,不知道是哪里出的问题。下面是我模拟i2c的代码:

struct gpiod_chip* gpiochip0;
struct gpiod_line* line_SCL;
struct gpiod_line* line_SDA;

int PE11Num = (4 * 32) + 11;
int PE12Num = (4 * 32) + 12;

bool i2cInit()
{
    gpiochip0 = gpiod_chip_open("/dev/gpiochip0");
    line_SCL = gpiod_chip_get_line(gpiochip0, PE11Num);
    line_SDA = gpiod_chip_get_line(gpiochip0, PE12Num);

    int reqSCL = gpiod_line_request_output(line_SCL, "SCL", 1);
    int reqSDA = gpiod_line_request_output(line_SDA, "SDA", 1);

    return !(reqSCL | reqSDA);
}

bool i2cSDAConf(bool toOutput)
{
    int reqSDA;

    gpiod_line_release(line_SDA);

    if (toOutput)
    {
        int reqSDA = gpiod_line_request_output(line_SDA, "SDA", 1);
    }
    else
    {
        int reqSDA = gpiod_line_request_input(line_SDA, "SDA");
    }

    return !reqSDA;
}

void i2cSDALevel(bool toHigh)
{
    gpiod_line_set_value(line_SDA, toHigh);
}

void i2cSCLLevel(bool toHigh)
{
    gpiod_line_set_value(line_SCL, toHigh);
}

void i2cDelay()
{
    for (int i = 0; i < 1000; ++i) { /* do nothing */ }
}

void i2cStart()
{
    i2cSDALevel(1);
    i2cSCLLevel(1);
    i2cDelay();
    i2cSDALevel(0);
    i2cDelay();
    i2cSCLLevel(0);
    i2cDelay();
}

void i2cEnd()
{
    i2cSDALevel(0);
    i2cDelay();
    i2cSCLLevel(1);
    i2cDelay();
    i2cSDALevel(1);
}

void i2cACK()
{
    // make sure the SDA is output before send
    i2cSDAConf(1);

    i2cSDALevel(0);
    i2cDelay();
    i2cSCLLevel(1);
    i2cDelay();
    i2cSCLLevel(0);
    i2cDelay();
}

void i2cNACK()
{
    // make sure the SDA is output before send
    i2cSDAConf(1);

    i2cSDALevel(1);
    i2cDelay();
    i2cSCLLevel(1);
    i2cDelay();
    i2cSCLLevel(0);
    i2cDelay();
}

bool i2cSDARelease()
{
    // i2cSDALevel(0);
    return i2cSDAConf(0);
}

bool i2cWaitAck()
{
    return !i2cGetSDA();
}

void i2cSend(u8 data)
{
    // make sure the SDA is output before send
    i2cSDAConf(1);

    for (int i = 0; i < 8; ++i)
    {
        if (data & 0x80)
            i2cSDALevel(1);
        else
            i2cSDALevel(0);
        
        i2cDelay();
        i2cSCLLevel(1);
        i2cDelay();

        i2cSCLLevel(0);
        i2cDelay();

        data <<= 1;
    }

    // 释放SDA
    i2cSDARelease();
}

bool i2cGetSDA()
{
    i2cSCLLevel(1);
    i2cDelay();

    bool level = gpiod_line_get_value(line_SDA);

    i2cSCLLevel(0);
    i2cDelay();

    return level;
}

u8 i2cReceive()
{
    i2cSDARelease();

    u8 data;

    for (int i = 0; i < 8; ++i)
    {
        data <<= 1;
        data |= i2cGetSDA();
    }
    
    return data;
}

u8 i2cReceiveDebug(u32* biasDebug)
{
    i2cSDARelease();

    u8 data;

    for (int i = 0; i < 8; ++i)
    {
        data <<= 1;
        data |= i2cGetSDA();
        *biasDebug <<= 2;

        // 查看pull寄存器状态
        static int dev_fd;
        unsigned char *map_base;
        dev_fd = open("/dev/mem", O_RDWR);
        map_base = (unsigned char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, GPIO_PAGE_OFFSET);
        *biasDebug |= (*(volatile u32*)(map_base + GPIO_BASE_OFFSET + rPE_PULL0)) >> 24 & 0b11;
        munmap(map_base, MAP_SIZE);
    }
    
    return data;
}

void i2cRelease()
{
    gpiod_chip_close(gpiochip0);
}

void i2cClear()
{
    i2cSDARelease();
    for (int i = 0; i < 32; ++i)
    {
        i2cSCLLevel(0);
        i2cSCLLevel(1);
    }
}

ADS1110读取,在start之前和end之后,我输出了一段scl的时钟,以期对清楚ADS1110的寄存器内容。

void ADS1110_ReadData()
{
    if(!i2cInit())
    {
        printf("I2C init error\n");
        i2cRelease();
        exit(1);
    }

    i2cClear();

    i2cSDAConf(1);

    i2cStart();
    
    u8 addr = 0b10010001;

    i2cSend(addr);

    if (!i2cWaitAck())
    {
        printf("none ACK received\n");
        printf("%d\n", gpiod_line_direction(line_SDA));
        i2cRelease();
        exit(1);
    }

    u8 data[3];

    data[0] = i2cReceive();
    i2cACK();
    data[0] = i2cReceive();
    i2cACK();
    data[0] = i2cReceive();
    i2cNACK();

    i2cEnd();

    i2cClear();

    i2cRelease();

    printf("%x %x %x\n", data[0] & 0xFF, data[1] & 0xFF, data[2] & 0xFF);
}

同时,总线上只有ADS1110一个设备:

# i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

#4 全志 SOC » 【I2C】当ADC输入大于1v时读取错误 » 2022-06-21 11:39:52

SwordofMorning
回复: 2

小弟今天用Licheepi Nano读取ADS1110,当输入数据小于等于1V时,能得到正确的数据,但是当输入大于1v时,得到的数据则是不正确的。代码如下:

#define NUMS 10
char readbuf[NUMS];

int main(int argc, char** argv)
{
    int file = open("/dev/i2c-0", O_RDWR);

    // addr = 1001 xxx
    int addr = 0b1001000;

    if (file < 0)
    {
        printf("openfile error!\n");
        exit(1);
    }

    if (ioctl(file, I2C_SLAVE, addr) < 0)
    {
        printf("ioctl error!\n");
        exit(1);
    }

    // Debug Gain 1
    readbuf[0] = 0x0C;

    if (write(file, readbuf, 1) != 1)
    {
        printf("write error!\n");
        exit(1);
    }

    if (read(file, readbuf, 3) != 3)
    {
        printf("read error!\n");
        exit(1);
    }

    printf("%x %x %x\n", readbuf[0] & 0xff, readbuf[1] & 0xff, readbuf[2] & 0xff);

    close(file);

    exit(EXIT_SUCCESS);
}

上述代码中我写入0x0C,使ADS1110以15sps、16bits输出,同时增益为1。当输入为1V时,输出为`3E 00 0C`,即,3E00 / 32767 * 2.048;当输入为1.5V时,输出大约应为`5E 00 0C'左右,但是我得到的数据大约为`1D 00`。使用调试器的时候能正确读取,请问我这里是哪里没写对吗,感谢大佬指出。

#6 全志 SOC » 【F1C100S】如何使用mmap控制GPIO? » 2022-05-20 11:08:30

SwordofMorning
回复: 3

我是一个嵌入式小白,前几天看了一位大佬的代码完成了基础的IO。源码是从PE4 PE5 PE6输出,我现在想通过PE2来输出信号,请问要怎么修改呢?可以请您具体讲一下例如&0X00000FFF之类的操作具体是什么含义吗?同时我要怎么完成信号输入呢?

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

#define GPIO_REG_BASE   0x01C20800      //GPIO物理基地址 (小页4kb)
#define MAP_SIZE        0x400 //MMU页大小
#define GPIO_BASE_OFFSET (GPIO_REG_BASE & 0X00000FFF) //GPIO基地址偏移计算
#define GPIO_PAGE_OFFSET (GPIO_REG_BASE & 0XFFFFF000) //获得页偏移

#define rPE_CFG0 0X90  //PE_CFG0寄存器地址偏移
#define rPE_DAT 0XA0    //PE_DAT寄存器地址偏移
#define rPE_PULL0 0XAC  //PE_PULL0寄存器地址偏移

int GPIOE_456_ON(unsigned char *MAP_BASE);//点亮PE4,PE5,PE6 这3盏LED
int  GPIOE_456_OFF(unsigned char *MAP_BASE);//关闭PE4,PE5,PE6 这3盏LED

int main(int argc, char **argv)
{
 static int dev_fd;
 unsigned char *map_base;
/*参数验证*/
    if(argc!=2 || (strcmp(argv[1],"on") && strcmp(argv[1],"off"))){
     printf("argv_error!please input 'on' or 'off'!\n");
       exit (0);
    }

    dev_fd = open("/dev/mem", O_RDWR );
    if (dev_fd < 0){
        printf("open(/dev/mem) failed.\n");
        return 0;
    }

map_base = (unsigned char *)mmap(NULL, 0x400,PROT_READ | PROT_WRITE, MAP_SHARED,dev_fd, GPIO_PAGE_OFFSET); //把物理地址映射到虚拟地址
if(*map_base)  printf("mmap_fail!\n"); //是否映射成功

if(!strcmp(argv[1],"on")) GPIOE_456_ON(map_base); //点亮PE4,PE5,PE6 这3盏LED
if(!strcmp(argv[1],"off")) GPIOE_456_OFF(map_base);//关闭PE4,PE5,PE6 这3盏LED
  //usleep(1000000);
    if(dev_fd) close(dev_fd);
    munmap(map_base,MAP_SIZE);//解除映射关系
    return 0;
}


//GPIOE_456_ON
int  GPIOE_456_ON(unsigned char *MAP_BASE)
{
unsigned int PE_CFG0,PE_DAT;
PE_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0);
PE_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0)=((PE_CFG0 & 0XF000FFFF)|0X01110000);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT)=((PE_DAT & 0XFFFFFF8F)|0X00000070);
}
//GPIOE_456_OFF
int  GPIOE_456_OFF(unsigned char *MAP_BASE)
{
unsigned int PE_CFG0,PE_DAT;
PE_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0);
PE_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0)=((PE_CFG0 & 0XF000FFFF)|0X01110000);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT)=((PE_DAT & 0XFFFFFF8F));
}

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn