从事安卓底层开发,工作一年,个人看法 ,处女答。个人感脚51就是就是搞嵌入式第一门技术。把c语言,模数电,硬件画板等第一次联系起来。在学校的时候我们的学习路线是:

1 : 51单片机(大二上学期的时候,我感觉我还是接触的挺晚的,嵌入式)

2:stm32+ucos ii (大二下学期到大三下学期)

3:Arm+linux (大四到毕业)

4.安卓驱动 ,JNI(工作,mtk平台)

然并卵,这句话适合51,但是也是非常非常非常重要的基础。如果作为学生的话,参加比赛啥的51还是不够用的。51作为最简单的单片机,真真的简单。相比于linux 安卓真的太简单。

第一次回答知乎问题,也不知道什么格式,我说到哪里就是哪里,以上一段是手机码的,回到家中,用电脑码字舒服多了。下面我是说到哪里就是哪里了。如果有啥问题欢迎评论,我会回答的,一有空。

---------------------------------------------------------------------------------------------------------------------------------------

51单片如我上文所说的,学生党接触的第一款单片机,答主是电子信息工程毕业的,接触的第一个单片机也是51,然后是STM32.51和STM32 STM32比51 难一点,不过本质上都是单片机,STM32片上外设多很多,定时器啥的复杂复杂复杂复杂复杂多的多。STM32片上外设多,功能强大,可以说学了STM32之后基本上所有的单片机应该都能马上上手的,虽然我也只是只接触到51 和STM32.。大四全国电子设计大赛之后就再也没有接触到单片机了。后来就一直是linux,android。下面是我毕业论文的一部分。

---------------------------------------------------------------------------------------------------------------

任何计算机系统都是软件和硬件的结合体,如果只有硬件而没有软件,则硬件是没有灵魂的躯壳;如果只有软件没有硬件,则软件就是一堆无用的字符。在底层硬件的基础上,操作系统覆盖一层驱动,屏蔽底层硬件的操作,通过特定的软件接口去操作底层硬件,用户在用户空间可以很容易的把软件设计目标放在策略与需求上,可以很方便的屏蔽掉底层实现,从而很好的完成客户功能需求。计算机系统是软件和硬件的结合体。而软件又分为应用层软件和驱动层软件。驱动层软件是应用层软件和底层硬件的纽带。通过驱动层软件实现对底层硬件屏蔽。

在裸机时代,比如单片机系统,程序员往往是直接操作硬件寄存器,直接设置硬件。而在Linux操作系统中,硬件驱动程序中实现对硬件直接操作,而用户空间,通过通用的系统调用接口,实现对硬件操作,应用程序没有直接操作底层设备,通过posix标准,应用程序的系统调用往往是被规定和限值,用户只能通过规定的接口实现对底层硬件的操作,导致了应用程序在类UINIX操作系统具有非常好的可移植性。

图2.1 直接操作硬件程序

上图2.1 是裸机时代,应用程序和硬件操作糅合在一起,应用程序和硬件操作高度耦合的框图,上述代码一般很难有良好的代码互用和移植性。往往从一个平台移植到另一个平台,甚至是同一平台不同硬件配置都要求很大的代码改动,另外从应用层来说,应用与驱动高度耦合,应用程序也几乎难以移植,甚至说是没有应用程序概念,原因在于应用与驱动的纠缠不清。

图2.2 无操作系统应用程序和设备驱动程序关系

上图2.2所示,良好的裸机代码框架,设备驱动层和应用层之间有良好的分层思想,用户可以较好的实现策略和需求,例如:客户要求实现流水灯程序,程序员在底层机制实现(硬件操作)的基础下,可以充分在用户应用程序中把主要精力方法流水灯的实现,即策略。但是在良好的裸机程序设计,代码移植性可能从一个平台移植到另外一平台只需要修改少量的底层驱动,例如:LED_ON()的实现。但是在用户空间,没有系统调用概念,函数接口千差万别。应用程序移植性差。

图2.3 Linux系统调用框图

操作系统中,需求决定应用程序,通过系统调用,调用底层驱动,此外,在驱动程序中,把一部分公用的驱动接口抽象出来,如此,程序员只需修改很少量的驱动资源,形成特定的驱动框架。导致用户只需添加专用的硬件属性作为平台资源,在内核中获取资源,大大解放了设备驱动开发,提高了设备驱动的通用型。在用户空间,由于遵循posix标准,类UNIX操作系统中,所有操作接口基本一样,从而方便了应用程序的移植,应用程序几乎不要做修改。如图2.3所示。

