LED 디스플레이를 제어하는 안드로이드 Gpio 용례

13644 단어 androidmcugpio
이 시험에서는 GPIO 포트 위쪽 드롭다운을 사용하여 소등의 켜기와 끄기를 제어합니다.응용층에서 프레임워크로 막 전환한 병사로서 이 글을 쓰면 공부를 도와줄 수 있기를 바랍니다.

GPIO 소개


GPIO는 영어로 모두 범용 IO 포트, 즉 범용 IO 포트라고 합니다.삽입식 시스템은 통상적으로 상대적으로 간단한 외부 설비/회로를 대량으로 가지고 있다.이 장치/회로 중 일부는 CPU가 제어 수단을 제공하고 일부는 CPU가 입력 신호로 사용해야 한다.또한 이러한 장치/회로 중 많은 것들은 한 자리만 필요합니다. 즉, 두 가지 켜기/끄기 상태, 예를 들어 불이 켜지거나 꺼지는 상태만 있으면 됩니다.이러한 장치/회로 제어에는 기존 직렬 또는 병렬 포트가 적합하지 않습니다.
따라서 보통 마이크로컨트롤러 칩에'유니버설 프로그래밍 가능한 IO 인터페이스', 즉 GPIO를 제공한다.
문외한으로 말하자면, 어떤 파이프 발은 고전평과 저전평을 출력하거나, 그것들을 통해 파이프 발의 상태를 읽을 수 있다. 그것이 고전평이든 저전평이든.

커널에서 장치 생성


의 원리


GPIO 포트 문자 장치 드라이버에 대해 다음 단계를 수행해야 합니다.
1 원리도에 해당하는 GPIO 포트를 찾아 출력 디렉터로 구성
GPIO 포트 구성(플랫폼 구성에 따라 다름)은 동일하지만 용도는 같습니다.GPIO 포트 출력 및 기본 로우 레벨 설정, 57개의 핀 연결
<&범위 561 0x1500>
<&range 571 0x1500> gpio 포트로 사용할 57개의 트랙을 나타냅니다. 기본값은 저전압
이 io 포트 레지스터 주소: 0xe46002e4
하지만 디버깅 과정에서
#define gpio_lp 57
gpio_request(gpio_lp,"pos_pwr");
gpio_set_value(gpio_lp,1);
GPIO 호출 요청 보고 오류로 인해 GPIO를 사용할 수 없지만 GPIO 포트를 변경하면 오류가 보고되지 않습니다.
이것은 intel의 특수성 때문입니다: gpio가 vmm를 대체하기 위해 호출되어 내부 핵에서 조작할 수 없습니다. (유니버설 플랫폼은 이 조작에 문제가 없습니다)
나중에 나는 다른 방법을 생각해냈다
void _iomem*ldo_mmio_base=ioremap(0xe46002e4,4);
iowrite32(0x1700, ldo mmio 기지)//1700은 레지스터 설정(0xe46002e4)이 GPIO 포트이고 출력이 높음을 나타냅니다.
iowrite32(0x1500, ldo mmio 기)//1500은 레지스터 (0xe46002e4)가 GPIO 포트이고 출력이 낮음을 나타냅니다.
입출력 포트 제어

이루어지다


원본 코드를kenel-3.10/drivers/char 아래에 놓고 시스템에 장치 노드를 생성합니다:/dev/mtgpio. 두 군데에서 수정해야 합니다.
먼저kernel-3.10/drivers/char 디렉터리에 들어가서 새 파일을 추가합니다. 이것을lp6735 스위치라고 명명합니다.c 코드는 다음과 같습니다.
kernel-3.10/drivers/char$vim lp6735 스위치.c
#include <linux/module.h> /* For module specific items */
#include <linux/moduleparam.h> /* For new moduleparam's */
#include <linux/types.h> /* For standard types (like size_t) */
#include <linux/errno.h> /* For the -ENODEV/... values ​​*/
#include <linux/kernel.h> /* For printk/panic/... */
#include <linux/fs.h> /* For file operations */^M
#include <linux/ioport.h> /* For io-port access */
#include <linux/platform_device.h> /* For platform_driver framework */
#include <linux/init.h> /* For __init/__exit/... */
#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
#include <linux/io.h> /* For inb/outb/... */
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h> /*kamlloc */
//#include <asm-generic/ioctl.h>

 //ioctl
