chore 不确定性有问题 真喜欢用无序列表啊
161
5.富有生命的嵌入式/5.2New meaning of C.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# New meaning of C
|
||||
|
||||
> Author:肖扬
|
||||
|
||||
在上一篇文章中,我们介绍了嵌入式相关的产品,其中芯片充当着及其重要的作用,本篇我们将以孵化器实验室的部分考核流程与教程作为参考,并且加以一定的概念解析,逐步地为大家解开单片机裸机开发的面纱。
|
||||
|
||||
PS:在学习此模块之前,我希望你们能熟练掌握 C 语言的基础知识,特别是指针方面的内容。
|
||||
|
||||
如果你还没有完成 C 语言的学习,可以参考此文章:[3.4C 语言](../3.%E7%BC%96%E7%A8%8B%E6%80%9D%E7%BB%B4%E4%BD%93%E7%B3%BB%E6%9E%84%E5%BB%BA/3.4C%E8%AF%AD%E8%A8%80.md)
|
||||
|
||||
## STC89C52--一款入门级的芯片
|
||||
|
||||
### 相关介绍
|
||||
|
||||
Intel 的 STC89C51\C52 系列早在上世纪 80 年代就已经广泛运用,考虑到其精简但较为充足的硬件资源以及其低廉的价格,笔者十分建议可以从 51 单片机系列开始去接触整个嵌入式行业(因为你需要知道自己适不适合进入到嵌入式行业,大学本就是一个试错的过程,而低廉的价格使得其试错成本变得很低)
|
||||
|
||||
以下是比较推荐的学习路线:
|
||||
|
||||
1、购买 51 单片机:[https://m.tb.cn/h.UuGJR5G?tk=kN94dm040JX](https://m.tb.cn/h.UuGJR5G?tk=kN94dm040JX) CZ0001 「普中 51 单片机学习板开发板 stc89c52 单片机实验板 C51 单片机 diy 套件」
|
||||
|
||||
2、推荐学习视频:【51 单片机入门教程-2020 版 程序全程纯手打 从零开始入门】[https://b23.tv/KmaWgUK](https://b23.tv/KmaWgUK)
|
||||
|
||||
3、相关学习资料:
|
||||
|
||||
软件安装包、开发板资料、课件及程序源码百度网盘链接:
|
||||
|
||||
[https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng](https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng) 提取码:gdzf,链接里压缩包的解压密码:51 ,如果打不开请复制链接到浏览器再打开
|
||||
|
||||
### 一些简单的任务
|
||||
|
||||
咳咳,摆烂一下,放一下 22 年实验室的培养计划(<del>只给第一期,不能再多了</del>):
|
||||
|
||||
在学习完这些内容后,你可以尝试如下的工程实践:
|
||||
|
||||
## 寄存器(VERRY--IMPORTANT!!!)
|
||||
|
||||
相信学完 C51 的内容,你已经对寄存器有了一定的了解。
|
||||
|
||||
但是由于其重要性,以及为了巩固各位的基础知识,防止出现有些人学了 A 只会 A,学了 B 只会 B,而不会 CDEF...的现象,所以这里我必须要着重重新讲解一下寄存器的概念。
|
||||
|
||||
在 C 语言中我们有 int、short、long 等变量,实际上 C 语言中还可以定义一个寄存器变量(register)。
|
||||
|
||||
那么为什么需要寄存器呢,或者说我们为什么需要一个寄存器变量呢。
|
||||
|
||||
这里我不从计算机组成原理或者微机接口与技术的概念入手,而是举一个简单的例子:
|
||||
|
||||
如果我们在图书馆上准备看书,去获取知识,此时我们是 CPU、书则是数据。
|
||||
|
||||
如果我们去图书馆里的书架上拿书并观看,则需要:走到对应书架-拿书(获取数据)-回到书桌,这需要花费相当一部分的时间,此时硬盘相当于书架;如果我们直接拿书桌上的书,则相对速度会快很多,此时书桌相当于主存;如果我们手上就有一本书,那么我们低头就可以看到,手就相当于寄存器。所以,寄存器是 CPU 内部用来存放数据的一些小型的存储区域,用来暂时存放参与运算的数据和运算结果以及一些 CPU 运行所需要的信息。
|
||||
|
||||
以我举例而言,<strong>可见寄存器获得数据的速度会快于主存与硬盘,而存储数据的大小将会小于主存与硬盘</strong>,如果这块不清楚的话也可以去看 也许你会用上的基础知识 中的存储器知识部分。
|
||||
|
||||
而从汇编语言的角度来讲(此为 Intel 的汇编语法):
|
||||
|
||||
```asm
|
||||
WAIT_FOR_TIMER:
|
||||
MOV A, LED_COUNT ;读取当前亮灯的编号
|
||||
CJNE A, #00H, NOT_FIRST_LED ;如果不是第一个灯,则跳转到NOT_FIRST_LED标签
|
||||
MOV A, #03H ;如果是第一个灯,则将延时设为3秒
|
||||
SJMP DELAY ;跳转到延时
|
||||
NOT_FIRST_LED:
|
||||
.......
|
||||
DELAY:
|
||||
.......
|
||||
;此汇编代码块中,累加器A作为一个常用的特殊寄存器,充当着暂时存储数据信息的作用
|
||||
;存储LED_COUNT的编号并用于比较大小,存储所需延时时间并用于DELAY块
|
||||
```
|
||||
|
||||
```asm
|
||||
ORG 0BH
|
||||
PUSH ACC ; 保存寄存器状态
|
||||
PUSH PSW
|
||||
......
|
||||
POP PSW ; 恢复寄存器状态
|
||||
POP ACC
|
||||
RETI ; 返回中断
|
||||
;此汇编代码块用于基本的中断处理,我们需要保存ACC、PSW的状态来维持中断以及中断后程序的正常进行
|
||||
```
|
||||
|
||||
以上简单例举了寄存器的一般作用,以汇编语言出发去讲的原因是:它能有效地展现底层代码的工作原理,既不会像机器语言那样只用 0、1 表示的晦涩难懂,又不会像高级语言那般难以直观地看到底层的工作方式。但是,我们做嵌入式入门开发的过程中并不会让你直接去写汇编语言,而是以最基础的 C 语言(相比汇编而言,C 在功能上、结构性、可读性、可维护性上有明显的优势),通过 Keil、IAR 等拥有交叉编译器的 C 语言软件开发系统来完成高级语言、汇编语言、机器语言的转码工作,从而通过 C 语言的编写来控制单片机等嵌入式系统的开发。
|
||||
|
||||
而抽象层面的 C 代码需要通过访问寄存器来直接控制硬件。所以在嵌入式开发的过程中,C 有了特殊的含义:<strong>C 里的数字代表的可能只是一个地址或者一个数据,但是在嵌入式开发里,这样一个数字也可以代表着一种寄存器状态。</strong>
|
||||
|
||||
下面引入一个 STM32F1 系列的 GPIO 部分寄存器图(来源正点原子提供的 F1 参考手册):
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
如果我们想做一个简单的实验-驱动一个 LED 灯(假设此 LED 灯以 PB5 为输出驱动口),在对相应的 RCC 时钟等配置之外,最重要的是对相应的 GPIO 口的配置,首先我们查阅其寄存器的物理起始地址:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
可见 GPIO 外设通过 APB2 总线进行地址定位与传输数据的,所以我们要控制 PB5 的话首先需要定位到对应的地址:
|
||||
|
||||
```c
|
||||
#define PERIPH_BASE ((uint32_t)0x40000000) //外设基址
|
||||
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) //APB2基址
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
|
||||
#define AFIO_BASE (APB2PERIPH_BASE + 0x0000)
|
||||
#define EXTI_BASE (APB2PERIPH_BASE + 0x0400)
|
||||
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
|
||||
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)//GPIOB基址,计算可得0x40010C00
|
||||
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
|
||||
#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
|
||||
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
|
||||
#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00)
|
||||
#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)
|
||||
//APB2还有相关定时器的基址,这里就不再展示
|
||||
|
||||
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
|
||||
```
|
||||
|
||||
根据如上提供的 CRL、ODR 寄存器的功能映射,要使得 PB5 推挽输出且初始电平输出为高,则需要:
|
||||
|
||||
```c
|
||||
void LED_Init(void)
|
||||
{
|
||||
RCC->APB2ENR|=1<<3; //GPIOB的时钟使能,只有使能对应的时钟后GPIO才能正常工作
|
||||
|
||||
GPIOB->CRL&=0XFF0FFFFF; //由图可知,CRL的第20-23位控制5口,此举是对第20-23位清零
|
||||
GPIOB->CRL|=0X00300000; //此举是对第20-23位赋值0011,根据寄存器功能可知此代表50Mhz推挽输出
|
||||
GPIOB->ODR|=1<<5; //设置ODR第5位为1,输出高电平
|
||||
}
|
||||
```
|
||||
|
||||
其中 GPIOB 的结构体如下所示:
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t CRL;
|
||||
__IO uint32_t CRH;
|
||||
__IO uint32_t IDR;
|
||||
__IO uint32_t ODR;
|
||||
__IO uint32_t BSRR;
|
||||
__IO uint32_t BRR;
|
||||
__IO uint32_t LCKR;
|
||||
} GPIO_TypeDef;
|
||||
```
|
||||
|
||||
所以由以上提到的例子而言,C 语言可以从如下三方面进行与寄存器之间的控制:
|
||||
|
||||
1. 寄存器的地址可以使用<strong>指针变量</strong>来访问。
|
||||
2. C 语言中的<strong>结构体可以用于表示寄存器映射</strong>。
|
||||
3. C 语言中的<strong>位域可以用于表示寄存器中的位</strong>。
|
||||
|
||||
而且 C 语言中的内联汇编可以用于直接访问寄存器。在某些情况下,如果我们需要直接访问寄存器来完成复杂的硬件控制操作,则可以使用汇编语言指令来直接访问寄存器,从而实现复杂的硬件控制操作。常见的如,堆栈大小的设置等。
|
||||
|
||||
```asm
|
||||
Stack_Size EQU 0x00000400
|
||||
|
||||
AREA STACK, NOINIT, READWRITE, ALIGN=3
|
||||
Stack_Mem SPACE Stack_Size
|
||||
__initial_sp
|
||||
```
|
||||
172
5.富有生命的嵌入式/5.3还玩裸机?上操作系统!.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# 还玩裸机?上操作系统!
|
||||
|
||||
> Author:肖扬
|
||||
|
||||
在 [New meaning of C](./5.2New%20meaning%20of%20C.md) 栏目中,我们已经从 stc51 单片机系列和 stm32 单片机系列进行了一定的裸机开发讲解,并且延伸到了通过相关的 datasheet 对刚接触到手的芯片进行开发(毕竟你总不能成为 stm32 开发工程师或者 cubemx 工程师对吧<del>【然鹅大多数急于求成的开发者往往忽视了这方面的能力,也许是为了更快入手竞赛】</del>)
|
||||
|
||||
而在此栏目中,我们将讲述相关操作系统在嵌入式上的应用,让你的嵌入式产品更加的智慧!(当然裸机并不一定就比带操作系统的嵌入式产品差,只是应用方向不同或者说有时候需要考虑产品的成本问题)
|
||||
|
||||
Ps:本栏目只例举几个目前开发工程中常见的操作系统的学习与开发,<strong>具体的移植过程可 web 或者自行探索-相信我,出色的移植能力是嵌入式开发者必不可少的。</strong>
|
||||
|
||||
## RTOS
|
||||
|
||||
MCU 本身就能做到一定的实时性,那为什么还是需要 RTOS(实时操作系统)呢,<strong>其实评判实时系统的关键并不是系统对外部事件的处理速度,而是处理事件的时间的可预见性和确定性。</strong>举个例子,Windows 操作系统在 CPU 没有其他任务时可以在很短的时间内对外部事件作出一定的响应,但是当某些后台任务在运行时,有时候响应速度会变得很慢甚至出现假死现象,这并不是因为 Windows 速度不够快或者效率不够高导致的,而是因为 Windows 对事件的响应不能提供准确性,所以其不能算作一个实时操作系统。<strong>并且在笔者看来,实时操作系统除了可以达到完成每次任务所需时间的一致性外,其相应的操作系统产品(例如我们本栏目将重点介绍的 FreeRTOS,这里可以简单提一下为啥要选 FreeRTOS,显而易见因为-Free)还具有可以简化整体架构、开发等工作的作用。</strong>
|
||||
|
||||
RTOS 中最重要的概念则是“任务”。
|
||||
|
||||
我们可以回想一下在 MCU 开发过程中,一般都是在 main 函数里做个 while(1)来完成大部分的处理,将一些相对来说对实时性要求高的函数(如 PID 控制器)扔到定时器中断当中,即应用程序是个无限的循环,是个单任务系统(前后台系统),while(1)作为后台,中断服务函数作为前台。这里采用了“正点原子”的一张图:
|
||||
|
||||

|
||||
|
||||
而 RTOS 则是一个多任务系统,那么它这么做有什么好处呢?
|
||||
|
||||
2>1 嘛(乐),实际上在前后台系统中,你的每项 Task 要轮流排队等着上次 Task 执行结束后再进行自己的程序,大大影响了其系统的实时性要求;而 RTOS 中我们把整个 while(1)区分成了很多小任务,并且在表面上看起来这些任务运行起来像是同时进行,实际上是因为任务所需的时间较少导致它看起来像是并行,但这将会带来新的疑问,到底什么任务先执行呢?RTOS 就为此提供了任务的相关 API 接口,赋予任务相应的执行优先级属性,并通过任务调度器来控制任务的执行顺序。这里同样采用了“正点原子”的一张图:
|
||||
|
||||

|
||||
|
||||
所以,<strong>其实可以这么说:RTOS 将整个流程变成了很多个 while(1)【每个任务都是个 while(1)】。</strong>
|
||||
|
||||
并且根据我上述所描述的内容,一个任务需要的属性大致如下(以启动函数为例进行介绍):
|
||||
|
||||
```c
|
||||
#define START_TASK_PRIO 1 //任务优先级
|
||||
#define START_STK_SIZE 256 //任务堆栈大小
|
||||
TaskHandle_t StartTask_Handler; //任务句柄
|
||||
void start_task(void *pvParameters); //任务函数
|
||||
|
||||
int main(){
|
||||
systemInit();//硬件初始化
|
||||
xTaskCreate(
|
||||
TaskFunction_t start_task, //任务函数
|
||||
const char * const "start_task", //任务名称
|
||||
const uint16_t START_STK_SIZE, //任务堆栈大小
|
||||
void * const NULL, //传递给任务函数的参数
|
||||
UBaseType_t START_TASK_PRIO, //任务优先级
|
||||
TaskHandle_t * const StartTask_Handler //任务句柄
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
至于有关于任务的运行态、挂起态、就绪态、阻塞态等我便不在此栏目进行讲解,希望读者能根据以上的引入去学习 FreeRTOS 的开发,可供参考的文档或者学习视频如下:
|
||||
|
||||
1、b 站正点原子官方 FreeRTOS 教学(在今年有做全面的更新,比之前讲的更为清晰,难得的优秀入门视频)
|
||||
|
||||
[https://www.bilibili.com/video/BV19g411p7UT/?spm_id_from=333.999.0.0&vd_source=6ee6cc25ef1d46409e1f14084644c1f7](https://www.bilibili.com/video/BV19g411p7UT/?spm_id_from=333.999.0.0&vd_source=6ee6cc25ef1d46409e1f14084644c1f7)
|
||||
|
||||
2、FreeRTOS 官网(官网往往是最适合学习的地方)[www.freertos.org](http://www.freertos.org)
|
||||
|
||||
## Linux(以 ROS 为例)
|
||||
|
||||
首先,如果你不了解 Linux 系统的话,我建议你去 [附加模块:Linux](../3.%E7%BC%96%E7%A8%8B%E6%80%9D%E7%BB%B4%E4%BD%93%E7%B3%BB%E6%9E%84%E5%BB%BA/3.Y%20%E9%99%84%E5%8A%A0%E6%A8%A1%E5%9D%97%EF%BC%9ALinux.md) 中进行一定的学习。
|
||||
|
||||
如果你不了解 Python,我建议你去以及 [3.6Python(灵巧的胶水)](../3.%E7%BC%96%E7%A8%8B%E6%80%9D%E7%BB%B4%E4%BD%93%E7%B3%BB%E6%9E%84%E5%BB%BA/3.6Python%EF%BC%88%E7%81%B5%E5%B7%A7%E7%9A%84%E8%83%B6%E6%B0%B4%EF%BC%89.md)中进行学习。
|
||||
|
||||
如果你已经对以上所涉及到的方面有了一定的了解,那么欢迎来到机器人开发者的殿堂-Robot Operating System!
|
||||
|
||||
由于硬件技术的飞速发展,针对于机器人软件设计的框架也面临着极大的挑战,而 ROS 的出现无异是所有机器人开发者的福音,因为如果按照以前的制作一个机器人流程来讲,也许你要经历以下步骤:硬件结构搭建、控制处理、相关算法构建等等,但是 ROS 的开源共享模式令其可以在其平台上巧妙利用别人的开源模型完成自己的机器人搭建,<strong>也就是说 Ros 的出现打破了原本各个开发者(或团队)闭门造车的开发现象,使得其可以共享优秀的机器人应用软件,换句话说就是提高了机器人研发的软件复用率。(毕竟哪个团队都不可能同时在建图、导航、视觉等机器人应用方面处于顶尖位置)</strong>
|
||||
|
||||

|
||||
|
||||
由于 ROS 中完成度最高的是 Ubuntu,所以我们建议你以此展开学习,当然你也可以选择 macOS、Debian 等 OS。
|
||||
|
||||
但是 Linux 只是一个通用系统,并没有在机器人开发上提供相应的中间件,所以 ROS 提供了基于 TCP/UDP 的通信接口(机器人的工作当然需要通讯),在再此之上提供了相应的基础开发库供给至应用层。
|
||||
|
||||
此时应用层则有个很重要的概念-Master(管理者),其负责管理整个系统的正常运行。如果我们需要获得比较成熟的相关领域开源机器人包,按以往的操作必将是进行一次比较复杂的移植(你需要考虑各种因素:比如硬件支持、与其他移植包是否冲突等等)。<strong>但是在 ROS 系统中引入了功能包的概念,你可以在 ROS 社区中下载相关版本(与你的 ROS 版本相匹配)的机器人应用功能包,完成一次非常简单的移植过程(CV),你不需要关注其内部的具体运行机制,只需关注接口的定义与使用规则便可进行相应的二次开发(在 ROS 中你需要关注的是相关节点之间的关系,可以通过 rqt_graph 获取清晰的节点图),相当于给你做好了一个跟机器人开发有关的高集成度</strong><strong>SDK</strong><strong>平台。</strong>(当然如果你感兴趣的话可以做一定的了解,但这将牵扯到相关内容的庞大体系,比如如果你想了解自主导航是如何运行的,你首先需要了解 SLAM 算法的运行机制以及激光雷达或者相关深度摄像机的运用,然后你需要了解什么是深度信息什么是里程计信息,为什么可以表示机器人的位置信息,要如何进行一些相关的位置信息修正,然后 bulabula。<strong>以笔者自身的学习经历而言,学习相关的理论基础体系,将对你的二次开发有极大的帮助,而不会造成盲目使用接口的情况</strong>)
|
||||
|
||||
根据以上我讲述的相关内容可知:<strong>ROS 系统的优点在于,你能将社区里的有关机器人的开发模块集大成于一身,并且通过 ROS 与控制板通讯(此时类似于 STM32 的裸机主控便变成了控制板-用于接收 ROS 的调控完成相应电机、舵机的控制,或者完成一定的例如 oled 显示的简单任务),从而完成 ROS 系统内部开源算法对整个机器人的控制。</strong>
|
||||
|
||||
以下我简单介绍一下 ROS 的基础通讯方式:
|
||||
|
||||
在裸机开发中,我们的通讯(不论是蓝牙、WiFi 还是最基础的串口通讯)本质上都来自于串口中断,也就是说裸机开发引入了 ISR 来处理相应的数据接收。ROS 通讯中同样需要这样的函数来完成对目标数据的处理,而在 ROS 中我们称之为回调函数。
|
||||
|
||||
我们以话题通讯机制来做简要介绍,在此通讯中需要有两个节点,一个 Publisher(发布者)以及一个 Listener(订阅者),他们将发布和订阅同一个来完成相应的通讯-将发布和订阅的内容交给 ROS Master(整体流程类似于 WiFi 中的 mqtt 协议通信,将发布和订阅的内容交给公共服务器,形成一个转接的效果)。
|
||||
|
||||
所以通过这样的一个流程,具体的代码如下(以 C++ 为例):
|
||||
|
||||
```cpp
|
||||
//Publisher
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
//首先我们要初始化节点
|
||||
ros::init(argc, argv, "talker");
|
||||
//其次,为了对这个类更好地进行处理,我们需要创建节点句柄
|
||||
ros::NodeHandle n;
|
||||
//创建一个Publisher=> pub,发布名为chat的topic,消息类型为std_msgs::String
|
||||
ros::Publisher pub = n.advertise<std_msgs::String>("chat", 1000);
|
||||
//设置循环的频率,对应着sleep延时
|
||||
ros::Rate loop_rate(10);
|
||||
|
||||
while (ros::ok())
|
||||
{
|
||||
// 初始化std_msgs::String类型的消息
|
||||
std_msgs::String msg;
|
||||
|
||||
/*
|
||||
对数据的处理
|
||||
*/
|
||||
|
||||
// 发布消息
|
||||
ROS_INFO("%s", msg.data.c_str());
|
||||
pub.publish(msg);
|
||||
// 循环等待回调函数
|
||||
ros::spinOnce();
|
||||
// 按照循环频率延时
|
||||
loop_rate.sleep();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
//Listener
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
//节点与节点句柄是必不可缺的
|
||||
ros::init(argc, argv, "listener");
|
||||
ros::NodeHandle n;
|
||||
// 创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatCallback
|
||||
ros::Subscriber sub = n.subscribe("chat", 1000, chatCallback);
|
||||
// 循环等待回调函数
|
||||
ros::spin();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
而其中,在 Listener 中出现了回调函数,其功能类似于裸机中的中断控制-当接收到对应的订阅消息后,进行对应的数据、逻辑处理,例如如果我只是想把接收到的数据打印出来的话,我可以这么写回调函数 chatCallback:
|
||||
|
||||
```cpp
|
||||
void chatterCallback(const std_msgs::String::ConstPtr& msg)
|
||||
{
|
||||
ROS_INFO("I heard: [%s]", msg->data.c_str());
|
||||
}
|
||||
```
|
||||
|
||||
至于 ROS 其他的内容便不在这里阐述,ROS 是机器人开发者的福音,此模块是希望有更多地人能注意到这样的良心开源平台,并督促各位进行相关的知识学习,可供参考的文档或者学习视频如下:
|
||||
|
||||
1、b 站古月居 ROS21 讲(讲的比较浅,但是可以作为入门学习视频,了解整个框架,感兴趣地可以看胡老师的 ROS2 系列视频,毕竟 ROS1 近期已经停更了,要保持不断学习的姿态)
|
||||
|
||||
[https://www.bilibili.com/video/BV1zt411G7Vn/?spm_id_from=333.999.0.0&vd_source=6ee6cc25ef1d46409e1f14084644c1f7](https://www.bilibili.com/video/BV1zt411G7Vn/?spm_id_from=333.999.0.0&vd_source=6ee6cc25ef1d46409e1f14084644c1f7)
|
||||
|
||||
<strong>提一嘴:很多人学 ROS 就学一个开头-比如就学了古月居的 21 讲,就认为自己已经了解到了 ROS 的大部分内容了</strong><strong>(不会有人现在还是纯看视频学习吧)</strong><strong>,实际上这是非常错误的想法。当你学完了视频的内容后,你甚至可能不会移植 wiki 上的功能包(x_x),甚至不知道如何去开发一个真实的机器人(因为此 21 讲只是理论上的讲解,去做一个虚拟机器人在 gazebo 上运行)。ROS 的学习上需要我们花大量的心思去学会接触新的东西,你们并不能只局限于我提供的推荐学习资料,因为相应的功能包不是一成不变的,而且也不是只有那么几个功能包,当你感受了 ROS 的自主建图、自主导航、机械臂控制、机器学习开发等等等等等等后,你才会发现 ROS 的世界是如此美妙!</strong>
|
||||
|
||||
2、b 站赵虚左 ROS 课程(讲得细致多了,需要耐心看下去,要是我入门 ROS 的时候有这个视频就好了)
|
||||
|
||||
[https://www.bilibili.com/video/BV1Ci4y1L7ZZ/?spm_id_from=333.999.0.0&vd_source=6ee6cc25ef1d46409e1f14084644c1f7](https://www.bilibili.com/video/BV1Ci4y1L7ZZ/?spm_id_from=333.999.0.0&vd_source=6ee6cc25ef1d46409e1f14084644c1f7)
|
||||
|
||||
3、古月居的《ROS 机器人开发实践》(根据国外的《ROS By Example》改编,但是更贴近于入门开发,会有相关功能包更细致的解析)
|
||||
|
||||
4、[http://wiki.ros.org/cn](http://wiki.ros.org/cn)(不会用 ROSwiki 的 ROS 玩家不是好 ROS 玩家)
|
||||
|
||||
如果未来有能力的话,希望我们能反哺 ROS 社区,促进开源社区的发展。
|
||||
|
||||
## 其他常见嵌入式操作系统(入门仅作了解)
|
||||
|
||||
相对于通用计算机操作系统而言,嵌入式操作系统除有任务调度、同步机制、内存管理、中断处理、文件处理等基本功能外更有其强大的实时性、强稳定性、硬件适应性等等。与通用计算机不同,嵌入式操作系统行业是一个百家争鸣的环境,没有一款产品能够占据绝对统治地位,但是也有很多应用面较广、有突出特色的嵌入式操作系统享有较高的知名度。
|
||||
|
||||
1、微软的嵌入式 Windows 操作系统(从个人计算机到嵌入式系统的更变)
|
||||
|
||||
此嵌入式操作系统的初衷就是“使当今的个人计算机复杂的软件环境扩展到嵌入式世界”,也就是说希望能在嵌入式产品上用到 windows 系统的桌面软件。主流上 EOS 分为两个:Windows Embedded Compact(WEC)系列和 Windows Embedded(WE)系列。常见用于手持设备、机顶盒、数码娱乐设备等等。
|
||||
|
||||
2、VxWorks(集多种处理器大成的操作系统)
|
||||
|
||||
VxWorks 是硬实时操作系统,比 FreeRTOS 这类软实时操作系统有更强的实时性,更加专注于人的交互性、可靠性,用于军事、航空、控制等领域。并且 VxWorks 支持 PowerPC、CPU32、x86 等多种嵌入式处理器体系,所以有较好的可裁剪性、兼容性。
|
||||
BIN
5.富有生命的嵌入式/static/CZ3cbiEhsoWDgJxhwXIcpUkAnMg.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
5.富有生命的嵌入式/static/HTFUbsQCNouQVzx0QYiciQWOnZf.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
5.富有生命的嵌入式/static/LJ1SbFfv6oUIgtx8CstcbWTNnRg.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
5.富有生命的嵌入式/static/MyDMbeCKLowC1Mx7Q6Ec9BLPn4g.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
5.富有生命的嵌入式/static/boxcnFySF1Cd02I052V0a9glH1c.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
5.富有生命的嵌入式/static/boxcnRy7E27xggqNshXX3cu4J5Q.png
Normal file
|
After Width: | Height: | Size: 682 KiB |
BIN
5.富有生命的嵌入式/static/boxcntQgR61yRboDpyb1bpI10Xp.png
Normal file
|
After Width: | Height: | Size: 58 KiB |