Linux操作系统对于所有的硬件都是当做一个文件来操作:一切设备皆文件。Linux设备文件一般分为字符设备,块设备,网络设备。在Linux系统中,除了网络设备之外,所有的设备都被映射到Linux的文件系统中。如图2.4所示。

图2.4 Linux操作系统与应用程序关系

--------------------------------------------------------------------------------------------------------------------------------------------

讲讲51,linux,安卓之间的差别。先申明一下,我是实际工作中没有使用过单片机,我使用单片机仅仅是用来参加全国电子设计大赛。工作主要在android driver这一块。我们这一行很多人说单片机是有瓶颈的,我也不是很清楚。但是实话实说,这鸟东西太简单了,没啥技术含量的,你要之后android的庞大。

欢迎点赞。后面会说说android,linux,51,32单片机之间的联系与学习方法,虽然我也是菜鸟,如果你现在看不懂也没关系,有个映像就行。以后就有方向去学习了。想当初我真的是一个人孤孤学习linux

===============================================================

补充一个:单片机要点亮一个led等,同样在安卓上你点亮一个灯也要驱动的,不然怎么亮呢,只是我们只看到了app。 背后驱动,怎么实现的,安卓架构,跟单片机有啥区别,相同的地方。其实手机arm芯片跟单片机都是嵌入式微处理器,单片机叫做微控制器。高通,mtk啥的也是嵌入式微处理器~都是一样的~但是难度你想想看就知道了。

51单片机大家都知道了,裸机,直接操作硬件,直观,简单,没有框架,没有系统。

STM32,可以学习一下RTOS了,实时的小系统,ucos II等等许多实时系统,STM32+ucos II这种组合学习方式还是挺好的。STM32比较难的在我印象中一个是时钟树,因为我们从51,没有时钟树的概念12M晶振,时钟不要你配置,而比较新的ARM框架,外设都是有时钟的。可能刚刚接触概念不是很清楚,但是也是很简单的。另外一个是定时器,什么输入捕获模式,定时器模式,编码器模式。。。。。强大的多,比起51。总的来说还是简单的。因为是没有框架的原因,代码量真的很少。你要知道,MTK android 5.1 所有的东西加起来 10G多,包括bootloader,linux kernel,android framework ,定制的部分。等等。我们接触的就那些目录,当你去看C++,java代码时,你就知道面向过程的代码真的很容易看。可能有些朋友不知道android的框架,以及android 与linux之间的关系,以及linux驱动与裸机的关系,联系与区别。你现在只要知道linux驱动比较大,android框架更大。单片机简单。单片机一般是C语言,而android一般涉及三种语言:底层linux内核C,中间的JNI层是C++,framework和app是java。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

学过51单片机的朋友知道,我们要点亮一个LED灯,是这样子的P0 = xxx ,我们就点亮了一个,好。一烧写,好,灯亮了。linux,上我们要亮一个灯,有点难了,有了操作系统,没那么容易了。一般人搞不定了。好,到android,更加难了。但是你想一想手机芯片也是ARM。亮灯这种肯定都是CPU的管脚操作。上了系统了,难了,点个灯都费劲的。本质上是一样的。很多人都知道单片机有瓶颈的。原因是会点硬件,会点C,轻轻松松就可以亮灯的。入门容易。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

我举一个小的例子说明一下51,linux,android三者的之间的差别。你就知道是啥区别。下面是51单片机:

大概是这样:

int main(void) //一个main函数 搞定{

P0 = 0xxx;

while(1);

return 0;

}

linux:

驱动程序:

#include#include#include //file_operatios#include//class_create/device_create#include //kmalloc#include //ioremap#include#include"led.h"

struct s5pv210_device *s5pv210_dev;

volatile unsigned long *gpc0con = NULL;

volatile unsigned long *gpc0dat = NULL;

static int led_open(struct inode *inode, struct file *file)

{

printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);

/*初始化GPC0_3,GPC0_4引脚功能为输出功能*/

*gpc0con &= ~((0xf<<12)|(0xf<<16));

*gpc0con |= ((0x1<<12)|(0x1<<16));

return 0;

}

static int led_close(struct inode *inode, struct file *file)

{

printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);

//iounmap(S5PV210_PA_GPC0CON);

return 0;

}

static ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *offset)

{

printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);

return 0;

}