#define CMD_FLAG'i'
#define led_PWR_ON _IOR(CMD_FLAG,0x00000001,__u32)
#define led_PWR_OFF _IOR(CMD_FLAG,0x00000000,__u32)
#define gpio_lp 57

static int major =0;
static struct classclass *led_class;
struct cdev_led {
    struct cdev cdev;
};
struct cdev_led *led_dev;

static int led_ioctl(struct file* filp,unsigned int cmd,unsigned long argv)
{
    printk(KERN_INFO "entry kernel.... \n");
    printk(KERN_INFO "%d\n", led_PWR_ON);
    void __iomem *ldo_mmio_base = ioremap(0xe46002e4, 4);

    switch(cmd)
    {
        case led_PWR_ON:
        {
#if 0
            gpio_set_value(gpio_lp,1); //
            printk(KERN_INFO "led on\n");
#endif
            iowrite32(0x1700, ldo_mmio_base)
            break;
        }
        case led_PWR_OFF:
        {
#if 0
            gpio_set_value(gpio_lp,0);
            printk(KERN_INFO "led off \n");
#endif
            iowrite32(0x1500, ldo_mmio_base);
            break;
        }
        default:
            return -EINVAL;
    }
    return 0;
}


//open
static int led_open(struct inode* i_node,struct file* filp)
{
    printk(KERN_INFO "larsonzhong open init.... \n");
    int err;
// larsonzhong Content between #if 0 #endif would comment, because there is no actual device
 #if 0
    err = gpio_request(gpio_lp,"led_pwr");
    if(err<0)
    {
        printk(KERN_INFO "gpio request faile \n");
        return err;
    }
    gpio_direction_output(gpio_lp,1);
 #endif
    return 0;
}

//close
static void led_close(struct inode* i_node,struct file* filp)
{
printk(KERN_INFO "larsonzhong close init \n");
// larsonzhong Content between #if 0 #endif would comment, because there is no actual device
#if 0
    gpio_free(gpio_lp);
#endif
    return;
}

/* file operations */
struct file_operations fops={
    .owner = THIS_MODULE,
    .open = led_open,
    .unlocked_ioctl = led_ioctl,
    .release = led_close,
};

static int __init led_init(void)
{
    printk(KERN_INFO "init .... \n");
    dev_t dev_no;
    int result,err;
    err = alloc_chrdev_region(&dev_no,0,1,"my_led"); //dynamic request device number
    if(err<0)
    {
        printk(KERN_INFO "ERROR\n");
        return err;
    }
    major = MAJOR(dev_no);
    led_dev = kmalloc(sizeof(struct cdev_led),GFP_KERNEL);
    if(!led_dev)
    {
        result = -ENOMEM;
        goto fail_malloc;
    }
    memset(led_dev,0,sizeof(led_dev));

    cdev_init(&led_dev->cdev,&fops);
    led_dev->cdev.owner = THIS_MODULE;
    result = cdev_add(&led_dev->cdev,dev_no,1);
    if(result <0)
    {printk(KERN_INFO "error\n");
        goto fail_add;
    }
    led_class = class_create(THIS_MODULE,"mtgpio"); //in sys/class create sysfs file
    device_create(led_class,NULL,MKDEV(major,0),NULL,"mtgpio"); //dynamic create device file /dev/myled
    return 0;
fail_add:
    kfree(led_dev);
fail_malloc:
    unregister_chrdev_region(dev_no,1);
    return result;

}

