目录
前言
这是我的tiny4412学习笔记(仅供学习),看的是韦东山老师的安卓四期视频,所以程序大体上都是跟韦东山老师的程序相同。
软件版本
Android Studio 4.1.3
Ubuntu 12.04(用的韦东山老师配置好的虚拟机)
APP编写
这里的界面还算简单,就4个Checkbox和1个Button。所以直接上代码了。
MainActivity.java
package com.example.app_0001_leddemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;
import hardlibary.*;
public class MainActivity extends AppCompatActivity {
private boolean ledon=false;
private Button button = null;
private CheckBox LED1=null;
private CheckBox LED2=null;
private CheckBox LED3=null;
private CheckBox LED4=null;
class MyButtonListener implements View.OnClickListener{
@Override
public void onClick(View v) {
ledon = !ledon;
if(ledon){
button.setText("ALL OFF");
LED1.setChecked(true);
LED2.setChecked(true);
LED3.setChecked(true);
LED4.setChecked(true);
for(int i=0;i<4;i++)
HardControl.ledCtrl(i,1);
}
else {
button.setText("ALL ON");
LED1.setChecked(false);
LED2.setChecked(false);
LED3.setChecked(false);
LED4.setChecked(false);
for(int i=0;i<4;i++)
HardControl.ledCtrl(i,0);
}
}
}
public void onCheckboxClicked(View view){
boolean check = ((CheckBox) view).isChecked();
switch (view.getId()){
case R.id.led1:
if(check){
Toast.makeText(getApplicationContext(),"LED1 ON",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(0,1);
}
else{
Toast.makeText(getApplicationContext(),"LED1 OFF",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(0,0);
}
break;
case R.id.led2:
if(check){
Toast.makeText(getApplicationContext(),"LED2 ON",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(1,1);
}
else{
Toast.makeText(getApplicationContext(),"LED2 OFF",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(1,0);
}
break;
case R.id.led3:
if(check){
Toast.makeText(getApplicationContext(),"LED3 ON",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(2,1);
}
else{
Toast.makeText(getApplicationContext(),"LED3 OFF",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(2,0);
}
break;
case R.id.led4:
if(check){
Toast.makeText(getApplicationContext(),"LED4 ON",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(3,1);
}
else{
Toast.makeText(getApplicationContext(),"LED4 OFF",Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(3,0);
}
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button= (Button) findViewById(R.id.BUTTON);
LED1=(CheckBox) findViewById(R.id.led1);
LED2=(CheckBox) findViewById(R.id.led2);
LED3=(CheckBox) findViewById(R.id.led3);
LED4=(CheckBox) findViewById(R.id.led4);
button.setOnClickListener(new MyButtonListener());
HardControl.ledOpen();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="leddemo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.005"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.022" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="ALL ON"
android:id="@+id/BUTTON"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="43dp" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED1"
android:id="@+id/led1"
android:onClick="onCheckboxClicked"
/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED2"
android:id="@+id/led2"
android:onClick="onCheckboxClicked"
/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED3"
android:id="@+id/led3"
android:onClick="onCheckboxClicked"
/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED4"
android:id="@+id/led4"
android:onClick="onCheckboxClicked"
/>
</android.support.v7.widget.LinearLayoutCompat>
HardControl.java
首先在java目录下新建hardlibary文件夹。然后创建HardControl.java,如图所示:
代码如下:
package hardlibary;
public class HardControl {
public static native int ledCtrl(int which,int status);
public static native int ledOpen();
public static native void ledClose();
static {
try {
System.loadLibrary("hardcontrol");
} catch (Exception e) {
e.printStackTrace();
}
}
}
编写JNI
编译libhardcontrol.so
新建hardcontrol.c,代码如下:
#include <jni.h> /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#if 0
typedef struct {
char *name;
char *signature;
void *fnPtr;
} JNINativeMethod;
#endif
static jint fd;
jint ledOpen(JNIEnv *env, jobject cls)
{
fd=open("/dev/leds",O_RDWR);
if(fd>=0)
return 0;
else
return -1;
__android_log_print(ANDROID_LOG_DEBUG,"LEDDemo","native ledOpen... %d",fd);
return 0;
}
void ledClose(JNIEnv *env, jobject cls)
{
__android_log_print(ANDROID_LOG_DEBUG,"LEDDemo","native ledClose...");
close(fd);
}
jint ledCtrl(JNIEnv *env, jobject cls,jint which,jint status)
{
int ret=ioctl(fd,status,which);
__android_log_print(ANDROID_LOG_DEBUG,"LEDDemo","native ledCtrl : %d, %d, %d",which,status,ret);
return ret;
}
static const JNINativeMethod methods[] = {
{"ledOpen", "()I", (void *)ledOpen},
{"ledClose", "()V", (void *)ledClose},
{"ledCtrl", "(II)I", (void *)ledCtrl},
};
/* System.loadLibrary */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "hardlibary/HardControl");
if (cls == NULL) {
return JNI_ERR;
}
/* 2. map java hello <-->c c_hello */
if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])) < 0)
return JNI_ERR;
return JNI_VERSION_1_4;
}
将hardcontrol.c上传至虚拟机,使用
arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include/ /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so
命令进行编译。将得到的libhardcontrol.so复制放到APP工程特定目录下,如图:
然后打开app的build.gradle文件:
在里面添加如下代码:
android {
defaultConfig {
//----------------------------------------------------------------------------
sourceSets {
main {
jniLibs.srcDirs = ['app/libs']
jniLibs.srcDirs = ['src/main/libs']
}
}
ndk {
// 设置支持的SO库架构
abiFilters 'armeabi'
}
//----------------------------------------------------------------------------
}
}
编写内核代码
新建leds_4412.c,输入以下代码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include<linux/device.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
static int led_gpios[] = {
EXYNOS4212_GPM4(0),
EXYNOS4212_GPM4(1),
EXYNOS4212_GPM4(2),
EXYNOS4212_GPM4(3),
};
static struct class *cls;
static int led_open(struct inode *inode,struct file *file){
int i;
for(i=0;i<4;i++)
s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);
return 0;
}
static long leds_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{ if((cmd!=0)&&(cmd!=1))
return -EINVAL;
if(arg>4)
return -EINVAL;
gpio_set_value(led_gpios[arg], !cmd);
return 0;
}
static struct file_operations leds_ops = {
.owner = THIS_MODULE ,
.open = led_open,
.unlocked_ioctl= leds_ioctl,
};
static int major;
int leds_init(void)
{
major=register_chrdev(0,"leds",&leds_ops);
cls = class_create(THIS_MODULE, "leds");
device_create(cls, NULL, MKDEV(major, 0), NULL, "leds"); /* /dev/leds */
return 0;
}
void leds_exit(void){
device_destroy(cls,MKDEV(major,0));
class_destroy(cls);
unregister_chrdev(major,"leds");
}
module_init(leds_init);
module_exit(leds_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liuziliang00000@gmail.com");
将leds_4412.c上传至虚拟机linux-3.0.86/drivers/char/目录下。修改Makefile文件,添加
obj-y += leds_4412.o
后保存。
然后返回linux-3.0.86/目录,使用make zImage
重新编译内核后烧写到开发板,这里略过,手册里有详细步骤,懒得写了。
最终效果