//write(fd, &val, 4)staticssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)

{

int ret;

unsigned int val;

printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);

/*获取用户空间数据*/

ret = copy_from_user(&val,buf,count);

if(ret)

{

printk(KERN_ERR"copy data from user failed!\n");

return -ENODATA;

}

printk(KERN_INFO"copy data from user: val=%d\n",val);

if(val)

{

//点亮LED*gpc0dat |= ((0x1<<3)|(0x1<<4));

}

else

{

//熄灭LED*gpc0dat &= ~((0x1<<3)|(0x1<<4));

}

return ret?0:count;

}

static struct file_operations led_fops={

.owner = THIS_MODULE,

.open = led_open,

.read = led_read,

.write = led_write,

.release = led_close,

};

static int __init led_init(void)

{

int ret;

printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);

s5pv210_dev = kmalloc(sizeof(struct s5pv210_device),GFP_KERNEL);

if(s5pv210_dev==NULL)

{

printk(KERN_INFO"no memory malloc for s5pv210_dev!\n");

return -ENOMEM;

}

/*注册*/

led_major = register_chrdev(0,"led",&led_fops);

if(led_major<0)

{

printk(KERN_INFO"register major failed!\n");

ret = -EINVAL;

goto err1;

}

/*创建设备文件*/

s5pv210_dev->led_class = class_create(THIS_MODULE,"led_class");

if (IS_ERR(s5pv210_dev->led_class)) {

printk(KERN_ERR "class_create() failed for led_class\n");

ret = -EINVAL;

goto err2;

}

s5pv210_dev->led_device = device_create(s5pv210_dev->led_class,NULL,MKDEV(led_major,0),NULL,"led");

if (IS_ERR(s5pv210_dev->led_device)) {

printk(KERN_ERR "device_create failed for led_device\n");

ret = -ENODEV;

goto err3;

}

/*将物理地址映射为虚拟地址*/

gpc0con = ioremap(S5PV210_PA_GPC0CON,8);

if(gpc0con==NULL)

{

printk(KERN_INFO"ioremap failed!\n");

ret = -ENOMEM;

goto err4;

}

gpc0dat = gpc0con + 1;

return 0;

err4:

device_destroy(s5pv210_dev->led_class,MKDEV(led_major,0));

err3:

class_destroy(s5pv210_dev->led_class);

err2:

unregister_chrdev(led_major,"led");

err1:

kfree(s5pv210_dev);

return ret;

}

static void __exit led_exit(void)

{

printk(KERN_INFO"%s()-%d\n", __func__, __LINE__);

unregister_chrdev(led_major,"led");

device_destroy(s5pv210_dev->led_class,MKDEV(led_major,0));

class_destroy(s5pv210_dev->led_class);

iounmap(gpc0con);

kfree(s5pv210_dev);

}

module_init(led_init);

module_exit(led_exit);

MODULE_LICENSE("GPL");

应用程序:

#include

#include

#include

#include

#include

#include

#include

#include

/*

** ./led_test on 点亮LED

** ./led_test off 熄灭LED

*/

int main(int argc, char **argv)

{

int fd;

int val =0;

fd = open("/dev/led", O_RDWR);

if(fd<0)

{

perror("open failed!\n");

exit(1);

}

if(strcmp(argv[1], "on")==0)

{

val = 1;

}

else

{

val = 0;

}

if(write(fd, &val, 4)!=4)

{

perror("write failed!\n");

exit(1);

}

close(fd);

return 0;

}

android:

不知道大家清不清楚android与linux之间的关系。

android是基于linux内核的,linux操作系统的5大组件:驱动,内存管理,文件系统,进程管理,网络套接字。android是基于linux kernel上的,大家平时只看到了app。app是java语言的,其实每运行一个java应用程序,实际上是fork一个linux应用程序。android四大组件,activity,service,Broadcast Receiver,Content Provider。这是android的主要框架,java应用开发是基于这开发的。android平台是基于linux 内核的。在linux运行之后才建立起java世界。

直接上代码:上面的linux的驱动在android是一样的,适用于android。驱动ok之后是应用层了,也就是应用程序。我下面就是最直接的应用,不包含任何android框架性的东西,大家可以直接看到,应用app->jni->linux驱动这三层调用关系。下面是jni代码是c++;

#define LOG_TAG "led-jni-log"#include

#include "jni.h"

#include #include #include #include #include #include #include

static int fd = -1;

jint open_led(JNIEnv *env, jobject thiz)