static void __exit led_exit(void)
{
    dev_t dev_no=MKDEV(major,0);

    unregister_chrdev_region(dev_no,1);
    cdev_del(&led_dev->cdev);
    kfree(led_dev);
    device_destroy(led_class,dev_no);
    class_destroy(led_class);
    printk(KERN_INFO "exit........ \n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("[email protected]");
MODULE_DESCRIPTION("control_led_power");
MODULE_LICENSE("GPL");

저장하고 종료한 다음 같은 디렉터리의makefile 파일을 수정해야 합니다.
kernel-3.10/drivers/char$vim Makefile에 다음과 같은 세그먼트를 추가합니다.
+obj-y+=lp6735 스위치.o
특정 코드는 csd에서 일부 특수 기호를 처리하기 때문에 그림만 업로드할 수 있습니다.

lp6735 스위치를 추가하면Makefile을 수정하면/dev//dev/mtgpio에서 펌웨어 생성 노드가 생성됩니다.
이 노드를 읽기와 쓰기를 하려면 노드의 시스템 소유자와 권한을 수정해야 합니다.이 절차는 init에서 실행됩니다.rc.
제 코드는 시스템/core/rootdir/init입니다.철근 콘크리트
   ...
   # added by [email protected] change my devices mqgpio
   chown system system /dev/mtgpio
   chmod 0766 /dev/mtgpio
   ...

실험을 시작하다


우리는 우리가 사용하고자 하는 작은 램프의 장치가 dev/mtgpio##Jni 헤더 파일이라고 가정한다
새 안드로이드 프로젝트를 만들고 새 클래스를 만듭니다. 여기는 Gpio LED입니다.자바.
대상
public class GpioLED {
To
//Control LED power on
public native static void ledPowerOn();
// Control the LED to power off
public native static void ledPowerOff();
}
대상
헤드 파일 생성
방법1: 간단하면서도 거칠다
자바 생성을 사용하려면 자바 환경이 설정되어 있음을 주의하십시오. (환경 설정 클래스 경로 설정 포함)
원본 코드에서 bin 디렉터리에 있는classes 디렉터리로 이동하고javah-jni 패키지 이름을 사용합니다.클래스 이름, 여기는javah-jni-com입니다.과반.래드는 간단해.래드피오
우리는 디렉터리에서 헤더 파일을 볼 수 있고 헤더 파일을 열 수 있다.성명을 베껴 넣다.
방법2: 편리함
[컴파일] 버튼 옆에 있는 작은 삼각형, [컴파일] 버튼 옆에 있는 도구상자를 클릭하여 드롭다운 목록을 팝업하고, [외부 도구 구성]을 클릭하여 대화 상자를 팝업하고,
우리는 프로그램을 선택하고 위의 새 단추를 눌렀다.그런 다음 다음과 같이 입력합니다.
기본 카드:
이름:javah
위치:javah가 있는 디렉터리를 선택합니다.C:\Program Files\Java\jdk1입니다.8.0_102\bin\javah.exe
작업 디렉터리: 변수 단추를 누르면 목록을 팝업하고 프로젝트 loc를 선택하여 확인한 다음 끝에\src를 추가합니다. 결과는 ${프로젝트 loc}\src입니다
매개 변수: -classpath${project loc}\bin\classes-d${project loc}\jni-jni${java type name}
카드 새로 고침:
완료 후 리소스 새로 고침 확인
일반 카드:
외부 도구를 선택하고 적용 을 클릭합니다.

jni 구현


새 c 파일과 mk 파일을 만듭니다.만약 eclipse를 사용하고 ndk를 설정했다면 (ndk는 eclipse에서 설정해야 할 뿐만 아니라 환경 변수에서도 설정해야 합니다.) 그렇지 않으면cygpath를 시작할 수 없습니다.Cygwin 오고 있나요?]잘못 1
항목을 마우스 오른쪽 버튼으로 클릭->Android 도구->네이티브 지원 추가
그리고 프로젝트 디렉터리에서 추가 폴더와 두 개의 파일을 볼 수 있습니다. 우리는 방금 복사한 헤더 파일 설명을 붙여 넣습니다.
내가 여기 있는 코드는 다음과 같다:ledcontrol.c
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<jni.h> // Must include this file
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <android/log.h>
//Command code in the driver.
#define CMD_FLAG'i'
#define LED_ON _IOR(CMD_FLAG,0x00000001,__u32)
#define LED_OFF _IOR(CMD_FLAG,0x00000000,__u32)

#define DEVICE_NAME "/dev/mtgpio"
int fd;


static const char *TAG="012";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

/* * Class: Linuxc
* Method: openled
* Signature: ()I
*/

JNIEXPORT void JNICALL Java_com_coban_ledsimple_LEDGpio_ledPowerOn(JNIEnv* env, jclass mc)
{
  LOGI("POWER ON BY LARSON");
  LOGI("LED_ON:%d LED_OFF:%d",LED_ON,LED_OFF);
  fd=open(DEVICE_NAME,O_RDWR);
  if(fd<0)
      {
            LOGI("don't open dev");
        }
        else
            {
            ioctl(fd,LED_ON,NULL);
            LOGI("open success");
            }


}

/* * Class: Linuxc
* Method: clsoeled
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_coban_ledsimple_LEDGpio_ledPowerOff(JNIEnv* env, jclass mc)
{
    LOGI("POWER Off BY LARSON");
    ioctl(fd,LED_OFF,NULL);
    close(fd);

}
여기에서 로그와 다른 헤더 파일을 사용했습니다. 관련 라이브러리를 포함해야 합니다.안드로이드를 수정합니다.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_LDLIBS := -lm -llog
LOCAL_MODULE := ledcontrol
LOCAL_SRC_FILES := ledcontrol.c

include $(BUILD_SHARED_LIBRARY)
주의해야 할 것은 LOCAL LDLIBS:=-lm-llog를include$(CLEAR VARS) 앞에 추가해서는 안 된다. 그렇지 않으면 삭제되고 효력을 상실할 것이다.
Application.mk
APP_ABI := all
모든 플랫폼의 so 파일을 컴파일한다는 뜻입니다. 컴파일을 지정하려면
APP_ABI:=armeabi armeabi-v7a x86
한 공간에 격리되다

so 파일 생성


우리는 소프트웨어를 직접 장치에 전송하거나 구축했다.프로젝트 디렉터리에 추가obj 폴더를 볼 수 있습니다.
libs 아래에 여러 개의 폴더가 있습니다. 이 폴더들은 서로 다른 플랫폼에 대응합니다.

어플리케이션 구현


제가 바로 여기서 코드를 발표할 거예요.
그는 웃었다.활용단어참조
package com.example.hellojni;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class HelloJniLED extends Activity {
private Button power_on;
private Button power_off;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
power_on = (Button) findViewById(R.id.power_on);
power_off = (Button) findViewById(R.id.power_off);

To
power_on.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("012", "power_on by android\n");
LEDGpio.ledPowerOn();

}
});
power_off.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("012", "power_off by android\n");
LEDGpio.ledPowerOff();

}
});

}
To
}

래드피오.활용단어참조
package com.coban.ledsimple;

import android.util.Log;

public class LEDGpio {
static {
try {
Log.i("012", "try to load ledcontrol.so");
System.loadLibrary("ledcontrol");
} catch (UnsatisfiedLinkError ule) {
Log.e("012", "WARNING: Could not load ledcontrol.so");
}
}

public native static void ledPowerOn();

public native static void ledPowerOff();
}

레이아웃 파일 활동 main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/position"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text=" power control "
        android:textColor="#ff0000"
        android:textSize="25sp" />

    <Button
        android:id="@+id/power_on"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/position"
        android:layout_centerHorizontal="true"
        android:layout_toLeftOf="@+id/position"
        android:text="power_on"
        android:textSize="18sp" />

    <Button
        android:id="@+id/power_off"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/position"
        android:layout_toRightOf="@+id/position"
        android:text="power_off"
        android:textSize="18sp" />

</RelativeLayout>

좋은 웹페이지 즐겨찾기