{

LOGD("$$$%s\n", __FUNCTION__);

fd = open("/dev/led1", O_RDWR);

if(fd < 0)

{

LOGE("open : %s\n", strerror(errno));

return -1;

}

return 0;

}

jint led_on(JNIEnv *env, jobject thiz)

{

LOGD("$$$%s\n", __FUNCTION__);

int val = 1;

jint ret = 0;

ret = write(fd, &val, 4);

if(ret != 4)

{

LOGE("write : %s\n", strerror(errno));

return -1;

}

return 0;

}

jint led_off(JNIEnv *env, jobject thiz)

{

LOGD("$$$%s\n", __FUNCTION__);

int val = 0;

jint ret = 0;

ret = write(fd, &val, 4);

if(ret != 4)

{

LOGE("write : %s\n", strerror(errno));

return -1;

}

return 0;

}

jint close_led(JNIEnv *env, jobject thiz)

{

LOGD("$$$%s\n", __FUNCTION__);

if(fd > 0)

close(fd);

return 0;

}

static JNINativeMethod myMethods[] ={

{"openDev", "()I", (void *)open_led},

{"onDev", "()I", (void *)led_on},

{"offDev", "()I", (void *)led_off},

{"closeDev", "()I", (void *)close_led},

};

jint JNI_OnLoad(JavaVM * vm, void * reserved)

{

JNIEnv *env = NULL;

jint ret = -1;

ret = vm->GetEnv((void **)&env, JNI_VERSION_1_4);

if(ret < 0)

{

LOGE("GetEnv error\n");

return -1;

}

jclass myclz = env->FindClass("com/ledtest/LedActivity");

if(myclz == NULL)

{

LOGE("FindClass error\n");

return -1;

}

ret = env->RegisterNatives(myclz, myMethods, sizeof(myMethods)/sizeof(myMethods[0]));

if(ret < 0)

{

LOGE("RegisterNatives error\n");

return -1;

}

return JNI_VERSION_1_4;

}

然后是java app:

package com.ledtest;

import android.os.Bundle;

import android.app.Activity;

import android.util.Log;

import android.view.Menu;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class LedActivity extends Activity {

final String TAG = "LedActivity";

public Button btn_on = null;

public Button btn_off = null;

public void init() {

btn_on = (Button) this.findViewById(R.id.btn1);

btn_on.setOnClickListener(clickListener);

btn_off = (Button) this.findViewById(R.id.btn2);

btn_off.setOnClickListener(clickListener);

}

OnClickListener clickListener = new OnClickListener() {

public void onClick(View v) {

switch (v.getId()) {

case R.id.btn1:

Log.d(TAG, "led on in app");

onDev();

break;

case R.id.btn2:

Log.d(TAG, "led off in app");

offDev();

break;

default:

break;

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_led);

init();

openDev();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.activity_led, menu);

return true;

}

@Override

protected void onDestroy() {

// TODO Auto-generated method stubsuper.onDestroy();

closeDev();

}

static {

System.loadLibrary("led_jni");

}

public native int openDev();

public native int onDev();

public native int offDev();

public native int closeDev();

}

框架是这样的:最上层是java ,点开app,点击一下一个button,点亮了LED,调用onDev();onDev调用c++的led_on,然后led_on是调用驱动的led_write,明白不?这样说吧:linux 驱动是最下层的,驱动嘛。然后是c++层,c++包装一下是给java调用的,然后到java层。下面是android比价经典的一张框架图。

linux在最下面。lib 是动态库。然后是JNI,然后是Framework(android框架),然后是大家喜闻乐见的app。

python打印七段数码管引脚图_前辈学51单片机的感悟是怎么样的?说说看相关推荐

  1. python编辑七段数码管引脚图_初识原理图

    在中学物理电路知识中,用简易电路图表示电路的实际连接情况,而在单片机硬件连接上,我们则用原理图来表示单片机的引脚与开发板板上的芯片等相关硬件的引脚通过电路板上的覆铜线两者相连. 1.回顾 单片机入门往 ...

  2. python编辑七段数码管引脚图_少儿Python程序第十二讲:单片机控制数码管

    本讲继续学习用Python控制单片机,并用单片机连接和控制其它硬件,具体目标是利用开发板控制四位数码管,显示指定的数字.实验效果如图12.1所示:图12.1 单片机控制四位数码管显示数字 注意:请先把 ...

  3. python绘制七段数码管引脚图_多个数码管显示

    1.余晖效应 流水灯如果在流速太快的基础上再加速,那么我们看到的则是一排灯都在亮着,这就叫人眼的余晖效应.同理,我们想让多个数码管同时亮,那么就要让三八译码器的IO0~IO5每个输出引脚轮流快速切换出 ...

  4. 两位一体数码管引脚图_两位一体数码管 两位一体数码管全新现货

    数码管驱动方式概述: 数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据数码管的驱动方式的不同,可以分为静态式和动态式两类. 1.静态显示驱动 静态驱动也称直流驱 ...

  5. 两位一体数码管引脚图_一种智能LED数码管的制作方法

    本实用新型涉及智能控制技术领域,特别是一种智能LED数码管. 背景技术: 我国的LED数码管产业在政策.资金.市场的推动下飞速发展,无论是产值规模还是产业链建设都取得了较好的成绩.但是,从全球视野看, ...

  6. 两位一体数码管引脚图_两位一体共阴数码管,第二位数字显示不出来,按钮第7按钮按下去来回显示,但第一位又不显示了,,,急...

    #include#defineuintunsignedint#defineucharunsignedcharucharflag;//水位是否蜂鸣器报警标志位uchardang;//水位高度的档位uch ...

  7. python七段数码管设计图案-Python绘制七段数码管实例代码

    七段数码管(seven-segmentindicator)由7段数码管拼接而成,每段有亮或不亮两种情况,改进型的七段数码管还包括一个小数点位置 绘制模式: input:输入当前日期的数字形式 proc ...

  8. python七段数码管设计图案-python实现七段数码管和倒计时效果

    8是典型的七段数码管的例子,因为刚好七段都有经过,这里我写的代码是从1开始右转. 这是看Mooc视频写的一个关于用七段数码管显示当前时间 # -*-coding:utf-8 -*- import tu ...

  9. python:七段数码管绘制数字详解

    python:七段数码管绘制数字详解 七段数码管由七段数码管拼接而成,每段有亮或不亮两种情况.这里,先给出程序的全部代码,如下所示. 定义了drawDigit()函数,该函数根据输入的数字绘制七段数码 ...

最新文章

  1. python十九:map,filter,reduce函数
  2. ChinaDNS 结合DNSMasq防dns挟持
  3. java8 collect 类型转换_Java 8 新特性 Stream类的collect方法
  4. Arcgis自下而上从左到右进行编号
  5. nginx普通配置/负载均衡配置/ssl/https配置
  6. php 返回josn 中文,php返回json数据中文显示不友好的问题的解决办法
  7. 开源社群系统 ThinkSNS+ 0.7.4 版本发布
  8. 用C++完成三国杀(无GUI)
  9. 客流分析江湖争端再起,新旧势力谁更胜一筹?
  10. c语言智能插座多线程原理,主芯片HLW8012 - 基于WiFi智能插座的智能家居电路及原理解析—电路精选(49)...
  11. Recorder︱深度学习小数据集表现、优化(Active Learning)、标注集网络获取
  12. 南京年薪10万以上软件人才买房买车可获退税
  13. 如何旋转PDF的页面方向?教你2种方法
  14. 新技能Get! 手把手教你接入CG Kit
  15. mysql fio测试_fio_飞哥最爱白菜_新浪博客
  16. 【读书笔记】《杜月笙全传》读书笔记
  17. ecshop小京东的模板切换到smarty3.1.3之去掉原生的php语法
  18. python jit_Pypy Python的JIT实现
  19. 拓展 - Webrtc 的回声抵消(aec、aecm)算法简介
  20. AJAX框架简笔画风景简单,好看简单的简笔画风景

热门文章

  1. 5.8G存在感应雷达模块,雷达智能感应灯应用,多普勒雷达技术发展
  2. 使用Kali上的Metasploit获取ssh登录到靶机权限
  3. 物研究所做一位科研人员
  4. 芝麻信用免押金成趋势 报告称租赁经济有望突破10万亿元
  5. 视频丨中兴通讯齐聚全球合作伙伴的力量 拥抱最好的时代
  6. 【工作笔记】Springboot一个比较通用的数据脱敏处理办法
  7. 中缀表达式转后缀表达式两位数_什么是圆形磁动势?永磁无刷电机是怎么转起来的?...
  8. 如何包装你的实验结果
  9. Stm32(寄存器)通道一--输出占空比50%的PWM
  10. 微信小程序05---聊天室的搭建