-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch_plus_index.json
More file actions
1 lines (1 loc) · 480 KB
/
search_plus_index.json
File metadata and controls
1 lines (1 loc) · 480 KB
1
{"./":{"url":"./","title":"Introduction","keywords":"","body":"Introduction (Linux) Embedded R & D Engineer, Jim, Birth 1990.04.19, 29, Male, H 178cm, W 85kg. Books The Cathedral and the Bazaar. Contact infomation email : 303683086@qq.com Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/gui/Qt.html":{"url":"pages/gui/Qt.html","title":"Qt","keywords":"","body":"1 Concept Cross-platform software development for embedded & desktop with C++ language, \"One framework. One codebase. Any platform.\", \"Light and Powerful\". refer to official website. Qt framework 1.1 History 1991 Norway Eirik Chambe-Eng & Haavard Nord -> 1994 Trolltech Co.,Ltd -> 2000 GPL version -> 2008 acquired by NOKIA and Add LGPL version -> 2011 sold to Digia Co.,Ltd 1.2 Dowload 中国科学技术大学:http://mirrors.ustc.edu.cn/qtproject/ 清华大学:https://mirrors.tuna.tsinghua.edu.cn/qt/ 北京理工大学:http://mirror.bit.edu.cn/qtproject/ 中国互联网络信息中心:https://mirrors.cnnic.cn/qt/ 2 Feature 2.1 Design Tools Everything you need for designing an amazing user interface and the ultimate user experience. Name Description Qt Design Studio UI desing and develoment environment Qt 3D Studio Qt Designer Intergrated into Qt Creator for GUIs desgin using Qt Widgets Qt quick designer Intergrated into Qt Creator for GUIs desgin using Qt Quick 2.2 Development Tools Qt has it's own cross-platform IDE and is chock-full of tools designed for developing applications and UIs once and deploying them across multiple operating systems. Name Description Qt QmlLive GammaRay Higher level debugging tools Emulator Device emulation Qt Creator Cross-platform IDE for Qt Qt Linguist Qt text translator qmake Intergrated into Qt Creator, makefile generator for Qt and other Proj Makeqpf QPF2 fonts Creator for Embedded Linux Meta-Object Compiler (MOC) Check macro 'Q_OBJECT' and generat C++ source file (for Signal-Slots .etc) User Interface Compiler (UIC) Read '.ui' file and generat C++ header file Resource Compiler (RCC) Embed resource (.qrc) into APP during the build process Qt D-Bus XML compiler (qdbusxml2cpp) D-Bus Viewer Qt Quick Compiler Compile QML to binary file for Qt Quick applications Qt VS Tools) MicrosoftVisualStudio suitable tools Qt Distance Field Generator Qt Installer Framework Qt APP installer creator for desktop Linux/Windows/MacOS Qbs Across-platform support tools Qt Assistant Intergrated into Qt Creator Qt Configuration Tool Creating and building smaller Qt binaries (Only for commercial license) On-device Depolyment and Debugging 2.3 Framework Essentials These are the APIs and libraries that provide the backbone of Qt. Qt contains a rich set of fundamental enablers,which provide higher-level UI and application development components. Name Description Qt Core Meta-Object, Signal & Slots .etc Qt GUI Image, fonts, text, 2D graphics .etc Qt Multimedia Camera, radio, vedio .etc Qt Multimesia Widgets Qt Network HTTP, TCP/IP, cookies .etc Qt QML Qt Quick Dialogs Qt Quick Layouts Qt Quick Qt Quick Controls Qt Quick Test Qt SQL SQL database support Qt Test Qt Widgets Provids UI, such as QLable, QTxxEdit .etc Tips : QML (Qt Markup Language) starts from Qt5 and design for mobile devices UI design and all 'Qt Quick xxx' are based on QML. 2.4 Framework Addones Qt is an unbelievably comprehensive framework full of features beyond the essentials all designed to provide you with a truly professional development experience Name Description Active Qt for ActiveX and COM Qt 3D Qt Android Extras Provides platform-specific APIs for Android Qt Bluetooth Provides access to Bluetooth hardware Qt Canvas 3D Qt Concurrent High-level multi-thread support Qt D-Bus Inter-process communication support Qt Gamepad For game Qt Graphical Effects Qt Help Similar to Qt Assistant for APP Qt Image Formats Plugins for additional image formats: TIFF, NMG, TGA .etc Qt Location Displays map, navigation and place content in QML APP Qt Mac Extras Qt NFC Provides access to to NFC hardware ... ... Click to view more 2.5 License Models Name Description Commercial $5508/Year LGPL v3 Free, commercial friendly GPL v3 Free GPL v2 Free Tips : Different Qt modules are under different license conditions. Using LGPL to write commercial code on the premise of only using QT DYNAMIC LINK LIBRARY. 2.6 Development Platforms MacOS, Windows, Linux. 2.7 Target Platforms Linux/X11, Windows, macOS, Android, IOS/tvOS/watchOS, WinRT/UWP10, Embedded Linux, INTEGRITY, QNX, VxWorks, Bare metal. 3 Development 零散知识点 QFileDialog::getOpenFileName(this, tr(\"open\"), \"c:\\\"); 使用该函数可以实现文件浏览器的功能,open字符串是弹出的浏览对话框的标题名,c:\\ 表示默认打开路径 打印调试信息使用qDebug(); 可以类似printf一样输入格式化信息,信息是直接打印在调试框的,而不是打印在GUI上 使用QMessageBox::information();可以弹出对话框打印信息。 Qt Creator 分析 产生项目 Qt Creator新建项目将产生两个文件夹,以项目名Demo为例: 1. build-Demo-Desktop_Qt_5_9_0_MinGW_32bit-Debug 包含debug、release目录和Makefile、ui_mainwindows.h文件 其中ui_mainwindows.h 是Qt 利用'mainwindow.ui'生成的,该文件见下文 这里也有Makefile,可见qmake的机制最终也是操作Makefile 2. Demo mainwindow.ui文件、Demo.pro、Demo.pro.user 和 所有源码及头文件 - mainwindows.ui 是GUI文件,文本类型,内容使用XML格式维护: .... x.ui文件内容是由Qt的UI设计界面生成的,在设计界面绘制的过程,就是在x.ui写入节点信息的过程 x.ui文件会被Qt解析(成ui_mainwindows.h),然后调用内部绘图函数,根据上述参数来绘制界面, Qt利用这种: \"UI界面 - XML - 代码绘制\" 的方式,屏蔽了底层绘制图形的复杂性,使得开发人员/UI设计人员可以直接上手 - xxx.pro 是项目文件, 文本类型, 内容类似Makfile, 它是qmake工具的操作对象,qmake使用该文件产生上述Makefile: Qt.pro & qmake VS Makefile & make - xxx.pro.user 也是项目文件,是XML类型,是维护项目信息使用的,类似VS下的“解决方案” Tips : qmake工具使用中间文件的方式生成Makefile,也是跨平台编译的要点之一 MOC Moc Meta Object compiler 元对象编译器 moc文件 在项目目录下的Debug或Release目录下产生 在启动调试时 MOC 读取项目中的头文件,找到所有包含 \"Q_QBJECT\" 宏的类, 然后为这些类生成moc_xxx.cpp源文件, moc_xx.cpp源文件 是这些类的 meta-Object代码,主要处理“信号-槽\"的机制,运行时类型信息和动态属性系统等 MOC以头文件为单位生成源文件,比如A.h中有10个包含O_QBJECT的代码 B.h中有1个包含O_QBJECT代码,则MOC生成一个moc_A.cpp和一个moc_B.cpp https://doc.qt.io/archives/qt-4.8/moc.html https://doc.qt.io/qt-5/why-moc.html Qt中的头文件\"x.h\"与无后缀头文件的区别 没有区别,无后缀的头文件中,只有一句话:包含带后缀的头文件,比如a.h,则A中包含了 '#include \"a.h\"' 图形的本质 图形的本质是内存中的像素点信息,显示的过程是内存的像素点信息到显卡的显存的赋值过程 任何GUI库的工作,都是绘制内存像素点的过程 如果存在操作系统,那么操作系统一定存在一套API来对接底层显卡接口 上层软件只需调用这套API就可以显示绘制图形 如果没有操作系统,那么软件就要针对该平台的CPU、GPU、显示芯片等直接进行操作 如果裸机所接的显示屏是未知的,那么就需要程序员来构造现实接口来对接上层软件的接口 培训教程 下载: Qt 安装与移植 Qt分为Qt库和Qt集成开发环境两部分 Qt Library: qt-everywhere-opensource-src-4.8.6.tar.bz2 Qt Creator: qt-creator-opensource-linux-x86_64-3.2.1.run Qt Creator用于开发Qt应用程序,Qt应用程序的编译和运行依赖于Qt库 Qt everywhere系列版本是qt库版本之一,如其名,可以应用在任何平台 以下是Qt库配置步骤: 注意:要编译Qt库,先要正确编译tslib并导出其环境变量; 要先安装g++ 目的:1. 编译出qmake供Qt Creator使用,以编译出在目标板中运行的Qt应用程序 移植编译好的Qt库到目标板文件系统中,以在目标板中可以运行Qt应用程序 步骤: 解压缩,进入目录 $sudo ./qteverywhere.sh $sudo make $sudo make install 安装路径为 /usr/local/arm/qt4.8.6 PC测试: cp /usr/local/arm/qt4.8.6/bin/qmake /usr/bin/arm-qmake arm-qmake -v 出现版本信息即为成功 移植到目标板中的文件系统: cd /usr/local/arm/qt4.8.6/ $ cp -ar lib/libQt* lib/fonts/ /myrootfs/xxx/lib $ cp -ar demos/embeddedialogs/embeddedialogs home/forlinx/work/rootfs-mini/forlinx/qt/bin 以上目录可能不同,其拷贝的库也是挑选来的,也可以将所有的Qt lib库拷贝过去, 第二个demos目录下的文件用于测试 这种方法是拷贝到还没有烧录到FLASH的文件系统,也可以在烧录并成功运行文件系统之后再通过USB/FTP 等路径拷贝进去 设置环境变量(目标板主的/etc/profile) export QTDIR=/forlinx/qt export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH export QT_QPA_GENERIC_PLUGINS=tslib export QT_QWS_FONTDIR=$QTDIR/lib/fonts export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins export QT_QPA_FB_TSLIB=1 export QWS_SIZE=800x480 export QTS_DISPLAY=LinuxFb:/dev/fb0 KEYPAD_DEV=/dev/input/event0 export LD_LIBRARY_PATH=/forlinx/qt/lib/plugins/imageformats:$LD_LIBRARY_PATH export QT_PLUGIN_PATH=/forlinx/qt/lib/plugins export QWS_MOUSE_PROTO=”Tslib:/dev/input/event1” 配置路径和参数要跟实际一致 测试方法 cd /forlinx/qt/bin ./embeddedialogs –qws 执行之后在目标板屏幕上会出现Qt界面 以下是Qt Creator的配置步骤: Qt Creator的安装就是一路下一步 Qt Creator的配置分为3步: 配置编译工具,要使程序能在目标板上运行,就要指定交叉编译工具 点击 工具-选项-编译和运行-选择编译一栏-点击添加-选择GCC-在下面路径浏览交叉编译工具xxxx-g++的路径 2.Qt version设置,这一步就是添加Qt everyone编译出来的qmake 点击 工具-选项-编译和运行-选择Qt version一栏-点击添加直接选择qmake路径 添加构建套件,这一步主要是选择Qt库版本和编译器种类 点击 工具-选项-编译和运行-选择Kits一栏-点击添加-选择编译器版本GCC-选择Qt版本Qt4.8.6(qt4.8.6) 最后Qt版本选择,应该是系统自动提示本地存在的Qt over 可以开始构建工程,编写应用程序 触摸屏校准 什么是触摸屏校准? 一般触摸屏在校准时在屏幕上打印3~5个采样点,用户跟随点出现的顺序依次点击即是触摸屏校准。 为什么要校准?目的是什么? 目的:点击哪里,就可以准确的在那里显示!(或者说 获取用户点击位置) 从用户角度看,这是理所当然的,但实际不是这样的(至少电阻触摸屏不是这样的,电容屏另讨论),电阻式触摸屏是多层设计, 其中触摸反馈层和显示层是独立的两层结构,通过垂直叠加组合起来。 触摸反馈层:即A/D转换层,将用户触摸到屏幕上的点的坐标转换成数值送到处理器 显示层 :接收来自MCU将要显示的数据、颜色等信息 这里提供实例系统中应用到的电路芯片: 触摸反馈层:ADS7843 显示层 :RA8875 RA8875有四个地址的寄存器是用于确定显示位置的:46H~49H;46H和47H组成10bit空间,48H和49H组成9bit空间,46H和47H定位横向坐标, 48H和49H定位纵向坐标,也就是说RA8875支持1024(2^10)x512(2^9)像素的LCD,MCU通过向RA8875输送坐标值和数据即可在指定位置显示数据。 在测试实例中,RA8875将左上角定义为(0,0),向右下延伸。 ADS7843时12bit的A/D转换器,即精度为2^12=4096,也就是ADS7843将整个触摸屏幕(通过电压分布反馈)的X和Y方向各平分为0~4095个数值。 在测试实例中,ADS7843将右上角定义为开始采样端(注意这里可能是[0,0]也可能不是[0,0],因为有精度、采样频率、通讯速度等影响,但 结果一定是一个固定的值),向左下角延伸。 显然,将ADS7843的坐标读出,直接放入RA8875的寄存器,显示的位置与点击的位置是不一致的,或者说无法准确获取用户点击位置。 通过如上数据得知,两个系统的坐标范围、原点、精度都是不相同的,所以要想达到:“点击哪里,就准确的在那里显示”,就需要进行算法 映射,也就是校准!! 另外,电阻式触摸屏根据材料、工艺的优劣程度可能需要定期校准(材料形变等原因导致的触摸层电压分布的变化)。 怎么校准? 两个坐标系存在三种因数:① 平移系数Sx、Sy ② 旋转系数θ ③ 缩放系数Kx、Ky 1) MCU向RA8875发送坐标数据RA8875-XY,并在该坐标打印一个点(下面称 RA8875-XY坐标为[Rx,Ry]) 2) 向触摸屏触摸该点,MCU获取坐标ADS7843-XY (下面称ADS7843-XY坐标为[Ax,Ay]) 3) 获取方程:Rx=MxAx+NxAy+Px Ry=My*Ax+Ny*Ay+Py (数学建模省略,详情自学矩阵、图形变换等知识) 上述方程为六元一次方程,因此至少需要6组数据来确定未知数,即需要重复1)2)3)至少3次 Rx1=Mx*Ax1 + Nx*Ay1 + Px Ry1=My*Ax1 + Ny*Ay1 + Py Rx2=Mx*Ax2 + Nx*Ay2 + Px Ry2=My*Ax2 + Ny*Ay2 + Py Rx3=Mx*Ax3 + Nx*Ay3 + Px Ry3=My*Ax3 + Ny*Ay3 + Py 解方程得: 设Q=(Ax1-Ax2)(Ay2-Ay3)-(Ax2-Ax3)(Ay1-Ay2) Mx = [(Rx1-Rx2)(Ay2-Ay3) - (Rx2-Rx3)(Ay1-Ay2)]/Q Nx = - [(Rx1-Rx2)(Ay2-Ay3) - (Rx2-Rx3)(Ax1-Ax2)]/Q Px = Rx1-Mx*Ax1- Nx*Ay1 My = [(Ry1-Ry2)(Ay2-Ay3) - (Ry2-Ry3)(Ay1-Ay2)]/Q Ny = - [(Ry1-Ry2)(Ax2-Ax3) - (Ry2-Ry3)(Ax1-Ax2)]/Q Py = Ry1-My*Ax1- Ny*Ay1 MCU给出的三个点要尽量分散,如左上角、中间、右下角. 公式的应用: 将校验系数存储到EEPROM,以后每次获取点击坐标Axy后,带入公式 Rx=Mx*Ax+Nx*Ay+Px Ry=My*Ax+Ny*Ay+Py 即可获取显示坐标Rxy, 1) MCU->LCD : 可以在Rxy绘制图文 2) LCD->MCU : 如果一个图形(自己设计的,预知位置的图形)范围包括了这个点,那么还可以对该点做出决策 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/gui/emWin.html":{"url":"pages/gui/emWin.html","title":"emWin","keywords":"","body":"1 Introduction emWin都是嵌入式系统图形库,由Segger公司研发. 1.1 使用条款 Segger公司提供定制服务,定制公司用于产品最终解释权,如Segger向ST公司定制STemWin,则使用含有STemWin库的ST芯片时无需支付库的使用费用;而Segger向Micrium公司定制μC-GUI,但使用μC-GUI时需要遵循Micrium公司许可条款。 Segger公司提供合作机制,如Segger与NXP公司合作,凡使用NXP芯片的用户,都可以免费使用emWin库(信息来源:https://www.nxp.com/pages/emwin-graphics-library:EMWIN-GRAPHICS-LIBRARY)[More](#Appendix-A)。 2 μC-GUI Segger面向Micrium公司的定制产品,Micrium公司的所有产品,在任何商业应用条件下都不是免费的,并且对所有产品拥有统一的在商业中使用的许可条文。 2.1 使用条款 单一产品许可:需指定CPU型号,最终产品名称,没有数量和时间限制 产品线许可:无需指定CPU型号,需指定最终产品名称 CPU类型(平台)许可:只需指定CPU型号,可以生产各种产品 站点许可:只需指定站点,CPU、最终产品名称和数量都没有限制 类型 价格(元) 时间 单一产品许可 RMB130,000 永久 产品线许可 RMB650,000 永久 CPU类型(平台)许可 RMB845,000 永久 站点许可 - - Micrium中国总代 - 北京麦克泰软件技术有限公司报价 Appendix-A:About Library Segger官网不提供免费emWin下载入口,相关平台库需在合作公司官网下载,如NXP_emWin. Appendix-B:Connect info Micrium 总部(美)联系方式: 电话:1-954-217-2036 传真:1-954-217-2037 邮箱: 销售邮箱:sales@micrium.com 信息咨询:info@micrium.com 官网:https://www.micrium.com/ Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/gui/MFC.html":{"url":"pages/gui/MFC.html","title":"MFC","keywords":"","body":"1 MFC command line debug information Add pre-compiled setting #progma in any file of project: #pragma comment( linker, \"/subsystem:console /entry:WinMainCRTStartup\") 2 Visual studio 2008 (VS2008) usage 2.1 Path 库目录1:项目-属性-链接器-附加库目录 库目录2:工具-选项-项目和解决方案-VC++目录-库文件 头文件目录:工具-选项-项目和解决方案-VC++目录-包含文件 2.2 生成安装包 打开要生成的项目,切换到Release版,重新生成一次解决方案 右单机该项目的“解决方案”,-> 添加 -> 新建项目 -> 其它项目类型 -> 安装和部署 -> 安装项目, 输入要生成的安装包的名称 -> 确定,此时在解决方案视图中可以看到安装项目 在\"文件系统\"视图中有三个目录”应用程序文件夹”、“用户的'程序’菜单”、“用户桌面”,分别对应软件安装后在【安装目录】、【开始菜单】和【桌面】上的内容 “应用程序文件夹”的操作 (右单击“应用程序文件夹”) 添加输出项目:-> 添加 -> 项目输出 -> 选择要生成的项目(默认就是第一步打开的项目),这一步VS2008自动解决了系统需求的动态库依赖,并将项目的exe文件导入(称为主输出) 添加依赖库:上一步只能解决系统依赖,但还需要手动添加软件依赖的其它动态库 -> 添加 -> 文件 -> xx.dll 添加安装和卸载支持:-> 添加 -> \"c://windows/system32/msiexec.exe\",该程序提供应用程序的安装和卸载的支持 在“开始”菜单栏中创建msiexec.exe的快捷方式,以方便用户卸载软件 : 右单击上一步导入的\"msiexec.exe\" -> 创建快捷方式 -> 命名为Uinstallxxx(软件名)-> 将该快捷方式文件拖入 “用户的'程序'菜单\" 在”桌面“中创建软件启动的快捷方式:右单击”主输出来自xxx的快捷方式“ -> 命名为软件名 -> 将该快捷方式文件拖入”用户桌面“ 也可以用上一步的步骤创建”开始“菜单栏中的软件启动快捷方式 添加icon:-> 添加 -> 文件 -> xxx.icon 添加其它一切软件需要的资源,要注意,有目录的要按照软件索引的目录结构建立 \"用户的'程序'文件夹\"和“用户桌面”的操作 为Uninstallxxx快捷方式文件更改属性:右单击卸载快捷方式 -> 属性窗口 -> 为Arguments属性添加值“ /x {ID} \" ,ID通过安装项目的属性”ProductCode“中获取,ID必须是这个值,否则将不能卸载软件 为软件启动的快捷方式设定图标icon:桌面和开始菜单中的操作相同 -> 右单击快捷方式 -> 属性窗口 -> Icon属性 -> 浏览,浏览到“应用程序文件夹”,这是第1步导入的icon 导入 .net framework : 右单击安装项目 -> 属性 -> 系统必备 -> 从我的应用程序相同的位置下载系统必备组件 -> 确定 生成 :右单击安装项目 -> 生成 在安装项目的解决方案目录可以看到Release和Debug目录,此时再Release下可以看到安装文件,其中只需将 xxx.msi 发布即可,setup.exe是指向xxx.msi的链接 如果想要再次安装时可以覆盖之间的版本,要做以下工作 在安装项目属性中(注意不是右单击得到的属性,而是左单击出现的属性视图),将RemovePreviousVersions属性值改为True 在安装项目属性中(注意不是右单击得到的属性,而是左单击出现的属性视图),将ProductCode属性值改为新的值,方法是左单击值,然后点击三个点,点击“新代码”即可 [OPT]在安装项目属性中(注意不是右单击得到的属性,而是左单击出现的属性视图),将Upgrade属性值改为新的值,方法是左单击值,然后点击三个点,点击“新代码”即可 注意: 第三点是可选的,如果操作了第三点 那么系统将允许存在两个Trimposer,在“控制面板\"卸载程序界面会出现两个Trimposer 再次生成? 当生成项目挂接到源码项目后,通过菜单栏的”重新生成解决方案“即可再次生成软件安装包,无需重新挂接”主输出“ 3 xxxRect / Rectxxx 'Rect' refer to 'Rectangle' and describes the origin at the left-upperside coner and 'Y' is to the right, 'X' is to the down. An area can be drawn by the seres of 'rect' functions used. 4 Client area The APP view is composed of 'Client area' and 'Non-Client area'. 'Non-Client area' is generated by MFC itself, and widgets can't be changed anymore. 'Client area' is generated by programmer, so it can be designed. MFC before win32程序框架: 程序代码 + UI资源 C++程序代码 通过 C++编译器 生成目标文件 .obj UI资源 通过 RC编译器 生成 .res(二进制) 连接器 将.obj和.res链接 生成 .EXE可执行文件 UI资源:功能菜单、对话框样式、程序图标、光标形状,实际文件如.ico、.bmp、.cur等, 这些资源必须在资源描述文档 x.rc中 描述,RC编译器会读取.rc文档以生成.res文件 .rc文件类似一个数据库,以文本的形式格式化维护UI资源信息,在VS中.rc是以结构化形式打开的,看不到直接的原貌。 看源代码需要用其它编辑器打开。 常用的资源有:ICON、CURSOR、BITMAP、FONT、DIALOG、MENU、ACCELERATOR、STRING、VERSIONINFO、TOOLBAR等 C++ 编译器编译 (.cpp .hpp) -> .obj RC 编译器编译 .rc -> *.res 链接 .obj + .res -> x.exe .rc与.rc2 .rc资源是可以在VS中编辑的,.rc2常存放不能由VS编辑的任何资源,即.rc2中的资源都是手动管理的 问题嵌入:关于error C2011: XXX 重定义 release版本编译通过,debug版本却不行,#parama once已经使用, 换成#ifndef...开关也不行 最后... 重新生成解决方案,就通过了...................., 因为是从别的电脑拷贝过来的,与当前电脑的编译环境不同,所以要是重新生成方案, 为什么release版本能编译通过呢?因为在之前的电脑上就没有进行release编译,所以在当前电脑上就是重新生成的方案... 4. _tmain、main与WinMain _tmain是为了UNICODE字符集而引入的宏,对于ASCII字符集,_tmain被解析为main 对于UNICODE字符集,_tmain被翻译成wmain 类推,VS中_t _T等类似接口,都与UNICODE字符集相关 windows应用程序入口和MFC程序都是从WinMain函数开始的, 对于“MFC应用程序”项目,主函数是被封装的,用户看不到主函数入口 5. #pragma once 不被普遍支持的、防止头文件被重复包含的机制 传统的方式为:#ifndef xxx defind xxx ... endif 这种方式仍然被广泛采用, 缺点是xxx宏命名容易冲突,为此要自己设计与众不同的宏名称 对于#parama one ,在文件开头声明一次即可,它不使用宏命名,因此不会有冲突问题, 但是,它的机制是只能保证被此语句所声明的文件不被重复包含, 所以如果一个头文件被复制多次,它也不知道这些头文件是相同的... 6. MFC应用程序 快速构建 A. 新建 文件-》新建-》项目-》MFC-》选择\"MFC应用程序“-》在当前对话框下面输入项目名称、位置、解决方案名等信息 ,确认之后,一路选择默认项即可 这里要注意,“单文档”(SDI)与“多个文档”(MDI)的区别,后者可以在对话框中再打开对话框,前者只能有一个对话框 B. 架构 新建之后,(解决方案)视图中出现“头文件”、“源文件”、“资源文件”和Readme.txt,三个文件夹(管理项)和一个说明文档 头文件中,自动生成的项目有: ChildFrm.h ---------------- 子窗口 如果是单文档的MFC,是没有该文件的 MainFrm.h ---------------- 主窗口 包含CMainFrame类,派生自CMDIFrameWnd/CFrameWnd,控制着所有MDI/SDI的框架的功能 Resource.h ---------------- 资源定义 Resource资源宏定义是在用VS打开并操作.rc文件时自动添加的, 如果手动修改了.rc文件内容,那么相同的ID值就需要手动添加到Resourse.h文件中 (要保证)Resource.h和.rc文件总是同步的,Resource.h的内容就像一个索引,通过 ID来找到具体的资源,而.rc文件定义了资源的具体表现形式 Resource.h是源代码和资源的连接桥梁 项目名.h ---------------- 主头文件,包含Resource.h 项目名Doc.h ---------------- 文档 项目名View.h ---------------- 视图 Document/View 是MFC的主要框架模式,文档用于数据的保存和加载,View用于查看这些对象 stdafx.h ---------------- 用于生成预编译头(PCH)和名为StdAfx.obj 的预编译类型文件 包含了MFC的核心组件头文件 targetver.h ---------------- 定义了最低平台的要求(宏),更改相应的宏,可以适配响应的操作系统和浏览器平台 源文件中,自动生成的项目有: ChildFrm.cpp(当MFC为多文档时存在)、MainFrm.cpp、项目名.cpp、项目名Doc.cpp、项目名View.cpp、stdafx.cpp分别对应头文件 以实现声明的类。其中stdafx.cpp中只包含了stdafx.h,用于生成预编译信息。 资源文件,自动生成的项目有: 项目名.ico ---------------- 应用程序的图标 项目名.rc ---------------- 应用程序使用的所有资源列表 项目名.rc2 ---------------- .rc是可以用VS编辑的,所有不能由VS编辑的资源放置.rc2中 项目名Doc.ico ---------------- 应用程序子窗口的图标(当MFC为多文档时存在) Toolbar.bmp ---------------- 工具栏位图,这个图片是一个连续的包含所有常用工具图标,IDR_MAINFRAME TOOLBAR中的数值 指定了使用范围,以此确定具体使用的图标。 常用资源说明: ACCELERATOR : 快捷键列表,一系列组合键的集合,常与菜单命令关联 7. #pragma comment( comment-type [,\"commentstring\"] ) “链接库在程序中指定”取代“在编译时以命令行方式指定”的方法 comment-type 可选 compiler,exestr,lib,linker compiler 放置编译器的版本或者名字到一个对象文件,该选项是被linker忽略的 lib 放置一个库搜索记录到对象文件中。commentstring 指定要搜索lib的名称和路径 linker 指定一个连接选项,替代命令行指定链接的方式 commentstring 为comment-type指定附加信息 8. Bcompare 分析 SCC项目工程使用“MFC应用程序”(单个文档、无数据库)方式建立,新建“MFC应用程序”项目,对比SCC工程如下: 不同的文件有:res文件夹(Toolbar.bmp修改)、MainFrm.cpp、MainFrm.h、Resource.h、项目名.cpp、项目名.h、项目名.rc 、项目名View.cpp、项目名View.h、stdafx.h 未更改的文件:项目名Doc.h、项目名Doc.cpp、targetver.h、项目名.rc2、stdafx.cpp 说明:MFC的DOC/VIEW结构是MFC的核心之一,DOC负责数据的管理、VIEW负责数据的显示, SCC项目没有用到DOC.*,说明没有把数据交给DOC管理 targetver.h是为兼容平台开放的宏开关,该文件没有修改,说明没有处理平台兼容相关内容 .rc2是加载VS不能直接管理的资源使用的,该文件没有修改,说明没有额外的资源通过.rc2管理 。或者说,SCC项目的所有资源都是可通过VS操作的,都是使用.rc统一管理的 stdafx.cpp 本身没什么内容,只包含了stdafx.h,而该头文件是为预编译准备的,SCC项目在该文件 中添加了若干\"#parama comment(...)\",来实现编译时的库的自动加载 新增的文件有: 资源: button/*.bmp - 按钮图标, fold/*.bmp fold/*.png - 文件夹图标 icon/*.bmp - 对话框中的一些示例图标 icon.ico - 执行程序图标,也是应用程序打开后左上角的图标 项目名2.ico - welcome.bmp - 软件打开后显示的图标 pdf.bmp - 库: lib/pdflib/ - pdf库 lib/pdf2img - pdf转图片库 lib/CxImage - 一个优秀的图像操作类库。它可以快捷地存取、显示、转换各种图像 lib/haru - 另一个pdf库,前者是收费库 lib/libhid - HID(Human Interface Device人机交互设备)库,被USB相关程序使用 注:其中pdflib.dll和pdf2img.dll被(拷贝)放置在源码目录以方便编译 USB相关: usb100.h - USB的一些结构体和宏定义,被USBTools.h所包含 USBStatusDlg.h&cpp - USB对话框,完成显示功能 USBTools.h&cpp - 完成USB设备的操作(打开、关闭、读写等) DataCommunicationManager.h&cpp - 利用USB进行通信的数据的定义方式 条形码相关: BarcodeManagementDlg.h&cpp - 条形码对话框,完成显示功能 CODE39.h&cpp - 3 of 9 code条形码处理程序(CODE39码编制简单、能够对任意长度的数据进行编码) 密码相关: PasswordSettingDlg.h&cpp - 设置密码对话框 工作组相关: RecycleDlg.&cpp - “工作组” 回收程序(删除) SaveJobListDlg.&cpp - “工作组” 添加程序 工具条相关: scbarg.h、scbarg.cpp - 可浮动工具(条/窗口) sizecbar.h、sizecbar.cpp - 可变大小工具(条/窗口) 注:这里的四个文件已成为”非正式模板“,实现可浮动、可变大小的工具条/窗口时可以直接加载使用 序列号相关: SerialNumberDlg.h&cpp - 序列号对话框 SerialNumberDlg.htm - HTML文件,被SerialNumberDlg.h、SerialNumberDlg.cpp文件引用 CardSerialNumberInfo.h&cpp - 卡片序列号信息,没有具体实现,仅有空的构造和析构函数 参数定制相关: CCustomizedParaManager.h&cpp - 没有具体实现,仅有空的构造和析构函数 语言相关: LanguageManager.h&cpp - 软件语言的加载、设定等 安全相关: SecurityManager.h&cpp - 哈希算法、MD5生成等 ???: CreaseTipDlg.&cpp - 压痕提示对话框 图片相关: InsertImgDlg.h&cpp - 插入图片对话框 时间相关: TimeManager.h&cpp - 更新时间、获取时间、设置时间戳等 机器限制相关: MachineLimitParaManagement.h&cpp - 设置机器参数(8335BSC、5375BSC、331SCC、331BSC) MachineLimitParaSetDlg.h&cpp - 参数设置对话框 BasicParameterDefine.h&cpp - 基础参数,含一些限定值(宏) PDF相关: PdfGenerator.h&cpp - PDF生成器 工具: SCCUtil.h&cpp ???: MainListDlg.h&cpp job管理: JobFileManager.h&cpp - job文件管理 作业参数设置相关: SCCWidgetInfo.h&cpp - 定义了一个很大的数组,供窗口调用来显示相关数据 ApplicationParaManagement.h&.cpp MachineParaManagement.h&cpp JobParaAutoSetDlg.h&cpp JobParaFastAutoSetDlg.h&cpp JobParaManuleSetDlg.h&cpp 其它: 项目名.aps文件 :该文件是资源文件的二进制版本,实际上是编译后VS自动生成的 ClassDiagram1.cd :类视图文件,由VS自动生成 HitArea.bmp : 与鼠标点击事件相关(点击区域位图文件),该文件未加载到项目中 MyControlBar.cpp&h : 头文件和源码文件都是空的,该文件未加载到项目中 test.bmp : 位图文件,该文件未加载到项目中 applicate.png : 申请表图片,该文件未加载到项目中 9. Bcompare 分析 DoDataExchange() 用于对话框上的数据与定义的变量的数据交换,可以将变量发送到对话框,或者将对话框中的数据赋值给变量,比如将用户名密码对话框中用户输入的数据赋值到变量, 以便进一步进行操作 使用的方法是重写它,并调用父类的DoDataExchange(),然后随即调用DXX_函数,DXX系列函数是具体操作 DDX_Text() 关联 变量 与 控件内容 DDX_Control() 关联 变量 与 控件,变量是虚基类CWnd的派生类的对象,可以进一步操作控件内容 Use: void subClass::DoDataExchange(CDataExchange* pDX) { Dialog::DoDataExchange(pDX); DDX_Text(pDX, 控件内容ID,BYTE类型变量); DDX_Control(pDX, 控件内容ID,CWnd派生类对象); return; } 该函数由MFC自动调用。 关于VS2008打包安装包,不能覆盖 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/OSPrinciple.html":{"url":"pages/os/OSPrinciple.html","title":"OS Principle","keywords":"","body":"实时操作系统的实时性,不仅取决于操作系统本身,还取决于程序设计 和 硬件中断系统 实时操作系统允许任务的实时切换,但程序上不给切换的机会,也是无法达到实时性的 比如uCOS,两个任务,优先级0 1, 0闲置切换到1时,1不给调度的机会,0也无法实时响应。 所以为了让高级任务能够实时响应,低级任务要在程序设计时在适当的位置插入调度代码(如ucos的延时),更可以小延时、多插入,比如写几行代码插入1ms延时(如果允许),这样高级任务得到调度的概率就会更大。 另外,如果程序开启了多个硬件外部中断,并且触发的非常频繁,那么实时操作系统也达不到预期效果。 可见, 尽量减少外部中断和减小外部中断频率 以及 低级任务增加调度代码数量 是高级任务获取实时响应的最好方案,是实时操作系统达到实时效果的最好方法。 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/GCC.html":{"url":"pages/os/GNUTools/GCC.html","title":"GCC","keywords":"","body":"Using LD - the GNU linker Free Software Foundation, ld version 2, last updated : November 07,1998. Copyright(C) 1991~1998 Free Software Foundation. 1 Overview LD是编译工作的最后一步,利用BFD库将目标文件(*.o)、归档文件(*.a/*.so)整合,以重定位数据(Relocates data)和绑定符号引用(Ties up symbol references)。GNU LD提供命令行和脚本(*.ld/*.lds)环境来配置运行参数,并提供尽可能多的调试信息。 [info] Note 整合分配将输入文件的所有相同SECTION集中归纳并重定位SYMBOL在存储器的位置(绑定符号的绝对引用),最终服务于编译器的执行决策。链接器脚本的实现与命令行功能部分重合,指定使用链接器脚本通过命令行-T选项,未指定链接器脚本时将使用编译器的默认链接库。 2 Command Line [info] Note Command Line and Environment Variables are ignored. For more info, click here。 3 Linker Script 链接器脚本由Command和Expressions组成,支持C语言的运算符、符号命名规则、表达式、赋值和注释(/*...*/)等。 3.0 Expressions 所有表达式的整型都为long或unsigned long类型、所有常量都是整型、支持所有C运算符、可以引用/定义/创建全局变量、提供内置函数。整型数值的使用与C相同,并支持以K、M、G结尾的缩略数值格式。符号(变量)类似解释型语言的弱类型变量,但不可以声明,需直接定义使用,符号作为全局变量定义于SECTIONS内/外,由点.、字母、下划线、数字和连字符-组成,并由点、字母或下划线开头,符号名不能与关键字冲突。赋值表达式需以分号结尾。 Functions Description Remarks ABSOLUTE(exp) ADDR(section) LOADADDR(section) ALIGN(exp) DEFINED(symbol) NEXT(exp) SIZEOF(section) MAX(exp1, exp2) MIN(exp1, exp2) Keywords Description Remarks AT FILEHDR FLAGS LENGTH NOCROSSREFS ORIGIN OVERLAY PROVIDE(symbol = expression) all commands - - all Functions - - 符号赋值表达式同C(支持所有C的赋值运算符,表达式以分号结尾)。SECTIONS中使用的特殊变量.是定位计数器,表示所引用位置的当前地址值,通过赋值(只能增加)来改变偏移量。 [info] dot . 特殊链接器变量.用于SECTIONS中记录当前地址偏移量,且只能执行累加操作。 3 Linker Script 3.1 Command Command Description Remarks ENTRY 定义程序入口,即输出文件中要执行的第一条指令 可选且唯一 MEMORY 定义存储器范围,服务于SECTIONS并提供溢出报错机制 可选且唯一 SECTIONS 整合并按序定位各段 必选且唯一 PHDRS 自定义ELF头部信息 可选且少用 VERSION 定义ELF共享库版本信息 可选且少用 CONSTRUCTORS - 可选且少用 CONSTRUCTORS - 可选且少用 FLOAT - 可选且少用 NOFLOAT - 可选且少用 FORCE_COMMON_ALLOCATION - 可选且少用 INCLUDE filename 包含其它链接器脚本,在当前目录或-L选项指定的目录搜索 可选且少用 INPUT - 可选且少用 GROUP - 可选且少用 OUTPUT - 可选且少用 OUTPUT_ARCH - 可选且少用 OUTPUT_FORMAT - 可选且少用 SEARCH_DIR (path) 定义归档文件的搜素目录,同-L选项 可选且少用 STARTUP - 可选且少用 TARGET - 可选且少用 NOCROSSREFS - 可选且少用 3.1.1 ENTRY ENTRY(*symbol*) /** [info] Note 入口地址优先级为(降序):命令行-e选项、链接脚本ENTRY(*symbol*)命令、链接脚本start符号、.text段的第一个字节的地址、地址0。 3.1.2 MEMORY MEMORY { *name [(attr)]* : ORIGIN = *origin*, LENGTH = *len* /**链接器默认存储器的所有连续地址都可用,通过MEMORY命令可配置存储器实际利用范围,最终通过name服务于SECTIONS(通过> name的方式将section定向于name区域)。可选的属性值有:a(Allocated sections)、l(Initialzed sections)、i(Initialzed sections)、r(Read-only sections)、w(Read/write sections)、x(Sections containing executable code)。 3.1.3 SECTIONS SECTIONS用于将输入文件(*.o、*.a、*.so)各段(.text、.data、.bss ...)按序整合并定位到存储器中,如果不定义SECTIONS,则链接器将每个输入部分按第一次在输入文件中遇到的顺序放置到同名的输出部分中。 SECTIONS { ... /**region :phdr=fill]* ... /** Define Description Remarks secname 输出段名,其命名受限于输出文件的格式 特殊名称/DISCARD/用于丢弃所指定段 start 强制将输出段定位到start地址 如果同时使用了region,则必须在region范围内 BLOCK(align) 以align对齐方式开始该段 - (NOLOAD) - - AT ( ldadr ) 指定该段存储地址 不指定时存储地址与链接地址相同 >region 将该段分配到MEMORY指定的区域 - :phdr 将该段分配到由ELF头描述的段 - =fill 填充(初始化)该段中所有未分配的区域 - contents 符号定义、指定输入文件、指定输入段 指定文件的所有相同输入段或所有文件指定输入段的混合,支持正则表达式 [info] Note 链接(运行)地址也是输出段的存储(加载)地址,当使用AT关键字时可将输出段的存储地址重定位,即该输出段在运行时将执行从存储地址到链接地址的拷贝操作(由编译器crt0库来完成)。 4 Others MRI Compatible Script Files、BFD、Machine Dependent Features。 Appendix-A : X 2 Invocation 2.1 Command Line Options 2.2 Environment Variables The behavior of ld can be changed with the environment variables GNUTARGET and LDEMULATION. GNUTARGET determines the input-file object format if you don't use -b (or its synonym --format). Its value should be one of the BFD names for an input format (see section BFD). If there is no GNUTARGET in the environment, ld uses the natural format of the target. If GNUTARGET is set to default then BFD attempts to discover the input format by examining binary input files. LDEMULATION determines the default emulation if you don't use the -m option. The emulation can affect various aspects of linker behaviour, particularly the default linker script. You can list the available emulations with the --verbose or -V options. If the -m option is not used, and the LDEMULATION environment variable is not defined, the default emulation depends upon how the linker was configured 3 Command Language The command language provides explicit control over the link process, describing the mapping between the linker's input files and its output. It controls : input files, file formats, output file layout, address of sections, placement of common blocks. A command file (also known as a linker script) SHOULD be supplied to linker through the -T option. 3.1 Linker Scripts Every meaningful command script must have a SECTIONS command, it specifies a \"picture\" of the output file's layout, in varying degrees of detail. No other command is required in all cases. The optional command MEMORY complements SECTIONS by describing the available memory in the target architecture. if a MEMORY command is not used, ld assumes sufficient memory is available in a contiguous block for all output Comments /* */ can be used as in C/C++ programming language. 3.2 Expressions The syntax for expressions in the command language is identical to that of C expressions, with the features: All expressions evaluated as integers and are of \"long\" or \"unsigned long\" type. All constants are integers. All of the C arithmetic operators are provided. Global variables can be referenced, defined and created. Special purpose built-in functions can be called. 3.2.1 Integers Octol Decimal Hexadecimal Suffixes K&M 010000 4096 0x1000/0X1000 4K The table refer to the same quantity. 3.2.2 Symbol Names Symbol names start with a letter, underscore or point and may include any letters, underscore, digits, points and hyphens. Unquoted symbol names must not conflict with any keywords. 3.2.3 The Location Counter The special linker dot . (NOT .xxx) refers to the current output location counter, and MUST always appear in an expression within a SECTIONS command. Assigning a value to the . symbol will cause the location counter to be moved, and a holes is created in the output section. The location counter may never be moved backwards. SECTIONS { output: { fileA(.text) . =. + 1000 /**3.2.4 Operators The linker recognizes the standard C set of arithmetic operators, with the standard bindings and precedence levels. 3.2.5 Evaluation The linker uses \"lazy evaluation\" for expressions, it only calculates an expression when absolutely necessary. The linker needs the value of the start address, and the lengths of memory regions, in order to do any linking at all, these values are computed as soon as possible when the linker reads in the command file. However, other values (such as symbol values) are not known or needed until after storage allocation. Such values are evaluated later, when other information (such as the sizes of output sections) is available for use in the symbol assignment expression. 3.2.6 Assignment: Defining Symbols 3.2.7 Arithmetic Functions 3.2.8 Semicolons Semicolons ; must appear at the end of assignment expressions and PHDRS statement. 3.3 Memory Layout 3.4 Specifying Output Sections 3.4.1 Section Definitions 3.4.2 Section Placement 3.4.3 Section Data Expressions 3.4.4 Optional Section Attributes 3.4.5 Overlays 3.5 ELF Program Headers 3.6 The Entry Point 3.7 Version Script 3.8 Option Commands 4 Machine Dependent Features 4.1 H8/300 4.2 Intel 960 family 5 BFD 组成: command ENTRY, MEMORY, SECTIONS, PHDRS SECTIONS { secname : { //secname 不是随意的,它一定是跟目标文件相关的格式,比如如果目标文件是a.out,那么secname只能选择.text,.data,.bss, 这怎么确定呢?到http://www.zap.org.au/elec2041-cdrom/gnutools/doc/gnu-assembler.pdf(gcc汇编)找就可以了 contents } } 在SECTION中使用的command PROVIDE:https://www.cnblogs.com/tureno/articles/3741291.html symbol 可以独立在command之外,也可以在command之内,类似C语言的变量,只不过没有类型,这类似于脚本语言的变量。 OLD GNU https://ftp.gnu.org/old-gnu/Manuals/ Linke (ld) https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html 散装知识点 1 EABI EABI : Embedded Application Binary Interface ,嵌入式应用程序二进制接口 任何符合EABI标准的编译器,编译得到的二进制文件是彼此兼容的。 ARM EABI,= AEABI,即是ARM平台下的嵌入式应用程序二进制接口 GNU EABI,或GNU AEABI,其实就是指EABI、AEABI,因为这些编译器都是以GNU编译器为基础制作的 arm-cortex_a9-linux-gnueabi 之所以gnu与eabi连写,是因为有些GNU工具要求编译器的配置名称在三个连字符及以内,所以实际上所有的GNU编译器的命名都是A-B-C, 有些GNU编译器也没有按照此方法命名,有可能出现不兼容的情况 ABI for the ARM architecture是很多规范的合集: AADWARF DWARF for the ARM Architecture AAELF ELF for the ARM Architecture AAPCS Procedure Call Standard for the ARM Architecture ADDENDA Addenda to, and errata in, the ABI for the ARM Architecture BPABI Base Platform ABI for the ARM Architecture BSABI ABI for the ARM Architecture (Base Standard) CLIBABI C Library ABI for the ARM Architecture CPPABI C++ ABI for the ARM Architecture EHABI Exception Handling ABI for the ARM Architecture EHEGI Exception handling component specimen implementations RTABI Run-time ABI for the ARM Architecture 2 大多数库,编译支持的选项 ./configure --prefix=绝对路径 --host=平台 注意,这里的平台是编译器的前缀,如编译器为arm-cortex_a9-linux-gnueabi-gcc,则平台为arm-cortex_a9-linux-gnueabi 3 路径的指定 头文件路径 C++ 头文件路径 命令行 : export CPLUS_INCLUDE_PATH=绝对路径:$(CPLUS_INCLUDE_PATH);环境变量名还可能为'CPLUSPLUS_INCLUDE_PATH'、'CXX_INCLUDE_PATH' 编译器选项 :-I绝对路径 C 头文件路径 命令行 :export C_INCLUDE_PATH=绝对路径:$(C_INCLUDE_PATH); 编译器选项 :-I绝对路径 库路径 动态库路径 命令行 :export LD_LIBRARY_PATH=绝对路径:$(LD_LIBRARY_PATH);环境变量名还可能为'LIBRARY_PATH' 编译器选项 :-L绝对路径 -l库名;库名是去掉lib和.so的库名称 配置文件 :echo 绝对路径 > /etc/ld.so.conf, 然后执行 ldconfig 静态库路径 静态库路径的搜索方式与动态库相同 Tips : 对于动态库的编译器选项 -Wl,rpath=xxx,-Wl选项用于将逗号后面的参数传递给连接器ld,-rpath用于指定运行时动态库的搜索路径,而-L只能用于编译时动态库的搜索路径 3.1 调用动态库or静态库? 静态库和动态库的搜索方式是相同的,如果静态库和动态库放在一个目录,那么编译器会调用哪一个呢? Linux系统下,默认先调用动态库,如果动态库不存在则调用静态库,如果强制使用静态库,可使用编译选项 : -static -l库名 3.2 混合链接 静态链接的库 使用-Wl,-dn -L静态库绝对路径 -l静态库名, 动态链接的库使用-Wl,-dy -L动态库绝对路径 -l动态库名:-Wl,-dn -Lxxx -lyyy -Wl,-dy -Lnnn, -lmmm ,其中-dn可以替换为-non_shared、-Bstatic、-static,其中-dy可以替换为-Bdynamic、-call_shared Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/Makefile.html":{"url":"pages/os/GNUTools/Makefile.html","title":"Makefile","keywords":"","body":"./configure ./make ./make install 项目 之 标准构建方式的生成 解析1 : ./configure 程序读取当前目录下的Makefile.in文件,来生成Makefile configure ------ | ----> Makefile Makefile.in----- 生成 configure 程序 autoconf + configure.ac --> configure configure.ac 文件 由 autoscan命令 扫描源码而生成 autoscan + 源码 --> configure.scan --> 改成configure.ac 生成 configure 总结: - $ autoscan - $ mv configure.scan configure.ac - $ autoconf 注意:configure.ac 文件要做相应的修改才能达到最终自动化编译的目的 生成 Makefile.in 文件 手动编写Makefile.am文件,配合configure.ac 由automake命令 生成Makefile.in文件 生成 Makefile.in 总结: - $ automake 最后的总结:首先源码准备好,然后准备两个依赖文件 configure.ac 和 Makefile.am,后者需要手写,前者可以通过autoscan生成,但还是要修改。 于是: autoconf + configure.ac = configure automake + Makefile.am = Makefile.in configure + Makefile.in = Makefile 注意:在生成configure的过程中,还可以添加一个aclocal.m4文件,该文件是aclocal生成的。于是:autoconf+configure.ac+aclocal.m4=configure Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/Git.html":{"url":"pages/os/GNUTools/Git.html","title":"Git","keywords":"","body":"1 Introduction 1.1 Background 数据脆弱、易变且易失,因此对项目持续备份和组织管理是非常必要的,版本控制是实现此目标的高效方案。版本控制系统(VCS)是对变更进行追踪管理(记录文件内容变化),提供增、删、改、查和回溯等功能的系统。Tips : VCS classification. 1.2 Git History 在Linux内核发展初期(1991~2002年)没有VCS维护,导致绝大多数的内核维护工作都花在了提交补丁和保存归档的繁琐事物上,2002年项目组开始使用BitKeeper来维护。2005年BitKeeper在其免费版本中加入额外限制,Linux社区意识到使用第三方软件不在是长久的解决方案,于是由Linus torvalds主导开发出了快速、并行、稳定且免费的分布式VCS - Git. Tips : This is an information management tool from hell - Linus torvalds. 2 Instructions 2.1 Command $ git [OPTION] cmd [ARGS] Cmd Args Description 书签:2020.4.9.pm - 《版本控制管理 第2版》 1.3GIT基础 git对待数据像“快照流”, 注意:快照技术,不同于备份。理解了快照技术,就理解了GIT的基本思想。 次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件 git存储和提取版本使用校验和算法(SHA-1),以保证完整性 1.4命令行 1.5安装 1.6配置 初次运行git前的配置:git config,操作gitconfig文件,来设置控制git外观和行为的配置 gitconfig存在/ect/gitconfig中、对应git config --system 选项,表示本机全局 ~/.gitconfig 或~/.config/git/config,对应git config --global,表示本机当前用户 .git/config ,表示本机该仓库 每一个级别可以覆盖上一个级别的配置 用户信息配置: git config [--system/--global/无] user.name “xxx” git config [--system/--global/无] user.email “xxxx” git config --list 列出所有git能找到的配置s git config 列出某一个配置,如git config user.name 2.1 获取GIT仓库 1.对现有项目管理,在项目目录使用git init 2.从服务器克隆:git clone 。如git clone https://github.com/libgit2/libgit2,则本地出现libgit2目录,如果想重新指定仓库名:git clone [name],如git clone https://github.com/libgit2/libgti2 mylib git支持http https和SSH协议 2.2 命令和几个区域 git status git add 文件,以开始跟踪这个文件 跟踪区域分为:未跟踪区、跟踪区、不跟踪区 未跟踪区到跟踪区,使用git add +文件,反之使用git checkout +文件 不跟踪的,添加到.gitignore文件中 git add是一个多功能命令,1是可以添加跟踪文件,2是如果修改了已跟踪的文件,那么需要再次add一下,来暂存更新,如果不运行这一次add,那么下一步进行提交时,就没有这部分修改更新,换句话说,add的作用是为了提交做准备。 文件 .gitignore 的格式规范如下: 所有空行或者以 # 开头的行都会被 Git 忽略。 可以使用标准的 glob 模式匹配。 匹配模式可以以(/)开头防止递归。 匹配模式可以以(/)结尾指定目录。 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。 所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 git diff 查看尚未暂存的改动, git diff --cache git difftool 可以调用插件 以图形化方式对比差异 git commit 存储快照!核心的一步,这就在git中增加了一个版本 git commit -m指定信息 如果直接使用git commit,将调用git指定的编辑器,来指定提交信息 git config ... core.editor 命令可以指定编辑器 git commit -a 可以跳过暂存,即不必add之后再commit git rm可以从已跟踪文件清单中移除文件,并连带从工作目录删除该文件,如果只想从清单中移除,而不想删除文件,使用git rm --cache。 如果删除之前,该文件修改过,还没有放入暂存区,则需要使用git rm -f 来删除,这是安全机制,避免没有形成快照的文件被删除,因为这样的数据不能被恢复。 git mv == mv A B, git rm A, git add B git log 查看提交历史,使用-p参数可以查看每次提交的内容差异,使用-n指定数字可以查看最近n次的内容,--stat显示简略信息,使用--prettye=子选项,可以显示不同格式信息,子选项有oneline、short、full、fuller、format等等。使用--graph可以显示使用ASCII字符模拟的图形 还有其他更多选项 撤销操作: git commit --amend 可以修改最近一次的提交信息 git reset HEAD +文件,是git add的逆操作 对git add之后的文件做了修改,要丢弃这部分修改使用git checkout -- +文件,该命令不可逆 1.6.1 一. 简介 Git(Global Information Tracker,全局信息追踪器)是一款免费、开源的分布式-版本控制系统(VCS),由Linus Torvalds创建(2005.04上线),最初用于管理Linux内核开发。因其性能优异,现已成为主流的分布式VCS。 Git官网:https://git-scm.com/;可在线安装:“#yum install git”;也可通过下载源码编译安装,源码下载地址:https://www.kernel.org/pub/software/scm/git/,其编译安装方式同通用步骤:“#configure && make && make install”;注:Git源码依赖Python、libcurl、perl、zlib、ssh等众多库。 https://git-scm.com/book 二.入门 a)创建版本库 新建一个空目录,或在你的工程顶级目录运行“#git init”,则创建了一个Git版本库,库名为隐藏目录“.git”,以下称“.git”目录为版本库。 b)添加文件 Git只对版本库内的文件负责,而不监测除版本库以外的任何目录。可以通过“#git add xxx”命令将项目文件添加到版本库,xxx可以是当前目录或其它目录下的一个或若干个文件。 使用git status可以查看当前版本库状态 git rm --cached ...\" 以取消暂存 add命令是暂存操作,Git将xxx文件暂存,暂存的目的是为避免项目文件的频发变化,可以多次添加,一次性提交,可以理解为add命令是将项目文件添加到缓冲区。 使用“git commit -m \"t1\" --author=\"zi 303683086@qq.com\"”命令,可将缓冲区的文件提交到版本库,-m和--author必须使用,-m是提交的备注信息,--author指定作者,格式必须为“Name ”,如果提示地址有问题,则可以通过配置文件永久指定地址或通过全局参数“--global”:“vim xxx/.git/config”修改name和email。或“git config --global user.name=’xxx@yyy.com’ && git config --global user.name ‘NAME’”也可以使用全局变量:“GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL”,上述两种方式是全局设置,可以通过不指定--global来本地生效。 -m 选项也可以通过环境变量配置,使每次提交时自动打开一个编辑器编写备注:“export GIT_EDITOR=vim”,这样只需运行命令“git commit”就会打开vim编辑器,按提示编写备注,保存退出即提交成功。 此时运行“git status”显示工作区干净的提示。 对xxx文件简单的修改,此时不必再运行add命令,直接可以commit提交,因为该文件已经提交到版本库,版本库已经对该文件建立了索引,但这次提交需要指定文件名:“git commit xxx” 两次提交之后,版本库中已经有两个版本的xxx了。 git log 可查看提交历史,从最早陈列一个简易列表,每次提交历史都包含一个“commit !@#$2341”,这是由Git产生的提交码,唯一指定提交历史,使用:“git show !@#$2341”,可显示当次提交的详细信息。如果不指定提交码则显示最近一次的提交历史。 使用git diff xxx yyy,(xxx yyy为提交码)可对比两次提交历史。 一种说法:注:git版本库中t版本库中存储每一提交文件的修改,而不存储文件本身(第一次提交存储全部内容)。git记录了每一次的修改内容,给每一次的修改记录索引,通过索引可以寻找和回滚历史版本。 有了Git,就不需要其它命令行工具来管理项目,比如要从项目中删除一个文件,则执行:“#git rm xxx”(前提是该文件已经提交到版本库),这样既从项目目录删除了xxx文件,又从版本库中删除了xxx文件。 删除之后同样要进行提交“#git commit”这样才能最终实现变更。 “git mv xxx yyy”命令可实现版本库文件的重命名,然后记得进行提交操作。 通过git clone 命令可以克隆任一版本库 git配置文件:git配置文件已.ini结尾,它们记录了Git命令使用的各种选项和设置,有些设置是个人偏好,有些设置是版本库正常运作的必须,三个位置存有git配置文件:“.git/config ~/.gitconfig /etc/gitconfig”,优先级按先后生效。也可以通过git config 或 git config --global临时生效。使用git config -l 列出所有配置文件的信息。可以使用git config --unset 或 git config --unset --global 来移除设置。 c) 三. 文件: 1.git 配置文件 分别在/etc/gitconfig ~/.gitconfig .git/config 对应命令:git config --system , git config --global, git config 2.忽略检测文件 touch .gitignore, 支持glob匹配模式,注释用# 3.重命名git mv x y= mv x y, git rm x, git add y mkdir src; git mv x src;git commit(新建文件夹并移动) 4.日志git log、git log -p、git log -p -2、git log --stat git log --pretty=oline/short/full/fuller/format/ git log --pretty=oline/format --graph git log + git show (+SHA-1) 5.git 中任何提交(commit)的都是可以恢复的 当多人在一个文件中协同作业时,提交自己的代码 到远程仓可能失败,是否失败取决于你是否是团队 第一次提交这次作业源码的人,如果不是,就要pull 一次,以更新团队代码到自己的源码中,然后在push checkout 用于从(本地)库 中恢复之前提交过的某一节 点文件(包含删除的文件) git remote show origin git remote rename xx git remote rm git push origin master account:xyZaki password:umbrellxxxx 【设置密码,免推送输入:echo https://xyZaki:umbrellaxxx@github.com > ~/.git-credentials;vim ~/.gitconfig , 输入[credential] helper = store】 git reset 重置分支到某一次commit的指针 --soft 只重置,不做指针破坏 --hard 删除重置后,从重置点到最芯一次commit的指针, git checkout -- + 文件 恢复文件(加--是为了避免分支名与文件名冲突) git checkout + 分支 切换分支 git branch newb 创建分支 git checkout newb 切换分支 git checkout -b newb 等于上述2条命令 git merge SOMEBRANCH 合并其它分支到当前分支,以更新当前文件 补丁操作: 创建补丁:git format-patch -N (N表示创建几个PATCH(从最后一次提交计算),结果是每次提交的补丁) 补丁用于给它人使用,以更新数据(推测可能不具备克隆的条件时使用) 应用补丁:git am(应用补丁并提交) /git apply(应用补丁不自动提交) 分支:git的分支,仅在本地分支、自己使用,是没有意义的。分支应该用于开发协作,分支应该起始于远程仓中(或由本地管理者本地建立后推送至远程仓) --- 分支与切换、存储问题实例:PSCC31项目需新增1.32版本,但又需要保留之前的1.31版本,所以新增分支V1.32 git branch V1.32 //新建分支V1.32 git checkout V1.32 //切换到新的分支 然后修改了一些(已经存在的)文件 修改之后,此时想回到master分支修改一些东西, git checkout master 但发现在V1.32里面修改的内容,也在master分支上同步了 原因是,在新的分支修改完内容之后,需要git add . & git commit -m “xxx” 再切换,内容才不同步, 但是,我现在又不想对新的分支进行提交, 那么就需要暂存起来:git stash 再切换到master,内容就不会同步了, 在master操作完成之后,要切回V1.32,把暂存的内容调出来继续编写 git checkout V1.32 git stash list //查看暂存列表,因为可能暂存多次 //类似这样:statsh{0}: WIP on V1.32:dca0dd7 ..... git stash applay stats{0}//这样就调出了指定的暂存内容 刚刚进行stash的时候,没有起名字,如果stash了多次,怎么才能调用出自己想要的呢? 那就是要起名字:git stash save xxxx 使用 git stash pop 可以调用最近一次stash的内容 使用git stash clear 清空所有stash 使用 git stash show 可以查看stash的修改 ==================================================================== GitHub Action 高效易用的 CI/CD 工作流,帮助我们自动构建、测试、部署我们的代码 Appendix-A:VCS classification 分为:本地VCS、集中VSC、分布式VCS 最简单的版本控制,就是一个版本,一个目录,但这样很蠢,容易出很多问题, 本地VCS(如RCS),利用硬盘上保存“补丁集”的办法记录文件的变化,通过所有补丁可以计算出各个版本的内容 本地VCS只能供自己使用(或只能供本台机器使用,或拥有一个磁盘的机器使用),如果想要多个开发者协同工作,那就需要一个集中式的VCS(如CVS、Subversion、Perforce等),集中式VCS使用单一的一个服务器,保存所有文件的修订版本,所有协作者通过客户端连接到服务器。 集中式VCS最大的缺点就是服务器的单点故障,在恢复之前不能进行协作开发工作,如果服务器磁盘故障,那么整个项目的变更历史都将消失,各个客户端只保存了单独的快照 于是分布式VCS出现了(如Git、Mercurial、Bazaar、Darcs),它不只提取最新版本的快照,而是克隆代码仓,这样服务器有问题,就可以使用任意一个客户端恢复。 分布式VCS还有许多新的优势 先例-- SCCS source Code control System,源码控制系统是UNIX上最终的几个系统之一,由M.J.Rochkind与20世纪70年代开发, IEEE:364-370,这是有证可查的UNIX系统上的最早的VCS SCCS提供的数据存储中心称为版本库,这个概念一致沿用至今 提供“锁\"模型来保证开发过程有序 这是中心版本库的先祖 Git从bitkeeper继承了分布式概念,从Mercurial、Monotone继承了散列指纹来唯一标识文件内容的概念, 从内部实现来说,称为“内容可寻址文件存储”CAFS。 git不是一个简单的VCS,更像是一个小型的文件管理系统 相比其他VCS,git几乎所有的操作都在本地完成,因为本地拥有项目的完整历史,因此速度极其快 没有网络时可以愉快的编写项目,直到有网络再上传,这样的操作在其它VCS是不存在的 github FUNCTIONS 开发者中心 : https://developer.github.com/ marketplace 允许在github上售卖软件,github提供售卖相关模块 软件包托管:https://github.com/features/packages 说明:支持npm和多种命令上传和下载 https://www.jianshu.com/p/5278180e191c https://www.runoob.com/nodejs/nodejs-npm.html https://zh.wikipedia.org/wiki/Npm 理解:npm 是NPM公司使用JavaScript编写的软件包管理系统,npm提供一个registry的仓库,库中包含百万计的模块,这些模块是全世界的程序员贡献上传的, 微软的GTIHUB收购了NPM,所以也就拥有了registry库,于是GITHUB用户可以通过npm上传自己的模块到GITHUB的registry,或者从上面下载 类似的,github还提供其它管理命令。 git 打tag tag 是在最近一次commit上打的标签,一般用于标记迭代的项目版本信息 列出tag : 1. $ git tag 2. $ git log //在log中的commit后面显示tag 3. $ git show v1.5 //查看tag详细信息,含commit信息等 4. $ git tag -l \"v1.*\" //通配符查看 新建tag : $ git tag v1.5 一个commit上可以新建N个tag $ git tag 9fceb02 v1.5 //给过去的commit打tag 备注tag : $ git tag -a V1.5 -m \"备注的信息\" 推送tag : 默认git push origin 是不推送tag的,所以git push origin --tags 才推送tag,可以与源码异步推送,可以理解为是独立的信息 GitHub release 在github上发布软件,github 以时间线列表的方式展示 功能在“Edit”按钮下方,与\"Commits\" \"branch\" \"packages\" 并列,名为\"release\" github release 功能依赖项目的tag标签 当推送tag后,在\"release\"自动生成版本线,并提供zip和tar.gz下载功能 GitHub issue 对于项目拥有者,可以作为任务管理系统使用,以跟踪问题,或列出将来的任务计划 对于团队,issue是项目的轻量级协作系统 对于路人,可以在别人的issue上提出意见和反馈问题 奇葩用法,也可以把issue当做论坛使用 issue可以被关闭,表示该问题的追踪已停止,问题已解决,讨论入口关闭 使用#n 表示issue的ID,该ID在发起issue时自动创建 当commit时,如果该commit解决了某个issue,那么可以通过 。。。 commit -m \"xxx\" , fixed #n 也可以在github中手动关闭issue issue不是github独有的,issue应该被称为“BTS (bug tracking system)”,即BUG跟踪系统, 市场上比较有代表性的BTS有Redmine、Trac、BugZilla等。 ISSUE支持markdown语法 Github wiki GitHubWikis是一种让其他人提供内容的简单方法。任何GitHub用户都可以创建和编辑用于文档、示例、支持或任何您希望的内容的页面。 类似维基百科的性质 默认不开启,可以在Setting中的Featrue中勾选,但库要公开才行(不然wiki就没有意义了),或者升级到GitHubPRO Github actions http://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html github actions 是 github 的持续集成服务,18年10月推出 持续集成服务不是github的特有 一个项目的研发周期,从设计、开发、测试、发布等要经过很多步骤,大部分项目的流程是类似的,于是可以将这些步骤编写成一个脚本来自动化运行(当然,也可以引用别人写好的脚本) ,以缩短开发周期,提高开发效率。github action就是做这些事情的. 换句话说,持续集成服务,就是让代码 频繁的、快速的产生结果的服务,好比种一颗花,需要选好土壤、种下种子、施肥浇水、监控温度和湿度、修枝剪叶、开花结果,每次种花你都要来这一遍,然后你发现基本上种所有的花多事这个步骤,那就做一个机器人,教他一次,以后让他自动执行,那么你的工作就是拿到种子就行了,如果这个过程不顺利,机器人帮你记录下哪里出错了,你再改正,然后再投一个种子,于是就形成了 种种子 - 开花, 种种子 - 开花, 种种子 - 反馈 - 种种子 - 开花。持续种种子-持续开花,马上种种子-马上开花,一种种子-就开花,总种种子-总开花, 这样你就能快速的找到问题(如果有的话),并迅速的得到成果。 每个action都是一个独立的脚本,多个脚本组成action脚本集 以完成项目所需 对别其它的持续集成服务,github action允许引用现成的脚本 并且 可以与git动作相关联(如commit),这是github持续集成的特别之处 使用gtihub action,意味着提交到仓库就自动化完成后续的所有工作,节省了开发人员的大部分精力,也减少了团队的 当然,持续集成也不适合所有项目,或者说不适合所有项目都完全自动化,比如嵌入式产品,最终软件还是要上机运行才能进行功能测试。 github action市场:https://github.com/marketplace?type=actions https://github.com/sdras/awesome-actions //由路人总结的action脚本链接 github action官方: https://github.com/actions github 实现action,需要在仓库中添加.github目录,并在该目录下创建workflow.yml配置文件, YAML语言是编写配置文件的语言,详见教程:http://www.ruanyifeng.com/blog/2016/07/yaml.html workflow.yml 中定义了一系列触发持续集成事件的方法、jobs、运行环境等等数据,action依据这些数据来完成持续集成自动化 如on:push ,当push时就触发持续集成 持续交付和持续部署是持续集成的后续或子集 \" 持续集成 -> 持续交付 -> 持续部署 \" 持续集成??? Continues integration - CI 持续交付? ? ? Continues delivery - CD 持续部署? ? ? Continues deployment - CD Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/Markdown.html":{"url":"pages/os/GNUTools/Markdown.html","title":"Markdown","keywords":"","body":"1 Introduction Markdown is easy mark language, created by John Gruber(US) in 2004. Featrue : Easy and concision HTML compatible Chart and formula support Can be export as HTML, doc, PDF etc Tips : markdown document end with .md or .markdown. 2 Title Start with # in a line, as below (1~6 level support) : # Level 1## Level 2### Level 3#### Level 4##### Level 5###### Level 6 3 Paragraph 3.1 Line break Add two space and a CR at the tail position or add a blank line before the newline. 3.2 Font Add one * or _ at both ends of text to make the italic style, and two pair is for bold sytle and three for italic-bold style, as below : *Italic style 1*_Italic style 2_**Bold style 1**__Bold Style 2__***Italic and Bold style 1 ***___Italic and Bold style 1 ___ 3.3 Line 3.3.1 Divid line Three or more - continues connection 3.3.2 Delete line Two ~ at both ends of text. 3.3.3 Under line Nothing used for markdown but HTML \\\\ 3.4 Annotation Text or image note for extra infomation which will be displaied when the mouse hover or click. [^Text to be annotated][^Text to be annotated] This is annotation text. 4 List Start with * or + or - (for unordered list) or 'digtal.' (for ordered list) at the begin of the each line of the list, and intentation with a tab (or four space) to start sub-list. Tips : Nest list can be used. 5 Block Start with > to make a block, as below : > block> > block nest 1> > > block nest 2 6 Code Add ` (for one code line) or ``` (for multi code line) at both ends of code, and programming language can be declared after the front end ```. 7 Link ,target and image [Annotation Text](web link address) or [Annotation Test](#local target ID). !Annotation Text Form | Head1 | Head 2 | Head 3| ... alignment style |ceil |ceil |ceil|... |ceil |ceil |ceil|... |ceil |ceil |ceil|... ... alignment style : - none \\:- left-: right \\:-: middle Math Formula Wrap TeX or LaTeX with two $ Escape use \\ Flow chart 1、横向流程图源码格式: graph LR A[方形] -->B(圆角) B --> C{条件a} C -->|a=1| D[结果1] C -->|a=2| E[结果2] F[横向流程图] 2、竖向流程图源码格式: graph TD A[方形] -->B(圆角) B --> C{条件a} C -->|a=1| D[结果1] C -->|a=2| E[结果2] F[竖向流程图] 3、标准流程图源码格式: st=>start: 开始框 op=>operation: 处理框 cond=>condition: 判断框(是或否?) sub1=>subroutine: 子流程 io=>inputoutput: 输入输出框 e=>end: 结束框 st->op->cond cond(yes)->io->e cond(no)->sub1(right)->op 4、标准流程图源码格式(横向): st=>start: 开始框 op=>operation: 处理框 cond=>condition: 判断框(是或否?) sub1=>subroutine: 子流程 io=>inputoutput: 输入输出框 e=>end: 结束框 st(right)->op(right)->cond cond(yes)->io(bottom)->e cond(no)->sub1(right)->op 5、UML时序图源码样例: 对象A->对象B: 对象B你好吗?(请求) Note right of 对象B: 对象B的描述 Note left of 对象A: 对象A的描述(提示) 对象B-->对象A: 我很好(响应) 对象A->对象B: 你真的好吗? 6、UML时序图源码复杂样例: Title: 标题:复杂使用 对象A->对象B: 对象B你好吗?(请求) Note right of 对象B: 对象B的描述 Note left of 对象A: 对象A的描述(提示) 对象B-->对象A: 我很好(响应) 对象B->小三: 你好吗 小三-->>对象A: 对象B找我了 对象A->对象B: 你真的好吗? Note over 小三,对象B: 我们是朋友 participant C Note right of C: 没人陪我玩 7、UML标准时序图样例: %% 时序图例子,-> 直线,-->虚线,->>实线箭头 sequenceDiagram participant 张三 participant 李四 张三->王五: 王五你好吗? loop 健康检查 王五->王五: 与疾病战斗 end Note right of 王五: 合理 食物 看医生... 李四-->>张三: 很好! 王五->李四: 你怎么样? 李四-->王五: 很好! 8、甘特图样例: %% 语法示例 gantt dateFormat YYYY-MM-DD title 软件开发甘特图 section 设计 需求 :done, des1, 2014-01-06,2014-01-08 原型 :active, des2, 2014-01-09, 3d UI设计 : des3, after des2, 5d 未来任务 : des4, after des3, 5d section 开发 学习准备理解需求 :crit, done, 2014-01-06,24h 设计框架 :crit, done, after des2, 2d 开发 :crit, active, 3d 未来任务 :crit, 5d 耍 :2d section 测试 功能测试 :active, a1, after des3, 3d 压力测试 :after a1 , 20h 测试报告 : 48h HTML Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/doxygen.html":{"url":"pages/os/GNUTools/doxygen.html","title":"doxygen","keywords":"","body":"doxygen 根据配置文件产生html和其它文档 格式:doxgen XXXX //XXX表示配置文件 配置文件里面都是相关的变量,如可以配置语言、搜索框、输出路径等等 OUTPUT_DIRECTORY 表示输出路径 GENERATE_LATEX 表示是否生成latex latex是生成PDF文档的资料,要生成PDF,先使用doxygen生成latex,然后再使用latex命令在doxygen输出的latex目录下生成PDF latex需要单独安装包支持https://www.tug.org/texlive/acquire-netinstall.html 安装包名称:install-tl-unx.tar.gz 安装好之后,运行make即可 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/Shell.html":{"url":"pages/os/GNUTools/Shell.html","title":"Shell","keywords":"","body":" 散装知识点 Patching with command diff and patch diff -ruN OldFile NewFile > x.patch -r : recursively compare any subdirectories found -u/-U NUM : output NUM (default 3) lines of unified context -N : treat absent files as empty patch -pN -RE oldFile x.patch -pN : Strip NUM leading components from file names eg : a/b/c/d/file ,patch -p0 ,cd a ,patch -p1 ,cd b ,patch -p2 ,... -R : Assume patches were created with old and new files swapped -E : Remove output files that are empty after patching Tips : Order is important for OldFile and NewFile in command 'diff', and the same with the option -R for command 'patch' Note : Patching means operations based on original files Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/GNUTools/License.html":{"url":"pages/os/GNUTools/License.html","title":"License","keywords":"","body":"1 Background 2 Introduction 3 Open source License 4 Open source Vs Free 软件协议列表 Apache License 2.0、GNU GPLv3.0、MIT License、BSD 2-clause、BSD 3-clause、Eclipse Public License 2.0、GNU AGPLv3.0、GNU GPLv2.0、GNU LGPLv2.1、GNU LGPLv3.0、Mazilla Public License 2.0 相关组织 OSI OSI(Open Source Initiative)开放源码促进协会是一个旨在促进和保护开源软件、项目和社区的国际性的非盈利组织。于1998年由布鲁斯·斐伦斯和埃里克·斯蒂芬·雷蒙等人创立,启发于当时网景公司与微软的IE浏览器竞争。印度、日本、南美和欧洲部分国家都是OSI董事会成员。 被OSI收录的开源协议具有一定权威性,详细参看OSI许可协议列表:https://opensource.org/licenses/category。 SFLC和 gpl-violations.org SFLC(Software Freedom Law Center)软件自由法律中心是一个为自由软件和开源软件提供无偿法律代理和相关法律支持的公益性组织。由哥伦比亚大学法学教授伊本·莫格林于2005年2月筹建,主要替FSF(自由软件基金会)发声。 gpl-violations.org由德国柏林著名Linux黑客、GPL合作者哈歪·德里什(Harald Welte)与2004年创建,旨在追查和起诉GPL协议的违规者。 美国SFLC和德国gpl-violations.org是用法律手段维æ¤自由/开源软件协议的两大阵营,曾向法院提起诸多诉讼,被告者包括思科、D-Llink、Skype、Monsoon等。更多细节参看附录G。 附:SFLC官网:https://www.softwarefreedom.org/ 开源协议的共性 所有开源软件许可协议都是无责任(No Liability)和无担保(No Warranty)的,部分许可协议还对商标使用(Trademark use)有限制。这使得任何使用这些协议的软件贡献者都无需向任何使用者承担任何责任。 所有的开源软件许可协议都是可以商用和个人使用的,并且可以修改和发布,但都要基于特定的条件。 开源协议对别 所有开源软件协议中,GPL协议是最为严谨和苛刻的,GPL尊重并发扬自由软件精神。LGPL是后期出现的宽松GPL版本,它要求如果软件使用了带有GPL协议的软件,但仅以该软件作为库来工作,则不必以LGPL协议发布。AGPL协议是GPL的分支,它要求如果使用了带有AGPL协议的软件的软件在服务器端运行,则凡是与服务器端通信的用户都可以获得该软件源码。 Apache 2.0、BSD和MIT是对商业友好的宽松许可协议,它们允许使用带有这些协议的软件的软件不开源。 附录A : GPL侵权诉讼案件 D-Link NAS案件(全球第一例自由软件侵权诉讼案件) 德国友讯(台湾友讯D-Link子公司)的NAS产品的驱动程序中采用了GPL程序,但没有提供驱动程序源码和GPL协议注释,所涉及的GPL程序有msdosfs、mtd 与 initrd。gpl-violations.org组织创建者Welte发现后向德国友讯提出更正措施无果,遂于2006年向德国法兰克福地方法院提起诉讼。结果以Welte胜诉告终,德国友讯向Welte支付了购买NAS产品和逆向解析等费用,并肯定社群开发者对于自由/开放源码软件的贡献。 这次法兰克福地院的判决则是经过完整的诉讼程序而产生,其间对于各项证据的检视以及双方争执点的辩论均较深入而完备,所产生的判决书因此也较具有代表意义与重要性。这表明,GPL 在德国法管辖区域内的法律有效性与可执行性正式确立。 参考网址:https://www.openfoundry.org/tw/legal-column-list/504--gpl-。 Monsoon Hava案件 2007年Busybox著作权人首次在美国境内提告,其透过SFLC向美国纽约南区联邦法院控诉美国Monsoon公司Hava产品采用Busybox但未公布源码,违反了GPL协议。结果以双方庭外和解而告终,Monsoon向原告一笔金额并未公开的赔偿金,并承诺公开该公司版本的Busybox源码并遵守GPL协议。 2007年到2009年器件,BusyBox著作权人通过SFLC代理向台湾约21家公司提起自由软件侵权控诉,此系列起诉讼案件标志着侵权利用自由软体的法律风险,已由欧洲扩散至美国,其后甚至可能演变至全球各地。 参考网址:https://www.openfoundry.org/tw/legal-column-list/2277--busybox-。https://torquemag.io/2013/03/busybox/。https://www.openfoundry.org/en/news/1287。 思科Linksys案件 2003年,FSF了解到思科的无线路由器Linksys WRT54G,在固件中使用了GNU/Linux系统,根据软件遵循的GPL许可证,消费者应该收到所有的源代码,但思科没有提供,FSF督促思科遵守协议,理解许可证所赋予的义务。但几年下来,思科并没有采取必要步骤去承担应尽义务,拒绝给予消费者完整的源代码以及其它在FSF看来是合理的要求。 2008年FSF决定以违反FSF所持有的版权为由起诉思科,这些程序包括GCC、binutils、和GNU C Library。同年9月FSF诉讼思科源码案以和解收场,并未走上法庭。 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/Unix.html":{"url":"pages/os/Unix.html","title":"Unix Programming","keywords":"","body":" 多人同时使用一台主机的解决方案: 主机配置多显卡、多接口,以让每个用户的键盘、鼠标、显示器连接,然后系统为每个用户设置账户 使用“瘦客户机“,NComputing 是瘦客户机的代表,瘦客户机是具备USB、网卡、显卡等类似主机接口的单片机,可以连接主机。主机同样为每个瘦客户机设置账户,主机通过路由器连接网络, 所有瘦客户机连接该路由器,每个的瘦客户机连接各自的显示器、键盘和鼠标等设备,瘦客户机通过输入主机为其配置的用户名和密码就可以登入共享主机资源(含网络) 使用瘦客户机主要是为了节约独立主机的成本,其次可以统一管理计算机资源,瘦客户机的方案也是计算机安全应用策略,集中管理也使得易维护和升级等等。 瘦客户机不适用于高性能设计开发等工作(除非主机及其强悍),可以运行一般软件,如浏览器、聊天工具等轻应用 1 Unix Basic 1.1 Introduction 1.2 Architecture 1.3 Standardization and Implementations 2 I/O 2.1 Standard I/O 2.2 File I/O 2.3 Terminal I/O 3 Process 3.1 Process Environment 3.2 Process Relationships 3.2.1 Daemon Processes 3.3 Process Control 3.4 Inter process Communication 3.4.1 Signals 4 Threads 4.1 Threads Control 5 Network IPC : Socket 6 File system Linux 操作系统的 实时性 分析 首先UNIX和类Unix操作系统 都是通用操作系统 通用操作系统是 批处理、分时、实时操作系统的集合体,主要性能表现在多用户+分时上 实时意味着需要 极快的响应速度 , 要在极短的时间内,无视任何情况,去响应请求。 专门的实时系统 在响应速度上比通用操作系统快,这仅在极致需求时才具有对比性,可能在90%~99%的情况几乎是没有差别的,甚至通用操作系统会更优秀, 因为通用操作系统 一般利用带有MMU的更快速、更高性能的CPU,足够快的分时轮询 足够小的时间片 比低速CPU的实时处理还要好。 所以实时性 除了处理方式 也要看硬件资源情况, 可以认为在足够好的硬件资源上使用通用操作系统,再加上多进程多线程的合理设计 其性能要优于 实时操作系统 https://blog.csdn.net/luckydarcy/article/details/53572620 ioctl(int fd, int request, ...) #include ioctl()是IO操作的万能函数,《UNIX高级环境编程》将其比喻IO操作的杂物箱,更多用于终端IO操作. 参数: fd 必须是一个打开的文件描述符 request 请求码(一般表示与设备相关的请求码) ... 多参,但一般是一个结构体或者一个char * 第三个参数是为第二个参数准备的,因为C语言没有重载功能,所以就利用fun(ID,...)这样的函数形式来 提供任意的功能. 所以第三个参数是否存在,存在几个,是入参还是出参,完全由第二个参数决定 如果ioctl用于操作终端IO,则还需另外头文件 在BSP中的设备驱动环节,是可以对ioctl进行注册的,于是在用户层就可以使用对应的命令码和参数来使用ioctl(). 1 Unix Basic 2 Process 2.1 Process Environment 2.2 Process Control 2.3 Process Relationships 2.4 Deamon Processes 2.5 Interprocess communication 2.5.1 Signals Signal is a 'soft interrupt', which used to handle asynchronous events. 2.5.1.2 Send Signals 终端发送 快捷键:$stty -a 查看发送终端信号快捷键集合 命令行:'kill [-s SigName/-n SigNum] PID/GID'. or 'Kill -L/-l' (显示系统SigName列表) 函数发送 给指定进程发送指定信号:kill(PID, SIG),当PID大于0时表示给指定进程发送信号,等于0时表示给当前进程发送信号,等于-1时表示给所有进程发送信号,小于-1时表示给进程组发送信号 给当前进程发送指定信号:raise(SIG) 给当前进程发送终止信号:abort(); 给当前进程发送闹钟信号:alarm(second); 超时后将发送SIGALRM信号,默认动作是杀死进程,重复调用该函数将重载设定时间并返回上次剩余时间,当参数为0时表示取消之前的闹钟,该函数一定要放置在捕捉函数之后 给指定进程发送并附加值:sigqueue(PID, SIG, VAL); 使用sigaction()获取VAL值(Union). 2.5.1.3 Processing Signals 忽略信号:被忽略的信号默认动作是忽略/终止进程 捕捉信号: signal(SIG, CALLBACK); 同一个信号注册多次则最后一个回调函数有效,该函数适合单信号处理环境 sigaction(SIG, ACT, OLDACT); 3 I/O I/O矩阵 阻塞 不阻塞 同步 1. R/W 2. R/W+O_NONBLOCK 异步 3. 多路复用(可配置为不阻塞) 4. AIO 1. 同步阻塞IO 用户空间的应用程序执行一个系统调用,这会导致应用程序阻塞。这意味着应用程序会一直阻塞,直到系统调用完成为止(数据传输完成或发生错误) 。调用应用程序处于一种不再消费 CPU 而只是简单等待响应的状态,因此从处理的角度来看,这是非常有效的 以read举例: 阻塞-》切换到内核态-》读完成-》切换到用户态(数据移动到用户缓冲区) 使同步阻塞IO并发的方式是利用进程和线程,所有阻塞IO各一个进程/线程,并且如果使用线程则需做好数据同步. 同步IO不一定阻塞,阻塞的也不一定是同步IO,同步IO表示 用户触发IO操作之后 要去阻塞等待或轮询IO结果,有了结果再同步执行其它指令,这就是同步的意思 异步IO不一定不阻塞,不阻塞的也不一定是异步IO,异步IO表示 用户触发IO操作之后 不用阻塞等待或轮询IO结果 这些都交给内核来完成 用户可以继续执行自己的指令, 等IO有结果之后内核会通知用户,这可以通过信号或回调函数来完成IO触发的既定任务。 异步IO好比到某机构登记注册,然后等电话通知再去取东西一样,这段时间你什么都行。而同步就是你要一直排队等待看看结果出来没有。 2. 同步不阻塞IO 这种情况下表示IO不会立即完成,为检测是否完成要一直轮询,并适当的加入延时,当没有获取到数据时errno会被设置成相应错误码,如EAGAIN(再来一次)或其它错误,所以可以通过函数返回值和错误码确定是否继续下一次循环。 3. 异步阻塞IO - 多路复用 这种模式相比“同步阻塞IO”,可以同时阻塞多个IO,并且阻塞的时长可以配置。 调用select、poll、epoll(linux)可以实现这个功能。 **当用这种模式只阻塞一个IO时,与同步IO的区别就只有 可以设置阻塞时长。** 实际上 同步阻塞IO 可以利用信号signal达到超时的设置。 另外,如果使用了 IO多路复用,那么I/O本身就不应该设置为阻塞了,比如使用了select/poll/epoll() ,read/write就不要再设置成阻塞了 ,显然 如果这样做 select、poll、epoll就失去或损坏多路复用的功能了。 特别的,如果多路复用函数解除阻塞后,要对该文件描述符做耗时操作,那么仍然需要开启一个进程或线程,以便快速进入下一个循环 Tips:多路复用是对事件阻塞,而不是对IO阻塞. 多路复用也不是完全的异步, 只能说在事件通知上是异步的,而实际读写函数还是同步完成的,因为仍然需要阻塞或轮询 4. 异步非阻塞IO - AIO 这种模式利用了处理速度与I/O速度之间的差异,处理器速度被认为是极快的,I/O速度被认为是慢操作。 在运行IO代码时,只对该IO进行注册登记,而不阻塞等待它的返回、也不对其轮询,而是继续下面的其它代码执行,对该IO的监控交给内核完成, 当IO响应达到时,会产生一个信号或或执行一个基于线程的回调函数来完成这次 I/O 处理过程 这类似于为未来要发生的事件准备好资源,当事件发生时自动触发和利用该资源,整个过程不用用户监控,用户要做的就是注册登记并准备资源。 任何的“同步”字样,可以想象你和别人跑步,跑的很快,然后到一个位置X停下来等待其它的人,其它的人中的某些到了X也停下来等待剩余的人,直到所有的人到达了X,然后继续往后走,这就是同步 。 异步可以描述为,你在开始跑之前就告诉其它人我不等人,但是到了X给我打电话我去接你们 2.1 阻塞式I/O 2.2 非阻塞式I/O 2.3 多路复用 2.4 异步I/O 异步I/O是不阻塞的,设定好事件和事件触发时调用的函数,然后就可以做其它的事情了。当事件发生时去执行回调函数。 所以注册的概念对异步I/O非常重要,你只管登记,然后就可以做其他的事,事件发生了就通知你回去做登记的事,于是你不必阻塞等待, 也不必循环轮询。 类似于注册了一个信号,然后按序继续执行其它代码,当信号到达时直接转去执行信号注册的函数 3 Asyn I/O (AIO) 3.1 I/O Multiplexing 背景: 对于文件描述符的状态(如socket的文件描述符、open的文件描述符等等,系统并不主动告诉我们任何信息,文件描述符关联的文件发生的任何变化都需要我们主动去查询, 有“阻塞+多进程/多线程”、“非阻塞查询\"和”异步I/O“可选,但这些方法都不理想 阻塞式IO :很明显,如果在一个进程/线程当中,被阻塞的下一条语句将一直无法执行,直到被阻塞函数不阻塞,这种方式适合非并发态的情况。但是大多数编程都是需要并发的,这也是操作系统存在的意义之一。所以就要为每一个IO开启一个进程和线程,进程资源很宝贵,而使用线程也需要解决锁和同步等问题,进程或线程+阻塞模式是可行的,这要评估项目实际的使用场景,如果只有很少量的IO是没有问题的,如果有类似TCP/IP-HTTP高并发服务器这种的,那很快就会崩溃的。因为进程和线程都不能无限制的增加,进程线程切换开销也很大。当进程、线程过多时,CPU大部分时间都用来切换了。 非阻塞模式,那就需要循环检查,也就是轮询,对于一个进程无限轮询,可以看到当前的CPU核接近100%,这与RTOS中的一个死循环任务中不加延时或调度产生的结果是一样的,也就是其它进程都无法执行了,CPU(如单核)无法给其它进程分配时间片,那就需要加延时,比如sleep睡眠,但睡眠设置多久呢?如果设置长了,那么就不能及时检查并处理已经发生事件的IO,如果事件发生的过快,很可能在被检查之前覆盖掉了上次的事件,导致漏检,更慢的周期还可能导致不及时处理产生的其它问题。如果设置的时间过短就产生其它进程无法分配时间片的问题。所以延时的时间很难把控。此外,频繁的调用I/O处理函数也是错误的表现,理论上任何函数都不应该非常频繁的被调用,特别是无意义的调用。 多路复用,相当于在一个进程/线程下达到阻塞多个I/O的目的,并且,这里的阻塞是有时间配置的,可以为0不阻塞,可以一直阻塞,也可以设定固定时长。 I/O多路复用是单进程下的 信号、轮询等多种方式的组合体. I/O多路复用,就是在单进程下使用内核机制检查描述符列表中的各个成员的状态,这相当于对每个文件描述符开一个进程,然后阻塞检查。 I/O多路复用 - 构造一个描述符列表,调用特定函数查询这些列表,直到这些描述符中有一个已经准备好进行I/O时才返回 select, pselect, 和 poll 是posix标准内的,eselect在Linux中存在 select int select(int nfds, fd_set readfds, fd_set writefds, fd_set exceptfds, struct timeval timeout); timeout - 在描述符列表中没有可读、可写、异常时,函数阻塞的时长,或描述为“没有捕捉到信号”等待的时长。 NULL为永久等待,即阻塞模式 timeout->tv_sec==0 && timeout->tvu_sec=0 不等待,轮询一次所有的文件描述符就返回,即非阻塞模式 对上述成员赋值即表示等待固定时长,如果超时后返回值为0表示没有可用fd 文件描述符是否是阻塞的,不会影响select,它的超时只由timeout决定 readfds/writefds/exceptfds 分别为读、写、异常文件描述符集的指针,POSIX对于fd_set类型的实现是可选择的,因为实际应用中并不会 直接使用该结构体,而是调用如下函数宏: int FD_ISSET(int fd, fd_set set); //判断文件描述符是否属于该集合 void FD_SET(int fd, fd_set set); //添加文件描述符 void FD_CLR(int fd, fd_set set); //删除文件描述符 void FD_ZERO(fd_set set); //删除所有文件描述符 nfds - 最大文件描述符编号+1, 因为文件描述符编号从0开始。该参数是一个范围限制,如果设置为N,则上述三个集合的文件描述符都必须小于N才能被检测, 非常保险的做法是设置FD_SIZE,该宏表示支持的最大文件描述符值。通常通过打开的文件描述符做比较,来确定哪一个才是最大的。 返回值: -1 出错,返回0(超时没有fd准备好),>0表示已经准备好了的文件描述符的数量,如果同一个描述符同时准备好读和写则返回值对其计数两次 准备好的含义是,select返回之后(大于0),可以read/write,且不会阻塞。另外对于普通文件,read、write和异常文件描述符总是准备好的 注意:select 遇到文件尾端时仍然认为是可读的,直到读完该尾端。select返回后,调用read返回0,因为到达了尾端 pselect int pselect(int nfds, fd_set readfds, fd_set writefds, fd_set exceptfds, const struct timespec timeout, const sigset_t *sigmask); pselect 将超时类型改为timspec,能精确到纳秒, 并增加了sigset_t类型,即信号量屏蔽集, 当sigmask为NULL时,pselect与select表现相同 信号屏蔽字,即信号屏蔽集,被屏蔽的信号不能发送给pselect所在进程(实际上是阻塞信号,因为恢复后信号仍然可用,被阻塞的信号仍然被发送),返回时恢复屏蔽信号。 poll poll支持任何类型的文件描述符(而select只支持读、写和异常的文件描述符), int poll(struct pollfd *fds, nfds_t nfds, int timeout); fds应该是一个数组,pollfd结构体如下: struct pollfd { int fd; //要检测的文件描述符,当设置小于0时,poll将忽略 short event; //告诉用户感兴趣的事件 short revents; //内核返回给用户当前发生的事件 }; nfds表示数组元素个数 events可选值为POLLIN/.....以及它们的或值 reevents另外可返回POLLERR/POLLHUP/POLLNVAL异常,这三个值events不能设置 POLLUP表示挂断,此时只能读文件描述符,而不能写 timeout = -1 表示永久等待,当有文件描述符准备好时返回一个+值,如果收到信号中断则返回-1, errno = EINTR。 = 0 不等待 0 毫秒值,如果超时未准备好则poll返回0 与select一样,文件描述符是否阻塞不影响poll,只由timeout决定 TIPs : poll与inotify函数组合 poll 使用 struct pollfd fds = { .fd = queue_fd, .events = POLLIN }; 关联inotify_init()返回的fd,也就是队列文件描述符,事件就是可读 如果队列可读,就表示queue_fd中的watch_fd可读了 同时发生在watch_fd的事件可能不止一个,所以使用read来循环读,一直读到没有。 然后继续poll循环,观察下一个watch_fd, 散装知识点 setpgid(pid_t pid, pid_t pgid) 将pid所在的组ID设置为pgid 如果pid=0 ,表示选择该函数所在的进程组 如果pgid=0,表示用该函数所在的进程的PID作为进程组ID 所以,setpgid(0, 0); 的含义为:将当前进程的进程组ID设置为当前进程的PID 注意:因为进程仅能修改进程本身组ID或其子进程组ID,所以参数pid必须其函数所在进程的PID或者它的子进程PID。 以下不是Posix接口,是Linux-specific 1 Inotify The inotify API provides a mechanism for monitoring and returning filesystem (file and directory) events. 1.1 API #include 1.1.1 int inotify_init(void) & int inotify_init1(int flags) Initializes a new inotify instance and returns a file descriptor associated with a new inotify event queue, inotify_init() is same as inotify_init1() when param flags = 0 1.1.1.1 Parameters IN_NONBLOCK/IN_CLOEXEC can be set for flags to perform block and close-on-exec behavior (for inotify_init1()). 1.1.1.2 Return value On success, return a new file descriptor. On error, -1 is returned, and errno is set to indicate the error : EINVAL - (inotify_init1()) An invalid value was specified in flags. EMFILE - The user limit on the total number of inotify instances has been reached. EMFILE - The per-process limit on the number of open file descriptors has been reached. ENFILE - The system-wide limit on the total number of open files has been reached. ENOMEM - Insufficient kernel memory is available. 1.1.1.3 Note Minimum kernel/glibc version requirements is V2.3.13/V2.4 for inotify_init() and V2.6.27/V2.9 for linotify_init1(). 1.1.2 int inotify_add_watch(int fd, const char *pathname, uint32_t mask) Add a new watch or modifies an existing watch for the file or directory whose location is specified in param pathname to the monitor queue. 1.1.2.1 Parameters fd is referring to which has been initialized instance. The events to be monitored for pathname are specified in the mask bit-mask argument. 1.1.2.2 Return value On success, return a nonnegative watch descriptor. On error, -1 is returned and errno is set appropriately : EACCES - Read access to the given file is not permitted. EBADF - The given file descriptor is not valid. EFAULT - pathname points outside of the process's accessible address space. EINVAL - The given event mask contains no valid events; or fd is not an inotify file descriptor. ENAMETOOLONG - pathname is too long. ENOENT - A directory component in pathname does not exist or is a dangling symbolic link. ENOMEM - Insufficient kernel memory was available. ENOSPC - The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource. 1.1.2.3 read() ssize_t read(int fd, void *buf, size_t count) SHALL called to featch filesystem events from structure struct inotify_event{} : struct inotify_event{ int wd; /* Watch descriptor */ uint32_t mask; /* Bits, mask describing event */ uint32_t cookie; /* Unique cookie associating related events only for IN_MOVED_FROM and IN_MOVED_TO */ uint32_t len; /* Size of name field (including '\\0') */ char name[]; /* Optional terminated with '\\0', exist only when file events watched and reaturn, and may have multi '\\0' endings to alignment content */ } Object Macro Events description Note file IN_ACCESS access + file IN_CLOSE_WRITE open for writing was closed + file IN_MODIFY modify + file IN_MOVED_FROM rename an old name + file IN_MOVED_TO rename a new name + file IN_MOVE = IN_MOVED_FROM | IN_MOVED_TO + file & dir IN_CREATE create + file & dir IN_DELETE delete + file & dir IN_OPEN open * file & dir IN_CLOSE_NOWRITE opened for non-writing was closed * file & dir IN_CLOSE = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE * file & dir IN_ATTRIB attributes were changed * file & dir IN_MOVE_SELF - * file & dir IN_DELETE_SELF - * - IN_ALL_EVENTS monitor all events for add - IN_EXCL_UNLINK except unlink events (since Linux 2.6.36) for add - IN_DONT_FOLLOW - (since Linux 2.6.15) for add - IN_MASK_ADD append instead cover for the same pathname for add - IN_ONESHOT remove it once occure (since Linux 2.6.16) for add - IN_ONLYDIR monitor only if it's directory for add - IN_IGNORED objcet which monitored has been removed for read - IN_ISDIR about directory for read - IN_Q_OVERFLOW wd == -1 for read - IN_UNMOUNT filesystem unmount for read mask of structure inotify_event and for inotify_add_watch() param Tips : or_ed can be used for the macro to create personnalized events. * refer that both for the directory itself and for objects inside the directory and + refer that only for objects inside the directory. 1.1.2.4 Note The param buf of read() should be set bigger enough for the reason of the member of structure inotify_event name, otherwise 0 will be return for the kernel version 2.6.21and EINVAL will be set for errno for the kernel version 2.6.21. 1.1.3 inotify_rm_watch(int fd, int wd) Remove an existing watch (wd) from an inotify instance which associated with the file descriptor fd. 1.1.3.1 Parameters - 1.1.3.2 Return value On success, inotify_rm_watch() returns zero. On error, -1 is returned and errno is set to indicate the cause of the error: EBADF - fd is not a valid file descriptor. EINVAL - The watch descriptor wd is not valid; or fd is not an inotify file descriptor. 1.1.3.3 Note Removing a watch causes an IN_IGNORED event to be generated for this watch descriptor. 1.1.4 Config /proc/sys/fs/inotify/max_queued_events, config the max queue events /proc/sys/fs/inotify/max_user_instances, config the max user instance /proc/sys/fs/inotify/max_user_watches, config the max user watch 1.1.5 Bug & Note Inotify is based on inode, so pathname movement does not affect any changes Inotify do not report events that trigs by mmap()/msync()/munmap() Release inotify resource by close(inotify_fd) instead of close(wd) The 'watch filedescriptor' isn't a file system object or a file descriptor, it's same like an ID which refer to a pathname resource, and only used by 'inotify_rm_watch()'. 1.1.6 Code example #include #include #include #include #include #include /* Read all available inotify events from the file descriptor 'fd'. wd is the table of watch descriptors for the directories in argv. argc is the length of wd and argv. argv is the list of watched directories. Entry 0 of wd and argv is unused. */ static void handle_events(int fd, int *wd, int argc, char* argv[]) { /* Some systems cannot read integer variables if they are not properly aligned. On other systems, incorrect alignment may decrease performance. Hence, the buffer used for reading from the inotify file descriptor should have the same alignment as struct inotify_event. */ char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); const struct inotify_event *event; int i; ssize_t len; char *ptr; /* Loop while events can be read from inotify file descriptor. */ for (;;) { /* Read some events. */ len = read(fd, buf, sizeof buf); if (len == -1 && errno != EAGAIN) { perror(\"read\"); exit(EXIT_FAILURE); } /* If the nonblocking read() found no events to read, then it returns -1 with errno set to EAGAIN. In that case, we exit the loop. */ if (len len) { event = (const struct inotify_event *) ptr; /* Print event type */ if (event->mask & IN_OPEN) printf(\"IN_OPEN: \"); if (event->mask & IN_CLOSE_NOWRITE) printf(\"IN_CLOSE_NOWRITE: \"); if (event->mask & IN_CLOSE_WRITE) printf(\"IN_CLOSE_WRITE: \"); /* Print the name of the watched directory */ for (i = 1; i wd) { printf(\"%s/\", argv[i]); break; } } /* Print the name of the file */ if (event->len) printf(\"%s\", event->name); /* Print type of filesystem object */ if (event->mask & IN_ISDIR) printf(\" [directory]\\n\"); else printf(\" [file]\\n\"); } } } int main(int argc, char* argv[]) { char buf; int fd, i, poll_num; int *wd; nfds_t nfds; struct pollfd fds[2]; if (argc 0) { if (fds[0].revents & POLLIN) { /* Console input is available. Empty stdin and quit */ while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n') continue; break; } if (fds[1].revents & POLLIN) { /* Inotify events are available */ handle_events(fd, wd, argc, argv); } } } printf(\"Listening for events stopped.\\n\"); /* Close inotify file descriptor */ close(fd); free(wd); exit(EXIT_SUCCESS); } Tips : function select(), poll() and epoll() can be used for inotify. 多线程编程与(动态)内存清零的重要性!! 在socket编程时发现使用多线程时,上次访问的数据总是在下次出现,这个数据是包含在函数的局部变量中的,只是是动态 不管是动态还是静态,函数结束总是释放的,况且自己也手动释放了 没错,是释放了 但是多线程访问时,有可能就是访问那个空间,也就是下次这个函数还开辟一样的动态空间,而每次都没有给这个空间清空 所以保留了上次操作的数据 引申一下, 一个内存被使用,作用域之外被释放,虽然释放了,但内容还存在那里,如果下次开辟空间刚好撞上了这个空间,那就 有很大的几率出错(比如这个空间没有被合理的覆盖) 所以,无论怎么开辟的,清空一下总是没错的!!! Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/BSP/DeviceDriver.html":{"url":"pages/os/BSP/DeviceDriver.html","title":"Device driver","keywords":"","body":"1 《设备驱动程序》 1.1 简介 设备驱动程序是进入Linux内核的大门 (除非特别情况) 一般情况下编写设备驱动程序时,应该注重于如何使硬件可用,而如何使用硬件留给上层应用程序,这样驱动程序就比较灵活。 设备驱动程序,就是设备硬件和应用程序之间的软件层。对于同一个设备,不同的驱动程序都可以驱动其工作,但每个驱动程序可以有不同的驱动实现,因此每种驱动程序都呈现一种特性。总的来说,驱动程序应该留给用户更多选项,并尽量保持简单。 1.2 功能划分 功能 描述 进程管理 进程创建、销毁,进程间通信,外部I/O,进程调度等 内存管理 虚拟地址空间,内存分配等 文件系统 内核在没有结构的硬件上构造结构化的文件系统 设备控制 - 网络功能 - 1.3 可装载模块 - 运行时扩展 把程序写入Linux内核有两种方式:作为一个目标文件(.o)编译进内核镜像或在操作系统中作为一个模块文件(.ko)在内核上进行插拔,前者通常在内核移植时完成。 内核模块的插拔、运行时扩展机制,克服了聚内核的缺点 1.4 设备和模块的分类 字符模块(字符设备)、块模块(块设备)和网络模块(网络接口),模块划分不是严格的, 字符设备 : 字符设备是可以向字节流一样被访问的设备,如字符终端、串口等 块设备 : 如磁盘等 网络接口 : 1.5 安全问题 驱动程序中尽量不要实现安全策略,这部分应该交给系统管理员完成。 编写程序时要严格,如变量清零、缓冲区溢出(如数组越界)等处理操作,很多在用户空间编写程序时可忽略的问题,在内核驱动中都必须注意。 对于内核插拔功能,在编译内核时也可选择开关,如果关闭了这个功能,那么就不能实现运行时扩展,所有的内核模块都必须在编译内核时同时编译到内核当中 1.6 加入内核开发团 邮件是从Linux诞生至今一直被Linux内核开发者使用的通信、交流、讨论的方式。 Linux内核邮件列表LKML,提供了不同的主体分类,通过邮箱订阅某一类来获取该类的消息推送。 LKML是Linux内核开发者的聚集中心,这是一个顶级质量的资源。 邮件订阅格式: 接收人:majordomo@vger.kernel.org //TBD 2 构造和运行模块 首先应该准备一个虚拟机Linux系统,用于“牺牲性”测试,因为对内核的操作很可能导致系统崩溃、甚至磁盘等硬件损坏。 2.1 设置测试系统 2.1.1 内核的来源与选择 首先内核有两种应用方向,一个是BSP、另一个是在宿主PC机,这里只讨论后者。 在PC宿主机开机时,在启动界面通常可以看到内核的选择,这是因为一个系统内是可以存在多个内核的,因为一切皆文件,所以可以理解为可以存在多个内核文件,但是在启动时只能指定一个装载运行。 www.kernel.org是Linux内核官网,是标准内核,与之相对应的就是发行版厂商的内核(如某个版本ubuntu、Fedora、Centos携带的和升级的内核等),后者会对某个版本内核打很多补丁,这些补丁会修改设备驱动程序使用的内核API。所以如果想要学习驱动程序的编写,标准内核是最好的。 为此,可以在官网上下载一个某版本的标准内核,然后手动编译安装到系统,重启时选择该内核,即可在此内核下进行模块测试。 另外,如何编译内核也是一门技术,如果没有掌握,那就暂时在发行版厂商内核下测试吧。 2.1.2 宿主机内核在什么目录 你正在使用的Linux操作系统中可能没有内核源码,查看目录/usr/src/kernels/xxx(在kernels目录下可能有更多的内核源码目录,这是系统自动更新的结果),更多被用到的目录是/lib/modules/xxx/build,实际上它是指向前者的软链接,这些目录下的Linux内核源码不是操作系统运行必须的,只是在有些软件要编译成在该平台的内核模块时才需用到(比如要编译一个dnw程序),所以安装完操作系统后这个目录可能为空。 可在线安装内核源码,在此之前一定要确定当前系统使用的内核源码版本“#uname -r”,然后可以通过https://pkgs.org/download/kernel-devel等网站下载安装,或者直接在线“#yum install kernel-devel”下载(red系列),后者不能保证与当前系统使用内核匹配,不匹配可能导致你所编译的模块不能在当前系统运行。 安装的过程就是简单的解压缩,你甚至可以把内核源码解压到任何目录,最好解压到默认标准目录:/usr/src/kernels/。 [info] Note 2.6以上的版本内核,编译模块时依赖源代码树。另外目标板BSP的内核与宿主机内核源码不同,它多用于嵌入式工程,且不能直接作为开发环境使用,它需要进一步配置。从这个意义上讲,宿主机上的内核源码更应该称为“内核开发包”(kernel_devel),它不是一个完整的内核。同样的,目标板内核源码版本也要与目标板正在使用的内核一致,通常这个源码应该是移植内核时使用的、已经配置好的那一份。 2.2 Hello world 模块 //最常用的头文件 #include #include #include MODULE_LICENSE(“Dual BSD/GPL”); //表示该模块遵循BSD/GPL双协议,如果不指定,则在装载模块时会有“垃圾”信息的提示 //多个文件编译成模块,只要有一个文件添加了协议声明即可。 //可选协议有:GPL, Dual BSD/GPL , Dual MPL/GPL , GPL v2, GPL and additional rights, Propreietary //最后一个是未声明协议时的默认协议,即私有协议,私有协议是会有“垃圾”信息的提示的,内核开发者也不愿意帮助有私有模块协议的模块开发问题 int __init_module(void) //回调函数 { printk(KERN_ALERT \"module init\\n”);//内核打印函数,常用于内核调试 //该函数支持优先级设定(在格式化消息前加优先级),优先级用字符串表示,KERN_ALTER就是代步这些字符串中的一个宏 //显式指出优先级的目的是,默认优先级可能不会将消息输出到控制台上 return 0; } void __exit_module(void) //回调函数 { printk(KERN_ALERT “cleanup module”); } module_init(__init_module); //装载到内核时调用 module_exit(__exit_module); //从内核移除时调用,如果未定义清除函数,则模块不允许卸载 //类似的,内核中有许多注册函数,大多以register_为前缀 //特别注意,__init和__exit前缀在内核中会被特别识别,要仅用在初始化和退出函数中。 2.3 用户空间和内核空间 操作系统的空间划分的实现实际是由CPU硬件支持的,即CPU的“级别”支持,不同的级别支持的操作不同,并提供有限的级别切换功能。 Unix系统设计时利用了这种硬件特性,当前所有的处理器多至少支持两个级别,诸如X86系列的CPU可支持更多的级别,此时Unix使用其最高级别和最低级别。 在Unix中,内核运行在最高级别(也称超级用户态),在这个级别中可以进行所有的操作。而应用程序运行在最低级别(用户态),在这个级别中,处理器控制着对硬件的直接访问以及对内存的非授权访问。 常将这两种运行模式称为”内核空间“和”用户空间“,不同模式下具有不同优先级和内存映射(地址空间)。 2.3.1 用户空间与内核空间的切换 两种情况会引发空间的切换(用户态到内核态): 应用程序执行系统调用(应用程序调用系统API) : 执行系统调用的内核代码运行在进程上下文,可访问该进程地址空间的所有数据 应用程序被硬件中断挂起 : 处理硬件中断的内核代码和进程是异步的,与特定进程无关 因为模块代码运行在内核空间,所以一个驱动程序至少要执行两类任务:系统调用 和 中断处理 2.3.2 内核中的并发 内核编程区别于应用程序层的编程在于对并发的处理(除了应用层的多线程,因为要共享资源)。在内核中,无论多么简单的模块,都要注意并发的处理。 多进程并发 应用层的多个进程在使用同一个驱动程序 中断并发 中断的异步处理 多核并发 多核处理器(对称多处理器SMP)调用同一个驱动程序 注:竞态 同一代码的 不同的执行顺序 导致 不同的、非预期行为发生的情况,称为竞态 2.3.3 当前进程 内核模块的大多数操作和某个特定进程相关,通过包含\\,使用current指针即可获取当前进程信息,current指向struct task_struct 2.3.4 其它细节 内核栈空间很小,可能只有4086Byte,因此需要较大空间时,应该使用堆 两个下划线开头的内核函数(__xxx)表明该函数要谨慎使用 内核代码不能实现浮点数运算,也不需要浮点数运算 3 编译和装载 注:编译需要合适的工具:内核文档目录中 Documentation/Changes 列出了编译当前版本内核需要的工具信。 版本依赖:一个模块和特定的内核版本关系紧密,特定版本内核源码树编译出的模块,必须在该版本内核中使用,否则可能导致(装载)错误。(不同版本的内核,其API也可能不同) 平台依赖:内核会对不同的CPU架构进行优化,在装载模块时,内核会检查模块在编译时使用的处理器相关配置选项,如果不同,则不会装载模块 如果要构造可以多个内核使用的模块,可以使用预处理。 3.1 编译模块 # 要编译的模块 obj-m := myModule.o # 该模块所依赖的文件 module-objs := x.o y.o # 宿主机的内核源码树路径 KERNEL_DIR = /lib/modules/$(shell uname -r)/build # -C -M 是make的搭配选项,-C表示进入并执行指定目录的Makefile,M表示返回到指定路径 # 在这里就表示:进入内核源码树调用其Makefile,然后在构造modules之前返回当前目录 # modules指代 obj-m 中的目标,实际modules是内核源码树Makefile中的make all的依赖项: `all : modules` all: make -C $(KERNEL_DIR) M=`pwd` modules install: make -C $(KERNEL_DIR) M=`pwd` INSTALL_MOD_PATH=$(ROOTFS) modules_install clean: make -C $(KERNEL_DIR) M=`pwd` clean 可以看到这里的各种目标的实际编译都是依靠内核源码树来完成的。 如果依赖的内核源码树不在系统中,则可以通过 \"#yum install kernel-devel\" 来完成,这里要注意下载的是否是和内核同样的版本,如果不同,则可以使用全称,如:\"#yum install kernel-devel-5.0.9-301.fc30.x86_64\" 3.2 装载和卸载模块 装载模块,可以用上述的make install,其本质也是调用insmod命令或modprobe命令。rmmod用于移除模块,lsmod用于列出当前装载到内核的所有模块。 insmode vs modprobe modprobe会考虑要装载的模块是否依赖其他模块,如果是,并且找到了,将 将所依赖的一起装载到内核。在这种情况下insmode会失败,在日志文件中记录\"unresolved symbols\"消息。另外modprobe只能从标准目录搜索模块,因此从指定非标准目录插入模块时,还是需要insmode。 插入需要管理员权限: $sudo insmod x.ko 注:printk没有打印到控制台的原因 控制台和printk都有日志级别,当printk的日志级别小于控制台时就无法输出(但可以通过dmesg查看日志),printk(X \"MSG\");其中X可以用如下代替: KERN_EMERG 0 KERN_ALERT 1 KERN_CRIT 2 KERN_ERR 3 KERN_WARNING 4 KERN_NOTICE 5 KERN_INFO 6 KERN_DEBUG 7 数字越小级别越高 另外在纯终端是可以看到内核打印信息的,这也是为什么在开发板中的终端总能看到打印的信息的原因。 rmmod 如果模块正在被使用,则可能卸载失败。在编译模块时使用特别选项可以强制卸载,但通常可以用重启操作系统来解决。 删除需要管理员权限: $sudo rmmod x.ko lsmod lsmod读取/proc/modules虚拟文件来获取相关信息。 4 内核符号表 符号即函数和变量的地址,内核符号表中包含了所有符号的地址,默认一个模块中的符号是不对外开放的(类似应用层的static变量和函数),如果要对外开放(即加入内核符号表中)则要导出: 在全局作用域内:EXPORT_SYMBOL(xxx); 或 EXPORT_SYMBOL_GPL(xxx); 后者导出的符号只能被使用GPL许可证下的模块使用。 4.1 内核符号表的应用 一个模块的符号对外部可见(加入了内核符号表),那么其它模块就可以引用这些符号(类似应用层编程中的extern),从而实现“模块化编程”和“层叠”的概念,一个模块A使用了另一个模块B导出的符号,那么A就依赖B,类似应用层中的库函数调用,显然一个通用的模块且其符号被导出,可以大大节省编程时间。 其它总结内容 模块 简单的内核模块程序:first.c 编译成内核模块:first.ko / test.ko 命令行编译和安装 编译:内核源码目录使用#make modules M=xxx(M指向的路径为first.c所在目录,也是fisrt.ko生成的位置)。 安装:编译成first.ko后,可手动拷贝到/lib/modules/xxx/extra目录下(目标板系统的路径为:/lib/modules/xxx/,如目录不存在可自行建立),安装不是必须的,但这有助于相关模块操作命令的使用。 使用Makefile编译和安装 obj-m = test.o test-objs = first.o KERNEL_DIR = /lib/modules/$(shell uname -r)/build #宿主机内核路径 ROOTFS= all: make -C $(KERNEL_DIR) M=`pwd` modules install: make -C $(KERNEL_DIR) M=`pwd` INSTALL_MOD_PATH=$(ROOTFS) modules_install clean: make -C $(KERNEL_DIR) M=`pwd` clean “obj-m”指定了要生成的模块名称,以模块名称为前缀的“test-objs”指定了要生成该模块依赖哪些目标文件. 多个目标文件编译成模块;test.ko /*增加函数声明配置文件*/ #ifndef __CONFIG_H__ #define __CONFIG_H__ void sec(void); void thi(void); #endif ---------- /*修改first. c*/ #include #include #include #include \"config.h\" MODULE_LICENSE(\"GPL\"); int init_module(void) { printk(\"module init\\n\"); second(); return 0; } void cleanup_module(void) { printk(\"module cleanup\\n\"); third(); } -------- /*增加second. c*/ #include void sec(void) { printk(“sec work\\n”); } -------- /*增加third. c*/ #include void thi(void) { printk(“thi work\\n”); } -------- /*修改Makefile*/ obj-m = test.o test-objs = first.o second.o third.o KERNEL_DIR = /lib/modules/$(shell uname -r)/build #宿主机内核路径 ROOTFS= all: make -C $(KERNEL_DIR) M=`pwd` modules install: make -C $(KERNEL_DIR) M=`pwd` INSTALL_MOD_PATH=$(ROOTFS) modules_install clean: make -C $(KERNEL_DIR) M=`pwd` clean 可以看到,多个文件编译成模块,只要有一个文件添加了GPL协议声明即可。Makefile文件在test-objs后追加了seconed.o、third.o,指定test.ko由三个目标文件组成 内核模块操作工具 ->模块加载insmod xxx.ko insmod 必须指定路径,上面命令是在xxx.ko文件所在目录执行的。 depmod modprobe xxx 执行过depmod之后,即更新了模块依赖信息,这时命令make install就起了作用,Makefile中定义的安装路径,就是depmod命令默认的模块依赖信息更新路径;modprobe也是进行模块插入操作,这个命令依赖depmod更新的信息进行寻找指定模块,并且不用.ko后缀。 加载模块之后在目标板上可直接看到(minicom等串口信息):“module init”,这是fisrt.c中的初始化函数打印的信息;在宿主机上需要使用#dmesg命令才能看到这些信息。 ->模块信息 modinfo xxx modinfo同样依赖depmod更新的信息,也不用指定后缀,它打印指定模块的模块信息,比如可以在什么平台运行等。 modinfo xxx.ko modinfo还可以查看指定模块信息,这使得不必插入就可查看模块信息。 lsmod 跟ls命令类似,它列出当前内核已插入的模块,可以通过lsmod | grep “xxx”寻找已经插入的指定模块来验证该模块是否已成功插入,lsmod不依赖depmod;实际lsmod是对/sys/module的操作。 ->模块卸载 rmmod xxx 拔出指定模块,它不依赖depmod,可指定或不指定.ko后缀。 modprobe -r xxx 使用modprobe也可删除模块。 卸载模块之后在目标板上可直接看到(minicom等串口信息):“cleanup modules”, 这是fisrt.c中的退出函数打印的信息,同样在宿主机中要使用#dmesg。 注: a. 在进行内核模块插拔时很有可能会修改内核对模块的校验机制(版本控制、CRC校验),使得某一时刻在此插拔模块时无效,详细解决这一问题有复杂的过程,较为简单的是重新安装内核,所以备份很重要 b. 一个只有初始化函数没有卸载退出函数的模块,只能插入不能拔出,所以要么都写,要么都不写 模块中的别名机制 module_init(my_init);/module_exit(my_exit); 通过两个宏,自定义了模块初始化和退出函数,很显然这不是必须的,但别名函数可以使用static修饰。要注意这两个宏要放别名函数之下,否则宏找不到这些函数。 C语言不象C++一样有名字空间,那么你写的函数名和变量名很可能与内核冲突,所以要用static关键字修饰你的函数(前提是该函数不会外部被调用),内核也是这么做的。 #include #include #include #include \"config.h\" MODULE_LICENSE(\"GPL\"); MODULE_AUTHOR(\"zhangji\"); MODULE_DESCRIPTION(\"test moudule\"); MODULE_ALIAS(\"1 module\"); static int my_init(void) { printk(\"module init\\n\"); second(); return 0; } static void my_exit(void) { printk(\"module cleanup\\n\"); third(); } module_init(my_init); module_exit(my_exit); 模块中极致的内存优化机制 Linux是节约内存的操作系统典范,任何可能节约下来的内存都不会放过,以初始函数为例,函数要被调用就要加载到内存空间,但初始化函数一般只调用一次,所以调用一次之后就应该把这段空间释放,退出函数也是一样。 #include #include #include #include \"config.h\" MODULE_LICENSE(\"GPL\"); MODULE_AUTHOR(\"zhangji\"); MODULE_DESCRIPTION(\"test moudule\"); MODULE_ALIAS(\"1 module\"); static int __init my_init(void) { printk(\"module init\\n\"); sec(); return 0; } static void __exit my_exit(void) { printk(\"module cleanup\\n\"); thi(); } module_init(my_init); module_exit(my_exit); 内核模块参数 像main函数在Linux命令行环境中接受命令行参数一样,内核模块也允许在插入时使用命令行参数,这个机制通过内核宏实现,模块接受参数要发生在初始化函数之前。 内核支持的参数类型有:bool、invbool(反转值bool)、charp(字符串指针)、short、int、long、ushort、uint、ulong #include #include #include #include #include \"config.h\" MODULE_LICENSE(\"GPL\"); MODULE_AUTHOR(\"zhangji\"); MODULE_DESCRIPTION(\"test moudule\"); MODULE_ALIAS(\"1 module\"); static int baudrate = 9600; static int port[4] = {0, 1, 2, 3}; static char *name = \"vser\"; module_param(baudrate, int, S_IRUGO); module_param_array(port, int, NULL, S_IRUGO); module_param(name, charp, S_IRUGO); static int __init my_init(void) { int i; printk(\"module init\\n\"); printk(\"baudrate: %d\\n\", baudrate); printk(\"port:\\n\"); for(i = 0; i 程序定义了三个参数变量,这些初始值将是没有参数传递时的默认值,module_param()是普通参数宏,其参数分别为:参数变量名、参数数据类型、参数修改权限;module_param_array()是数组参数宏,其参数分别为:数组参数名、数组参数、数据类型、数组中元素个数指针/参数修改权限 权限在linux/stat.h中定义,跟普通文件的定义方法一样,S_IRUGO,其UGO表示 user/group/other,R 表示读,同样的有S_IWUGO、S_IXUGO、...,但模块参数应尽量保持只读性。 通过inmod test.ko baudrate=115200 port=1,2,3,4 name=”mybaudrate” 可在插入模块时传入参数,插入的模块及参数可以通过#ls /sys/module/test/parameters -l查看。 模块依赖之前奏 – nm符号列表命令 可以列出目标文件/可执行二进制文件/.ko模块文件的符号信息,主要导出函数和全 局变量;共三列,包括:符号值、符号类型、符号名称,其中符号类型的含义如下: b或B - bss段/d或 D - data段/r或 R – 只读段/ t或T – text段/ U – 未决 更多信息可通过#man nm查看。 U所在行对应的信息表示此函数存在于其它文件当中,被当前文件调用,对于该函 数所在文件来说,nm列出的该函数的结果是T(T表示可以被调用,t表示不可以)。U表示一个未决符号,表示是在编译阶段不知到此符号对应函数地址,实际该函数地址是通过EXPORT_SYMBOL()宏导出,通过类似共享库函数的方式进行动态链接,内核有大量的符号导出,这为模块设计提供了丰富的基础设施。 注意:导出的即是全局的,全局的符号(全局变量/函数)是不允许重复的,因此如 果一个模块使用过了,你就必须要使用不同的。 内核模块依赖 两个C文件相互调用很简单,通过包含头文件或使用extern存储类型指示即可,但当一个模块调用另一个模块中的函数或使用另外一个模块的全局变量时,该函数/变量必须是导出的。使用EXPORT_SYMBOL(变量名/函数名)导出全局变量或函数,且必须在全局环境中导出,使用EXPORT_SYMBOL_GPL()导出的模块只能被GPL许可证下的模块使用。 注意事项: 在插入模块时,必须先插入被依赖的模块,再插入依赖的模块,否则会出错,因为依赖的模块使用了被依赖模块的导出符号;在这一点上,可以看出modprobe插入命令的优势,它可以自动寻找依赖模块,而这又归功于depmod命令,它会将依赖模块的信息在/usr/src/kernel/xxxx/modules.dep中更新,而modprobe将会根据这些信息去依次插入模块。 存在依赖关系的两个模块不能分别编译,否则不能正确使用,除非被依赖模块集成到内核镜像中。 在拔出模块时,必须先拔出依赖的模块,再拔出被依赖的模块(这里要注意,modprobe -r 不能解决卸载依赖)。 //first.c中调用依赖模块中的val值和函数 ... extern int expval; extern void dep(void); ... ------ //first_dep.c导出val和dep函数的符号 ... MODULE_LICENSE(\"GPL\"); static int expval23 = 10; EXPORT_SYMBOL(expval23); ... static void dep(void) { printk(\"dep work\\n\"); } EXPORT_SYMBOL_GPL(dep23); ... ------- /*同时编译两个内核模块*/ obj-m = test.o test-objs = first.o second.o third.o obj-m += dep.o dep-objs = first_dep.o ..... 可以看到first_dep作为单独的一个模块(当然,最终的模块起名为dep.ko)同样加入了GPL协议声明,在Makefile中编译了两个模块,注意后面的模块要使用“obj-m += ” 附: $ uname -a 查看内核版本 字符设备 概念 Linux操作系统一切皆文件,字符设备也通过文件维护,位于/dev目录下,称之为“字符设备文件”,通过“#ls -l /dev”可查看到以“c”开头标识的文件都是字符设备文件。 主次设备号 字符设备文件编码由“主次设备号”组成,主设备号标识驱动程序编号表示哪一类设备,次设备号由内核使用来标识具体设备,多个驱动程序可共享主设备号,但通常一个主设备号对应一个驱动程序。 中定义了32位的dev_t(typedef unsigned int),前12位作为主设备号,后20位作为次设备号。可以通过中定义的宏来获取主次设备号:MAJOR(dev)、MINOR(dev);也可以通过宏将主次设备号合并成dev_t类型:MKDEV(major, minor)。 注册设备号 中定义了字符设备号注册函数:int register_chrdev_region(dev_t first, unsigned int count, char *name);“first”是分配设备号的起始值,该值通常由MKDEV()产生,“count”是连续设备号的个数,“name”是所注册设备号对应的设备名。该函数执行成功返回0,错误返回负值。 以上是静态注册方式,缺点是无法提前知道哪个设备号可用,动态注册方式可随机分配可用设备号:int alloc_chrdev_region(dev_t dev, unsigned int firstmi nor, unsigned int count, char name);“dev”是出参,保存被分配的第一个设备号,“firstminor”为第一个次设备编号,“count”和“name”与静态注册函数相同。 注册后的设备号及相关信息可从“/proc/devices”中获取。 注销设备号 void unregister_chardev_region(dev_t first, unsigned int count);注销和注册动作应该分别在模块释放和模块初始化函数中出现。 创建字符设备文件 设备文件通常是自动创建的,也可通过已有设备号手动建立设备文件:“#mknod /dev/abc c 256 0”,该命令创建了主设备号为256、次设备号为0的字符设备文件,这样就通过有效设备号与设备文件进行关联,对该设备文件进行读写,即是对已注册的设备号指向的设备进行读写。 简而言之,mknod命令就是将文件名、文件类型、主次设备号等信息保存在磁盘上 重要的数据结构 file_operations定义在中,包含一组函数指针用于关联指定函数来实现用户层的系统调用(System API),具体实现的函数由用户调用时传参。结构体中涉及到__user空宏,目的是作为一个标识方便维护程序。不使用或当函数指针被赋值为NULL时表示设备不支持该操作,内核对不同函数指针赋值为NULL的处理行为不同。 通常该结构体指针名定义为:struct file_operations *fops; 不同于C库中的FILE结构体,内核file结构体定义在中,file结构代表一个打开的文件,它不限于设备文件,每个打开的文件在内核中都有一个对应的机构体,它由内核在open时创建,在close时释放,在创建时会将file结构体传递给在该文件上操作的所有函数。通常该结构体指针名定义为:struct file *filp; inode结构表示文件,区别与file结构是表示打开文件的描述符,一个文件可能被多个程序打开对应多个file结构,而此文件只指向一个inode结构。inode结构包含大量有关文件的信息,但只有两个成员对驱程有用:dev_t i_rdev和struct cdev *i_cdev;前者包含了真正的硬件层的设备编号,因内核版本变化的历史原因,该结构应该使用下列宏代替来保证最高兼容性: unsigned int imajor(struct inode *inode); unsigned int iminor(struct inode *inode); 后者表示字符设备,定义在。 字符设备的注册/注销 这里是设备注册/注销,要区分与上面的设备号注册/注销,老的办法(2.6内核之前)现在仍然可用:int register_chrdev(unsigned int major, const char *name,struct file_operations *fops); int unregister_chardev(unsigend int major, const char *name);这套函数的限制是主次设备号不能大于255,注册函数会给指定的主设备号分配0~255之间的次设备号,并为每个设备建立cdev结构。注册函数的返回值是major值,这要求参数major应该是全局变量,这样可以在注销函数时正确释放。使用这套函数的驱动程序必须有处理256个次设备上open调用的能力。 新的方法使用cdev接口: void cdev_init(struct cdev cdev, struct file_operations fops); int cdev_add(struct cdev dev, dev_t num, unsigend int count); void cdev_del(struct cdev cdev); 注册函数的cdev参数是出参,这要求该参数应该是全局变量,以方便注销函数获取使用。 注:设备号注册用于内核对设备建立索引,设备注册是将设备与文件建立关联,设备注册与注销函数应该位于设备号注册与注销函数之间 open和release操作 打开操作:int (open)(struct inode inode, struct file filp);关闭操作:int (release)(struct inode inode, struct file filp); 对于打开操作应该完成如下内容:首次打开进行错误检查和初始化、分配并填写filp->private_data,该成员为void类型指针,用来保存用户私有数据/结构指针以便在读写操作中对其操作。 对于关闭操作应该完成如下内容:释放由open分配的保存在filp->private_data中的所有内容、在最后一次关闭操作时关闭设备。 通常,保存在filp->private_data指针变量中的结构体地址,即用户使用结构体维护数据,为了获取该结构体地址可能用到宏:container_of(ptr,struct_type,mem);struct_type是结构体类型,mem是结构体中的一个成员,ptr是该成员的指针(地址)。 read和wirte操作 read拷贝数据到用户空间(从用户角度的读):ssize_t read(struct file filp, char __user buff, size_t count, loff_t offp);write从用户空间拷贝数据(从用户角度的写):ssize_t write(struct file *filp, const char __user *buff, size_t count, loff_t offp);参数buff指向用户空间的缓冲区,内核代码不能直接引用其内容,而应该使用内核专用函数:unsigned long copy_to_user(void __user *to, const void *from, unsigned long count);unsigned long copy_from_user(void *to, const void __user *from, unsigned long count);这两个函数在中定义。 注意:永远不要引用用户空间指针以危及系统安全性。以上两个内核专用拷贝函数不仅拷贝数据,还同时检查指针有效性。read与write的实现应该与系统调用保持一致,如正确执行返回读取/写入的字符个数、错误执行返回负值、返回0到达结尾等等。具体的错误值在中定义。 readv和writev操作(暂略) 注意:内核代码必须拥有很高的质量,主要反映在内核运行和用户调用两个方面,如果调用者是自己则把关注点放在内核运行的稳定性上即可 示例:一个完整的字符设备驱动程序框架 /*test.ko*/ #include #include #include #include #include #include #define DEVICE_MINOR 0 #define DEVICE_NAME \"TEST\" #define DEVICE_COUNT 1 int m_open(struct inode *inode, struct file *filp) { filp->private_data = xxx; return 0; } ssize_t m_read(struct file *filp, char __user *buff, size_t count, loff_t offp) { ssize_t copied; copy_to_user(xxx); return copied; } ssize_t m_write(struct file *filp, const char __user *buff, size_t count, loff_t offp) { ssize_t copied; copy_from_user(xxx); return copied; } int m_release(struct inode *inode, struct file *filp) { return 0; } static dev_t m_dev; static struct cdev m_cdev; static struct file_operations m_ops={ .owner = THIS_MODULE, .open = m_open, .read = m_read, .write = m_write, .release = m_release }; static int m_init(void) { alloc_chrdev_region(&m_dev, DEVICE_MINOR, DEVICE_COUNT, DEVICE_NAME); cdev_init(&m_cdev, &m_ops); cdev_add(&m_cdev, m_dev, DEVICE_COUNT); return 0; } static void m_exit(void) { cdev_del(&m_cdev); unregister_chrdev_region(m_dev, DEVICE_COUNT); } module_init(m_init); module_exit(m_exit); MODULE_LICENSE(\"GPL\"); MODULE_AUTHOR(\"Dumor\"); MODULE_DESCRIPTION(\"A test driver\"); 示例:虚拟一个串口设备 #include #include #include #include #include #include //2.6版本内核的FIFO头文件 #define MY_MAJOR 256 #define MY_MINOR 0 #define MY_COUNT 1 #define MY_NAME \"ZJ'S CDEV\" static struct cdev my_cdev; static DEFINE_KFIFO(myfifo, char, 32);//使用内核FIFO, 建立32个char空间 static int my_open(struct inode *inode, struct file *filp) { return 0; } static int my_release(struct inode *inode , struct file *filp) { return 0; } static ssize_t my_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { unsigned int copied = 0; kfifo_to_user(&myfifo, buf, count, &copied); return copied;//系统调用的read函数要求返回读到的字节数 } //对于支持随机访问的设备pos值才有作用 static ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos) { unsigned int copied = 0; kfifo_from_user(&myfifo, buf, count, &copied); return copied; } static struct file_operations my_ops={ .owner = THIS_MODULE, .open = my_open, .release = my_release, .read = my_read, .write = my_write }; static int __init my_init(void) { int ret; dev_t dev; dev = MKDEV(MY_MAJOR, MY_MINOR); ret = register_chrdev_region(dev, MY_COUNT, MY_NAME); if(ret) return ret; cdev_init(&my_cdev, &my_ops); my_cdev.owner = THIS_MODULE; ret = cdev_add(&my_cdev, dev, MY_COUNT); if(ret) return ret; return 0; } static void __exit my_exit(void) { dev_t dev; dev = MKDEV(MY_MAJOR, MY_MINOR); cdev_del(&my_cdev); unregister_chrdev_region(dev, MY_COUNT); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE(\"GPL\"); /* 上述程序没有用到打开关闭功能,读写功能也仅用到了内核FIFO,很多形参也暂时 没有用到,通过下面命令可以进行验证: #mknod /dev/abc c 256 0 #make && make install && depmod && modprobe cdev_fifo #echo “hello fifo” > /dev/abc #cat /dev/abc hello fifo 可以看到,通过用户向字符设备写入数据,通过cat命令查看该内容,可以证明内 核FIFO生效 */ 示例:虚拟两个串口设备 #include #include #include #include #include #include #define MY_MAJOR 256 #define MY_MINOR 0 #define MY_COUNT 2 #define MY_NAME \"ZJ'S TWO CDEVs\" static struct cdev my_dev; static DEFINE_KFIFO(myfifo0, char, 32); static DEFINE_KFIFO(myfifo1, char, 32); static int my_open(struct inode *inode, struct file *filp) { switch (MINOR(inode->i_rdev)) { case 0: filp->private_data = &myfifo0; break; case 1: filp->private_data = &myfifo1; break; } return 0; } static int my_release(struct inode *inode, struct file *filp) { return 0; } static ssize_t my_read(struct file *filp, char __user *buf, size_t count, loff_t *pos) { unsigned int copied = 0; struct kfifo *myfifo = filp->private_data; kfifo_to_user(myfifo, buf, count, &copied); return copied; } static ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos) { unsigned int copied = 0; struct kfifo *myfifo = filp->private_data; kfifo_from_user(myfifo, buf, count, &copied); return copied; } static struct file_operations my_ops = { .owner = THIS_MODULE, .open = my_open, .release = my_release, .read = my_read, .write = my_write }; static int __init my_init(void) { int ret; dev_t dev; dev = MKDEV(MY_MAJOR, MY_MINOR); ret = register_chrdev_region(dev, MY_COUNT, MY_NAME); if(ret) return ret; cdev_init(&my_dev, &my_ops); my_dev.owner = THIS_MODULE; ret = cdev_add(&my_dev, dev, MY_COUNT); if(ret) return ret; return 0; } static void __exit my_exit(void) { dev_t dev; dev = MKDEV(MY_MAJOR, MY_MINOR); cdev_del(&my_dev); unregister_chrdev_region(dev, MY_COUNT); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE(\"GPL\"); /* 上述程序增加MY_COUNT值为2,即次设备号从0~1,同时初始化两个内核FIFO:myfifo0、myfifo1,open接口取出次设备号进行判断来决定将 哪个FIFO结构体的地址保存到file结构体中的private_data(驱动私有数据指针) 通过#mknod /dev/abc c 256 0 &&mknod /dev/def c 256 1建立两个字符设备文件,通过插拔模块、#echo “hello 0 ” > /dev/abc && echo “hello 1” > /dev/def向字符设备文件写数据,通过#cat /dev/abc && cat /dev/def可以看到成功写入的数据 上述程序是1个cdev对象使用1个驱动对应多个同类设备,也可以用多个cdev对象使用1个驱动对应多个同类设备 */ Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/BSP/FileSys.html":{"url":"pages/os/BSP/FileSys.html","title":"FileSys","keywords":"","body":"1 Introduction File system (alias 'filesystem', 'fs') provides the mechanism for data storage and retrieves, on physical media (permanent and volatile, local and network). And help users interactive with OS. https://en.wikipedia.org/wiki/File_system VFS 是Linux内核的虚拟文件系统层,它屏蔽了不同文件系统的差异,提供统一的操作接口, read(), write(), ... | -------VFS--------------- | | | | ext2 ext3 network .... # Linux 内核文件中包含多种文件系统,如ext2 ext3 ext4 ntfs fat ...,通过配置可使内核支持其中一种到多种,当物理磁盘按所配置的文件系统格式进行格式化,内核启动后就会识别该磁盘。 要明确的是,文件系统不等于目录文件结构,支持这个文件系统只是说明内核能够识别并操作基于该文件系统的文件, 而磁盘上有什么文件,或者说一个合格的Linux操作系统下应该有什么目录文件结构,这不是文件系统的内容, 而属于“文件系统层次标准Filesystem Hierarchy Standard”的内容(称为FHS), FHS规定了层次结构、根目录下的各个子目录名称及其应该存放的内容. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard Linux内核是不提供这些内容的,rootfs就是FHS的实现之一。rootfs提供了基本的目录结构 / /root /bin /lib /sys 等等,并且在这些目录结构下包含适当够用的命令工具和函数库。 FHS的存在,也是让内核能够顺利启动的原因之一。如果没有FHS,那么内核将没有足够的启动资源。 所以FHS一方面为内核启动准备了资源,另一方面为内核系统后的用户操作提供了磁盘的可视化窗口 https://www.docin.com/p-1779855302.html tmpfs、ramdisk、ramfs、rootfs等都属于虚拟文件系统(VFS)系列。 tmpfs(在之前被称为shmfs),是基于ramfs代码开发的,比ramfs更优秀 软件的任何数据都不会、也不能独立存在,要么在内存(Ram)中,要么在辅存(或磁盘、硬盘、Flash、ROM)中。 RAMDISK - RAM disk, 内存磁盘,虚拟在内存的磁盘,可以像操作普通磁盘一样对其操作 RAMFS - RAM File System, 内存文件系统, ROOTFS - Root File System,是RAMFS的特例 Ramdisk nux RamDisk 使用简介 来源: ChinaUnix博客 日期: 2008.01.29 00:26 (共有条评论) 我要评论 linux RamDisk 使用简介 1、Ram Disk介绍 1.1 什么是Ram Disk Ram Disk 就是将内存中的一块区域作为物理磁盘来使用的一种技术。 对于用户来说,可以把RAM disk与通常的硬盘分区(如/dev/hda1)同等对待来使用。 1.2 Ramdisk与硬盘分区的不同 RAM disk不适合作为长期保存文件的介质,掉电后Ramdisk的内容会随内存内容的消失而消失。 RAM disk的其中一个优势是它的读写速度高,内存盘的存取速度要远快于目前的物理硬盘,可以被用作需要高速读写的文件。 注意:在2.6版本后,Ramdisk的这一作用开始被tmpfs(Virtual memory file system support)取代。 1.3 Ramdisk的作用 内存盘对于保存加密数据来说是一个福音,因为我们如果将加密的文件解密到普通磁盘的话,即使我们随后删除了解密文件,数据仍然会留在磁盘上。这样是非常不安全的。而对于 RamDisk 来说,没有这样的问题。 假设有几个文件要频繁的使用,你如果将它们加到内存当中,程序运行速度会大副提高,因为内存的读写速度远高于硬盘。 象WEB服务器这样的计算机,需要大量的读取和交换特定的文件,因此,在WEB服务器上建立RamDisk会大大提高网络读取速度。 RAM disks can be a great place to store temporary data. 2、前提条件 为了能够使用RAM disk 你的内核必须要支持RAM disk,即:在编译内核时,要选中RAM disk support这一选项,会在配置文件中定义CONFIG_BLK_DEV_RAM。 为了让内核有能力在内核加载阶段就能装入RAMDISK,并运行其中的内容,要选中initial RAM disk(initrd) support 选项,会在配置文件中定义CONFIG_BLK_DEV_INITRD。 3、操作步骤: 3.1系统中已有的“内存盘” 3.1.1 查看系统中有那些“内存盘” Linux 内核默认创建了 16 个 ramdisks。它们目前是未启用的,不占用任何内存空间。这 16 个设备分别是 /dev/ram0 -- /dev/ram15。虽然我们可以看到还有 /dev/ram16 -- 19,但是它们默认是不可用的。 通过更改rd.c的配置,可以使系统支持的RAM disk的数量增加到255个。为了使用更多的RAM disk,我们可以使用“mknod /dev/ramX b 1 X”命令创建更多的RAM disk设备文件,并且通过chmod命令将他们的访问权限改成我们想要的。 使用下面的命令查看: [root]# ls -l /dev/ram*lrwxrwxrwx 1 root root 4 Jun 12 00:31 /dev/ram -> ram1brw-rw---- 1 root disk 1, 0 Jan 30 2003 /dev/ram0brw-rw---- 1 root disk 1, 1 Jan 30 2003 /dev/ram1brw-rw---- 1 root disk 1, 10 Jan 30 2003 /dev/ram10brw-rw---- 1 root disk 1, 11 Jan 30 2003 /dev/ram11brw-rw---- 1 root disk 1, 12 Jan 30 2003 /dev/ram12brw-rw---- 1 root disk 1, 13 Jan 30 2003 /dev/ram13brw-rw---- 1 root disk 1, 14 Jan 30 2003 /dev/ram14brw-rw---- 1 root disk 1, 15 Jan 30 2003 /dev/ram15brw-rw---- 1 root disk 1, 16 Jan 30 2003 /dev/ram16brw-rw---- 1 root disk 1, 17 Jan 30 2003 /dev/ram17brw-rw---- 1 root disk 1, 18 Jan 30 2003 /dev/ram18brw-rw---- 1 root disk 1, 19 Jan 30 2003 /dev/ram19brw-rw---- 1 root disk 1, 2 Jan 30 2003 /dev/ram2brw-rw---- 1 root disk 1, 3 Jan 30 2003 /dev/ram3brw-rw---- 1 root disk 1, 4 Jan 30 2003 /dev/ram4brw-rw---- 1 root disk 1, 5 Jan 30 2003 /dev/ram5brw-rw---- 1 root disk 1, 6 Jan 30 2003 /dev/ram6brw-rw---- 1 root disk 1, 7 Jan 30 2003 /dev/ram7brw-rw---- 1 root disk 1, 8 Jan 30 2003 /dev/ram8brw-rw---- 1 root disk 1, 9 Jan 30 2003 /dev/ram9lrwxrwxrwx 1 root root 4 Jun 12 00:31 /dev/ramdisk -> ram0 3.1.1 查看系统中内存盘的大小 [root]# dmesg | grep RAMDISKRAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksizeRAMDISK: Compressed image found at block 0 也就是说,默认的 RamDisk 是4MB的。 3.2 格式化RamDisk 接下来就需要做文件系统了,也就是格式化。RamDisk是临时性的,所以没有带日志的文件系统的必要,所以我们一般做 ext2 就可以了: [root]# mke2fs -m 0 /dev/ram0mke2fs 1.32 (09-Nov-2002)Filesystem label=OS type: LinuxBlock size=1024 (log=0)Fragment size=1024 (log=0)4000 inodes, 16000 blocks0 blocks (0.00%) reserved for the super userFirst data block=12 block groups8192 blocks per group, 8192 fragments per group2000 inodes per groupSuperblock backups stored on blocks:8193Writing inode tables: doneWriting superblocks and filesystem accounting information: doneThis filesystem will be automatically checked every 22 mounts or180 days, whichever comes first. Use tune2fs -c or -i to override. mke2fs 的-m百分比值>选项:指定给管理员保留扇区的比例。在这里,-m 0,即:不为管理员保留任何扇区,任何普通用户都可以使用所有可用的空间。 3.3 创建挂载点并挂载 RamDisk 现在,我们的 RamDisk 已经可以使用了,只需要再将它挂接到一个可访问的目录点: [root]# mkdir /mnt/rd[root]# mount /dev/ram0 /mnt/rd 我们来验证一下,RamDisk是否已经挂在成功了: [root]# mount | grep ram0/dev/ram0 on /mnt/rd type ext2 (rw)[root]# df -h | grep ram0/dev/ram0 16M 13K 16M 1% /mnt/rd 3.4 使用RamDisk Now that it has been created, you can copy, move, delete, edit, and list files on the ramdisk exactly as if they were on a physical disk partiton. To unmount the ramdisk, simply enter the following: [root]# umount -v /mnt/rd/dev/ram0 umounted 4、与RAMdisk有关的命令行参数: 4.1 ramdisk_size=N 这个参数告诉RAM磁盘驱动将RAM磁盘的大小设置为N k,默认是4096(4 MB)。 RAM磁盘的大小会根据需要动态的增长,因此其大小有个上限加以限制以免它用光所有可用的内存而坏事。ramdisk_size这个参数实际是设置这个上限值的。 我们可以通过命令:dmesg | grep RAMDISK来查看这个上限值。要注意的是,这个值在系统运行阶段是不能再被修改的。 尽管RAM磁盘的大小有个最大值,但我们可以指定需要使用的RAM磁盘的容量。比如,在本例中我们设为2MB。通过写入RAM磁盘设备来创建。命令为dd if=/dev/zero of=/dev/ram0 bs=1k count=2048。当我们没有指定需要使用的RAM磁盘的容量,而直接在其上挂载文件系统时,它的容量是其上限值。 4.2 load_ramdisk=N 这个参数告诉内核是否要载入一个RAMDISK映像。load_ramdisk =1时指定核心将软盘载入内存。默认值是0,表示内核不要去载入RAMDISK映像。 4.3 prompt_ramdisk=N 此参数告诉内核是否要给你个提示要求插入含RAMDISK映像的软盘。 在只用一张软盘的配置下RAMDISK映像与刚刚载入/启动的核心在相同的软盘上,故不需要提示,这种情况可以用 `prompt_ramdisk=0'。 在使用两张软盘的配置下你需要交换软盘,故可以使用 `prompt_ramdisk=1'。因为这是预设值,所以不必真的去指定它。 4.4 ramdisk_start=NNN 为了使内核映像能够与压缩的RAMDISK映像放在一张软盘内,所以加入这个 `ramdisk_start=' 指令。 内核不能够放在压缩过的RAMDISK磁盘的文件系统映像里,因为它得从最开始的第零磁区开始放置,这样基本输出入系统(BIOS)才能载入启动磁区而内核也才能够开始启动执行。(参考Documentation/ramdisk.txt,但是我不太明白)????????? 注意:如果你使用的是没有压缩的RAMDISK磁盘映像,那么内核可以是要载入的RAMDISK磁盘的文件统映像的一部份,且该软盘可以由 LILO 启动,两者也可以如同压缩的映像那样为分开的两部份。 如果你使用启动/根(boot/root)两张磁盘的方式(内核一张,RAMDISK映像放第二张)那么RAMDISK磁盘会由第零磁区开始,并使用零作为偏移值(offset)。因为这是预设值,你根本不必真的去使用这个指令。 5、使用\"rdev -r\" 命令“rdev –r”设置内核镜像文件中的两个字节(32bit),这两个字节中各个位的含义如下: 低11位(0 -> 10)指定了一个偏移量(以1K的块为单位),最到能寻址到2M,用以指定到何处去寻找RAM磁盘。 第14位指示RAM磁盘是否被加载。 第15位指示是否在加载RAM磁盘之前给出一个提示并等待用户指令。 如果随着数据被写入RAM磁盘,RAM磁盘的大小是动态增长的,那么指定RAM磁盘的大小的域将被忽略。11到13位没有被使用,所以可以为0。 上面所列的数据并非什么秘密,可以在参照下列地方: 进入内核源码所在目录: ./arch/i386/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK 0x07FF ./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG 0x8000 ./arch/i386/kernel/setup.c:#define RAMDISK_LOAD_FLAG 0x4000 考察一个典型的\"两张软盘启动\",内核在第一张软盘上,并且已经将一个RAM磁盘镜像文件放到了第二张软盘上。 所以你希望将0到13位设置为0,这将意为着你的RAM磁盘处于从软盘起始地址偏移量为0KB的地方。相同功能的命令行参数为:\"ramdisk_start=0\" 你希望第14位为1,即声明加载RAM磁盘。相同功能的命令行参数为:\"load_ramdisk=1 你希望第15位为1,这是声明希望显示一个提示并等待用户的按键以得到一个提示机会来更换软盘。形同功能的命令行参数为:\"prompt_ramdisk=1\" 将上述的标志位综合在一起得到:2^15 + 2^14 + 0 = 49152作为参数传递给rdev用来设置内核镜像里的两个字节。所以如果创建上述的第一个磁盘,你需要进行如下操作: /usr/src/linux# cat arch/i386/boot/zImage > /dev/fd0 /usr/src/linux# rdev /dev/fd0 /dev/fd0 /usr/src/linux# rdev -r /dev/fd0 49152 如果你创建一个使用了lilo的启动磁盘,为了得到上面说明的那些效果,你需要使用下列lilo的参数: append = \"ramdisk_start=0 load_ramdisk=1 prompt_ramdisk=1\"考虑到默认的start = 0和prompt = 1,你可以简化lilo的命令行参数为: append = \"load_ramdisk=1\" 6、一个创建压缩RAM磁盘的例子: 为了创建一个RAM磁盘的镜像,你需要你一个单独的块设备。这个块设备可以是一个RAM磁盘设备本身,也可以是一个未使用的磁盘分区(比如一个没有被挂载的交换分区)。在这个例子中,我们将使用RAM磁盘设备:\"/dev/ram0\"。 a)确定你希望使用的RAM磁盘的容量 比如,在本例中我们设为2MB。通过写入RAM磁盘设备来创建。最好写入0,这样下一步创建镜像时进行最大比例压缩的时候比较方便压缩未使用的块。命令为: dd if=/dev/zero of=/dev/ram0 bs=1k count=2048 b)创建一个文件系统。在本例中使用ext2fs。命令为:mke2fs -vm0 /dev/ram0 2048 c)挂载这个磁盘设备 无论是一个RAM磁盘设备,还是一个单独的分区,向里面拷贝你需要的文件(比如:/etc/ /dev/ ...)。然后卸载这个设备(umount)。 d)压缩这个RAM磁盘镜像。 压缩之后,被实际使用的空间大约能压缩到原来的50%,并且未被使用的空间几乎被完全压缩到0。命令为:dd if=/dev/ram0 bs=1k count=2048 | gzip -v9 > /tmp/ram_image.gz e)将内核放入软盘。 命令为:dd if=zImage of=/dev/fd0 bs=1k f)将RAM磁盘镜像放入软盘。 使用一个比内核所占空间略大的偏移量。之所以要有一个略大的偏移量,可以方便以后更换内核,而不会覆盖到RAM磁盘的镜像。比如,如果内核占用了350KB,那么写入RAM磁盘镜像的时候使用400KB的偏移量是比较合理的。注意:确定\"偏移量+RAM磁盘镜像的体积\"不会超出软盘的容量(通常是1440KB)。 命令为:dd if=/tmp/ram_image.gz of=/dev/fd0 bs=1k seek=400 g)使用rdev命令设置启动设备,RAM磁盘偏移量,是否提示换磁盘标志,等等。 比如设置:prompt_ramdisk=1, load_ramdisk=1,ramdisk_start=400,这些标志时,可以计算出来:2^15 + 2^14 + 400 = 49552,使用的命令可能为: rdev /dev/fd0 /dev/fd0 rdev -r /dev/fd0 49552 到此为止,你已经获得了你自己的启动/根压缩RAM磁盘(软盘),你也可以将步骤d和步骤f通过管道一步执行。 培训内容 QT网络文件系统 a. 解压 [root@deng Qt]# ls rootfs_qtopia_qt4-20141213.tar.gz [root@deng Qt]# tar -xzvf rootfs_qtopia_qt4-20141213.tar.gz b. 拷贝文件 [root@deng Qt]# mv rootfs_qtopia_qt4 /qtrootfs 授权 [root@deng /]# chmod -R 777 qtrootfs/ c. 配置nfs [root@deng /]# vim /etc/exports[root@deng /]# cat /etc/exports/qtrootfs *(rw,sync,no_root_sqush) 关闭防火墙 [root@deng /]# iptables -F 关闭安全linux [root@deng /]# setenforce 0 setenforce: SELinux is disabled 重启rpcbind服务 [root@deng /]# /etc/init.d/rpcbind restart 重启nfs服务 [root@deng /]# /etc/init.d/nfs restart 验证是否共享 [root@deng /]# showmount -e 192.168.8.88 Export list for 192.168.8.88: /qtrootfs * d. 设置启动参数 minicom: DengJin # set bootargs \"root=/dev/nfs nfsroot=192.168.8.88:/qtrootfs ip=192.168.8.77 console=ttySAC0,115200 lcd=S70 ctp=2 \" DengJin # save 最小网络文件系统的构建(重点) 1) 创建共享目录 [root@deng /]# mkdir rootfs 2) 编译busybox [root@deng arm]# ls busybox-1.17.2-20101120.tgz busybox-1.17.2-20101120.tgz 解压 [root@deng arm]# tar -xvf busybox-1.17.2-20101120.tgz [root@deng arm]# cd busybox-1.17.2 生成默认的配置文件 [root@deng busybox-1.17.2]# make defconfig 配置 [root@deng busybox-1.17.2]# make menuconfig │ ┌───────────────────────────────────────────────────────────┐ │ │ │ Busybox Settings ---> │ │ │ │ Archival Utilities ---> │ │ │ │ Coreutils ---> │ │ │ │ Console Utilities ---> │ │ │ │ Debian Utilities ---> │ │ │ │ Editors ---> │ │ │ │ Finding Utilities ---> │ │ │ │ Init Utilities ---> │ │ │ │ Login/Password Management Utilities ---> 出现如下界面 │ General Configuration ---> │ │ │ Build Options ---> │ │ │ │ │ │ Installation Options ---> │ │ │ │ Busybox Library Tuning ---> │ │ │ │ 出现如下界面 │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ [ ] Build BusyBox as a static binary (no shared libs) │ │ 2 GB) │ │ │ │ () Cross Compiler prefix │ │ 按下回车 输入arm-linux- │ │ () Additional CFLAGS │ │ │ │ 最终配置如下: │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ [*] Build BusyBox as a static binary (no shared libs) │ │ 2 GB) │ │ │ │ (arm-linux-) Cross Compiler prefix │ │ ! /bin/sh /bin/mount -a 创建dev设备 /sbin/mdev -s 修改inittab内容如下 [root@deng rootfs]# cat etc/inittab ::sysinit:/etc/init.d/rcS ::respawn:-/bin/sh tty2::askfirst:-/bin/sh ::ctrlaltdel:/bin/umount -a -r 拷贝库 [root@deng rootfs]# cp -rf /usr/local/arm/4.5.1/arm-none-linux-gnueabi/lib/* lib/ 配置nfs共享 [root@deng rootfs]# vim /etc/exports /qtrootfs *(rw,sync,no_root_squash) /rootfs *(rw,sync,no_root_squash) 设置启动参数 DengJin # set bootargs \"root=/dev/nfs nfsroot=192.168.8.88:/rootfs ip=192.168.8.77 console=ttySAC0,115200 lcd=S 70 ctp=2\" DengJin # set bootcmd \"movi read kernel 0 0x40008000;bootm 0x40008000\" DengJin # save -------------- 1. 从SD卡启动文件系统 a. 打包 [root@deng rootfs]# tar -cjvf nfs.tar.bz2 * b. 挂载 minicom: [root@DengJin /]# mount /dev/mmcblk0p2 /mnt c. 解压到指定的目录 minicom: [root@DengJin /]# tar -xjvf nfs.tar.bz2 -C /mnt d. 卸载 minicom: [root@DengJin /]# umount /mnt e. 重启进入uboot 设置启动参数 DengJin # set bootargs \"root=/dev/mmcblk0p2 console=ttySAC0,115200 lcd=S70 ctp=2\" DengJin # save f. 测试 断掉网线 看看能否进入文件系统 2. 从SD卡启动Qt文件系统 a. 打包 [root@deng /]# tar -cjvf qtrootfs.tar.bz2 qtrootfs b. 挂载(先进入网络文件系统) [root@DengJin /]# mount /dev/mmcblk0p4 /mnt c. 解压到指定的目录 [root@DengJin /]# tar -xzvf rootfs_qtopia_qt4-20141213.tar.gz -C /mnt d. 卸载 [root@DengJin /]# umount /mnt e. 烧写ramdisk-u.img minicom: DengJin # fastboot PC: [root@deng Qt]# fastboot flash ramdisk ramdisk-u.img f. 设置启动参数 DengJin # set bootcmd \"movi read kernel 0 40008000;movi read rootfs 0 41000000 400000;bootm 40008000 41000000\" DengJin # set bootargs \"root=/dev/mmcblk0p4 console=ttySAC0,115200 lcd=S70 ctp=2\" DengJin # save err0: mount: mounting /dev/mmcblk0p4 on /r failed: No such device or address Waiting for SD Card... mount: mounting /dev/mmcblk0p4 on /r failed: No such device or address Waiting for SD Card... mount: mounting /dev/mmcblk0p4 on /r failed: No such device or address Waiting for SD Card... mount: mounting /dev/mmcblk0p4 on /r failed: No such device o 将uboot烧写到EMMC a. 打开emmc设备 从SD卡启动uboot DengJin # emmc open 1 b. 下载bl1 minicom: DengJin # dnw 40008000 PC: [root@deng tiny4412]# dnw E4412_N.bl1.bin minicom: DengJin # mmc write 1 40008000 0 0x10 [Notice] mmc:命令 write: 写 1: 第一个设备 40008000: 从该地址读内容 0: 从第0块开始写 0x10: 写16块 每一块512个字节 c. 下载bl2 minicom: DengJin # dnw 40008000 PC: [root@deng tiny4412]# dnw bl2.binminicom: DengJin # mmc write 1 40008000 0x10 0x1c d. 下载uboot minicom: DengJin # dnw 40008000 PC: [root@deng tiny4412]# dnw ../../u-boot.bin minicom: DengJin # mmc write 1 40008000 0x30 0x290 e. 关掉emmc设备 DengJin # emmc close 1 f. 测试从emmc启动 看看能否正常启动uboot 下载内核 a. 分区 DengJin # fdisk -c 0 500 800 500 格式化 DengJin # fatformat mmc 0:1 DengJin # ext3format mmc 0:2 DengJin # ext3format mmc 0:3 DengJin # ext3format mmc 0:4 b. 下载内核 minicom: DengJin # dnw 40008000 PC: [root@deng linux-3.5]# dnw arch/arm/boot/zImage minicom: DengJin # movi write kernel 0 40008000 DengJin # set bootargs \"movi read kernel 0 40008000;bootm 40008000\" DengJin # save EMMC 最小网络文件系统 DengJin # set bootargs \"root=/dev/nfs nfsroot=192.168.8.88:/rootfs ip=192.168.8.77 console=ttySAC0,115200 lcd=S70 ctp=2\" DengJin # save EMMC Qt网络文件系统 a. 分区 DengJin # fdisk -c 0 500 800 500 DengJin # fatformat mmc 0:1 b. 下载ramdisk-u.img minicom: DengJin # fastboot PC: [root@deng Qt]# fastboot flash ramdisk ramdisk-u.img c. 设置启动参数 DengJin # set bootcmd \"movi read kernel 0 40008000;movi read rootfs 0 41000000 400000;bootm 40008000 41000000\" DengJin # set bootargs \"root=/dev/nfs nfsroot=192.168.8.88:/qtrootfs ip=192.168.8.77 console=ttySAC0,115200 lcd =S70 ctp=2\" DengJin # save 将最小文件系统烧录到emmc中 a. 从网络文件系统启动 挂载 [root@DengJin /]# mount /dev/mmcblk0p2 /mnt 解压到挂载的目录 [root@DengJin /]# tar -xjvf nfs.tar.bz2 -C /mnt 解挂 [root@DengJin /]# umount /mnt 重新启动进入uboot 设置启动参数 DengJin # set bootargs \"root=/dev/mmcblk0p2 console=ttySAC0,115200 lcd 将Qt文件系统烧录到emmc中 同SD操作 烧写Adnroid到emmc中 笔记同第二天 NFS 网络文件系统 Fedora例 任何一个存储设备,都有文件系统,如一个磁盘、一个U盘,网络文件系统也是如此,可以把网络文件系统类比成网络磁盘 像普通磁盘一样,要使用该磁盘,就要挂载它 下载服务器并配置 Fedora中,网络文件系统服务器名为:nfs-server 配置文件不变:/etc/exports 同样设置一个目录,并添加到exports文件中,如: /home/jim/NFS *(rw,subtree_check,no_root_squash,no_all_squash,sync) 详看NFS服务器支持的配置语法,这里的意思就是/home/jim/NFS这个目录就是“网络磁盘”,后面是一系列权限和配置 然后在给NFS赋予权限,777,理论上说不必777完全权限,但这样很省事 所以,第一步其实很简单,就是” 下载、配置exports、建立文件夹并赋予权限” 测试 本机也可以挂载,注意格式:sudo mount -t nfs 127.0.0.1:/home/jim/NFS /mnt;将127.0.0.1下的/hom/jim/NFS网络磁盘,挂载到/mnt下。 如果挂载成功,shell不会有任何提示,然后在NFS中写任何文件,在/mnt中都会同步出现,即挂载成功。 上机 要注意的是,既然是网络文件系统,就要联网线(网络磁盘所在机器和目标板) 换个IP就可以了,要注意的是目标板的IP要么处于网络中(比如连接了路由器),要么与PC在同一网段(比如PC直接连接目标板), mount -t nfs -o nolock,rw,nfsvers=3,vers=3 192.168.1.121:/hom/jim/NFS /mnt -o的含义如下: -o, --options comma-separated list of mount options 即后面nolock,rw,nfsvers=3,vers=3都是命令列表,注意不能有空格 详细内容可查看man文档 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/BSP/Kernel.html":{"url":"pages/os/BSP/Kernel.html","title":"Kernel","keywords":"","body":"1 Introduction 内核是管理计算机软硬件资源、驱动下层、承接上层的程序,分为微内核(winodws)和聚内核(linux或叫宏内核、单内核)。聚内核把所有模块编译在一起形成一个单独的内核镜像文件,各个模块之间通过函数调用,效率非常高,微内核只实现核心功能,其它功能单独编译,各模块之间通过进程间通信机制完成。 因聚内核的特点,其每增加删减一个功能就要重新编译整个内核,所以模仿微内核增加了模块插拔机制,聚内核把核心的/不常改动的功能编译在一起,而把易于变动的功能做成模块来动态插拔,这同时减少了内核镜像的体积,节约了内存空间。 附:Linux内核使用GNU C开发,内核的开发需遵循GPL协议;编译内核时可设置是否支持模块,也可禁止在系统启动后装载模块;Linux内核已从传统的奇偶稳定性发展为全部稳定,更多版本相关:https://baike.baidu.com/item/Linux%E5%86%85%E6%A0%B8 1 Kernel porting 2 Kernel programming inode 结构体 Unix系统一切皆文件,inode标识着这些文件,包含着所有文件的所有信息, 对文件系统操作的一些命令,本质是对inode的操作,如df ls stat find grep...命令 文件系统百分之一的空间分配给inode 文件类型:普通文件、目录、设备文件、链接文件、管道文件、套接字文件等 管理方式:目录树 inode是理解Linux文件系统和硬盘存储机制的基础 inode是在物理存储区(如硬盘、flash等)的、用于记录文件所有信息(除文件名)的存储区域,在系统中表现为一个结构体,文件与inode一一对应。 inode的数量再物理存储区格式化时就已经确定,每N个字节分配一个inode,每个inode占128byte (如果N是1K,物理存储空间是1G,那么会分配1024个inode,占用空间为128M) 因为一个文件对应一个inode,所以系统可能出现 仍有剩余空间 但已无法创建新的文件的情况 使用df -i命令查看每个每个分区分配的inode数量和使用情况 每个inode都有一个唯一ID,使用ls -i可以查看 inode的存储区域与文件数据的存储区域是分开的, 对文件进行移动、重命名等操作不会影响到inode的ID 复制文件相当于创建,会增加inode 删除文件与inode 删除文件其实并不是删除文件数据,而是标记此inode可复用了,如果有新的文件需要覆盖这个空间,那么数据就会被清除 硬链接与软链接 软链接 软件连接是一个文件,具有唯一inode ID,假设软链接文件是A,被链接文件是B,则A指向B 操作A会被指向B,删除A不影响B,删除B将不能访问A,除非A再指向其它(非软链接)文件 可以有多个软链接文件指向链接文件 硬链接 硬链接也是一个文件,但其inode ID与被链接文件相同,假设硬链接文件是A,被链接文件是B 操作A相当于操作B,反之亦然, A和B永远保持着相同的内容,并且删除任何一个都不影响另一个 仍然可以有多个硬链接文件。硬链接相当于文件副本,只是文件名不同。 ext2 ext3 ext4等文件系统都支持inode,但分区和排布情况不同 从视图上看,文件系统将物理存储区划分为:引导块、超级块、inode表、文件数据块。 引导块 - 引导代码 boot区,如果没有操作系统,该块可能为空 超级块 - 存储文件系统的信息 inode表 - 存储文件 的信息, 操作文件时内核会将该表加载到内存 要明确的概念是,文件系统与操作系统是独立的概念,文件系统可以脱离操作系统而存在,但操作系统必须依赖文件系统 。比如你可以将一个U盘或SD卡等格式化成某个文件系统,然后这个存储介质就以如上视图划分了,但显然没有任何操作系统 根文件系统 是指已经在上述视图中存在结构树的文件系统,比如Linux根文件系统,已经包含了/ /lib /bin等等,只是不同的版本包含的不一样. 显然,跟文件系统是已经布局好的文件系统,直接与操作系统运行环境相关。 内核、文件系统、根文件系统、操作系统之间的关系 内核是操作系统的基本核心,与文件系统、根文件系统无关,是独立的。 文件系统就是如上所述的,也是独立的,与内核、操作系统都没有关系,格式化为某种文件系统,其视图结构就已经确定。 根文件系统是在文件系统上的填充,文件系统只有结构框架,而根文件系统就是在其框架下的内容填充,填充了什么呢?这与操作系统相关,如果是Linux,一般填充/ /bin /etc /lib ...等等目录和文件,这些是操作系统必备的运行环境和工具,不同的根文件系统版本等区别也会导致内容的不同。 操作系统 在UNIX高级环境编程 中提到是 内核+shell&公共函数库 (+App) 的集合,实际就是 内核 + 根文件系统,这也是为什么在Linux移植的过程中,Uboot启动之后只需烧录Linux内核和根文件系统的原因。 shell和公共函数库都包含在了根文件系统当中。 /sys , 内核数据结构的可视化窗口,非磁盘文件系统,可以理解为内核在内存中的树结构视图映像,使得用户可以实时访问和调试内核 --- 培训内容 编译内核源码 内核官网: www.kernel.org a. 解压 [root@deng arm]# ls linux-3.5-20151029.tgz linux-3.5-20151029.tgz [root@deng arm]# tar -xzvf linux-3.5-20151029.tgz b. 配置内核 清除相关文件 [root@deng linux-3.5]# make distclean 使用已经移植好的配置 [root@deng linux-3.5]# cp tiny4412_linux_defconfig .config 关闭TrustZone [root@deng linux-3.5]# make menuconfig 注意: 使用方向键控制上下移动 │ ┌────────────────────────────────────────────────────────────────────┐ ││ │ [] Patch physical to virtual translations at runtime │ ││ │ General setup ---> │ ││ │ [] Enable loadable module support ---> │ ││ │ [*] Enable the block layer ---> │ ││ │ System Type ---> │ │ [ ] FIQ Mode Serial Debugger 出现如下界面 │ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ [] MMU-based Paged Memory Management Support │ ││ │ ARM system type (SAMSUNG EXYNOS) ---> │ ││ │ ** Boot options │ ││ │ [ ] S3C Initialisation watchdog │ ││ │ [ ] S3C Reboot on decompression error │ ││ │ [] Force UART FIFO on during boot process │ ││ │ (0) S3C UART to use for low-level messages │ ││ │ (0) Number of additional GPIO pins │ ││ │ (0) Space between gpio banks │ ││ │ -- ADC common driver support │ ││ │ [] PWM device support │ ││ │ * Power management │ ││ │ [ ] S3C2410 PM Suspend debug │ ││ │ [ ] S3C2410 PM Suspend Memory CRC │ ││ │ SAMSUNG EXYNOS SoCs Support ---> │ ││ │ Processor Type │ ││ │ Processor Features ** │ ││ │ [] Support TrustZone-enabled Trusted Execution Environment │ │ │ │ [] Support Thumb user binaries │ ││ │ [] Enable ThumbEE CPU extension 不要选中Support TrustZone │ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ [] MMU-based Paged Memory Management Support │ ││ │ ARM system type (SAMSUNG EXYNOS) ---> │ ││ │ ** Boot options │ ││ │ [ ] S3C Initialisation watchdog │ ││ │ [ ] S3C Reboot on decompression error │ ││ │ [] Force UART FIFO on during boot process │ ││ │ (0) S3C UART to use for low-level messages │ ││ │ (0) Number of additional GPIO pins │ ││ │ (0) Space between gpio banks │ ││ │ -- ADC common driver support │ ││ │ [] PWM device support │ ││ │ * Power management │ ││ │ [ ] S3C2410 PM Suspend debug │ ││ │ [ ] S3C2410 PM Suspend Memory CRC │ ││ │ SAMSUNG EXYNOS SoCs Support ---> │ ││ │ Processor Type │ ││ │ Processor Features ** │ ││ │ [ ] Support TrustZone-enabled Trusted Execution Environment │ │ │ │ [] Support Thumb user binaries │ ││ │ [*] Enable ThumbEE CPU extension 然后 exit ... exit 保存 c. 编译 [root@deng linux-3.5]# make -j4 LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready 出现以上信息 表示内核编译成功 安装dnw工具 a. 解压 [root@deng arm]# ls dnw-linux.tar.gzdnw-linux.tar.gz [root@deng arm]# tar -xzvf dnw-linux.tar.gz b. 编译 [root@deng arm]# cd dnw-linux [root@deng dnw-linux]# make c. 安装 [root@deng dnw-linux]# make install d. 测试 [root@deng dnw-linux]# dnw Usage: dwn [-a load_addr] Default load address: 0x57e00000 启动内核 minicom: DengJin # dnw 0x40008000 PC: [root@deng linux-3.5]# dnw arch/arm/boot/zImageload address: 0x57E00000 Writing data... 100% 0x0048FF8A bytes (4671 K) speed: 3.896146M/S [root@deng linux-3.5]# minicom: DengJin # bootm 0x40008000 如果能够启动内核 表示Ok 4. Android系统的烧写 a. 对SD卡进行分区 DengJin # fdisk -c 0 500 800 500 b. 格式化分区 DengJin # fatformat mmc 0:1 c. Android工具的安装 解压 [root@deng arm]# ls android_tools.tgz android_tools.tgz [root@deng arm]# tar -xvf android_tools.tgz 将相关命令拷贝到/usr/local/bin目录中 [root@deng arm]# cp usr/local/bin/* /usr/local/bin/ 测试 [root@deng arm]# fastboot usage: fastboot [ ] d. 编译内核 [root@deng linux-3.5]# cp tiny4412_android_defconfig .config 关掉TrustZone [root@deng linux-3.5]# make -j4 e. 使用fastboot烧写Android系统 相关文件 images\\Android\\zImage Android 内核 images\\Android\\ramdisk-u.img Android 根分区映象 images\\Android\\system.img Andorid 系统分区映象 image\\Android\\userdata.img Andorid Data 分区映象 minicom: DengJin # fastboot PC: 烧写自己编译好的内核 [root@deng linux-3.5]# fastboot flash kernel arch/arm/boot/zImage PC: (格式化userdata和cache) [root@deng Android4.2.2]# fastboot -w 烧写ramdisk [root@deng Android4.2.2]# fastboot flash ramdisk ramdisk-u.img 烧写system [root@deng Android4.2.2]# fastboot flash system system.img minicom: 设置启动参数 DengJin #set bootargs \"console=ttySAC0,115200n8 androidboot.console=ttySAC0 lcd=S70 ctp=2\" DengJin #saveenv 说明: bootargs 是内核启动的参数 console 是Linux输出的串口 androidboot.console Android的输出串口 lcd 是屏幕的型号 ctp 触摸点数 设置启动命令 DengJin #set bootcmd \"movi read kernel 0 40008000;movi read rootfs 0 41000000 400000;bootm 40008000 41000000\" DengJin #saveenv 说明: bootcmd 启动uboot之后 执行的命令 复位 重启 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/os/BSP/Bootloader.html":{"url":"pages/os/BSP/Bootloader.html","title":"Bootloader","keywords":"","body":"uboot简介 uboot是GNU开源、嵌入式领域的Bootloader,用于初始化硬件和加载内核(加载模式),并提供基础命令行环境以调试硬件和下载程序(开发模式)。 官网:http://www.denx.de;(下载)ftp://ftp.denx.de/pub/u-boot/。 uboot分析 1.版本分析 uboot分为官网版本、Soc厂商版本和第三方版本。 官网uboot每年约2~3个月发布一个版本,到2017年为止大约有70个版本,可分为三个阶段:初阶段版本-2010.6(不含)之前的版本,中阶段版本-2010.6~2014.10(不含)之间的版本,现阶段版本-2014.10以后的版本。各版本间主要有以下变化: 版本号变化:2008年8月以前的版本按版本号命名,其后按年份命名 目录树变化:第一次从u-boot-1.3.2版本增加了“api”目录,第二次从2010.6版 本合并了“cpu”与“lib_xxx”目录到“arch”目录,并分离出通用的“lib”目录。 配置的变化:从2014.10版本开始支持图形界面配置“$make menuconfig” Soc厂商uboot从官网uboot移植以支持其Soc和核心PCB,第三方一般是PCB底板厂商,其uboot从Soc厂商移植以支持其底板PCB。 2.目录分析 u-boot-2019.07版本uboot有1630个目录、21757个文件,其主要目录结构及含义如下: 附:参考目录树,u-boot-2019.07版本示例 ├── api Machine/arch independent API for external apps [用于外部应用程序的独立于机器/架构的API] ├── arch Architecture specific files ├── board Board dependent files ├── cmd U-Boot commands functions ├── common Miscellaneous architecture independent functions [混杂的独立于体系结构的功能] ├── configs Board default configuration files ├── disk Code for disk drive partition handling ├── doc ├── Documentation ├── drivers Commonly used device drivers ├── dts Contains Makefile for building internal U-Boot fdt [flatted device tree - 设备扁平树] ├── env├── examples ├── fs Filesystem code (cramfs, ext2, jffs2, etc.) ├── include Header Files ├── lib Library routines generic to all architectures [所有体系结构通用的库例程] ├── Licenses ├── net Networking code ├── post Power On Self Test ├── scripts Various build scripts and Makefiles ├── test └── tools Tools to build S-Record or U-Boot images, etc 3.编译原理 uboot编译依赖于Makefile技术。在u-boot-2014.10版本之前,编译主要依赖顶层目录的“Makefile”、“config.mk”及各子孙目录的“Makefile”文件。在u-boot-2014.10版本之后,增加了图形界面,其编译除依赖上述文件外还依赖“Kconfig”文件。 //TBD uboot编写 uboot移植 编译 移植的最终目的是生成“uboot.bin”二进制文件,其 //TBD 附录A:BIOS BIOS(Basic Input Output System)基本输入输出系统是固化在ROM芯片内、(PC)上电后执行的第一个程序,用于开机自检(POST)、硬件配置等最底层的硬件控制。 通过BIOS可以指定Bootloader启动介质,从而进一步启动操作系统。嵌入式系统中通常使用简单的拨码方式代替BIOS的该项功能。 附录B:BootLoader Bootloader(启动加载器)是一种引导程序,用于初始化硬件和加载操作系统内核,是计算机上电后执行的第一个或第二个程序(第一个是BIOS)。 Bootloader与硬件相关,因此都集成了很多平台,PC端有适用Linux的Lilo/Grub、适用Windows的NTLDR。嵌入式端有红帽的Redboot、ARM的blob/ARMboot、三星的vivi/Bios-it、GNU的uboot等等。 附录C:uboot(Hush-shell)命令 散装知识点 固件(firmware):存储于ROM中的(固定或永久性)程序。 培训内容 交叉编译、环境变量配置、固定的解压位置、 编译tiny4412的uboot 配置 : $make tiny4412_config 编译 :$make 生成工具: $ cd sd_fuse && make 烧录到SD; $dd if=/dev/zero of=/dev/sdb bs=1024 count=1 $./sd_fusing.sh /dev/sdb minicom 配置 : minicom -s 更改uboot提示 $ vim include/configs/tiny4412.h 将255行 255 #define CONFIG_SYS_PROMPT \"TINY4412 # \" 改为 255 #define CONFIG_SYS_PROMPT \"DengJin # \" 关闭MMU $vim include/configs/tiny4412.h + 331, 注释#define CONFIG_ENABLE_MMU 修改基地址 $ vim board/samsung/tiny4412/config.mk , CONFIG_SYS_TEXT_BASE = 0xc3e00000 改为0x43e00000 从新编译uboot并烧录SD uboot常用命令 md 显示内存的数据 mm 修改内存的数据 coninfo 打印串口设备信息 exit 退出脚本 reset 重新启动uboot version 打印uboot版本信息 printenv 显示环境变量 setenv 设置环境变量 saveenv 保存环境变量 1. md 查看从0x50000000 1 开始的4个字节 DengJin # md 0x50000000 1 查看从0x50000000 1 开始的8个字节 DengJin # md 0x50000000 2 查看从0x50000000开始的1个字节 DengJin # md.b 0x50000000 1 50000000: ff . 查看指定地址的内容 .w代表以两个字节为单位 1代表多少个单位 DengJin # md.w 0x50000000 1 50000000: ffff .. 查看指定地址的内容 .l代表以四个字节为单位 1代表多少个单位 DengJin # md.l 0x50000000 1 50000000: ffffffff .... 2. mm 查看帮助信息 DengJin # help mm mm - memory modify (auto-incrementing address) Usage: mm [.b, .w, .l] address 每次以字节为单位修改内存的数据 DengJin # mm.b 0x50000000 50000000: ff ? 11 50000001: ff ? 22 50000002: ff ? 33 50000003: ff ? 44 50000004: ff ? 55 50000005: ff ? 50000006: ff ? q DengJin # 每次以两个字节为单位修改内存的数据 DengJin # mm.w 0x50000000 50000000: 2211 ? 1111 50000002: 4433 ? 2222 50000004: ff55 ? 3333 50000006: ffff ? 4444 50000008: ffff ? q 每次以四个字节为单位修改内存的数据 DengJin # mm.l 0x50000000 50000000: 22221111 ? 111 50000004: 44443333 ? 222 50000008: ffffffff ? 333 5000000c: ffffffff ? q 将所有的可编程的LED全部灭 DengJin # md 0x110002e4 1 110002e4: 0000000c .... DengJin # mm 0x110002e4 110002e4: 0000000c ? f 110002e8: 00005555 ? q 将所有的可编程的LED全部亮 DengJin # mm 0x110002e4 110002e4: 0000000f ? 0 110002e8: 00005555 ? q DengJin # md 0x110002e4 1 110002e4: 00000000 .... DengJin # Buzzer CON 0x114000A0 DAT 0x114000A4 设置为输出 DengJin # mm 0x114000A0 114000a0: 00000000 ? 1 设置为高电平 Buzzer会叫 DengJin # mm 0x114000A4 114000a4: 0000000c ? 0xd 设置为高电平 Buzzer不叫 DengJin # mm 0x114000A4 114000a4: 0000000c ? 0xc 3. coninfo DengJin # coninfo List of available devices: serial 80000003 SIO 4. printenv 查看所有环境变量 DengJin # printenv 查看指定的环境变量的值 DengJin # printenv bootdelay 5. setenv 设置环境变量 DengJin # setenv bootdelay 10 取消设置的环境变量 DengJin # setenv AA 6. saveenv 保存环境变量 DengJin # saveenv Saving Environment to SMDK bootable device... done 7. boot 执行bootcmd的命令 DengJin # boot helloworld uplooking 1. fdisk 帮助信息 DengJin # help fdisk fdisk - fdisk for sd/mmc. Usage: fdisk -p - print partition information fdisk -c [ ] - create partition 查看分区信息 DengJin # fdisk -p 0 partion # size(MB) block start # block count partition_Id 1 5804 3535680 11887200 0x0C 2 327 137160 670560 0x83 3 811 807720 1661160 0x83 4 520 2468880 1066800 0x83 DengJin #fdisk -c 0 320 806 518 fdisk is completed partion # size(MB) block start # block count partition_Id 1 5804 3535680 11887200 0x0C 2 327 137160 670560 0x83 3 811 807720 1661160 0x83 4 520 2468880 1066800 0x83 2. fatformat 格式化的帮助信息 DengJin # help fatformat fatformat - fatformat - disk format by FAT32 Usage: fatformat - format by FAT32 on 'interface' 格式化第一个分区 DengJin #fatformat mmc 0:1 关于32-64bit交叉编译的注意事项 PC宿主机平台是64bit的,而交叉编译器是32bit的, 32bit的交叉编译器在工作时要依赖32bit的宿主机库,如arm-a9-gcc依赖32bit宿主机的libstdc++.so.6,所以要单独下载这个缺失的库 一般情况下直接在宿主机下不支持使用yum、dnf(可能ubuntu支持apt直接安装)安装,因为与现有的64bit库冲突,所以要单独下载文件, 手动安装到某一位置。 注:最开始产生这种问题的时候,还有疑惑:管他是宿主机32还是64,交叉编译工具链是编译目标板平台的,有什么关系呢? 这样想是没有错误的,但问题出现在,交叉编译链本身也是一个软件,它依赖所工作的平台,因为你装的交叉编译工具链本身就是在别的32bit平台下 编译出来的,所以依赖的库也不同。 所以,如果你有交叉编译工具链源码的话,那就在你的宿主机平台下再编译一次工具链。 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/programming/RegExp.html":{"url":"pages/programming/RegExp.html","title":"RegExp","keywords":"","body":"1 Introduction Regular expression (regexp or regex) is a sequence of characters that define a search pattern, comes from formal language theory. and supported by IEEE Posix with sets BRE(Basic Regular Expression) and ERE(Extended Regular Expression). 2 Posix metacharacters 2.1 Basic regular expression MetaCh_BRE Description ^S matches the string start with S (of any line) S$ matches the string end with S (of any line) [S] bracket expression. Matches a single character in the scope of S ([S1-S2], [S1-], [-S2], ...) [^S] complement of [S] . matches any single character, except '\\n' line-break S* matches S zero to gigantic times S{m, n} matches S at least m and not more than n times (exp) sub-expression \\n n $\\subseteq$ [1, 9], refer to which sub-expression 'S', 'S1', 'S2' refer string or single character 2.2 Extended regular expression MetaCh_ERE Description (exp) same as (exp) S{m, n} same as S{m, n} S? matches S zero or one time + matches S one to gigantic times S1|S2 optional S1 or S2 'S', 'S1', 'S2' refer string or single character Tips : Because of its expressive power and (relative) ease of reading, many other utilities and programming languages have adopted syntax similar to Perl's — for example, Java, JavaScript, Julia, Python, Ruby, Qt, Microsoft's .NET Framework, and XML Schema, PHP, awk, sed, etc. 3 Character classes The character class is a quick way to express the expressions set. POSIX Perl Vim ASCII Description [:alnum:] - - [A-Za-z0-9] Alphanumeric characters [:alpha:] - \\a [A-Za-z] Alphabetic characters [:blank:] - \\s [ \\t] Space and tab [:cntrl:] - - [\\x00-\\x1F\\x7F] Control characters [:digit:] \\d \\d [0-9] Digits [:lower:] - \\l [a-z] Lowercase letters [:upper:] - \\u [A-Z] Uppercase letters [:print:] - \\p [\\x20-\\x7E] Visible characters and the space character [:space:] \\s _s [ \\t\\r\\n\\v\\f] Whitespace characters [:xdigit:] - \\x [A-Fa-f0-9] Hexadecimal digits comparison of different standards about character class 3 Lazy and possessive matching 4 Unicode 5 Wildcard Vs RegExp Wildcards are placeholders while regular expressions are searching pattern, and only '.' in regexp is a wildcard. MetaCh Description * placeholder for any characters, zero - gigantic ? placeholder for any single character wildcards meta-ch list Tips : some implementations also contain meta-ch similar to regexp, such as [S], [!S] (which equal to [^S]). Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/programming/Python.html":{"url":"pages/programming/Python.html","title":"Python","keywords":"","body":"1 Introduction Python是解释型、面向对象、动态数据类型的高级编程脚本语言,由Guido van Rossum发明与1989年,开源且使用GPL协议。Official website. Tips : Paython目前有两个版本线,2.x和3.x,官方宣布2020年1月1日,停止2.x的更新(最后版本2.7) 1.1 Feature Easy, Tortable,Extensible, Terminal mode, Rich Libs, Glue lang, Database, GUI, AI, Big data, Game, Web... ... 1.2 VS C++ 标识符 标识符与C++相同,但下划线作为标识符在Ptyhon中有特别的用途 _A\\ __A _A_ __A__ python保留字符(python关键字) and exec not assert finally or break for pass class from print continue global raise def if return del import try elif in while else is with except lambda yield 代码块 python使用严格的缩进来解析代码块,缩进尺寸可配置(一般为单个制表符),但必须一致。 引号 还可以使用单引号和三引号来表示字符串,三引号可跨行 注释 使用#,可以放在空白起始行也可以放在语句后面,在空白行可以使用三个单引号和三个双引号开头和结尾表示多行注释 语句 python语句结束后的分号可选,但一行写多个语句时必须使用 命令行: $python > 命令行解析: $python xx.py 一般.py文件中没有在头部声明解析脚本及路径时使用这种方法解析 Key word Python Guido 1989 OpenSource OOP Object oriented programming Glue language (C/C++/JAVA/C#/HTML/CSS/PHP....) Script language dynamic language Less code Simple easy quick Terminal mode is supported Database and GUI is supported AI Big Data Search engine Reptile Automated management There should be one - and preferably only one - obvious way to do it Format fasten Constraint syntax format Compare with C++ key words: and exec not assert finally or break for pass class from print continue global raise def if return del import try elif in while else is with except lambda yield SAME WITH C/C++: assert break fro class continue if return try else while SAME: + - * / % ~ >> = != == >= grammer For linux/unix: 1. Explain mode ------------- test.py -------------------------- #!/usr/bin/env python3 (or #!/usr/bin/python3) print(\"hello python\") ------------------------------------------------ $ chmod +x test.py $ ./test.py $ hello python Note : multiple statements print(\"hello\"); print(\"world\"); $hello $world 2. Termial mode $ python //In >>> ... >>>exit() //Out More: $ python -d //Display debug info while explaining $ python -O //Same as GCC $ python -V //Version $ python +file //eg: python test.py .... 3. Python IDE Omit ----------------------------------- A LITTLE DIFF (about structure): if True : //Note the clone ... else : //NOte the clone ... Coding #!/usr/bin/evn python3 #coding=utf-8 //Note: this is default for python3 Identifier Same as C/C++ (construct with alpha number and _, and can't start with number, and Case sensitive) Indent Python use indent instead of '{}' to include code block indent value can be changed but must be same (same type : tab or space AND same number) Mutiple line: totle = a + \\ b + \\ c arr = ['a', 'b', \\ 'c'] OR arr = ['a', 'b', 'c'] //'\\' can be omit while [] or {} or () encap Comment #!/usr/bin/env python #This is comment print(\"hello\") # This is comment too ''' This is multiple line comment with THREE single quotation mark ''' ''' This is an other style ''' ''' This is ok, yes really''' \"\"\" This is multiple line comment with THREE double quotation mark AND OTHER MODE same as ''' \"\"\" VAR Python support 'weakness' data type, and all data type key word will be omit: #--------- error int a = 10 print a #--------- OK!!! a = 10 print a ===================== Python standard data type : Number/String/List/Tuple/Dictionary Number: int long (only in python 2.x) float complex String: str = \"abcdefg\" index ASC : str[POSIVE NUMBER] index DES : str[NIGTIVE NUMBER] print str[0] # out a print str[1:4] # out bcd , str[4] = e, so -> [ ) semi-closure print str[1:-2] # out bcde, str[-2] = f, so str[-1] = g print str[:] # out abcdefg == print str print str[:3] # out abc print str[1:] # out bcdefg print str[1:5:2] # out bd, 1 for str[1], 5 for str[5], 2 for step length (default is 1) + : str2 = str + \"123\" print str2 # out abcdefg123 * : str3 = str2 * 2 print str3 # out abcdefg123abcdefg123 List : same as \"array with constructure\" in C/C++: mylist = [1, 'a', \"hello\", 2.3] # List is an kind of 'mixed array' print mylist[0] # out 1 print mylist[-1] # out 2.3 print mylist[:] # out [1, 'a', \"hello\", 2.3] == print mylist print mylist[1:3] # out ['a', \"hello\"] -> [ ) semi-closure print mylist[1:] # out ['a', \"hello\", 2.3] print mylist[:3] # out [1, 'a', \"hello\"] mylist2= ['b', 'c', 10] print mylist + mylist2 # out [1, 'a', \"hello\", 2.3, 'b', 'c', 10] print mylist2 * 2 # out ['b', 'c', 10, 'b', 'c', 10] Tuple : Tuple is Read-Only list Tuple is same as 'const' mixed array, can only be read mytuple = (1, 'a', \"hello\", 2.3) VS mylist = [1, 'a', \"hello\", 2.3] mylist[2] = \"world\"; print mylist[2] # out world mytuple[2] = \"world\" # error, can not be assignment Dictionary : Dictionary construct with : \"key : value\" pair. and index with key instead of index-offset mydict = {1:1, 'a':2, \"hello\":\"world\", 2.3:\"haha\"} print mydict['a'] # out 2 print mydict[\"hello\"] # out world print mydict[2.3] # out haha Insert: mydict[\"newkey\"] = \"newvalue\" print mydict # out {1:1, 'a':2, \"newkey\":\"newvalue\", \"hello\":\"world\", 2.3:\"haha\"} print mydict.keys() # internal function, out [1, 'a', \"hello\", 2.3, \"newkey\"] print mydict.values() # internal function, out [1, 2, \"world\", \"haha\", \"newvalue\"] Note : dictionary is non-order data type Read from mydict.keys() and mydict.values() output result, we can see that dictionary is a kind of 'mixed list' del can be used to delete var (or object) eg: a = 10 del a print a # error : 'a' is not defined Data type trans float(x) # x can be integer or digital-string print float(2) #out 2.0 print float(\"123\") #out 123.0 print float('a') # error print float(\"abc\") # error print float(mydict) # error print float(mylist) # error print float(myTuple) # error str(x) # x can be any object print str(123) #out 123 print str(mydict) #out {1:1, 'a':2, \"hello\":\"world\", 2.3:\"haha\"} ... ruple(x) list(x) chr(x) hex(x) oct(x) ... Operator basically the same as C/C++ except : logical operator and vs && or vs || not vs ! member operator in ont in eg: Mylist = {1, 2, 3, 4 ,5} if (1 in Mylist) : print(\"yes\"); #out yes if (2.3 in mydict.keys()): print(\"yes\"); #out yes ID operator is is not a = 10; b = 10; if (a is b) print(\"yes\"); # out yes b = 20; if (a is b) print(\"yes\"); else print (\"no\"); # out no ------------ is VS == A is B : Juge if A and B use the same storage space A == B : Juge if A's value == B's value NOTE: python do no support ++ -- Operator priority Condition statement if xxx : ... elif xxx: ... elif xxx: ... else: ... Note : switch is not supported AND '()' brackets can be used or not xxx --> (a == b) / a == b / a > 10 and a 10 and a 1 and a Loop statement while for break continue pass ---------------- a = 10 while a pass if a == b pass # do nothing elif a > b ... else ... Import Library (or module) eg: import math #import math library/module import cmath #import cmath library/module >>> import math >>> dir(math) # check math package content >>> math.sqrt(9) # out 3.0 Internal math function abs() exp() log() ... Internal random function import random choice : random.choice(range(10)) # chose 0 ~ 9 randrange random() : [0, 1) seed() ... traingle function asin() acos() atan() ... Math Const pi e Escape character Same as C/C++ Use 'r/R' to generator origin character eg: print \"this is a test \\n' # out this is a test print r\"this is a test\\n\" # out this is a test\\n Format string print \"My name is %s and I am %d years old\" % (\"zj\", 30) # out My name is zj and I am 30 years old another feature same as C strings function str1 = \"124\" print str1.isalnum() # out Ture . *** NOTE : PYTHON TRIED VARIABLE AS OBJECT/CLASS, AND EACH OBJECT/CLASS HAS IT'S OWEN FUNCTION SET!!! *** date and time Always start from 1970.1.1 import time time_stamp = time.time() time.sleep() time.ctime() time.gtime() time.clock() ... print time_stamp Format time: time.asctime(xxx) Auto define format time: time.strftime(xxx) eg: time.strftime(\"%Y-%m-%d %H-%M-%S\") time.strftime(\"%Y-%m-%d %H-%M-%S\", time.localtime()) --- %y - year (xx) %Y - year (xxxx) %m - month %d - day %H - hour (24) %I - hour (12) %M - minute %S - second %a - local simple week %A - local complete week %b - local simple month %B - local complete month .... calendar import calendar print calender.month(2016, 1) ---# out February 2020 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Other data & time module datetime pytz deteutil Function 1. Internal function such as print() 2. self-define function def function_name(parameters) : expression return [expression] Note : Python function do not set return type, this is really diff from C/C++ eg : def my_print( strings ) : print strings return my_print(\"hello\") # out hello def my_add(v1, v2) : \"THE FIRST LINE can be used to comment this function\" return v1+v2 print my_add(1, 2) # out 3 ---------------------------------- PARAMETERS 1. Trans mode number and string and tuple type : trans by value list and dictionary type : trans by address 2. Type 1) normal parameter 2) key-word parameter def fun(v1, v2, v3) ... fun(v2 = 10, v1 = 20, v3 = 5) # param order can be changed by key-word type 3) Default parameter def fun(v1, v2, v3=20) ... fun(10, 30) # Same as C++ 4) Indefinite length parameter def fun([normal-args,] *var) eg: def printAny(*param) : for var in param print var return printAny(1, 2, 3) # out 1 2 3 def printAny2(v1, *param) : print v1 for var in param : print var return ---------------------------------- Anonymous function - lambda sum = lambda v1, v2 : v1 + v2 print sum(1, 2) # out 3 Module Python module is a file that terminated by \".py\" eg: test.py import test test.fun() ---- from x import y: import part of module eg: test.py (test contain fun1() fun2()) from test import fun2 test.fun2() --- search path 1. currunt dir 2. evn : PYTHONPATH 3. default dir namespace Package Python package is just a file folder that contain sub-folder and modules eg: $ tree mypackage mypackage/ ├── init.py ├── m.py └── subpackage ├── init.py └── mm.py from mypackge.m import pprint2 #import part from package import mypackge.m #import m module from package import mypackge.subpackage.mm #import mm module from sub-package **** NOTE : __init__.py MUST BE EXIST AT ALL LEVEL, and the content can be empty __init__.py to identify the folder is a PACKAGE I/O 1. standard I/O screen : print keyboard: raw_input / input (input can recive expression) 2. file open(filename [, mode]) #same as C/C++ open(filename [, mode] [, buffering] [, encoding=None] [, errors=None] [, newline=None] xxxxx) check file info : myfile = open(\"test.txt\", \"r\") print myfile.name # file name print myfile.closed # check if the file has been closed print myfile.mode # access mode ... close() #file will be closed after fresh the file buffer write() read() seek(offset [, from]) # Byte base import os os.rename(curname, newname) os.remove(file) # delte file os.mkdir() os.chdir() .... Exception 1. Standard exception ... 2. try/except/finally try: # some expression except exp1 [, exp2] [, exp3]...: # same as C++ catch # expression catched else: # if exception do not appair finally: # ignore anything, always excute # the code will be excute whatever exception accure or not 3. raise #same as C++ throw OOP class class name : \"comment string\" content # construct with function and data (same as c++) __init__() -> constructure function __del__() -> destructure function _xxx -> protected member __xxx -> private member __xxx__ -> system internal Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/programming/C++.html":{"url":"pages/programming/C++.html","title":"C++","keywords":"","body":"1 Concept C++起源于贝尔实验室,从C派生、与C兼容、编译时绑定。C++融合了POP、OOP和泛型编程(模板)等编程方式,使用 类 和 对象 来描述数据,强调数据的表达方式,具有封装、继承、多态、异常处理等特性。 C++之父Bjarne Stroustrup的个人主页 2 抽象 抽象指从具体事物中被抽取出来的相对独立的各个方面、属性和关系等 -- 《辞海》。C++的抽象是通过类来表示一类实物的共有属性,是泛型编程的基本思想。 类的本质是操作受限的结构变体,对象是结构体变量,关键词class和struct在C++中等效。类的成员分为属性(变量/数据等)和方法(函数/行为/动作/功能等)。 Code : class/struct CLASS_NAME{...attribute list AND function list...}; 传统结构体的使用方式是类的使用方式的子集,类还具有方法成员和权限控制能力,且方法成员可以在类中直接实现。 Tips : 类的方法成员可以在类中直接实现,这对于C++程序的后期扩展非常重要,例如源码被制作成库文件,那么可以在其头文件中追加功能补丁。 2.1 静态成员与this指针 this指针 : 对象的地址向成员函数的传递是编译器自动完成的,方式是作为成员函数的第一个隐含形参,这个形参就是this指针。this指针属于类,指向被实例化的对象。通过*this/this可返回对象/对象地址,常用于避免成员变量与形参同名产生的歧义。 静态成员 : 类中的静态成员是受限于类作用域的static类型的变量和函数,不属于任何对象,不占用对象空间,也没有this指针,静态函数只能访问静态变量。访问静态成员的方法是直接使用类作用域“::”,类中一切不需要实例化就可以确定行为方式的函数都应该设计为静态的。类的静态变量必须在类外,main函数之前初始化,且需指定类并省略static关键字。 3 封装 C++类的成员具有访问限制:Private(私有,默认)、Protected(保护)、Public(公有)。 封装方式 访问限制 Public 无 Protected 类、友元函数、派生类 Private 类、友元函数 一般将数据成员设计为私有、方法成员设计为公有,仅对派生类开放的成员设计为保护类型。类的对象通过公有或保护方法来操作私有数据。C++将结构体扩展成类,具备类的所有特性,但默认访问限制为公有。 Code : class/struct CLASS_NAME{... pulic:... protected:... private:...}; C++类的特殊方法成员可以在对象创建、复制和销毁时被系统自动调用:构造函数、拷贝构造函数和析构函数。 3.1 构造函数与创建对象 构造函数是类中与类同名的公有方法成员,可缺省、可重载、无返回值,在对象被创建(于堆或栈)时由系统自动调用,常用于初始化属性成员和自定义初始动作。 Code :class/struct CLASS_NAME{... pulic: CLASS_NAME(Param list){...};}; 3.1.1 创建对象的方法: 栈中:class/struct CLASS_NAME OBJ ; 堆中:class/struct CLASS_NAME *Pobj = new OBJ ; 默认构造函数形参为空,创建对象时未传参则调用默认构造函数。如果构造函数被重载且默认构造函数又缺省,则无法使用缺省构造函数创建对象。 Tips : 将构造函数设定为私有权限,则该类将无法创建对象,这等同于纯虚函数的效果。 3.2 拷贝构造与复制对象 拷贝构造函数是构造函数的特例,本质是构造函数的重载,含一个类引用形参,在对象被复制时由系统自动调用,用于处理因对象复制可能导致的内存泄露、重叠等问题。原则上凡是包含堆和指针成员的类都应该提供拷贝构造函数并合理重载“=”运算符。对象复制发生于三种情形:向函数形参传递对象值、从函数返回对象值、对象赋值。 Code :class/struct CLASS_NAME{... pulic: CLASS_NAME(CLASS_NAME &){...};}; 3.2.1 浅拷贝与深拷贝 浅拷贝又称位拷贝,同普通变量赋值,即将A的内存空间数据按位复制到B。缺省的拷贝构造函数和未重载的“=”运算符都为浅拷贝。 当类中存在指针时,如使用浅拷贝,对象A和B的指针成员将指向同一内存空间而导致内存重叠,如果指针指向堆,则在对象销毁时该空间会被释放两次,深拷贝需要设计拷贝构造函数,使对象复制发生时完全拷贝内存镜像。 3.3 析构函数与销毁对象 析构函数是类中与类同名的、带有“~”前缀的公有方法成员,可缺省、不可重载、无参、无返回值,可手动调用或在对象被销毁(于堆或栈)时由系统自动调用,常用于释放空间和自定义结束动作。 Code :class/struct CLASS_NAME{... pulic: ~CLASS_NAME(){...};}; 3.3.1 销毁对象的方法: 栈中:栈中的对象在其所在作用域结束时自动销毁 堆中:delete Pobj; 3.4 友元函数和友元类 友元是类外的、可以访问该类中所有成员的函数或类,称友元函数和友元类,使用friend关键词声明。友元关系是单向的,不具有传递性且不能被继承。友元破坏了类的封装性又适当的打破了封装的局限性,使编程更加灵活。 Code :class/struct CLASS_NAME{... friend R_TYPE FUN(...); ...friend class CLASS_NAME;}; 4 继承 继承是C++代码重用和功能扩展的重要机制子类(派生类)通过继承父类(超类、基类)来重用、实现和扩展父类的功能,并可多重继承,是自下而上的过程。 Code :class/struct CLASS_NAME : WAY CLASS_B, WAY CLASS_C, ...{...}; WAY表示Public、Protected和Private继承方式,用于限制子类对父类成员的访问权限。 继承方式 父类成员 public protected private public public protected none protected protected protected none private private private none 父类私有成员总是对子类不可见的,父类公有成员限制随继承方式改变,父类保护成员仅在私有继承时改变访问限制。在内存分配上,子类深拷贝了父类Public和Protected成员。构造、拷贝构造和析构函数不能被继承,子类构造对象时先调用父类(默认)构造函数,并可指定形参以调用父类重载的构造函数。子类拷贝对象时先调用父类拷贝构造函数、析构对象时反之。 Code : CLASS_NAME::CLASS_NAME() : FATHER( [PARAM] ) { ... ... } 4.1 多继承与二义性 一个子类可继承于多个父类(一般多继承),当不同的父类中拥有与子类同名(和同参)成员,且子类可访问时,则可能产生二义性。消除一般多继承二义性的方法是子类重载或重写父类二义性成员或调用父类二义性成员时指明作用域“::”。 4.2 虚继承与二义性 在一般多继承情形下,如果不同的父类继承于同一个超类(菱形多继承)且子类可访问时,则可能产生二义性。消除菱形多继承二义性也可通过消除一般多继承二义性的方法,或使用虚继承,即超类在派生父类时使用关键字“virtual”。 Code :class/struct CLASS_PARENT : virtual WAY CLASS_Base, ...{...}; 5 多态 C++继承衍生了多态特性,继承于同一父类的不同子类通过重写父类的(纯)虚函数来实现不同功能的方式称为多态,是自上而下的过程。 5.1 静态联编 函数重载(和操作符重载)是实现静态联编的主要方式。在编译阶段,编译器会根据重载函数参数类型和个数的不同而生成不同的符号列表,从而形成可根据不同参数类型和个数来调用的同名函数。 5.1.1 函数重载 在同一个作用域中声明的具有相同函数名而不同参数个数和(或)类型的函数,称为函数重载(与返回值无关)。 默认形参与二义性C++允许在定义函数时指定形参默认值,顺序必须从右向左,调用函数时可以从右向左省略形参以使用默认形参。如果带有默认形参的函数又被重载,则调用时必须指定足够个数的参数以避免二义性。 Code :R_TYPE FUN_NAME (Param1, Param2=N, Param3=M, ...){...}; 5.1.2 函数重写(覆盖) 派生类会覆盖基类中与基类同名、同参函数,如需调用基类函数,则需使用作用域“::”。 5.1.3 运算符重载 重载的运算符表现为由关键字operator指定的、以运算符为函数名的函数,重载的运算符必须是有效的C++运算符(附录D),参数个数必须与运算符操作数相等,且至少一个属于复合类型(class/struct/enum)。 运算符将表达式中的第一个操作数作为第一个形参,第二个操作数作为第二个形参。操作符重载可以定义在类的内外,当在类中定义时,第一个形参省略,默认为所在类的类类型。运算符“=”必须在类中定义。 Code :R_TYPE operator 操作符([class/struct/enum] NAME [OPT *指针, &引用, ...], ...){...}; C++只检测形参的合法性,不检测函数内部实现机制,也不要求返回值,但重载的功能应该符合原运算符的语法规则、属性和优先级。合理的返回值设计也方便参与连续的链式运算。 [info] Special operator operator double(){} 类似的,为特殊操作符重载,当强制转换一个对象时时将返回重载类型,如 : (double)(a),将调用该重载操作符,返回一个浮点数。 5.2 动态联编 动态联编是C++多态的主要实现方式,它通过虚函数与虚类、纯虚函数与抽象类在运行而非编译时确定接口的实现。 5.2.1 虚函数与虚基类 将基类函数声明为虚函数,通过派生类的重写即可实现运行时多态,包含虚函数的类称为虚基类。声明成虚函数的意义在于对内存模型的建立(虚表),从而可用基类的指针通过赋值不同的派生类对象地址来实现不同的功能。 Code :class/struct CLASS_NAME{public/protected: virtual R_TYPE FUN_NAME(...){...}; ...}; 构造、拷贝构造与析构函数是否声明为虚函数与虚函数表技术有关,参看附录E。 5.2.2 纯虚函数与抽象类 纯虚函数只有声明没有实现,也不能实例化对象,所有的实现都交给派生类,包含纯虚函数的类称为抽象类。抽象类的派生类必须实现抽象类中所有的纯虚函数,抽象类表现为一个行为接口。 Code :class/struct CLASS_NAME{public/protected: virtual R_TYPE FUN_NAME(...)=0; ...}; Tips : 派生类未重写抽象类的纯虚函数时,该派生类仍是一个抽象类。 6 模板 模板是C++泛型编程的基础,可以独立于任何特定变量类型的方式编写代码,包含函数模板和类模板。在设计函数和类时可以在任何关于变量类型的地方设置模板(T),在使用时可以指定任意类型变量以实现泛型编程。 Code : template class CLASS_NAME{}; / ... FUN_NAME(...){}备注 : 模板函数的形参必须包含所定义的所有模板,不要求返回值。模板在类中可自由定义 6.1 STL (Standard template library) 标准模板库由HP实验室研发,现已成为C++标准。STL包含大量数据结构和算法的类模板,并将数据结构和算法分离。 STL包含三种类型代码:容器(Containers)、算法(Algorithms)和迭代器(iterators);容器是抽象数据类型的模板实现(模板类),即数据结构,如动态数组、列表、队栈、图等。算法用于操作容器(模板函数),如增、删、改、查等。迭代器(又称游标)用于遍历容器,如递增、递减、定位等, 迭代器的本质是 (变量) 指针。 容器类中的方法是针对特定的数据结构而设计的,更多使用的是非成员方法(即算法)来操作容器。特别的,容器类中存在与算法同名的方法,原因是相比通用算法其执行更有效率。 模板使得算法独立于特定的数据类型,迭代器使得算法独立于使用的容器类型。 7 异常 C++异常是处理程序错误的重要机制,不同于传统C的返回值判定、信号、断言、错误编号、跳转等处理方式,异常处理可获得更详细和精准的信息并将问题检测和问题处理分离,通过关键字try检查异常、throw抛出异常、catch捕获异常,如果抛出异常后未进行捕获,则程序将被终止。 Code : CODEBLOCK{throw [expression]}; try{CODEBLOCK}catch(exception param list){...}...catch(...){...} try-catch语句可以(在try代码块中)嵌套,catch列表及外层catch列表中至少要有一个形参匹配所抛出的异常量类型,否则发生异常时程序将被终止。可在列表最后设置catch(...)以匹配任何异常类型。 将嵌套内层捕获到的异常再抛出(到嵌套外层)的方法是再次利用throw语句,但表达式为空。 一般当嵌套内层无法处理某些异常时会利用该方法。 Tips : throw语句将终止执行后续指令、expression可以是任何表达式语句. 在函数声明和定义时可使用关键词noexcept修饰以说明该函数不会抛出异常,如果该函数仍然抛出异常,则程序将被终止。这种机制可有效阻止异常的扩散。 Code : R_TYPE FUN_NAME(...) noexcept {...} 7.1 标准异常 C++内置多个标准异常类,所有异常类都包含what()方法用以描述异常信息。其中exception是所有标准异常类的父类(详见附录F),可以通过继承标准异常来扩展异常。 Appendix-A:C++命名空间与作用域 Code : namespace SPC_NAME{...}; using namespace SPC_NAME; using SPC_NAMEi; C语言定义了三类作用域:文件、函数和复合语句,C++增加了类作用域“::”和命名空间作用域,命名空间将同名全局作用域的函数和变量分离,使程序扩展更加便捷。命名空间可以嵌套,使用命名空间通过using关键字或直接限定前缀SPACE_NAME::。 C++标准命名空间为“std”,标准库无“.h”或“.hpp”后缀的头文件均包含于标准命名空间中。 Appendix-B:C++引用 Code : var_type "e = var;var_type &fun(...var_type &); 引用是变量的别名,类似Unix系统下的软链接,不占存储空间,向函数传参和作为返回值时相比传值、传址(指针)具有较高的效率和安全性。引用的声明和定义必须同时完成,一旦定义就不能重复绑定。 Appendix-C:C++兼容C Code : #ifdef __cplusplus extern “C” { #endif ... C function declare list ... #ifdef __cplusplus } #endif 在C++出现之前已有大量的C源码,为向下兼容,C++允许与C代码混合编程 (C++调用C),方法是使用关键字extern “C”限制于C函数声明列表。 Appendix-D:不可重载运算符 运算符 描述 . 成员访问运算符 * -> 成员指针访问运算符 :: 域运算符 sizeof - ?: 三目运算符 # 预处理符号 Appendix-E:虚函数表与指针 编译器会为虚基类(和抽象类,下同)中的虚函数建立虚函数表(V-Table),虚函数表是一个数组,数组元素是按虚函数声明顺序排列的、指向各虚函数的指针(_vptr)。 虚基类及其派生类都使用一个指针空间(前4Byte或8Byte)来存放虚函数表指针,虚基类每实例化一个对象,就为该对象添加一个虚函数表指针,对于多重继承的类就添加多个虚函数表指针。一个类的所有对象都共享同一个虚函数表。 派生类继承虚基类的同时继承其虚函数表,派生类的虚函数指针列表存放于虚基类的虚函数指针列表之后,当派生类重写某个虚函数时,就将虚函数表中虚基类的虚函数地址覆盖掉。 E.1 虚析构函数与内存泄漏 当虚基类的指针指向派生类的对象实现多态时,销毁基类指针时系统只能调用基类析构函数而不会调用派生类的析构函数,从而可能产生内存泄漏。通过将基类析构函数声明为虚函数,在销毁基类指针时还会调用派生类的析构函数。 E.2 虚基类成本分析 TBD Appendix-H:C++标准异常 异常 父类 描述 std::exception none 所有标准 C++ 异常的父类 std::bad_alloc std::exception 通过 new 抛出 std::bad_cast std::exception 通过 dynamic_cast 抛出 std::bad_exception std::exception 处理 C++ 程序中无法预期的异常时非常有用 std::bad_typeid std::exception 通过 typeid 抛出 std::logic_error std::exception 理论上可以通过读取代码来检测到的异常 std::domain_error std::logic_error 当使用了一个无效的数学域时,会抛出该异常 std::invalid_argument std::logic_error 当使用了无效的参数时,会抛出该异常 std::length_error std::logic_error 当创建了太长的 std::string 时,会抛出该异常 std::out_of_range std::logic_error 通过std::vector 、 std::bitset<>::operator等抛出 std::runtime_error std::exception 理论上不可以通过读取代码来检测到的异常 std::overflow_error std::runtime_error 当发生数学上溢时,会抛出该异常。 std::range_error std::runtime_error 当尝试存储超出范围的值时,会抛出该异常。 std::underflow_error std::runtime_error 当发生数学下溢时,会抛出该异常 Appendix-I:C++标准 ANSI 与ISO 于1998年通过C++98标准, 03年更新标准为C++03,该标准只修正了C++98标准的错误,因此用C++98表示 C++98/C++03。2011年通过了C++11标准,该标准较C++98增加了众多特性,同时还提供了C++标准类库。Offical website. Appendix-J:C++ new与delete C++使用new和delete开辟和销毁堆空间,与C中的malloc和free的使用方式类似,本质上是对malloc和free的封装。 虚函数/纯虚函数 在软件设计的重要性 除了多态之外,虚函数/纯虚函数的存在,可以使得程序框架清晰明了, 以库Xerces-C++为例,该库的基类和大部分基类的派生类都是纯虚函数,并且很多派生类没有再向后派生实现了,而是将这一接口留给用户实现 ,这看起来没有什么用,但是却给用户一个重要的信息:“XML就这么点东西,实现了我的接口,就实现了XML的操作” ,如果没有虚函数/纯虚函数搭建的框架,就要自己阅读学习XML,并且不一定很专业的开发出正确的API 类A嵌套类B,但类B只有带参构造,如何解决? class B{ public: B(int x){}; }; class A{ public: A(){}; class B b; //错误,因为b带形参,当b不带形参时正确 class B b(1); //错误,C++不支持这样的初始化 }; class A{ public: A():b(1){}; //正确,下面的语句只作为声明使用。 //这种方式类似继承于父类之后,指定调用父类的构造函数一样,其实本质是一样的,含义是调用我的构造函数时,先要调用另一个构造函数,如果有形参,就要特别指定。 class B b; }; 奇怪现象之:ASCII非'\\0'字符,被认为是'\\0'处理 描述:欲构造一个产生唯一字符串的函数,生产的字符串包含到string,cout string可完整输出,但c_str()或data()却有时输出不完整, 检查发现,会把非'\\0'字符当成'\\0'字符截断 如 唯一字符串为: sWUhln0Qx 检查str[2] = '\\0',竟然为真,实际c_str()也只是输出到sW就没有了 于是将该字符串直接以string ss = \"sWUhln0Q\"的形式给出,但无论怎么输出都没有截断 (类似的还有很多字符都被当成 ‘\\0’处理,如9,b,_,y,...等等) 还有,string本身输出总是完整的,并且size和length值都是正常的,一旦转换为c_str()或者data()就有可能乱套了 这是什么问题呢???? --再次描述: string本身输出总是完整的,并且size和length值都是正常的,一旦转换为c_str()或者data()就有可能错误(出错原因就是来自'\\0'的错误判定) 将出错的字符串以string ss=\"出错字符串\"的形式赋值,输出又没有错误了。 string construct_uniq(uint8_t _size) { static uint8_t seed_count = 0; string uniq_string =\"\\0\"; char asciibet[] = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-\"; auto time_ms = chrono::duration_cast(chrono::system_clock::now().time_since_epoch()); default_random_engine e(time_ms.count() + (seed_count++)); for (int i = 0 ; i = '0') && (uniq_string[0] } 构建唯一字符串的为上述代码, 解决:问题出现在 1. sizeof(asciibet) 是包含结尾的'\\0'的,随机生成的时候不知哪次就将随机到的'\\0'放到里面了 2. string cout的时候,会把'\\0'隐形掉,自己查看字符串数量sWUhln0Qx是9个,所以掺杂一个\\0在中间,而string将其隐形掉了 包含string等结构体的变量写入到文件中的问题! 如果一个结构体要写入文件,并且这个结构体包含string这样的类,那么读取时将会出现段错误! 因为string实际保存的字符串是指向堆的,保存结构体到文件时虽然给出了结构体指针,但是string中的数据并未保存进去。 所以,结构体中的string要替换为字符数组。 C++ 新标准关键 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/programming/C.html":{"url":"pages/programming/C.html","title":"C","keywords":"","body":"生成.i文件 可查看预处理状态 //预处理后的.i文件非常大,因程序引用了很多头文件都要导入 gcc -S 1.i -o 1.s //编译工作-由编译器完成-:将c语言代码生成与平台相关的汇编代码,不同平台 //的编译器产生不同的汇编代码,众多平台为c设计了生成其平台的c编译器,这增强了c语言的可移植性 //编译后的.s文件很小 gcc -c 1.s -o 1.o //汇编工作:-由汇编器完成-:将汇编代码生成二进制目标代码,汇编后的文件又变大 gcc 1.o -o 1.out //链接工作:-由链接器完成:将目标代码与库进行链接生存可执行文件,链接后的文件最大 2.C标准 20世纪70年代末,随着微型计算机的发展,C语言开始移植到非UNIX环境中,并逐步成为独立的程序设计语言。在1978年,Kernighan和Dennis Richie的C Programing Language》第一版出版,在这本书中,C语言通常被表述成“K&R C”; 1988年ANSI对C语言进行了标准化,产生了“ANSI C”,在ANSI标准化的过程中,一些新的特征被加了进去,包括C函数库。之后,ANSI C标准被ISO采纳成为ISO 9899,ISO C的第一个版本文件在1990年出版。C标准在90年代末才经历了改进,这就是ISO9899:1999(1999年出版)。这个版本就是通常提及的C99,它被ANSI于2000年采用。 更多有关国际标准组织的知识请参见:《TBD》 C标准: K&R C ANSI C ISO C (ANSI/ISO C) C语言没有官方标准,Kernighan和Dennis Richie的C Programing Languag称为大家接收的标准,称为K&R C 或经典C,该附录定义了C语言却没有定义C库,因为缺乏任何官方标准,所以提供UNIX实现的库称为了一个事实标准。 c标准与POSIX K&R C (旧式C 非官方标准) C89 (ANSI C) C90 (ISO C; 1990年发布) C99 (ISO C; 1999年发布) C11 (ISO C; 2011年发布) posix标准 定义操作系统API的标准,含C库标准、系统调用标准和其它接口标准 ISO C 规定了标准C的方方面面 POSIX 在标准C基础上增加了一系列API,(POSIX包含标准C库)。 SUS(single UNIX Specification):SUS是POSIX的扩展,POSIX是SUS的基本部分 扩展标准C的还有其它标准:BSD、System V,因为它们是早期比较成功的Unix操作系统,所以很多特色函数都被广泛使用 3.心得 有符号数与无符号数不可比较 循环变量要用有符号数 特别对于-的变量 巧用预处理,特别是固定的数值运算,使用宏可以在预处理阶段由预处理器自动计算完成 数组溢出与内存栈: 1. char str[10]; char str2[10]; 如果str溢出,将影响str2的值,特别是在裸机环境下 (小端模式下,str2溢出,将影响str的值) 2. char str[2]; char str2[2]; str[-1] = 'a'; str[-2] = 'b'; putchar(str2[0]); //b putchar(str2[1]); //a 结构体报错问题: 结构体(和联合、枚举等)存储大小未知的问题: 1.没有原型 - 头文件没有包含 2.写错原型 常量指针与函数 下面这段代码,在cstr和str作用域内,其值是不会改变的: const char * cstr = \"123\"; char * str = \"123\"; 下面这段代码,在cstr2和str2作用域内,其值是否改变是不确定的: cosnt char * cstr2 = fun(); fun2(); char * str2 = fun(); fun2(); 原因是cstr2或str2 指向的是函数返回值,这个值是很可能在栈中的,所以这个值在某个函数运行后 会改变栈的数据,值即变化 4.C++ 兼容C的预处理 C与C++程序的兼容性 “很多”C标准库头文件和很多成熟的第三方C库头文件都带有 #ifdef __cplusplus extern \"C\" { #endif ... #ifdef __cplusplus } #endif 这是避免C++调用C库时可能出错,所以加上预编译开关。 并且在C++中,自带宏“#define __cplusplus” 所以这样做的目的就是为了C兼容C++程序 5.NULL 有NUL NUL - ASCll - ‘\\0’ 不存在C中 NULL - 值为0的指针 在stdio.h中 值同 可互换 6.内联汇编(GCC) 一.简介 内联汇编是C/C++编译器支持的特性,这使得汇编代码可以嵌入到C/C++代码中,嵌入汇编代码的意义是使代码更灵活、更高效、更符合硬件特性。不同的编译器支持不同的内联汇编格式,一般以“asm、_asm、__asm__”开始,其内容以“()”或“{}”包含,其结尾以“;”等结束。 二.语法 GNU-GCC编译器支持内联汇编,分为基本内联和扩展内联,其格式如下: ·基本内联 __asm__ __volatile__ (“cmd”); 如命令部分有多条语句需要分行写的,可加“\\n\\t”。 __asm__ __volatile__ ( “cmd1 \\n\\t” “cmd2 \\n\\t” ... ... ); ·扩展内联 __asm__ __volatile__ (“cmd” : “输出操作数” : “输入操作数” : “破坏描述部分”); 或 __asm__ __volatile__ ( “cmd” : “输出操作数” : /*可选*/ “输入操作数” : /*可选*/ “破坏描述部分” : /*可选*/ ); 在扩展内联的cmd中可使用“%0、%1、%2...”表示输出或输入操作数,使用“%%寄存器名”来调用寄存器。输入输出操作数中可使用“r、=r、w、=w ... ...”等约束符,最后的破坏描述部分是描述使用的寄存器,这一部分通常省略,交给编译器自动解决。 7.自定义printf scanf 1. FILE uartio = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); stdout = &uartio; 然后定义 uart_putchar() uart_getchar() 就可以在单片机程序中使用printf()和scanf() 2. 使用 myPrintf(const char *fmt, ...) { int i; char buff[BUFF_SIZE]; va_list ap; va_start(ap, fmt); vsprintf(buff, fmt, ap); while(buff[i] != 0) { uart_putchar(buff[i]); i++; } va_end(ap); ... } 注意: 有些单片机的libc库不支持%f的格式化输出,代替输出的是一个?号 8.以数组为形参的函数 #include void fun(int p[2]) { printf(\"%d\\n\", p[0]); printf(\"%d\\n\", p[1]); return; } int main(void) { int p[2] = {1,2}; fun(p); return 0; } //实际上int p[2]的形参形式,与 int *p 或 int p[]、 int p[0]、 int p[100]的形式是等价的, //给予数字的提示告诉了用户该函数需要指向元素的个数 9.解释型与编译型语言对比 两种语言的区别 本质上是 运行速度 与 移植性 的较量与权衡 注意,这里说的是移植性,而不是可移植性 现在的编译型语言可以做到可移植, 但移植速、移植时间、移植复杂性等需要考量 而解释型语言可以做到快速移植,或者可以基本不加改动的移植到其它系统中使用 (解释型语言移植的是解释器本身,而编译型语言除了编译时要用跨平台的编译器,还需要跨平台的运行库支持) 因为解释型语言依靠解释器,无论何时想要执行都必须有解释器存在,这使得解释型语言相对效率较低(解释解释,什么叫做惊喜) 而 编译型语言编译一次即可 现代是计算机 计算力过剩的年代,所以一般情况下感受不到解释器速度的延时 看起来与编译型编译出来的二进制代码执行速度无差别 10.restrict C99关键字 restrict 是C99标准添加的关键字 restrict 用于指针约束,以告知编译器所有访问该内存空间的都使用当前指针,即:内存空间的访问具有唯一性。 Note:该关键字是给编译器优化使用的,编译器根据该关键词优化出更具效率的汇编代码,而非用于程序间指针的约束, 也就是即便给指针使用该关键字,指针指向的空间仍然是可以通过其它指向该空间的指针改变的,所以restrict关键字 应该有两层含义: 1. 告知编译器,该内存空间只通过该指针访问 2. 编程人员不应该再使用其它指针指向该内存空间,也不能使两个restrict关键字约束的指针指向同一个内存空间,否则不能正确优化 11. C++更强调数据的处理方式, 数据 C更强调处理算法。 - 算法 变量声明的意义:1.向前声明,作用域识别。2.语法检查 - 保证用过的每一个变量都是用户自己声明的、存在的、不重复的。 定义对变量来说是开辟空间,对函数来说是实现。 常量: 编译器默认小数为double类型,整数为有符号int类型 1.0f 强制指定该小数为float类型 1.0L 强制指定该小数为long double类型 1U 强制指定该整数为unsigned类型 1L 强制指定该整数为long类型 1UL 强制指定该整数为unsigned long类型 char是否为有无符号数由编译器决定,如果有无符号很重要,则需要显示指定:signed char, unsigned char。 C++11 重新定义了auto关键字的含义,在C中auto是存储类型,在C++中auto是一个变量类型,C++中auto变量因赋值改变而改变: auto a = 10; //a为int类型 auto b = 10.0; //a为double类型 auto c = 10.0f;//a为float类型 整数与浮点数运算 结果为浮点数 类型转换: 数值类型转换发生在变量在任何情况下未进行预期输入的情况,如变量赋值、表达式计算、手动输入、函数传参等等。 进行转换的数据类型通常是浮点数和整型,整型有级别大小之分 有符号 long long > long > int > short > signed char 无符号 unsigned xxx 同上 浮点数 long double 》 double 》 float 分级别的概念是为了在表达式中进行转换的依据: 1.表达式中有一个浮点数,其它都转换为浮点数,浮点数转换按级别转,如有一个为long double,其它都转为long double,否则有一个double 都转换为double,否则由一个float都转换为float 2.表达式中都是整数 (1)如果都是有符号数或无符号数,则以最高级别为标杆转换 (2)如果有无符号数混用 ①如果无符号数级别高,则按无符号为标杆转换, ②如果有符号数级别高,且有符号数能表示无符号数所有区间取值,则转换为有符号数,否则转换为无符号数 通常较小存储空间的类型向较大存储空间类型转换不会发生问题 在赋值或传参时,将小空间整数转换为大空间整数没有问题,反之将截短。将浮点数转换为整数将丢失小数。将double转为float将丢失精度。 以上进行转换时都是自动的,存在潜在问题也是自动处理的,除了自动的还可以强制转换 C风格 int a = (int)10.1 C++风格int a = int(10.1) 除此之外C++还引入4个强制转换运算符 assert 断言 void assert(int expression) 形参接收一个表达式的返回值,如果结果是0,则表示断言成功,系统立即停止运行,并报错 如果返回1,则表示断言失败,程序继续运行 例子: void fun(char \\*s) { assert(NULL != s);//如果给形参s为NULL,则返回值为假,断言成功,程序停止,报错 }  嵌入式 C 嵌入式C编译器会增加特别的解析,如FLASH空间的定义,ICCAVR将const变量都定义到FLASH中,而AVR-GCC利用 PROGMEM 宏 将变量定义到FLASH空间 AVR允许定义变量到FLASH空间,通常应该贮存读取频次不高的或者存储量太大的常量到FLASH空间, 这是通过AVR汇编“\\_\\_flash”实现的,不同编译器对它有不同的封装。 WINAVR定义和读取FLASH常量的方法: 1. 一般常量 定义:prog_uint8_t x = 1; 读取:pgm_read_byte(&x); 读取并赋值给SRAM变量:uint8_t sx = pgm_read_byte(&x); 2. 一维数组常量 定义:prog_uint8_t x[] = {1, 2, 3, 4}; 读取:pgm_read_byte(&x[0]); pgm_read_byte(&x[1]); pgm_read_byte(&x[2]); pgm_read_byte(&x[3]); 读取并赋值给SRAM变量:uint8_t sx = pgm_read_byte(&x[0]); 3. 二维数组常量 读取:pgm_read_byte(&x[0][0]); pgm_read_byte(&x[0][1]); pgm_read_byte(&x[1][2]); 读取并赋值给SRAM变量:uint8_t sx = pgm_read_byte(&x[0][0]); 也可: uint8_t sx[2][3]; sx[0][0] = pgm_read_byte(&x[0][0]); 另一种定义方式: uint8_t x PROGMEM = 1; 等价于 prog_uint8_t x = 1; uint8_t x[] PROGMEM = 1; 等价于 prog_uint8_t x = {1, 2, 3, 4}; ... ... 这种定义方式更为灵活,比如可以定义结构体数组: struct st{ uint8_t x; uint8_t y[100]; }; const struct st arr[] PROGMEM = {... ...}; 如果是第一种定义方式,是无法定义结构体常量的 可以看到,处理定义和取值方式不同,其它操作都是一样的。除此之外还有更多的常量定义形式: prog_void、 prog_char、prog_uchar、prog_int8_t、 prog_uint8_t、 prog_int16_t、 prog_uint16_t、 prog_int32_t、 prog_uint32_t。 读取方式有:pgm_read_byte(), pgm_read_word(), pgm_read_dword(), pgm_read_float。其参数 都是短整型地址,要注意的是读取函数必须在函数中才可以使用。另外,AVR的SRAM和FLASH是独立编址的, SRAM是8bit编址,FLASH是16bit,所以在FLASH赋值/赋址给SRAM变量时,根据编译器的不同可能要进行强 制转换,如uint8_t x = (uint8_t)pgm_read_byte(&y),否则可能会出现警告或错误。 附:如果是在ICCAVR中,直接配置编译选项”treat const as __flash“即可将const常量都存储在FLASH ,读取时使用img[]。注意,配置此选项后,所有的const都将存储在FLASH中,这相比WINAVR也是一个缺点。 data)) /* 》往下走一步怎么办:p = p->next, 这样得到的值是ram中的,错误! /* 正解为:p = pgm_read_xxx(&(p->next)); /* /* 另一个实例:((void (*)(void))pgm_read_word(&(Gvar_menu_pointer_e->fun)))(); /* 读取函数无视于任何类型数据,它返回的都是整型的;上述语句是读取一个函数指针,读取 /* 到之后再强转为该函数指针类型,然后才能如函数一样去调用,其它指针类型也是类似的 /************************************************************************************************/ --> 编译器或IDE选项 Release版本 和 Debug版本的区别: Debug 为调试版本,调试版本使编程人员集中于程序逻辑设计,而不用考虑程序的细节问题,比如变量初始化、数组越界、内存对齐、数据类型转换、动态内存释放等等,这些任务 在Debug版本中 编译器都帮你做了,你只需几种精力解决逻辑部分。 并且,debug版本还支持中断调试、逐步调试等等功能,允许程序员在某些位置设定标志位,允许在程序运行时查看变量值等等。 因为如上原因,debug版本的程序相对比较大。 如果程序在Debug版本中运行通过了,那至少证明一点:你的程序逻辑是正确的。 Release 为发布版本,很多情况下,从Debug版本切换到Release版本后会出现程序错误的现象,原因就是Release要观察所有程序的细节了:没有初始化的变量、越界的数组、数据类型转换导致的精度丢失、动态内存没有及时释放等等, 如果在Debug版本中可以运行,而在Relase版本中不能运行,你至少不用去理会程序逻辑问题了,而原因可能有: 上述提及的 变量、越界、转换、内存 等等细节问题要检查修复 Debug和Release版本,在一些IDE中它们索引资源的路径不一样,比如库的路径、头文件的路径等等,并且对索引资源要求也可能不同,比如要使用一个库A,库A还分Debug版本和Release,那么在引用时就要注意版本问题 IDE的重新编译问题:一些IDE,当切换了版本之后,比如VS2008,如果你直接按F5调试运行,可能会报错一大堆,那可能并不是真的有问题,而是VS2008不检查上次的目标文件是什么版本生成的,导致Debug版本生成的目标文件还存在,release版本就直接拿这些来编译链接。所以最好的做法是,无论是维护别的程序还是自己切换了版本,第一步就是“重新生成解决方案”。 --> 2022年6月17日 09:30:09 char c = -1; if ( -1 != c ) { .... } //这段代码竟然工作了!!! 环境:ARM7_LPC2214, ARM GCC 原因是,整个环境中的常数都是int类型的,-1赋值给c时,只赋值前8bit, 当进行对比时,-1当然不能等于c, 实际的比较方法应该是:if ( (char)-1 != c ).. 给-1强转之后,比较的就是-1的前8bit,结果就是相同的 这个跟操作环境也有关系,测试X86下没有问题 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2022-06-17 09:40:51 "},"pages/programming/SoftwareCopyrights.html":{"url":"pages/programming/SoftwareCopyrights.html","title":"SoftwareCopyrights","keywords":"","body":"1 Concept 计算机软件著作权是指软件的开发者或者其他权利人依据有关著作权法律的规定,对于软件作品所享有的各项专有(民事)权利。 2 软件著作权的作用 APP上架 :主流应用市场上架必备 平台入驻:腾讯、阿里、百度等平台入驻必备 项目投标:政府/商业项目竞标资质条件 国家补贴:高企/双软,享政府补贴 无形资产:帮助企业增资、递延纳税优惠 维权有据:保护著作权,防止盗版侵权 个人优势:技术入股、职称评定、人才证明等 3 详细登记、申请流程 3.1 填表 3.1.1 注册 进入中国版权保护中心官网注册用户信息,为方便在线登记业务可在注册界面“进一步完善资料”,注册完成后点击”同意以下注册条款,提交注册信息“,然后通过邮箱激活账号。 3.1.2 登录 通过邮箱激活账号后将直接调转到中国版权保护中心官网的登录界面,登录后点击“版权登记”栏中的“计算机软件著作权登记”进入办理指南界面,包含申请须知、办理步骤、所需文件、填表说明、审批流程等详细内容。 3.1.3 填表 在办理指南界面左下角点击“在线填表”以填写计算机软件著作权登记申请表,填写完成后点击“保存”、“确认提交”,然后下载到本地。 Tips : 建议在浏览器的IE兼容视图下完成。 3.1.3.1 注意事项 软件代码行,要填写全部代码(无空格、无注释)的行数 软件名称,应当以“平台”、“软件”、“系统”等名称结尾 硬件环境,软件运行的最小硬件环境,如内存、CPU、硬盘空间等 软件环境,操作系统平台和额外要求等 主要功能和技术特点,要分主要功能和技术特点两个方便写 3.2 材料 3.2.1 计算机软件著作权登记申请表 将在线填写的计算机软件著作权登记申请表下载并打印,然后盖章(企业申请)或签字(个人)。 3.2.2 身份证明材料 企业营业执照副本复印件(要加盖公章)、联系人身份证复印件(正反面共页)一份。个人申请的提供个人身份证复印件(正反面共页)。 Tips : 有几个著作人就需要几个复印件、联系人必须与申请表中的一致。 3.2.3 软件相关文档 不做具体选材要求,如软件总体设计、软件详细设计、软件使用说明等都可以选用,其中软件使用说明书使用的较多,以下是说明书文档协作注意事项: 必须包括软件的硬件环境、软件环境、安装及卸载等章节 使用A4纸张,纵向、单面、黑白打印,文字应当从左到右排列 文档右上角应标注页码 文档每页不少于30行,有图除外 提交前连续的30页和后连续的30页,不足的全部提交 按序排好,无需装订 Tips : 申请人若在源程序和文档页眉上标注了所申请软件的名称和版本号,应当与申请表中相应内容完全一致 3.2.4 软件源码文档 使用A4纸张,纵向、单面、黑白打印 不能有空行和注释 文档右上角应标注页码 源码文档每页不少于50行,最后一页应是程序的结束页, 提交前连续的30页和后连续的30页,不足的全部提交 按顺排好,无需装订 全部源程序文档留存,备查,应当和提交60页文档相同页码部分完全一致 Tips : 可使用相关自动生成软件快速生成源码文档。 3.3 申请 将所有材料邮寄到”北京市西城区天桥南大街1号天桥艺术大厦A座三层302(邮编:100050)“或携带资料直接去大厅现场(天桥艺术大厦A座一层 版权登记大厅)办理 AppendiX A 联系方式 软件登记咨询电话 软件登记业务咨询:010—68003934、64097080 办理进度查询:010—84195634 邮寄证书查询:010—64097920 软件登记补正查询:010—84195640 软件档案查询及补换发证书咨询电话 办理进度查询:010—68003887—7050 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/computer/ComputerOrg.html":{"url":"pages/computer/ComputerOrg.html","title":"Principles of Computer Organization","keywords":"","body":"LPC2214芯片复位逻辑 BOOTLOADER[CPU控制权期] [MEMMAP 1:0 = 0, 挂接BOOTLOADER中断向量] 上电/重启 -> PC=0X00000000, CPU控制权期开始 -> 执行复位向量的中跳转指令跳转至BOOTLOADER程序入口 -> 初始化 -> 《CPR使能?》[YES] -> 禁止DEBUG | [NO ] -> 使能DEBUG | -> 《看门口标志置位?》 [YES] ---------------------------| [NO ] -> 《ISP模式使能?》 [NO ] | -> 《片外BOOT使能?》 [NO ] -> 《用户代码有效?》[YES] -> 执行内部用户代码,CPU控制权期结束 [NO ] -> TO ISP [YES] -> 《CRP使能? 》[NO ] -> 执行外部用户代码,**CPU控制权期结束** [YES] -> TO ISP [YES] -> TO ISP TO ISP : 自动波特率(一直到成功)-> 接收晶振频率,处理ISP命令. 1.0 BOOTLOADER BootLoader是一段固件代码,存储在片上FLASH的最顶端8KByte(也就说实际用户可用的片上FLASH只有248KByte), 在CPU复位之后这个区域也会被映射到地址0x7FFFE000-0x7FFFFFFF(这是片上存储区域的最顶端),也就是说从FLASH最顶端和存储区域的最顶端都能执行BootLoader。 映射的目的是为了与将来的衍生产品兼容,即使用同一体系的不同FALSH&RAM存储容量的CPU可以共享BOOT处理方式。 1.1 CRP Code Read Protection, 代码读保护,从Bootloader V1.61固件开始实现的功能,类似AVR的加密熔丝位,只不过需要编程实现,使能方法是将地址0X000001FC赋值为0X87654321。代码读保护使能后JTAG、外部存储器BOOT和ISP命令都不能写RAM、不能读存储器空间、不能执行GO指令、不能将RAM拷贝到FLASH,此时只能使用ISP命令擦除FLASH中的所有用户扇区。 另外,IAP模式不受代码读保护使能的影响。 1.2 异常(中断)向量 Address Exception(Interrupts) 0x0000 0000 Reset 0x0000 0004 Undefined Instruction 0x0000 0008 Software Interrupt 0x0000 000C Prefetch Abort (instruction fetch memory fault) 0x0000 0010 Data Abort (data access memory fault) 0x0000 0014 Reserved (用于存放验证用户有效代码的值) 0x0000 0018 IRQ 0x0000 001C FIQ 0x0000 0000 ~ 0x0000 001C ~ 0X0000 0020 共32Byte,指定的异常发生时CPU会自动跳转到这些入口(也即中断),用户可以在CPU控制权期结束后重新定义这些向量,也就是当异常发生时可以指向自己的子程序。 在CPU控制权期间内,BOOTLOADER的中断向量挂接到异常向量,Reset异常向量地址包含了一条跳转指令,该指令跳转到BOOTLOADER固件入口。当CPU控制权期结束后,用户至少要重新定义Reset向量,否则将循环跳转到BOOTLOAD固件入口。 所谓“挂接”就是指在0X00000000~0X0000001C地址处存放子程序地址,如在0X0000 0000放入子程序START,因为复位时PC=0X0000 0000,那么就会执行0X0000 0000处的代码,在CPU控制权期 BOOTLOADER通过在此处放入子程序START,那么CPU就会执行START的代码,START子程序内包含一条指令:PC=XXXX,那么执行到这条指令就跳转到BOOTLOADER设定的固件入口了。 换句话说,CPU复位时由硬件自动将BOOTLOADER的某个子程序加载到地址0X0000 0000中,这个子程序中包含一条跳转到BOOTLAODER固件的入口,然后就执行了BOOTLOADER。 所以当用户获取控制权时,只需在0X0000 0000地址处放入自己的子程序入口,然后操作PC,就可以控制执行路径了。 1.3 WATCHDOG 看门狗,程序正常执行时可以周期性喂狗,一但无法及时喂狗,将产生CPU复位信号,无法喂狗的情况是自定义的。 看门狗复位标志位WDMOD.WDTOF在任何看门狗超时的情况时置位,该标志只能通过软件清除或者外部导致的CPU复位时硬件清除,也就是说一旦看门口超时导致CPU复位,这个标志是不会被硬件清除的,这样做的目的是为了重启后给BOOTLOADER做决策点,即如果是看门口复位的,则跳过ISP检测。 也就是说,如果已经烧录程序,CPU已经跑起来,并且开启了看门狗,一旦看门狗复位,即便是P0.14是低电平,也不会进入下载模式。 1.4 ISP模式 将P0.14引脚置为低电平,即表示准备进入ISP模式,一旦BOOTLOADER读取到,将进入ISP模式。下载软件可以依据LPC2214手册定义的ISP命令来编写烧录程序。 1.5 BOOT FROM 当 P2.27(BOOT1) 和 P2.26(BOOT0) 引脚 都是高电平时,CPU从内部FLASH引导程序,否则从外部引导程序。要注意,从外部引导的程序是没有代码读保护机制的。 1.6 用户有效代码 地址0X0000 0014用于存放 验证用户代码有效 的值,该值必须为剩余中断向量的校验和的2's complement(此时所有中断向量的校验和是0)。如果验证成功,那么CPU将PC值重设为0X00000000,并将控制权交给用户。 1.6.1 校验和 被校验的所有数据之和,如0X01020304的校验和是0XA. 1.6.2 模与补码 一个一圈12个平均分布点的圆,分别命名为0~11,你站在1上,你想走到6有两种走法:① 1->2->3->4->5->6,即顺时针走5步. ② 1->0->11->10->9->8->7->6,即逆时针走7步;事实上,无论你处于哪一个点,你都有两种方式到达另一个点,并且这两种方式的步数是12。 12就是这个系统的模,+5和-7的结果是一致的,于是+5和-7互为补数,+5称为-7的12的补数,-7称为+5的12的补数,同理+6和-6、+4和-8、+3和-9、+2和-10、+1和-11都是互为补数,可见在这个系统中可以使用加法来替代减法,即只需将负数换成其补数即可。 补码在计算机中的存在,是为了解决有符号数减法运算的问题,目的是将减法换算成加法,这样就可以将负数和正数统一使用加法运算器来运算,负数的原码向补码的转化是编译器来完成的。 2's complement \"2的补码”,实际上这种翻译容易被误导,2's complement 应该被视为一种运算方式,就是经常说的“取反+1”。 1.6.3 LPC2214的中断向量 1.6.3.1 统一地址分配 LPC2214是冯诺依曼结构,采用统一地址映射,其PC寄存器是32bit,因此可以寻址 0~4G-1,FLASH、SRAM、外部存储器和AHB、VPB总线连接的设备都映射到 0~4G-1 的空间内。FLASH + SRAM + 片内存储区保留区共占2G空间(0~2G-1,包含中断向量空间)。 1.6.3.2 中断向量映射 LPC2214异常(中断)向量如1.2节所示,共占32Byte空间,并占用额外的32Byte空间(即32+32,0x00000000~0x0000001F是中断向量所占32Byte空间,0x00000020~0x0000003F是中断向量利用的额外空间),中断向量区存放于FLASH空间的起始地址的64Byte字节:0X00000000~0X0000003F。 为了不同存储器映射模式下对中断向量的利用,实际中断向量的子程序由实际的中断向量映射来实现 存储器映射模式由寄存器MEMMAP(存储器映射控制寄存器)的1:0位来控制,当=0X00时(复位默认)进入BOOTLOADER模式,此时BOOTBLOCK中的中断向量子程序将与中断向量地址挂接,以便于BOOTLOADER运行时使用其中断,当=0X01时(由BOOTLOADER自动切换)进入内部FLASH模式,因为中断向量就是存在于内部FLASH,就是不用映射,贮存于该区域的用户中断向量被挂接,当=0X10时(由用户程序切换,当需要时)进入内部SRAM模式,SRAM底部64Byte的中断向量挂接到中断向量地址。当=0X11时(复位时由引脚BOOT1:0的电平决定,即从外部启动时 BOOTLOADER完成后自动切换到该模式)进入用户外部模式,外部存储器底部64Byte挂接到中断向量地址。 也就是说,FLASH底部的64Byte可以被不同模式下的中断向量子程序覆盖使用,不同模式下执行不同的中断向量子程序,来达到不同的目的。 1.6.3.3 剩余中断向量的校验和的2'S complement 剩余中断向量,是指1.2中除了Reserved的以外的7个异常中断向量,剩余中断向量的校验和是指异常中断向量所挂接/分配的子程序入口值的校验和,也就是0X00000000~0X0000001C装入的(除Reserved向量)7个32bit值的校验和。 每个32bit值都是下载到FLASH后,自定义分配的对应的子程序入口地址。 这些子程序入口地址,(Reserver处可以先临时随便分配一个)需要通过反汇编来具体查看(如objdump生成的.lss文件),然后手动算出校验和的补码,最后在分配子程序入口地址时,再分配这个值。 1.6.3.4 Q&A Q : 既然要验证用户代码有效之后才能将控制权移交给用户,那用户的程序岂不是永远没有机会将合适的数值写入验证区了? A : LPC2214要求:所有剩余中断向量校验和的2's complement等于校验值,换句话说就是所有的中断向量地址所包含的值的和加起来是0,所以下载完程序之后、CPU移交控制权之后FLASH底64Byte完全都是0,校验和自然就是0,用户代码当然有效,除非上次有程序且所有校验和不是0,且当前烧录时又没有擦除FLASH,那就永远都不会执行用户代码了。 CPU INIT[用户控制权期] CPU控制权期结束后,将PC赋值为0X00000000,即从统一内存映射区的起始段开始执行,而0X00000000~0X0000001C刚好是异常中断向量的入口地址,这些异常中断向量不像普通的中断向量那样拥有开关选项,而是出现异常后CPU强制跳转到这些地址,所以要做两件事:① 为每个异常中断向量分配好出现异常时要执行的子程序地址,并计算和写入用户有效代码判定值 ② 必要的初始化操作 BOARD INIT[用户控制权期] main ARM不同模式的发生情况: CPU执行无效指令,进入Undefined模式 CPU执行指令异常,进入Abort模式 当有中断发生时, 进入IRQ或FIQ模式 系统模式,权限最高模式,仅由软件配置进入该模式 1 Endianness Endianness (alias is byte/bit order) refers to the order of bytes/bits within a binary data of Protocols, CPU, Memory, etc. Include Big-endianness and Little-endianness. bytes order is the ordering of bytes within a multi-byte data and bits order within a byte. https://en.wikipedia.org/wiki/Endianness 1.1 Big-endianness 1.2 Little-endianness 2 Bit numbering 位序 表示一串比特数的顺序表示,分为Most Significant Bit和Least Significant Bit,即最高有效位和最低有效位,在通信和存储中,不同的位序表达的数值结果不同,如“M 1010 S”表示数值10,而“S 1010 M”表示数值5,约定位序可使通信双方正确解码数值。 LSB还可以用于判定一个数是奇数还是偶数,如果LSB为1,则一定是奇数,否则是偶数 MSB还可以判定有符号数的符号(1负0正) TBD:SPI有两种传输配置M先或S先,这样配置的意义是什么呢?是为了发送给拥有不同序列处理的芯片?还是跟大小端有关系(位序到底与大小端是否有关???) 字节序 endianness: 表示多个字节的顺序表示,分为Most significant Byte和Most significant Byte,即最高有效字节和最低有效字节,在通信和存储中,不同的字节序表达的数值不同。 在大端(Big-endian)模式中,低地址存放高字节,高地址存放低字节,如:0X1234,0X34为低字节,0X12为高字节,大端存储模型为0X34 0X12,网络通信和部分主机都是用大端模式。小端(little-endian)模式中,低地址存放低字节,高地址存放高字节,如:0X1234,按顺序存放:0X12 0X34,大部分主机都是用小端模式 大端模式跟符合人类阅读模式,小端模式跟符合数据存储模式 编程语言总是使用大端模式处理数据,无论在哪种系统环境下工作 如uint16_t X = 0X1234;那么X的高地址存储0X1234中的高字节0X12,X低地址存储0X1234中的低字节0X34; 在编程语言中,左移,总是表示向高位移动,右移,总是表示向低位移动 大小端对字节序和位序的影响 https://en.wikipedia.org/wiki/Bit_numbering 编码 1 Introduction Character coding system is the binary set translator for the certain charset (which alias 'code pages'), used for data recognition and storage. Coding Sys trans 2 Coding system & charset 2.1 ASCII 2.1.1 Introduction American Standard Code for Information Interchange (ASCII). 2.1.2 Coding Use 7 bits of 1 Byte, supports 128 character encoding, and 8 bits supports 256 character encoding of EASCII. And ASCII is subset of EASCII. 2.1.3 Charset English alphabet, Control characters(0~31 and 127), Punctuations, parts of western europe characters. 2.2 GB2312-80 2.2.1 Introduction Guo Biao (GB) 2312, 1980, Chinese national standard. 2.2.2 Coding Use 2 Bytes, construct with High Byte and Low Byte, both from 0XA1 to 0XF7 and contain ASCII, supports 7396 + 128 character encoding. 2.2.3 Charset Simplified Chinese, Chinese punctuations, ASCII, Japanese, Roman alphabet and math symbol, etc. 2.2.4 GBK(CP936) Guo Biao Kuo (GBK, which alias 'CP936') is extension of GB2312 (use remaining space of GB2312), designs by Microsoft. 2.2.5 GB18030 GB18030 is latest characters coding system of China, compatible with UTF-8 and supports more characters. 2.3 BIG5 2.3.1 Coding Use 2 Bytes, construct with High Byte from 0X81 to 0XFE and Low Byte from 0X40 to 0x7E + 0XA1 to 0XFE. 2.3.2 Charset Traditional Chinese, Chinese punctuations, Geek alphabet, etc. 2.4 UTF-8 2.4.1 Introduction 8-32 bits Unicode Transformation Format. 2.4.2 Coding Use 1 to 4 Bytes, flexiable length. 2.4.3 Charset Unicode - Universal charset, supports by ISO/IEC 10646, contains ASCII, Latin, Greek, Abaric, ..., etc. 2.3.4 UTF-16 and UTF-32 UTF-16 is 16 bits Unicode Transformation Format and UTF-32 is 32 bits, but they are fixed length and preformance is not as good as UTF-8. 2.5 Collection diagram Charset collection 3 Programming with character coding system //TBD 快算:( 一个2^10(1024)升K,两个升M,三个升G) 随便一个十六进制地址空间,如0XFFFF,首先需快速算出bit数为16bit,然后拆分2^16 = 2^6 2^10 = 64Kbit,更快的算法就是一 看到16,就想到2^62^10,而2^10代表K,于是就是64Kbit 0X0000 ~ 0XFFFF 多大地址空间? 0XFFFF 可以快速看出是16bit Max = 2^16 = 65536bit 2^16 = 2^6 * 2^10 = 64Kbit 65536 / 1024 = 64Kbit = 8KByte 实际2^10 = 1024 ,所以 直接用2^16 /2^10 = 2^6 = 64Kbit 前提是地址空间大于2^10时这样算 0X000 ~ 0XFFF 多大地址空间? 2^12 / 2^10 = 2^2 = 4Kbit 或者 2^12 = 2^2 * 2^10 = 4Kbit( 一个2^10(1024)升K,两个升M,三个升G) 0X00 ~ 0XFF 多大地址空间? 2^8 = 256bit 0X00000000 ~ 0XFFFFFFFF 多大地址空间? 2^32 / 2^10 = 2^22 = 2^10 2^10 2^2 = 410241024 = 4G 含有一个1024升为K,两个升为M,三个升为G,四个上升为T,五个上升为P...更多见 国际单位制(SI)词头 所以2^32一看就能看出包含三个2^10,还余下2^2所以为4G 0X0000000000 ~ 0XFFFFFFFFFF 多大地址空间? 2^40 包含4个2^10,为1T 0x0000000 ~ 0xFFFFFFF 多大地址空间? 2^28 包含2个2^10,所以为256M 0X0000000000000000 ~ 0XFFFFFFFFFFFFFFFF ? 2^64 包含6个1024,所以为16E 附:SI词头 10E24 尧(它) Y Yotta 10E21 泽(它) Z Zetta 10E18 艾(可萨) E Exa 10E15 拍(它) P Peta 10E12 太(拉) T Tera 10E9 吉(咖) G Giga 10E6 兆 M Mega 10E3 千 k Kilo 10E2 百 h hecta 10E1 十 da deca 10E-1 分 d deci 10E-2 厘 c centi 10E-3 毫 m milli 10E-6 微 μ micro 10E-9 纳(诺) n nano 10E-12 皮(可) p pico 10E-15 飞(母托) f femto 10E-18 阿(托) a atto 10E-21 仄(普托) z zepto 10E-24 幺(科托) y yocto I/O引脚的读取 每个I/O端口都有三个寄存器:数据寄存器 PORTx、 数据方向寄存器 DDRx、 端口输入输出引脚寄存器 PINx, PORTx和DDRx为读/写寄存器,而PINx为只读寄存器。 无论配置DDRx是输入(0)还是输出(1),PINx的数据都可以读取,PINx就代表当前引脚的高低电平,这可以 用电压表测量出来,如要读取PINx的某个位,则可以如下操作: 设要读取PINA的第0位,判断其是否是高电平: uint8_t x = PINA; if(0x01 == (x&=0x01)) { ... } 要注意的是,PINx是只读寄存器,下面这样的操作是不对的: if(0x01 == (PINA&=0x01)) { ... } 如果针脚作为输入时要读取端口数据,则要使能该引脚的上拉电阻: DDRA &= 0XFE; //设置为输入 PORTA|= 0x01; //使能上拉电阻 uint8_t x = PINA; if(0x01 == (x&=0x01)) { ... } 上拉电阻的意义其一是给定该引脚确定的电平,以方便程序匹配 判断,如上述程序中先使能为高电平,然后再判断是否还是高电平,如 果是就没有读到相关信号。其二是当将外部的电路拉低时该引脚将输出 电流。 处理器的 主频、IPC与MIPS 振荡器(晶振/RC等)是硬件系统的指挥家,指挥速度就是振荡频率,处理器的主频是指处理器能接受的频率范围/适应的工作范围,比如主频500MHz(max)的处理器,使用600MHz的振荡器(在不分频的情况下)是应用不了的,IPC是指振荡器振荡一个周期处理器能处理多少条指令,于是 1秒振荡的次数(主频) x 每次振荡处理的指令数量(IPC)= 每秒处理百万条指令数(MIPS)/每秒处理的指令条数(IPS) 时钟周期? 晶振振荡一次(一个来回)的时间 指令周期? 假设1秒振荡100次,1次执行1000个指令,那么1秒就执行了100 000个指令,那么一个指令就是0.00001秒 PLC PLC VS DCS PLC早期是以代替继电器目的而生产的 开关量 嵌入式计算机,随着发展,现在已经丰富了很多功能。 DCS是处理模拟量的嵌入式设备. PLC有三种输出接口: 1. 晶体管输出-低电压,速度快,但不能直接驱动外设(电流小) 2. 晶闸管输出-中电压 3. 继电器输出-高电压,因为继电器需要双接口接输出,所以设计出一个公共端子 速度慢(开关需要10ms,高频开关还会损坏继电器)但可以直接驱动外设(电流大mA) 在20世纪60年代末,由于发达国家工业和信息产业的快速发展,导致了PLC的出现:汽车产业一直以当时传统的控制方式来操作产线(大量的继电器开关组成的电路),随着产线的增多,这种控制方式越来越吃力(主要表现为驱动和维护),恰好信息产业出现,于是招标一种易用、耐用的电气控制产品,PLC各个厂家考虑到当时的市场环境(基本上都是电子电力人才),于是制作了梯形图为编程入口,而屏蔽了底层复杂的汇编代码 梯形图的符号,正式电子电力学科常用的符号,连线逻辑也及其相似,于是PLC市场迅速打开,沿用至今。 实际上PLC有多种编程入口(如直接指令),梯形图(间接指令)是最常用的,也是最直观的 常用的指令如下: LD常开 LDI常闭 OUT输出 CTU增量计数器 TON接通延时指令 NOP空指令 上升沿触发 下降沿触发 SET置位(相当于74HC574保持) RST复位(相当于74HC574保持) \\= > \\ PLC输入端子上标有x00 x01 x02 等等,输出端子上标有y00 y01 y02等等,而在PLC梯形图中,只要使用了这些符号,就等于操作了输入输出端口 另外要注意,这些都是8进制表示的,比如x10是第八个端子 s/s是Xn的公共端 (实际上s/s与Xn之间连接了发光二极管,所以只要导通,输出端就能输出) com是Yn的公共端 (要注意,电流是否能驱动负载,如果不能则需要外加电源) 交流电机力巨大,但调速特性特别差,因此出现了变频器来调节交流电机速度, 直流电机调速特性好,但力矩相对较差。交流电机+变频器=直流电机,只是价格更贵 继电器,电磁继电器,一般的用法是小电流控制大电流,但在电子电力工程领域,有各式各样的继电器,已经不单单是小控大的作用了,而是成了“条件触发器”, 比如速度继电器(达到设定速度就触发)、时间继电器(定时触发)...等等 100万的项目, 10%电气 无自动化 20%电气 一般自动化 30% 有自动化 30%+ 高自动化 常开常闭是指无激励时的开关状态 PLC的显示 因历史原因和设计原因,PLC不带显示器,因此常规的LCD、普通按键驱动起来非常麻烦,而且耗费端口,因此最常用的方式是直接连接另一个具有处理器的显示器,然后 使用modbus进行通讯 比如麦科的PLC和深圳显控制公司的LCD,后者也是一个单片机,内置modbus协议,它们通过modbus进行通讯,LCD触碰某个图形触发哪个点,可以直接在后台配置,如果被触发,则用modbus返回 I/O端口都有三个寄存器:数据寄存器 PORTx、 数据方向寄存器 DDRx、 端口输入输出引脚寄存器 PINx, PORTx和DDRx为读/写寄存器,而PINx为只读寄存器。 无论配置DDRx是输入(0)还是输出(1),PINx的数据都可以读取,PINx就代表当前引脚的高低电平,这可以 用电压表测量出来,如要读取PINx的某个位,则可以如下操作: 设要读取PINA的第0位,判断其是否是高电平: uint8_t x = PINA; if(0x01 == (x&=0x01)) { ... } 要注意的是,PINx是只读寄存器,下面这样的操作是不对的: if(0x01 == (PINA&=0x01)) { ... } 如果针脚作为输入时要读取端口数据,则要使能该引脚的上拉电阻: DDRA &= 0XFE; //设置为输入 PORTA|= 0x01; //使能上拉电阻 uint8_t x = PINA; if(0x01 == (x&=0x01)) { ... } 上拉电阻的意义其一是给定该引脚确定的电平,以方便程序匹配 判断,如上述程序中先使能为高电平,然后再判断是否还是高电平,如 果是就没有读到相关信号。其二是当将外部的电路拉低时该引脚将输出 电流。 定点数&浮点数 Fixed point VS floating point 浮点数,根据IEEE 754-1985:F = sign x 尾数 ^ 指数 一个32bit的浮点数定义: ---------------------------------------- | sign(1bit) | 尾数(8bit) | 指数(23bit)| ---------------------------------------- 浮点数,意味着小数点位置可变,也就是说一个浮点变量,它可以接收的浮点数不是固定的,只要在范围内的都可以接收,比如float F = 0.123,还可以F = 10000.2 浮点数变量一般用来表示小数,但也可以存储整数,其实就是存储小数点后面没有数值的数(小数点在末尾) 定点数,意味着小数点位置不变,假设一个定点数D的小数部分有3位, 则D=0.123或D=0.234,但D=0.1234就不行了 在编程语言中没有直接表示定点数的方法,需要转义实现,比如一个定点数的整数部分由2位,小数部分有10位,则可以标示为Q(2,10) 在没有浮点运算器(硬件)的CPU,浮点数运算会被编译器转换成大量的逻辑代码,运算起来非常耗时,在DSP中还不能用浮点数,因此这些情况下 如果必须使用小数表达数据,那么就需要定点数。 因为定点数是逻辑表示的,因此运算也是逻辑的。 ARM处理 ARM处理器之多重模式意义的猜想: 用户模式、快速中断、中断、管理模式、系统模式、ABORT、未定义... 这些模式好像可以对应到Linux操作系统中,比如用户模式下就是Linux一般用户的权限下工作, 中断/快速中断 由软件或硬件产生 管理模式,就是Linux管理员权限下的操作 系统模式 是内核上下文??? ABORT 终止,任何异常的终止 多重模式也可能是为了预留接口给芯片制造商使用,比如未定义模式可以用来扩展协处理器(周立功) 烧录到单片机内的程序存储在哪里?在哪里运行? 第一答案肯定是烧录并存储到了FLASH中,运行肯定是在RAM了 哈弗体系的程序和数据是分开存储的,所以可以从FLASH中读取指令,而从RAM中读取数据??? 指令与数据: 以C语言为例,任何变量和常量都是数据,而指令是各种语句, 当烧录程序到FLASH中后,单片机运行时,先将变量和常量都加载到内存中, 然后执行时从FLASH中取指令,从RAM中取数据 但冯诺依曼体系数据和程序是通过一条总线搞定的,难道在运行前程序和数据都要加载到RAM中吗? 冯诺依曼体系 与 哈佛体系 本质的区别是程序与数据通道, 即 冯诺依曼体系使用一条总线访问程序和数据,而哈弗体系程序和数据各有一条总线, 这就导致了速度上的差别, 一条指令被执行要经历三个步骤:取址、译码、执行;如果一条指令涉及数据运算,对于冯诺译码只能等下一个指令周期来获取数据, 而哈弗结构可以(可能)立即完成 流水线:如ARM7TDMI,采用三级流水线结构,也就是三级缓存,假设为L1,L2,L3,CPU在开始运行的时候,先将前三条指令存储L1,L2和L3, 当CPU需要取址时先从L1取,取完交给译码器,译码器译码的同时,L2被取址,此时开始执行第一条代码,当执行完第一条代码后译码器又工作完成.... 这样取值、译码和执行三个步骤就无缝连接,提高了运行效率,另外预取指令也节省了CPU等待数据从RAM加载到寄存器的时间。 ARM7系列都采用冯诺依曼体系结构,ARM9-ARM11采用哈弗结构 冯 冯诺依曼体系的还将要执行的指令从FLASH加载到FLASH中诺依曼曾被普利斯顿大学聘为教授,可能其体系的研发构想与大学息息相关,所以冯诺依曼体系结构又称为普利斯顿体系结构 CPU中的特殊寄存器之 程序计数器: PC - Program counter 一条指令的执行过程:取址、译码和执行。取址时从哪里取呢?或者说是从哪个地址取呢?如何操控CPU取址的地址? 就是通过程序计数器PC,或者称为指令计数器。 CPU取址时将以 PC寄存器中存放的值 为地址 来取址。 为什么叫计数器呢?因为每次CPU取址完成,PC将自动累加预存下一条即将被执行的指令(除非人为的干预),如果没有人为 干预,那么将不断的累加,所以又叫计数器。 PC累加一次,不一定是累加1,步长是根据指令长度决定的, 如ARM7TDMI有ARM的32bit指令 也有Thumb的16bit指令,如果试用的是32bit指令,那么累加一次那就是+4(4x8=32),16就是+2(2x8=32) ,注意 无论哪种CPU,最小操作单元都是Byte,也就是一个Byte一个地址。 所以8bit的指令集,累加一次就是+1 如果是变长指令,那是多少就加多少。 PC与寻址能力: ARM7TDMI的PC寄存器是32bit的,所以可以存放最大值是2^32,即4G,所以寻址范围是0~4G-1,或者说是0X0000 0000 ~ 0XFFFF FFFF LPC2214有16K的RAM和256K的FLASH,采用的是ARM7TDMI-S内核,也就是采用的冯诺依曼体系结构,而冯诺依曼体系结构程序与数据共存于存储器, 如果是电脑,则掉电时代码存储在硬盘,上电时将程序和数据都拷贝到内存执行。 但LPC2214中如果存储了200K的程序,RAM只有16K,显然不可能将程序和数据都拷贝到内存执行, 但又是冯诺依曼体系结构,一条总线会从FLASH中读指令又从RAM中读数据???? 冯诺依曼体系描述说共存于存储器的数据和程序以地址区分,那么如果FLASH和RAM执行统一地址映射,且共有一条总线,那么就没有问题了, 这也就是说,PC不仅仅可以指向RAM,它也可以指向FLASH空间,或者说可以指向统一地址映射的所有空间, 果然,查看LPC2214手册,0~4G-1空间被统一映射,RAM空间在0X40000000~0X40003FFF,FLASH空间在0X00000000~0X0003FFFF ,AHB,VPB等等也在其中 ,那就是说只要给PC赋值任一地址值,那么CPU就执行那个地址的指令,如果指向AHB/VPB的空间?那就执行那里的指令,而AHB和VPB是ARM7TDMI-S内核的外设总线 是用于连接LPC2214中的I/O AD SPI IIC USART RTC TIMER WD等部件的,这些部件显然没有指令可执行,那么 ARM中的7中模式中的未定义指令模式,应该就是未这个设计的,如果执行到了未定义的指令,就跳转到这个模式中,至于为什么未定义指令模式可以用于扩展 协处理器?未知,可能是未定义指令,可以“自定义指令”,也就是这个模式下用于激活一下协处理器,然后再跳转回来工作??? 当然AHB还连接了外部存储控制器,用于连接外部存储器,如果外部存储器中有指令,那么就可以执行了 预取址异常和数据终止异常: 是指LPC2214统一映射的地址中有些是预留的,有些是未分配的,当程序访问到这些地址时(取址或数据访问),将产生异常,跳转到0x0000 000C或0x0000 0010 通讯技术 CATALOG 一. 串行通信基础 1 异步串行通信 1 同步串行通信 1 主从串行通信 2 二. 串行通信线路 2 单工通信 2 半双工通信 2 全双工通信 3 三. 串行通信协议 3 UART 3 (1) UART组成 4 (2) RS232 4 (3) RS422 5 (4) RS485 6 SPI 6 IIC 7 //TBD 7 附录A:奇偶校验(Parity check) 8 附录B:波特率与比特率 9 附录C:握手(流控) 10 附录D:RS232接口标准 11 附录E:UART转RS232(DB9) 12 附录F:UART转RS422 13 附录G:共模抑制 14 一.串行通信基础 计算机的数据传输有并行和串行两种方式,并行传输的特点是每个数据位都使用独立的数据线同步传输,传输速度快、效率高,缺点是长距离传输成本高且存在电磁干扰,因此常用于短距离的计算机内部数据传输。 串行数据传输的特点是所有数据位都通过一根数据线传输,速度相对较慢,但传输距离远(几十米到上千米)、成本低,是网络通信、处理器与外设通信的主要方式。串行通信按时序分为同步和异步两种方式,按控制规则分为一主多从和多主多从两种方式。 并行接口一定都是同步的,因为为了高速,不会向异步传输那样增加很多校验位,同时 显然 就必须增加一根时钟线,传输的高速特性也同时限制了传输长度 1.异步串行通信 异步串行通信是以数据帧为单位的间歇传输形式,通过插入标志位来实现数据收发双方的协调。数据帧中包含起始位、数据位、奇偶校验位和停止位。起始位(1位)用于标志传输开始、数据位为5~9位、奇偶校验位用于数据有效性检查(见附录A)、停止位(1/1.5/2位)用于标志数据传输已结束。 上图方框部分表示该数据位可能是高电平“1”,也可能是低电平“0”,每一位都有固定的时间宽度,称为位时间。“MARK”表示空闲时高电平,SPACE表示有效电平,这两个术语可以追溯到二十世纪六十年代。 异步串行通信可以是连续的:上一帧的停止位之后立即发送下一帧的起始位;也可以是断续的,新的数据帧可以在任何时刻开始,并不要求整数倍的位时间。 2.同步串行通信 同步串行通信将传输数据按相等的时间间隔划分成数据帧进行传输,并同时发出同步信号以保证收发同步,每个数据帧的开始用同步字符来标志。 同步串行通信要求收发双方的时钟信号(频率、相位等)必须始终同步,且每个数据帧之间不能有间隔,如果线路空闲或没有数据传输,则需发送同步字符串。 同步串行通信的特点是传输效率高,其数据帧大小几乎不受限制(可达几十到几千字节),但因对时钟同步的要求导致硬件实现成本较高,所以同步串行通信一般用于数据量大、对速度要求较高的串行通信场景。 同步串行通信就是在异步串行通信的基础上加了一条时钟线, 其实这就是SPI总线 3.主从串行通信 在主从通信系统中至少有一个为主机,并允许有多个主机和多个从机。主机负责发送时钟和仲裁(如片选、广播)信号,从机通过总线仲裁来判定是否与主机通信。 二.串行通信线路 串行通信线路包括单工通信、半双工通信和全双工通信,同步和异步串行通信都可以使用这几种形式: 1.单工通信 单工(Simplex)形式使用一根数据线进行数据的单向传输,通信双方固定一端为发送端,另一端为接收端。 例如,计算机与打印机之间的串行通信就是单工形式,只能有计算机向打印机传输数据,而不能有反向数据。 2.半双工通信 半双工(Harf-duplex)形式的数据传输是双向的,但任何时刻只能由其中一方发送数据,另一方接收数据。半双工形式既可以使用一根数据线,也可以使用两根数据线。下图为一根数据线示例。 3.全双工通信 全双工(Full-duplex)形式的数据传输是双向的,可以同时发送和接收数据,因此全双工形式的串行通信需要两条数据线。 三.串行通信协议 串行通信协议包含对接口电气属性的定义、电路结构及线路连接方式的实现、数据传输性能和传输方式的描述等等,所以也称串行通信协议为串行通信接口或串行通信总线。 在现代MCU内部,基本都集成了一个或多个(相同和不同的)串行通信总线,通过配置寄存器即可实现协议所定义的功能。 1.UART UART(Universal Asynchronous Reciver/Transmitter),通用异步接收器/发送器,也称异步通信接口适配器(ACIA)。UART是最简单的串行通信实现方式。UART出现在电子通信早期,当时是一个由齿轮、继电器和电动机械寄存器组成的机械设备。 一般MCU都集成USART(通用同步和异步接收器/发送器),它可以实现UART和USRT(通用同步接收器/发送器)功能,但在单片机的串行通信中,最常用的是异步方式,因此常把USART写为UART。 异步模式的UART不分主从机,在发送数据的同时可以接收数据。如果在同步模式下,则当使用外部时钟时,UART处于从机地位,当使用内部时钟时,UART处于主机地位。 (1)UART组成 UART由发送缓冲寄存器、接收缓冲寄存器和输入移位寄存器组成,发送缓冲寄存器的本质是一个移位寄存器,它将计算机内的并行数据转换为串行数据,并按配置插入标志位形成数据帧,然后通过Tx接口输出。 接收缓冲寄存器和输入移位寄存器组成双缓冲结构,以避免在数据接收过程中出现数据帧重叠错误。输入移位寄存器将Rx接口输入的串行数据过滤,并转换成并行数据,然后存入接收缓冲寄存器,计算机通过读取接收缓冲寄存器来获得数据。 (2)RS232 RS-232C(简称RS232)是古老的串行通信接口标准,可追溯到20世纪60年代,现在正逐渐被高速网络取代,但它对嵌入式系统来说仍然是一种非常重要、简单而有用的连接工具。RS232通信距离可达25米,传输速度可达38.4kbps。 RS232最开始被用来连接数据终端设备(DTE)和数据通信设备(DCE),因此RS232协议标准默认其一端连接的是DTE,另一端连接的是DCE。在计算机出现之前,DTE是一种电传打字机,DCE是一种调制解调器: 当计算机出现以后,刚开始没有更多的可靠通信接口可选用,于是RS232被应用到计算机当中(计算机既可以作为DTE设备也可以作为DCE设备),并一直沿用到现在。RS232使用DB9(D型9引脚接口)或DB25(D型25引脚接口)作为连接接口,其标准定义参看附录D。 如果单片机与计算机通信则必须将单片机看成DTE或DCE设备,此时需要将单片机UART接口改装成DB9或DB25,然后使用RS232与计算机进行通信。需要注意的是单片机使用的TTL电平与RS232电平不一致,需要进行电平转换(参看附录E): 当使用UART在两个单片机之间通信时只需对接Tx和Rx接口即可: (3)RS422 RS232传输的数据位的电压电平是相对于本地的地,这种不平衡的传输方式有很差抗噪性。RS422使用双绞线传输数据(见附录G),传输距离可达1200m,双绞线电压差在4V~12V之间,该电压差值范围刚好在RS232逻辑电平范围之内,如果将RS422双绞线中负电压一端接地,则可实现与RS232兼容。(RS422与UART的连接参看附录F)。 注意,RS422只规定了标准电压,而没有像RS232一样规定插脚引线等实现细节,所以RS422的具体实现是未定义的,它可以按照实现者的想法自由连接。 (4)RS485 有些RS422的接口芯片具有三态功能,当RS422使用这种芯片实现时就扩展成为RS485。RS485可以实现高效率、低成本的一主多从式多机通信,并支持许多通信协议。它是最简单和最容易实现的网络之一。 如图,主机和从机之间使用一根双绞线进行通信,所有事务都有主机来初始化,从机只有在接收到特定命令后才进行传输。 2.SPI SPI(Serial Peripheral Interface)串行外围设备接口,是由Motorola公司开发的同步、全双工、一主多从式串行通信总线,常用于微控制器与其外围设备的连接。 (1)SPI组成 SPI有4根信号线:MOSI/SI/SDI(Master Out Slave In)、MISO/SO(Master In Slave Out)、SCLK/SCK、SS/CS。大多数处理器的SPI模块带有片选接口,如果需连接多个从机,则需要使用GPIO。 SPI主机和从机都包含一个(8bit)串行移位寄存器,主机通过写寄存器来通过MOSI信号线发起一次传输,从机同步的将寄存器中的数据通过MISO信号线返回。如果主机仅进行写操作,则忽略收到的字节(数据)即可,如果主机要读取从机一个字节,就必须发送一个空字节来引发从机的传输。 如果主机发送连续的数据流时,有些外设(如存储器)可以进行多字节传输,在这种传输模式下,从机必须在整个传输过程中保持低电平。 (2)SPI时序 根据时钟极性和时钟相位的不同,SPI有四个工作模式以适配不同外设的时序和数据处理需求。时钟极性(CPOL)表示时钟空闲时的状态,时钟相位(CPHA)表示数据采样时的有效性。 当时钟相位为0、时钟极性为低电平时,MISO和MOSI在SCK的上升沿有效。 当时钟相位为0、时钟极性为高电平时,MISO和MOSI在SCK的下降沿有效。 当时钟相位为1、时钟极性为低电平时,MISO和MOSI在SCK的下降沿有效。 当时钟相位为1、时钟极性为高电平时,MISO和MOSI在SCK的上升沿有效。 (3)SPI速度 官方标准没有规定SPI的传输速率,目前已知器件可达Mbps水平。 3.IIC IIC(Inter Integrated Circuit Bus,I2C、I2C、TWI)总线是飞利浦公司(Pilips)开发的同步、半双工、多主多从式串行通信总线,常用于微控制器与其外围设备的连接。 (1)IIC组成 IIC只有2根信号线:SDA串行数据线和SCL串行时钟线;两根线接上拉电阻或正极电源,挂载到IIC总线的(N个)设备通过寻址识别,每个器件都可作为主/从设备,但任何时刻只能有一个主控设备。 (2)IIC速度 IIC标准规定标准速度为100Kbps、快速400Kbps、高速3.4Mbps。 TBD... 2.总线协议 IIC总线有三种信号和两种状态:开始信号、应答信号、停止信号、总线空闲、总线忙碌 附:SDA、SCL默认置高电平状态 开始信号:SCL保持高电平,SDA出现下降沿,表示数据开始传输 应答信号:接收设备收到8bit数据之后,发送一个ACK位给发送设备,且每 8bit数据之后必须有一个应答位 停止信号:SCL保持高电平,SDA出现上升沿,表示数据停止传输 总线空闲:SCL和SDA都处于高电平状态 总线忙碌:开始信号之后,停止信号之前 3.传输格式 IIC总线的传输格式为主从式:主发送从接收、从发送主接收 ·主发送从接收模式 主设备开始信号之后,发送第一个字节为控制字节(从到地址到低地址 = 7位地址寻址位 + 1位方向位,方向位决定主设备是从从设备读数据还是向从设备写数据,为0时表示写、1时表示读),接下来发送数据,该数据可以是一个或N个字节,从设备每接到1个字节都要返回一个应答信号(ACK = 0),主设备在应答时钟周期为高电平时释放SDA,转由从设备控制(发送应答信号),从设备在这个时钟周期的高电平期间必须拉低SDA,并使之为稳定低电平,以作为有效的应答信号 ·从发送主接收模式 仍然从主设备开始信号,主设备向IIC总线发送控制字节(“广播”),从设备进行地址位比对,之后检查控制字节的第8位是1/0,当为1时,表示主控设备要读数据,此时从设备先发送一个应答信号(ACK = 0)给主设备,接着发送数据到主设备,同样的主设备收到一个字节(8bit)后,也要发送一个应答信号给从设备,不同的是如果这个ACK = 0(有效应答信号)那么从设备继续发送数据,如果ACK = 1(停止应答信号)则从设备停止发送数据。主设备也可以控制从设备从什么地址开始发送数据(默认从设备从主设备发送过来的控制字节地址发送数据),发送多少字节 基本操作 IIC总线是主/从双向通信,主设备和从设备都可以发送和接收,但总线必须由主设备控制,主设备产生串行时钟SCL,并产生开始和停止条件,在开始条件之后SDA线上的数据状态仅在SCL为低电平期间内才能改变,在SCL高电平期间SDA上的数据改变用来表示开始和停止条件 ·控制字节 在开始条件之后,第一个字节必须是控制字节,其中高4位是器件类型标识符(不同器件有不同的意义:如EEPROM为1010),接着3位为片选(这意味着同一器件不能超过8个),最低位为读写控制为,即1 - 读/0 - 写 5.总线仲裁 wating... 6.IO模拟 如果单片机带有IIC总线接口(高级单片机一般都带有若干个),则直接挂载设备即可,如果没有,则可以使用普通IO口模拟 ·硬件上 硬件上只需两个GPIO引脚,一个作为串行时钟线SCL,一个作为串行数据线SDA,并且都挂接到上拉电阻或正极电源 ·软件上 软件上要严格模拟IIC总线数据传输规则,示例: 子程序如下: ORG 1000HBSEND: MOV R2, #08H ; 1字节8位 SENDA: CLR P3.2 ; SCL置低 RLC A ; 左移一位 MOV P3.3, C ; 写一位 SETB P3.2 ; SCL置高 DJNZ R2, SENDA ; 写完8个字节? CLR P3.2 ; 应答信号 SETB P3.3 ; SDA置高 SETB P3.2 ; SCL置低 RETEND 附:MSB与LSB MSB:Most Significant Bit,最高有效位,在时序图中表示高字节先发送或表示最高位,在二进制数中表示最高加权位,位于数据位最左侧 LSB: Least Significant Bit,最低有效位,在时序图中表示低字节先发送或表示最低位,在二进制数中表示最低加权位,位于数据位最右侧 附录A:奇偶校验(Parity check) 奇偶校验是验证数据传输有效性的简单验证方式。一串二进制数据帧,其中“1”的个数只有两种可能:奇数或偶数。 奇校验(ODD CHECK),就是将该数据帧添加一位“0”或“1”,使得新的数据帧中“1”的个数为奇数,新添加的二进制位就是校验位,接收方收到数据后,再次对原数据帧进行奇校验,对比添加的校验位是否一致,如果一致就说明数据完好。 偶校验(EVEN CHECK),就是将该数据帧添加一位“0”或“1”,使得新的数据帧中“1”的个数为偶数,新添加的二进制位就是校验位,接收方收到数据后,再次对原数据进行偶校验,对比添加的校验位是否一致,如果一致就说明数据完好。 奇偶校验,是轻量级数据校验方式,它只适用于数据受干扰较小的情景,如果数据受干扰较大,则二进制数据帧有可能有偶数个数据位变化,导致最后校验结果无误,但实际数据已经损坏。 附录B:波特率与比特率 比特率是指每秒钟传输或处理比特(bit)或位的数量,单位为“bps或bit/s(Bit Per Second)”,常用于计算机通信领域。比特率的单位是千进制:1Kbit/s = 1000bit/s、1Mbit/s = 1000Kbit/s、1Gbit/s = 1000Mbit/s。 每秒1次的信号变化为1波特(baud),原用于表示电信设备传输速率,现用于调制解调器的数据传输速率。波特率是指每秒钟传输符号的数量,单位是波特。通过不同的信号调制方式,可以在一个符号上负载多个比特信息,当调试方式是二进制调制时,波特率与比特率的值一致,单位可使用“bps”等。 附录C:握手(流控) 当两个系统进行串行通信时,在接收者处理完接收数据之前,必须禁止发送者发送新的数据,这个过程称为握手(shake hands)或流控(flow control),握手有三种方式:软件方式、硬件方式、不握手。 不握手是最简单的方式,用于发送系统在准备和发送数据上都比接收系统慢得多的场合,比如1MHz的低速单片机发送给1GHz的高速单片机,或者手工向计算机输入数据。注意,当接收端使用高速处理器,但使用了实时反映能力较弱的操作系统,则也有可能需要握手。 硬件握手方式在不同的硬件中有不同的实现方式,以RS232为例,它使用两个信号:RTS(请求发送)和CTS(清除发送),当发送者希望发送数据时就置RTS有效,高速接收者有数据等待发送,而当接收者准备就绪时就将CTS置为有效,来通知发送者可以发送数据。 软件握手用于无法实现硬件握手的场景。软件握手用两个字符来实现流控,一个代表请求对方暂停传输、另一个代表清除暂停传输的请求,继续传输数据。通常这个两个字符是Ctrl-S(0X13)和Ctrl-Q(0X11)。 附录D:RS232接口(母口)标准 信号 功能 DB25 DB9 方向 Tx 发送数据 2 2 DTE-DCE Rx 接收数据 3 3 DTE-DCE RTS 请求发送 4 7 DTE-DCE CTS 清除发送 5 8 DTE-DCE DTR 数据终端就绪 20 4 DTE-DCE DSR 数据设备就绪 6 6 DTE-DCE DCD 数据载波检测 8 1 DTE-DCE RI 振铃指示器 22 1 DTE-DCE FG 侦测地(机壳) 1 - 共用 SG 信号地 7 5 共用 注:① DB25和DB9接口呈“D”型,它们又被称为COM口;② 这些信号中许多都是用来对调试解调器进行控制器的,如果要在一台计算机和一个终端之间建立一个很简单的链接,仅需Tx和Rx信号就够了。另外,许多系统都将FG和SG连接到一起。 附录E:UART转RS232(DB9) TTL逻辑高电平为:输出 - >2.4V,输入 - >2.0V;逻辑低电平为:输出 - MAX232支持两个输入输出端口:T1IN、T2IN、T1OUT、T2OUT、R1IN、R2IN、R1OUT、R2OUT;通过附录D可知,DB9第2和3针为Rx、Tx,第5针为SG信号地(必要): 注:① DB9有公头和母头之分,它们的引脚顺序定义不同,且母头的第一引脚在右上角(倒梯形时),其它引脚依次向左排列;② 没有用到的接口,可以用作嵌入式系统的电源线;③ 与PC通信时,波特率不宜设置太高,以免有乱码出现。 附录F:UART转RS422 MAX3488是一款用于RS422电平转换的芯片,同RS232一样,其Tx和Rx接口可直接与UART相连: 上图中Rt是一个终止电阻,用来消除信号反射,信号反射发生在远距离传输过程中,并且是远距离传输所必须的。Rt的标准阻值是100~120Ω。 附录G:共模抑制 用两根线之间的电压差来代表逻辑电平,这两根线称为双绞线或差分对(different pair),两个信号振幅相等、相位相反,当出现噪声时,双绞线同时受到干扰,于是两根线之间的电压差几乎没有变化,这种现象又称为共模抑制。 Modbus (OSI7/OSI2) 1. 简介 Modbus是由Modicon(施耐德)公司于1979年开发、用于PLC通信的一主(客户端)多从(服务器)式通信协议,在工业环境中应用广泛,现已成为事实上的业界标准。实现方式有:TCP/IP、串行通信(EIA/TIA-232-E, EIA-422,EIA/TIA-485-A等)和高速令牌网络Modbus PLUS。 Modbus使用功能码来指定请求内容/应答结果, 2. Modbus over serial line 2.1 Master/Slaves protocol principle Only one master (at the same time) and 1 to 247 slaves nodes are connected to the bus. Slave nodes will always waiting for the master initiated a request and then response, slaves nodes can't comm with each other. The master initiated only one MODBUS comm at the same time. The master initiated a request in two modes - Unicast and Brodcast : Unicast : the master addresses an individual slave, after receiving and processing the request, the slave returns a messate to the master Broadcast : the master addresses all slaves and no response from slaves 2.2 Address rules 0 for broadcast, 1~247 for indeividual slaves and 248~255 are reserved. The address must be unique at the same Modbus serial line, and the master has no specific address 2.3 Frame description Protocol Data Unit (PDU) = Function code + DataApplication Data Unit (ADU) = Slave Address + Function Code + Data + CRC/LRC Slave Address : For master to address a slave, for slave to indicate who it is Function Code: For master to indicate what kind of action to perform, a slave set the same code when comm normally and set the code + 0X80 when exception occured Data : The field can be empty or set request/response parameters of function code CRC/LRC : Error checking field of ADU (exclude CRC/LRC) 2.4 Two transmission modes RTU(Remote Terminal Unit) mode (default and must be inplemented) and ASCII mode (optional) 2.4.1 RTU transmission mode The format(11bits) for each byte in RTU mode:Coding system : 8-bit binaryBits per Byte : 1 start bit, 8 data bits (LSBit sent first), 1 bit for parity (Even is default), 1 stop bit (if no parity is selected, 2 stop bit is needed) Frame ADU (256Bytemax) = 1 Byte Slave Address + 1 Byte Function Code + 0~252 Bytes Data + 2 Bytes CRC 2.4.1.1 RTU message framing External of frame : There is no obvious frame boundary in RTU mode, so timing is required. Message frames are separeted by a silent interval of at least 3.5 character times (t3.5). Internal of frame : The entire message frame must be transmitted as a continuous stream of characters, if a silent interval of more than 1.5 character times (t1.5) occurs between two characters, the message frame is declared incomplete and should be discarded by the receiver. Remark:t1.5 and t3.5 implement will cause a heavy CPU load when high comm baud rates is used, so when baud rates 19200Bps 750us and 1.75ms is used for t1.5 and t3.5 2.4.1.2 Communication logic Device (master/slave) power on and start t3.5 loop to receive incomplete frame until expired then turns to IDLE state, frame receive or emit will be performed (only) from IDLE state. If demand of emission is command, t3.5 loop is started until expired then turns to IDLE state If demand of reception is command, t1.5 and t3.5 loop is started when the first character received until t1.5 expired, frame will be checked (CRC, Parity and Slave addr) meanwhile, then the flag will be set (OK or NOK) until t3.5 expired, frame will be deleted if it's NOK or will be processed if OK Note : t1.5 or t3.5 loop means that tn will be init by each character until time-out 2.4.1.3 CRC Checking The CRC field checks the entire message (ADU exclude CRC and except parity bits), CRC filed conttains 2 Byte values and low order byte is sent first 2.4.2 ASCII transmission mode TBD 1 加密狗 1.1 Introduction 加密狗又称加密锁,是用于软件加密的、软硬件结合的加密产品。其内置非易失性存储器或嵌入式系统,用于与上位机软件交互通讯以实现防止软件被非法使用的加密目的。含并口(早期)和USB接口样式。 1.2 分类 早期加密狗以并口和并口接口卡形式出现,现代加密狗多为USB接口,外形似U盘: Dongle type 市场上以序列号认证使用软件的方式也是软件加密的一种形式,但通常不称为加密狗。 1.3 原理 上位机运行的软件必须与加密狗通讯才能正常运行,其本质就是通过各种手段来实现软硬件安全交互通讯和捆绑运行。 Dongle runing 生产加密狗的厂商对加密狗进行硬件设计和算法编程,软硬件的质量决定了加密狗的价格。软件厂商对加密狗设置算法因子,以使得每一个软件厂商的加密狗对外都是安全的。常见的加密狗算法有AES、ECC、RSA、DES、3DES等。 1.4 设计DIY 1.4.1 硬件设计 最简单的加密狗内部至少需要一个非易失性存储器,通过向其写入固件,在上位机软件运行时不断读取该固件来实现简易的加密。 Dongle DIY 为增强安全系数,现代加密狗内部都是由处理器、存储器等组成的嵌入式系统。AVR单片机的智峰USB_ISP烧录器内置AVR_ATMEGA8处理器,是一个比较稳定的电路结构,其外形和加密狗相似,通过对该烧录器进行固件改造即可成为加密狗。 1.4.2 软件设计 //TBD 1.5 品牌排行榜 品牌 公司 接口 算法 圣天狗 赛孚耐/SafeNet(美) USB、并口 AES/ECC/DES Hasp HL 阿拉丁/Aladdin(以色列) USB AES/RSA 深思洛克 北京深思洛克 USB RSA/3DES 飞天诚信 北京飞天诚信 USB RSA/3DES HTTP 之TCP/IP 拆包与粘包 在网络中的信息经常会被拆分路由,分片传送到接收端,特别是对于大文件传输。 于是在接收端一次调用recv往往不能接收到完整的数据 所以,一个循环的recv接收必须使用 char buf[10000]; char *p = buff; while ( true) { int recvBytes = recv(fd, p, sizeof(buff), 0); p += recvBytes; //将包粘接 } 但是这里存在一个问题:如何知道对方发送结束??? recv表现的行为是:返回值-1是错误,返回值0是对方关闭,返回值大于0是接收的数量,且默认是阻塞的,所以如果对方不关闭且我方不出错, 那么将一直阻塞下去,不会退出循环。 有一个好的解决办法就是预先知道对方一共要发多少,那么通过循环接收累计接收的字节数,接收到了就不循环了-退出 char buf[10000]; char *p = buff; int size = 0; while ( true) { int recvBytes = recv(fd, p, sizeof(buff), 0); size += recvBytes; if ( size >= 1234) //双方约定的本次发送的字节数 { break; } p += recvBytes; //将包粘接 } 那么如何确定双方约定的发送字节数呢? HTTP头部信息有一个content_length,这个表示整个HTTP信息中body 的信息(即不包含line和所有header) 一般情况下,HTTP头部信息很小,所以不会被分包,所以先收头部信息,再将剩余的收完 如果担心HTTP头部也会被拆包,那么就一个一个字符读,一直读到\\r\\n\\r\\n,那么头部就读完了,然后将其content-length取出,循环读取剩下的信息即可 char buf[10000]; char *p = buff; char c; while ( true) { int cnt = 0; while (true) { if ( 1 == recv(fd, &c, 1, 0)) { *p = c; p++; //无论如何都要将读到的存储到buff switch ( cnt ) { case 0: if ( '\\r' == c) { cnt++; } break; case 1: if ( '\\n' == c) { cnt++; } break; case 2: if ( '\\r' == c) { cnt++; } else { cnt = 0; } break; case 3: if ( '\\n' == c) { cnt++; } break; } if ( 4 == cnt ) break; } } //略:解析buffer, 拿到content-length while (true){ int recvBytes = recv(fd, p, sizeof(buff), 0); p += recvBytes; //将包粘接 if ( recvBytes == length) { break; } } } 特别要注意的是,在客户端和服务器都是在本地的话,数据包是不经过路由的,所以会看到可以一次性接收大文件,所以测试还是要将服务器和客户端放在不用的网络中(可以是局域网) 关于MOdbus-RS485通讯时序问题: 关于Modbus-RS485的时序问题:使用RS232和全双工RS485时不存在额外的时序问题,但使用单双工的RS485时可能存在时序问题:既然是单双工,就存在信号方向切换动作,不同的RS485芯片(或芯片组)切换速度不同,主要问题就是这里引起的:假设主机RS485芯片每次切换信号方向时长为T1、从机RS485芯片每次切换信号方向时长为T2,则主从通信时主机发送消息后等待接收(设超时为T3),如果从机处理时长T4+T2T3,那么主机就按超时处理:所以应 T4+T2>=T1, T4+T2 T1 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/hardware/PCB.html":{"url":"pages/hardware/PCB.html","title":"PCB","keywords":"","body":"1 PCB Foundation 1.1 Concept PCB (Printed Circuit Board) 印制电路板,简称电路板。PCB是电子元器件的电气连接载体和支撑体,在20世纪50年代开始推广,是现代广泛采用的集成电路构建技术。 Tips : Appendix-A Ancient circuit construction mode 1.2 Structure PCB consists of Solder mask, Medium, Copper and Silk layer. 阻焊剂常呈绿色,覆盖于PCB上下表面以阻止被保护电路被焊接,丝印层于阻焊层之上用于描述元件、备注等信息,铜层是PCB的核心,表铜层覆盖于阻焊层之下,内铜层以介质层分隔,各层之间通过过孔通信。 Tips : PCB铜层厚度以盎司Oz为单位,1Oz = 35um,常规规格为1Oz,另有2Oz、3Oz等。介质层由FR-4等级的环氧树脂、玻璃纤维和填充剂复合而成。 1.3 PCB Design Schematic layout and PCB layout are the core of PCB design,schematic uses nets to describe connection of circuit component pins and PCB uses the nets to generate pin-index to guide wiring. Tips : PCB设计的重点是电路和电磁兼容性的设计,本质是对模电、数电和电磁理论的运用。设计软件本身并不重要。 1.3.1 Schematic & symbol Schematic layout is the first step of PCB design and which is consists of symbols and net. symbols are abstractions of components with the same number of pins and nets indicates electrical connection between symbol pins. Symbols are stored in symbol library and can be created in software. Simple design steps in schematic layout : 1-circuit design, 2-select/create symbols, 3-nets connection. Tips : It is feasible to design PCB directly without schematic, but it will make PCB design difficult. In addition, schematic diagram is very important for software engineers 1.3.2 PCB & footprint PCB layout is the second step of PCB design and which is consists of footprint and wiring. footprints are graphical components with accuracy data info (package mode and size, pin spacing and LxWxHxD, etc) and wiring is the realization of (schematic) nets, it's a visible connection on the surface of PCB. Footprints are stored in footprint library and can be created in software. Simple design steps in PCB layout : 1-data set (wire width and spacing, drill diameter and spacing), 2-size and shape design and component palcement, 3-Wiring, 4-copper filled, 5-set origin and auxiliary flags Tips : The placement of components directly affects the difficulty of wiring that use layers and drills (note : both sides can be used). 1.3.2.1 Layer The concept of 'layers' in software is not exactly the same as that actual PCB and there are different names and types in different software and some layers are not real layers, such as 'mechanical layer' in Altium Designer and 'graphic x' in KICAD, all of these layers are auxiliary. Only silk, solder mask and copper layers are unified and correspond to reality one by one. Copper layers can be used as signal, GND or PWR, common design scheme as below : layer Nu copper scheme 1 scheme 2 scheme 3 1 F.Cu MIX - - 2 F.Cu MIX SIG+PWR GND B.Cu MIX GND SIG+PWR 4 F.Cu SIG SIG PWR In1.Cu PWR GND SIG In2.Cu GND PWR SIG B.Cu SIG SIG GND 8 F.Cu SIG SIG SIG In1.Cu GND SIG GND In2.Cu SIG GND PWR In3.Cu GND SIG SIG In4.Cu PWR SIG SIG In5.Cu SIG PWR GND In6.Cu GND SIG PWR B.Cu SIG SIG SIG Tips : Power layer can mix signal wire if necessary, but try to keep GND layer clean. 1.3.2.2 Drilling Drilling is the electrical hub between PCB layers, including Through, Blind, Buried and Macro type. 1.3.2.3 NetList Netlist is a text file with the content about 'nets' generated by the schematic automatically, it's also the hub for transition from schematic to PCB layout. 1.3.2.4 Copper filled Copper filling objects are GND, PWR and other special nets on EACH LAYER to reduce the loop area and improve PCB performance. Copper filled comparison of 4 layers PCB Tips : Island copper filling is not allowed, connect to GND if it exist, otherwise, some unpredictable problems MAY arise. Note : Dense drilling affect the effect of copper filling. 1.3.3 Gerber, BOM and Drill Files Gerber is an international standard format for describe PCB images, which provides data for each process of PCB maker. Drill files is extracted from Gerber for describe position, size and type of drillings. BOM-Bill of Material for describe PCB components and properties. Tips : *.pcb file can be provided directly to PCB maker, but some unpredictable problems MAY arise. 1.4 PCB standard IPC standard is an international PCB standard about the whole life cycle of PCB. Official website IPC standards tree 2 PCB Electromagnetic compatibility 2.1 Concept EMC (Electromagnetic compatibility) 电磁兼容性,用于描述设备或系统在电磁环境中抵抗干扰 (EMS-Electromagnetic susceptibility 电磁耐受性) 和释放干扰 (EMI-Electromagnetic interference 电磁干扰) 的特性. 2.2 Source 分布式电容、分布式电感、脉冲噪声、PCB天线、静电等辐射发射和传导发射源是电磁干扰的主要来源. 分布式电容 : 非电容态的形式电容,PCB上下层和同层导线可能产生的电容效应,影响高频电路。 分布式电感 : 非电感态的形式电感,PCB导线和元件的分布可能产生的电感效应,影响高频电路。 干扰源: 1. I/O 2. 电源 3. 辐射 2.3 Tactics Copper filling, GND separation (for signal layer), 3W wiring (for same layer) & 20H, Cross wiring (between layers), Open-loop check, Resonance rules, Short line rules (for special signal, such as clock signal), Power overlap rules, Angle rules (acute and right angle are not allowed), Same type - Same side, Same type - Same layer and Less drilling .etc. 3W and 20H Cross wiring Angle Open-Loop Responance 2.4 Impedance TBD 3 PCB design software 3.1 KICAD Refer to KICAD Official website 划线时按住Ctrl,可以走垂直、水平和45度角线 KICAD中的\"点\" 辅助轴原点,又称\"钻孔/原点\" 网格原点,又称“本地坐标原点\" KICAD中的网格,每一个点又叫Achor锚点 以上三种点,在精确放置元件时都可以利用到,KIACD快捷键是Ctrl+M,此时可以输入XY坐标,并相对于以上三种点, 在移动元件时(只是用M快捷键)只能按网格的最小单位捕捉吸附移动,如果想移动在两个网格点中的位置,那么只能增大网格密度 ,但也未必能放到想要的位置,因为网格密度也有限,所以通过输入XY坐标可以精确移动到非网格点的任意位置 ,相对于以上三种任意一种都能做到相对精确位移 层对齐标记 注意 KICAD中执行电器规则检查(EMC)时可能在电源引脚处报错(引脚连接其他引脚,但不受任何引脚驱动),根据官方文档,可以给地与电源标记为PWR_FLAG(即地连接PWR_FLAG、VCC/+24V/+15V或其它电源等也要与PWR_FLAG连接),PWR_FLAG可以在KICAD的电源中寻找。 3.2 Altium designer Refer to Altium Official website 知识点 可以从已有的PCB文件中导出封装库 Error 打开DXP中的原理图,生成PCB时出现“Footprint not found” 和 “unknown pin”的错误,后者的解决方法:首先切换到PCB设计界面,1)设计-》网络表-》清除所有网络 2)设计-》类-》Component classes 找到PCB名,右单击删除类 3)将当前的PCB文件删除,重新建立一个。前者的错误,没有找到原因,解决方法是在原理图中将出现问题的元件删除,重新放置一次 网络标签要贴近画的“线”而不能贴近引脚的线,否则PCB中将不显示飞线 关于器件摆放的心得 可以参考原理图,了解元件的作用,比如电容、电阻等元件,有些电容和电阻从哪些引脚引出的,是可以直接看到的,因此这些元件就要离这些引脚很近,以此类推,所有元件就有摆放位置了。然后是翻转、排版和正反面选择。所以摆放元件的第一步并不是上来就摆好,而是相关的元件先放到一起,然后再一个单元一个单元摆放 因此可以先摆放IC元件,然后将连接其引脚的电容、电阻等找到,最后排版 元件之间不能摆放的太密集,因为到布线的时候常常要在元件周围打过孔 在画原理图的时候,对元件的命名,尽量按顺序,比如U1、U2两个元件周围都有很多电阻和电容,U1使用的电阻和电容可以命名为:C1、C2、C3...、R1、R2、R3...,U2也是同样排序,而不是U1使用C1、C3、C18,在U2中又使用C2、C9、C5...。这样做的好处是1)方便维护,2)画PCB时,对摆放元件步骤很有帮助,你可以将U1的周围元件很快找出来并排列好。 元件命名还可以“批次化”,比如一个板子只有三个同样的IC,实现的功能和引脚都是一样的,则将U1使用的电阻命名为C1、C2、C3...,而U2中与U1同样位置的电阻命名为C11、C12、C13...。以此类推.这样在元件摆放时非常方便 同一类型元件尽量摆在一起,并且尽量方向一致(如二极管),这样方便维护和避免手工安装元件出错 发热元器件远离IC,并且要适当加大彼此间隔 丝印文字适当大小,并且尽量保持方向一致 输入输出引脚两侧对向放置 电源线和流经大电流的线要比信号线宽 在PCB布线时,如果有布不通的时候,也可以在原理图上做更改,然后更新到PCB;比如原理图上引脚顺序的变动对实际布线有很大的影响。 引脚第一针脚绕PCB按顺时针或逆时针放置,并且防呆接口的内外朝向要一致 电机驱动线1~1.5mm, 电源线可以更宽,一般信号线0.25即可。线间距0.3,边缘切割层线宽0.1mm 尺寸标注(是指标有N的工具),要选中.CrtYd层时绘制才有效(类似边缘切割层,一定要先切换到该层再绘制,绘制好之后再切换到同层时还会保留) 芯片封装,一定要搜索芯片的全称手册,否则封装可能不同,比如CD4051B和CD4051BM就是两个尺寸的封装 宁可走直角也不要走锐角 电源线宽度尽量全图一致 关于引脚Jx 引脚在排列时,一排或一列的第一个引脚方向要一致(并且按顺时针或逆时针顺序走),这会为调试、使用者提供极大的方便。如果这样放置对布线增加了复杂度,那么就在原理图中重新定义引脚排序 输入引脚与输出引脚尽量分开排列,尽量在对立方向,比如一个驱动板,左面是主板输入信号的引脚,右边是输出信号驱动电机的引脚,这样分开有助于施工人员的现场布线, 也对抗干扰有一定的帮助 电源插座靠边放 为PCB生产而准备 PCB画好之后,就要开始生产,多数PCB厂家都支持GERBER文件,也有厂家可以直接支持原图, 工艺边 如果需要SMT流水线焊接,那么你的PCB可能要加工艺边,加工艺边的目的是可以使你的PCB在机器上能加工,如果PCB元器件距离边界小于5mm,那么就需要加工艺边了,工艺边就是非电路板使用部分,只是为了生产而已,工艺边一般5mm。 另外,如果是不规则PCB,那么一定要加工艺边。如果规则图形一侧小于5mm,一侧大于5mm,那么一侧加工艺边就行,其实本质就是保证: 如果用SMT焊接,就需要加工艺边,目的是保证有一个平行边有5mm的宽度。 https://www.baidu.com/link?url=OEkEeqMCxsRNze53BxBp2DuqYH3c_QmaseOp2MepW_ZaYMr8LwuTud8Q3bXAdz9WH9pFl1Jskmv8aq9VKqjfM7akkxXoZZP8Ighbwy-8zja&wd=&eqid=936cd9620009cd2d000000065faf5f93 mark点 mark点也是为SMT焊接准备的,用于光学定位,有局部mark点,全局mark点,另外工艺边上一定要加mark点 KiCad中的mark点封装为Fiducial 详情参考:https://www.cnblogs.com/zhiqiang_zhang/p/11179605.html https://blog.csdn.net/longkousong/article/details/83689873 定位孔 定位孔是工艺边上,用于定位使用的机械孔 Vcut和邮票孔 如果需要自己拼板(拼板的目的是为了批量生产PCB,节省成本,因为做PCB有最小面积需求,小于最小面积都是一个价格,类似快递首重,所以要一次生产同样的多个板或者不同样的多个板子,那么就需要拼板),那么每个板子之间可以用Vcut槽或邮票孔,Vcut槽就是两个板子之间一条V沟壑的槽,等PCB生产回来之后 可以轻松分开使用,邮票孔也是同样的道理,将板子的连接处打上一条小孔,就减少了板子之间的连接力度,也是为了方便掰开,能用Vcut尽量用Vcut,Vcut比较整齐,但有些情况Vcut,因为大多数厂家对Vcut有要求:比如PCB的厚度、板子之间要“一条线”等等(一条线就是从A到B,A和B是必须是两边,中间不能有PCB),这时邮票孔就派上用场了。 邮票孔一般没有限制,但实际试用时 掰断有凹槽,影响美观。 https://bbs.21ic.com/icview-2578974-1-1.html https://jingyan.baidu.com/article/d71306357f850b52fdf475de.html https://www.bilibili.com/video/BV1xZ4y1x7Cy 拼版 拼版(PANELIZING) 拼版目的是为了一次生产多块同样的或不同的PCB(PCB厂对于面积是收费标准之一,像快递的首重一样,没到首重算首重,PCB面积也是一样,没到一定面积收这个面积的钱,所以一块一块生产显然是不划算的,不如拼凑在一起当成一个PCB来处理),每块板子之间通过邮票孔或者Vcut连接,这时每个单独的一块板都不需要工艺边了,而是将整个拼好的板子加上工艺边。 另外,如果是SMT贴片的,还需要在拼版的工艺边上加上mark点。 参看:https://jingyan.baidu.com/album/d71306357f850b52fdf475de.html?picindex=1 https://hackaday.com/2019/03/12/panelizing-boards-in-kicad/ 拼板与工艺边: https://www.baidu.com/link?url=J83m2_be7l97nUT1i4_2-OZd_n64jpUlMtXRKfCbBA8AlAuas0TsmHLQzIwwlwFN&wd=&eqid=c1e946ff0005b3a9000000065fafa78b 4-1 : kicad拼版 1. 从电脑中独立启动PcbNew(注意:不能从工程中启动,要独立启动,比如windows下的开始中可以找到PcbNew,实际上PcbNew、Schema等都是KICAD的独立程序) 2. 点击设置电路板,进行图层数量、层勾选(如果参与拼版的PCB铜层数量相同就好办,还没试过铜层不同的,那应该与最多层的一致) 3. 点击菜单栏“文件->添加PCB”,选择要拼版的PCB(在其它的KICAD工程中已经画好的PCB),并添加,反复如此添加所有要拼版的PCB 注意:添加好之后每个板子之间会出现若干飞线,最起码有GND飞线,这是KICAD认为这些同名的点是电气相通的,不用理会,隐藏飞线即可 4. 每一种板 都可以选中(选中该板)后右单击,然后选择“重复”(这个类似复制一次)或者选择“创建阵列”(复制成 成行成列的)来创建多个副本,按需求创建,然后将所有板子排列好。板与板之间可以用邮票孔或者Vcut槽链接,板与板之间的距离根据邮票孔或Vcut或实际情况来确定。 邮票孔一般成两排,但每排长度根据实际情况确定,小板子拼接排长就短一点,否则就长一点 5. 以上步骤都是建立在每个板子都没有加工艺边的情况,因为要拼版生产,对单独一个板子加工艺边就根本没有必要了, 所以现在要对整个拼板加工艺边,工艺边与拼好的板子之间也可以选择用邮票孔或Vcut槽,工艺边宽度5mm,如有必要则在每个工艺边上加定位孔,如果要机器SMT贴装则还要在工艺边上加mark点 注意:有些PCB厂家支持给用户拼版的,只需提供GERBER文件(或原图)。PCB厂家按最小面积或最指定量来生产,比如100平方mm是最小面积,你的板子是10个平方mm,那么默认就给你做10块,你给了gerber之后,注明最小面积,自由拼板,厂家就给你做出来了。 自由拼板(不管是几种不同的还是相同的)省心省力,缺点是PCB厂可能不会按照最节省的方式拼接,同样是拼图,有省面积的方法,也有浪费的方法,PCB厂肯定不会考虑这些,他们应该考虑最高效的拼接方式。所以 如果你的板子 对于不同的拼接方法 会有很大面积的节省(也就是可以多产出很多板子),那么就自己拼,否则就让厂家搞定就好了。 最终成品参看:https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=PCB%E6%8B%BC%E6%9D%BF&step_word=&hs=0&pn=40&spn=0&di=40920&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=1613643730%2C4136934760&os=732104247%2C3610206982&simid=4219698652%2C964665625&adpicid=0&lpn=0&ln=594&fr=&fmq=1605346003639_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fimg-blog.csdnimg.cn%2F20181103192314204.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_ZmFuZ3poZW5naGVpdGk%2Cshadow_10%2Ctext_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xvbmdrb3Vzb25n%2Csize_16%2Ccolor_FFFFFF%2Ct_70&fromurl=ippr_z2C%24qAzdH3FAzdH3Fks52_z%26e3Bvf1g_z%26e3BgjpAzdH3Fs5g2h57f5g2AzdH3Fw6ptvsjAzdH3F1jpwtsfAzdH3Fbnmblb0n&gsm=11&rpstart=0&rpnum=0&islist=&querylist=&force=undefined https://image.baidu.com/search/d l?ct=503316480&z=0&ipn=d&word=PCB%E6%8B%BC%E6%9D%BF&step_word=&hs=0&pn=54&spn=0&di=28930&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=172591740%2C1824188642&os=2235375691%2C4158812490&simid=3413606615%2C358575057&adpicid=0&lpn=0&ln=594&fr=&fmq=1605346003639_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fwww.51wendang.com%2Fpic%2Ffb3f043f8502a102e4b0803a%2F1-471-png_6_0_0_0_0_0_0_892.979_1262.879-893-0-0-893.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bc8ojg1wg2_z%26e3Bv54AzdH3F15vAzdH3Fuknua9nubcadw8adj9kabanw&gsm=11&rpstart=0&rpnum=0&islist=&querylist=&force=undefined https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=PCB%E6%8B%BC%E6%9D%BF&step_word=&hs=0&pn=30&spn=0&di=11220&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=1526030979%2C1507801258&os=732008947%2C1231645015&simid=0%2C0&adpicid=0&lpn=0&ln=594&fr=&fmq=1605346003639_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180914%2F776d959fe8be47cfa282813597610b02.jpeg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bf5i7_z%26e3Bv54AzdH3FwAzdH3Fdcnbmbmcl_0l8a8n&gsm=1e&rpstart=0&rpnum=0&islist=&querylist=&force=undefined 注:工艺边是因为SMT工艺存在的,如果你的板子不需要(SMT)机器上锡并且不需要(SMT)机器焊接,那么就不需要工艺边,换句话说,裸板生产是不需要工艺边的。 Dumor邮票孔参数:长6.4mm 宽(两排邮票孔之间)1.55mm,两排,每排7个孔 (整个宽度【含孔】推荐2mm) 拼版有两种方向:第一是通过将PCB在绘图中拼凑, 第二个是通过特别的软件将不同的gerber文件拼成一个gerber(较少用)# AD18 小技巧&快捷键 原理图 PCB shift + s,2阶淡退非相关层,有助于看清当前层元素,如焊盘和飞线,连续按三次恢复淡退。 Li PCB总结(+15V/+24V驱动板) 线宽 混合线宽,24V电源线多种规格:80mil、60mil和30mil等。80mil的24V电源线呈总线形式贯穿(从左到右)PCB,支线电源线宽有60、30、20等。向芯片提供电源的线相对比较窄,向输出(引脚)提供的电源的线相对较宽。部分信号线 线宽最终的依据是经过的电流大小,电流越大线宽要越宽。 地线是回流的,所以也要根据电流大小设定粗线,另外对GND覆铜也相当于增大了宽度。 线间距 6mil 8mil 10mil,一般使用8或10mil 孔 孔大小无需严格,一般可选16、28、30mil等规格,太大的孔对走线有影响,尽量小孔 对于很宽的线,可以打多个小过孔以建立更好的电气连接、承载更多的电流 GND层之间可以多打一些空,如果有位置的话,目的也是为了更好的电气连接 IC下面打孔和走线是允许的,不会产生影响,而且可以节省空间 一面上的线不能呈锐角和直角,但过了孔就无所谓了,可以是直角锐角 分支线 从A点引线要走到B和C,较好的走法是从A到B再到C或从A到C再到B,而不应该从A走到一个点,然后分岔路给B和C 相同的器件尽量朝一个方向摆放,以方便维护,也防止焊接出错。(宁可走线麻烦,也朝一个方向放) 适当的手动增加一些丝印,特别是对于引脚,这样在使用时可以直观看到功能,而不用去看图纸了。 板子是否引出地,连接机器外壳? 主板可以,相当于无形的增加了覆铜面积,增大了抗干扰能力 对于驱动板等大功率板,尽量不要,因为它们要与主板在一起工作,它们的回流地可能会通过机壳影响主板 留边 不要太靠边界,可能导致器件、引脚不牢固等问题 Ctrl+D调出视图,在这里可以隐藏、显示视图,如覆铜等 Appendix-A:Ancient circuit construction mode A.1 快速构建 这是一种非常草率的方法,只对构造极其简单的电路原型有用。它通过在任意大小的空间里把元器件焊接在一起来构成非常简单的电路。 如图,将晶体放在处理器上方,晶体引线直接焊接到处理器引脚,其它引线也焊接到处理器引脚来引入电源和接地从而把处理器的I/O和外部连接起来。 A.2 面包板 面包板又称电路实验板,是带有排列孔的塑料/铁/磁块儿,它被设计用来盛放DIP封装(双列直插封装)的集成电路和离散元器件。术语“面包板”可追溯到真空管时代,当时真空管无线电设备是建立在一块用于切面包的结实木板上的,因此得名。 使用面包板也不是搭建健壮可靠系统的方法,面包板限制于过多的电容、串扰及噪声敏感度,长期使用后还有机器故障。面包板上的电路连接是通过一段段小的电线来实现的,而这些电线构成了小的天线,这些小天线会吸收周围零散的电磁辐射从而影响电路。 A.3 绕接技术 绕接曾经是常用的电路构建技术,必须是DIP封装的电路才能使用绕接,它通过约0.6英寸的引脚安装在插座上,然后用绕砸工具(绕砸器和剥线器)在引脚周围绕上电线,这样便构成了一个电路,这也被称为冷焊技术,即不带焊接的一种线与引脚间的紧密电气连接技术。 绕接是一种非常快速的原型技术,且健壮和可靠。在早期,NASA(美国国家航天局)惯于使用绕接技术构建宇宙飞船电子设备,并且许多大型计算机也使用这种技术。 Appendix-B:PCB process B.x 焊接 PCB元件焊接有回流焊和波峰焊两种方法,回流焊是贴片元件焊接的一种低成本方法:将钢网抠刻出与欲焊接的PCB元件的位置和大小相同的区域,然后将PCB与铁网固定并刷锡浆,同时人工放置元件以完成焊接;使用SMT自动贴片机可高效完成贴片元件焊接,但成本较高。波峰焊是插件元件焊接的方法:PCB插装元件后经过锡炉即焊接完成,并通过剪脚机将管脚剪短。 Appendix-C:PCBA and ICT C.1 Concept PCBA(Printed Circuit Board +Assembly)又写作PCB’A,是指对PCB空板的装配过程,也指通过该过程生产的成品印刷电路板。PCBA测试是对完成焊接的PCBA板进行程序烧制和有关通路、环境、电压、电流、压力等方面的测试,是PCBA加工过程中的一个重要环节,处于生产工序的末端,是严控出货品质的重要手段。 C.2 PCBA测试方式及PCBA测试架 小批量生产的PCBA可以借助专业测试设备或手工万用表的方式对测试点检测,对于大批量生产的PCBA测试则要使用测试架(Fixture)来辅助完成。PCBA测试架又称PCBA测试治具,其原理是通过测试顶针与PCB板的测试点连接,从而获取电路中的电压、电流等关键数据,并在测试架的显示屏幕上显示,达到快速检测的目的。客户在设计PCB板时,就应该考虑其测试方案并预留PCB测试点,然后出具专业的测试文档或测试方案给制造商。 制作PCBA测试架要提供的文件。 C.3 测试分类及原理 PCBA测试的方法主要包括:ICT测试、FCT测试、老化测试、疲劳测试、振动测试、高低温测试。 C.3.1 ICT测试 - 导通性测试 ICT (In Circuit Test) 又称在线测试仪,ICT测试主要是通过测试探针接触PCB的测试点 (ICT测试点) 来检测线路的开路、短路以及PCBA板上元器件的焊接情况(不涉及到功能按键或者输入输出方面的测试)。ICT测试具有操作简单、准确性高的特点。一些中低端的PCBA板可专门制作ICT测试治具,可有效的降低测试成本。 C.3.1.1 ICT测试对PCB设计的要求 PCB对角上需设计两个125MILS的非金属化的定位孔,并且每个网络都至少有一个ICT测试点,测试点可以是PCB焊接面的焊点或过孔,检测点的焊盘尺寸最小为24mils (0.6mm),两个单独测试点的最小间距为60mils (1.5mm)。 C.3.2 FCT测试 - 功能性测试 FCT测试由又可称为PCBA功能测试,是指对目标内部功能的测试,可对测试目标提供模拟的运行环境(激励和负载),使其工作于各种状态之中,以测量输出端的参数是否符合要求。测试的内容主要包括电压、电流、功率、功率因素、频率、占空比、亮度与颜色、字符识别、声音识别、温度测量、压力测量、运动控制、FLASH和EEPROM烧录等。 C.3.3 老化测试 老化测试是指对PCBA板进行长时间的通电,进行输入输出方面的测试,模拟用户的操作,以确保其性能符合市场的要求。 C.3.4 疲劳测试 疲劳测试是指对PCBA进行高频、长时间的操作,观察是否出现失效,判断测试出现故障的概率,以此来检查PCBA板的工作性能。 C.3.5 震动测试 震动测试采用专业的震动测试仪进行长周期测试,确保焊接元件无任何脱落情况出现,抽样测试比例根据客户要求决定。 C.3.5 高温测试 高温测试是指将PCBA放入测试房,并针对性地提供-40℃至100℃等常见温区的测试服务,充分模拟产品的环境温度,最大化确保产品的可靠性。 C.4 PCBA测试材料与价格 C.4.1 测试探针 目前测试探针分国产、台湾香港、进口三种。进口产品一般是德国、美国、日本的产品,品牌有INGUN、TCI、日电、华荣、中探、亚探等。测试探针的质量主要体现在材质、镀层、弹簧、套管的直径精度及制作工艺。目前包括国内的产品其材质很多用进口材质,所以除非是偷工减料一般探针材质问题不是很大,针及套管的直径精度方面国内与台湾香港的产品差不多,进口稍好但一般影响不大,弹簧及镀层的质量这方面进口产品比国内要好很多,台湾香港产的比国内稍好一些,原因主要是工艺水平上的差别,国产的探针镀层抗磨损较差镀层容易脱落。如果制作的测试治具使用时间及测试次数超过15万次以上选用进口产品较为合适,但进口的探针价格较贵。目前国内的制作水平和工艺逐步提高,并且在当前价格大战的情况下,不少代理商用国产针冒充进口或台湾产的探针出售。如果测试要求和测试次数不高的话建议可选用国产探针。探针的质量主要对测试治具制作中的测试次数及接触是否良好有关。 C.4.2 测试线 目前测试线都是国外进口或台湾香港地区生产,其产品的区别不大。价格为约125元一卷。 C.4.3 测试板材 测试治具中所选用的板材一般有压克力(有机玻璃)、环氧树脂板等。普通的探针孔径大于1.00毫米的治具,其板材以有机玻璃居多,有机玻璃价格便宜,同时有机玻璃相对较软钻孔时有胀缩探针套管与孔的结合紧密,由于有机玻璃是透明的治具出现问题检查十分容易。但是普通的有机玻璃在钻孔时容易发生溶化和断钻头,特别是钻孔孔径小于0.8毫米时问题很大,一般钻孔孔径小于1毫米时都采用环氧树脂板材,环氧树脂板材钻孔不容易断钻头其韧性及刚性都好但价格较贵一些,环氧树脂板没有胀缩所以如果钻孔孔径不精确会造成探针套管与孔之间很松动产生晃动。环氧树脂板不透明如果治具出现问题检查较困难一些,另外有机玻璃温差变形比环氧树脂板大一些,如果测试的密度非常高的需采用环氧树脂板。板材的选用及钻孔的精度对整个测试治具的精度起关键的作用。 治具的底座大部份是用PVC或有机玻璃制作的,大部份的厂家制作治具底座时是根据测试板材的大小临时制作的,所以底座的质量及底座的重复使用率不是很好,所以建议统一底座大小及标准,本网站提供二种标准的底座可适用大部份的专用测试机,其材料采用20毫米的有机玻璃,由有机玻璃厂家制作质量及工艺非常好,可重复使用,价格虽然稍贵但物有所值。 Appendix-D:Common component packaging Class Type Name Picture Footprint 3D surface mount BGA/PAC Ball Grid Array BGA BGA surface mount QFP Quad Flat Package LQFP LQFP surface mount SOT Small Out-Line Transistor SOT SOT surface mount SMD Surface mount devices SMD SMD surface mount / inline SOP/SO Small Out-Line Package SOP SOP surface mount / inline TO Transistor Outline Package TO TO inline SIP single in-line package SIP SIP inline AXIAL - AXIAL AXIAL inline DIP/DIL dual in-line package DIP DIP Binding COB Chip On Board - - Appendix-E:HUAWEI PCB design specification Standard : China GB/T 4588.3-2002 & IPC-2221 E.1 布局规范 遵照“先大后小,先难后易”的布置原则,即重要的单元电路、核心元器件应当优先布局 IC器件布局时,栅格应为50--100mil. 小型表面安装器件 (如表面贴装元件) 布局时,栅格设置应不少于25mil 同类型插装元器件在X或Y方向上应朝一个方向放置。同一种类型的有极性分立元件也要力争在X或Y方向上保持一致,便于生产和检验。 发热元件要一般应均匀分布,以利于单板和整机的散热,除温度检测元件以外的温度敏感器件应远离发热量大的元器件 元器件的排列要便于调试和维修,如小元件周围不能放置大元件,需调试的元器件周围要有足够的空间 BGA封装元件与相邻元件的距离应>5mm,其它贴片元件相互间的距离>0.7mm。贴装元件焊盘的外侧与相邻插装元件的外侧距离>2mm;有压接件的PCB,压接的接插件周围5mm内不能有插装元、器件,在焊接面其周围5mm内也不能有贴装元、器件 E,2 布线规范 E.2.1 布线优先次序 关键信号线优先:电源、摸拟小信号、高速信号、时钟信号和同步信号等信号优先布线 密度优先原则:从单板上连接关系最复杂的器件着手布线,从单板上连线最密集的区域开始布线 E.2.2 PIN密度与层的关系 PIN密度的定义为 : 板面积(平方英寸)/(板上管脚总数/14) PIN密度 信号层 板层 1.0以上 2 2 0.6-1.0 2 4 0.4-0.6 4 6 0.3-0.4 6 8 0.2-0.3 8 12 10 >14 E.2.3 线宽、线厚与电流的关系 线宽(mm) 铜厚35um 铜厚50um 铜厚70um 电流(A) 0.15 0.20 0.50 0.70 0.20 0.55 0.70 0.90 0.30 0.80 1.10 1.30 0.40 1.10 1.35 1.70 0.50 1.35 1.70 2.00 0.60 1.60 1.90 2.30 0.80 2.00 2.40 2.80 1.00 2.30 2.60 3.20 1.20 2.70 3.00 3.60 1.50 3.20 3.50 4.20 2.00 4.00 4.30 5.10 2.50 4.50 5.10 6.00 E.2.4 线间距与绝缘电压的关系 线间电压(V) 内层线间距(mm) 外层线间距(mm) 5000 11.5 14.5 4000 9 11.4 3000 6.5 8.43 2000 4 5.38 1000 1.5 2.33 500 0.25 0.8 300 0.2 0.4 100 0.1 0.13 0.05 0.1 Tips : 可击穿绝缘体的电压为绝缘体电压. E.2.5 PCB工艺限制 限制 国内 国际先进水平 推荐最小线宽/间距(mil) 6/6 4/4 极限最小线宽/间距(mil) 4/6 2/2 E.2.6 孔、焊盘与板厚的关系 板厚(mm) 3.0 2.5 2.0 1.6 1.0 最小孔径(mil) 24 20 16 12 8 焊盘直径(mil) 40 35 28 25 20 热焊盘直径(mil) 50 45 40 35 30 Tips : 大面积覆铜的连接的焊盘有良好的散热效果以导致元件焊接不稳定,将焊盘制作成十字花形状可以避免这个问题,这种焊盘称为花焊盘或热焊盘. TBD 设置原点Set origin 原点是为PCB加工方设置的,加工方以原点为坐标对PCB上的元件和线路等所有元素进行定位 原点的坐标是(0,0),可以设置在PCB工作区(workspace,在PCB布线区内)的任何位置(但常在左下角lower-left边缘位置,以矩形PCB为例,它就在左小角边界交叉线的交叉点上), 然后PCB设计界面的任何元件的位置都是相对于该原点的坐标 考虑到PCB切割的边缘精度问题,因此建议选择左下角的 元件焊接点 或 标记点 作为原点 MCU与外设的连接一定要注意:电压、电流和频率参数, 比如5V的主板要接24V的传感器,是不行的,因为24V的传感器的发射信号的电压也是24V的,5V的主板会被烧掉, 又比如5V的主板要接24V的驱动设备,那根本驱动不起来, 再比如5V的主板接5~30V的继电器,电压是够了,但电流可能不够,一样驱动不起来 还比如一个光耦的最高工作频率是1000Hz,但你给的输出信号大于1000Hz,那么实际工作结果就有问题了 布线技巧: 如果最终要为该层的一个整层的某个网络铺铜,那么就可以先忽略该网络,等到铺铜时自动解决,没有解决的再通过打孔或改线实现。 比如双层板的GND,设计时先可以忽略GND网络,因为最终正反两面都要为GND铺铜,铺铜之后99%的GND都自动解决了,剩下没解决的一般可以通过打孔解决。 注意:如果要打孔解决的,那么有可能需要多打几个孔,看实际负载情况,并且注意如果打多个孔 这些孔不要靠的太近,避免PCB局部承受力变小甚至断裂 PCB焊接心得: 1. 贴片封装芯片焊接:将电烙铁加热到高温(实际使用电烙铁最高温度480摄氏度),先点焊一或两个焊盘使芯片固定,然后将PCB倾斜,然后将锡(这种锡直接融合了松香等助焊剂)涂抹在PCB芯片较高的一侧(要多涂抹,涂抹量看芯片引脚大小及长度),因为电烙铁高温的原因,锡会像水珠一样从顶端滚落到下端(也就是电烙铁要跟着锡走),直至脱离芯片,这时芯片的一侧就焊接完成了,其它侧以此类推。 2. 贴片小电阻/电容/二极管等拆卸:电烙铁高温,电烙铁上锡,对准要拆卸的贴片较长一侧左右涂抹,这时贴片会粘在电烙铁上,此时马上将其磕落下来,然后用电烙铁将贴片上粘的锡抹掉 3. 贴片。。。等焊接:用镊子夹住贴片,电烙铁上锡,先点焊一侧,然后焊另一侧 4. 引脚及直插元件焊接:插入元件,先在正面固定一个脚,然后可以像贴片芯片那样在背面滚落焊接,如果引脚之间较远,则可以点焊,即电烙铁上锡,然后贴到焊盘与引脚之间,使锡灌入缝隙则焊接完成 5. 焊盘脱落: - 无论什么封装焊接,都不易将电烙铁放置于焊盘太久,以免焊盘脱落 - 电烙铁不易与PCB直接接触,或挂蹭 - 拆卸元件或引脚时一定要保证锡完全脱落,否则使用蛮力可能使焊盘脱落 6. 贴片芯片拆卸:用镊子夹住芯片,左右涂抹锡(电烙铁温度一定要高),左右反复,直到芯片可夹起或脱落(利用高温,快速 一侧未凝固) =--- MC3305使用心得: MC33035连接直流无刷电机(两线),默认EN和break是使能的,所以仅操作break就可以让电机转起来,所以主板信号在上电时应给break高电平 EN低电平 8pin与11pin使用可调电阻分压控速,8与11之间短路和断路的情况结果是一样的:最高速(最高输出电压),另外输出电压是PWM横流斩波的,所以对于不同电机的调速范围不同。 用电压表测得的输出电压也是不正确的,另外用24V风机查看调速结果也不准确,因为低压对于风机无效 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/hardware/Analog.html":{"url":"pages/hardware/Analog.html","title":"Analog Elec","keywords":"","body":"Chapter 0. 基本线性电子元件(Basic linear electronic element):电阻、电容、电感 电容 (capacitance) 存储电荷(物质带电量)的元件,基本构造为:两块接近且平行放置的金属板分别连接电源两极;原理为:当未通电时,两块接近的金属板正负电荷量相等,呈电中性。如果仅正极通电后,连接正极的金属板A中的电子流向电源正极,由于没有形成通路,(电子往返于金属板与电源之间)最终金属板A仍呈电中性。如果仅负极通电,则电源负极的电子流向金属板B,由于没有形成通路,最终金属板B仍呈电中性, 对AB通电,B中流入电源电子,A中电源电子流向电源,同时B中电子对A中电子产生排斥作用,进一步使得B中电子增加,A中电子减少。此时形成从A到B的电场 电容越大,容纳电荷量越多,增加电容容量的方法有三种: 增加极板面积 减少极板之间距离 在极板之间放入特殊介质(这种介质可以在极板间电场形成时,对A面形成负电荷,对B面形成正电荷,这样A面将进一步排斥电子,B面将进一步吸引电子,从而使容纳电荷量更多) 电容特性:通交流,隔直流。 本质上,B中的电子永远不会走到A中,因为实际上没有连接成通路,但如果给电容通交流电,那么会形成对电容的周期性充放电过程,对于电容的另一侧而言,虽然是自己的电子在往复运动,但仍然形成了周期性电流(电子的流动形成电流),所以达到了“通交流”的效果。隔直流是因为直流电不会导致电容周期性充放电(仅在第一次上电时充电一次),所以电子不会周期性往复运动,不会形成电流。 电容的应用: 对电容的应用,来源于其核心特性和基本功能,即通交流隔直流和存储电荷,所以应用场景有:滤波、去耦(或旁路)和储能。 去耦和旁路及储能: 在直流系统中(比如直流电路板中),理论上总是走平稳的直流电的,但实际应用中直流电源总是被电磁噪声干扰者,产生不稳定的直流电源(比如高电平不总位置再5V),电源的偏低和偏高都会对半导体器件造成对执行的严重误判, 为了消除噪声,会在IC器件的信号输入端接入电容(信号线经电容接GND),使得不稳定部分(当作交流电处理)通过电容流入GND,一般将处理输入到IC的信号的电容称为旁路电容(如输入信号、IC电源等),将处理从IC输出的信号的电容称为去耦电容。 因为负载的实际使用情况大多也是不固定的,所以可能造成IC供电不稳定,这是旁路电容存储的电荷发挥了作用,因为电容的放电速度非常快,可以快速补偿IC的用电,这时旁路电容就像一个临时缓冲区,随时补偿IC用电,使得IC工作稳定。 在电路PCB设计中,要将电容放置到离IC相关引脚很近的地方。 去耦电容一般比较大, 10uF/更大? 旁路电容一般比较小,0.1uF/0.01uF? 选择公式? 滤波: 仍然利用通交流隔直流的特性,所以去耦、旁路和滤波的本质都是一样的,用大电容过滤低频?用小电容过滤高频? 电容的单位是法拉,简称法,符号F(Farad),对于电容,F是一个很大的单位(=10^3uF),一般电路中使用的都是微法uF(=10^3nF)、nF(=10^3pF)、pF单位。电容在电路中使用C表示。 电容极性: 电容分为有极性电容和无极性电容 根据工艺复杂程度、容量大小等制作出了各式各样的电容,如铝电解质电容、瓷片电容、独石电容 Chapter 0. Preface 0.1 电信号 随时间变化而变化的电压u或电流i : u = f(t) or i = f(t). 0.1.1 数字信号和模拟信号 模拟信号对应于任意时间t值,均匀确定的函数值u或i。数字信号在时间和数值上均有离散性,u或i的数值是一个以某个最小整数值为基值的倍数,当实际信号数值在N和N+1之间时,则根据所设定的阈值将其确定为N或N+1,N与N+1之间的数值没有意义。 几乎所有物理量都是模拟信号,为计算器要处理物理量则需进行模数转换,处理后再根据需求转化为模拟信号驱动负载。 0.2 电子系统 电子系统由:信号提取系统、信号处理系统和信号驱动系统组成; 0.2.1 信号提取 被提取的信号来源于各种物理量的传感器或信号发生器(用于测试)。来自传感器的信号其幅值(通常)很小、噪声大且易受干扰,因此需利用隔离、滤波、阻抗变换等方法将信号提取,并进行放大。 0.2.2 信号处理 当信号足够大时,执行信号的运算、转换、比较等不同的加工。若要进行数字化处理则需通过A/D转化电路将处理后的模拟信号转换为数字信号输入至数字系统。 0.2.3 信号驱动 经过处理的信号一般还要经过功率放大以驱动负载,若是经过数字化处理的,则需通过D/A转化电路将数字信号转换为模拟信号再将其功率放大。 0.3 模拟电路 对模拟信号的最基本处理是放大,并且放大电路是构成各种模拟电路的最基本电路。 常用模拟电路 功能描述 放大电路 用于信号的电压、电流或功率的放大 滤波电路 用于信号的提取、变换或抗干扰 运算电路 完成信号的加减乘除积分微积分对数指数比例等各种运算 转换电路 电流与电压信号的转换、直流与交流信号的转换、直流电压与频率的转换等等 发生电路 用于产生正弦波、矩形波、三角波、锯齿波 直流电源 将交流电转换成不同输出电压和电流的直流电,作为各种电子电路的供电电源 0.4 电子系统组成规则 电路应尽量简单,元器件数、连线、焊点数越少越好,能用集成电路就不用分立元件、能用大规模集成电路就不用小规模集成电路。这样可以使故障率最低、系统可靠性增强。另外要考虑电磁兼容性,即:既能抵御周围电磁场的干扰,又能较少的影响周围环境,通常采用隔离、屏蔽、接地、滤波、去耦等技术来获得较强的抗干扰能力。必要时应选用抗干扰能力强的元器件。 要注意,设计电路和选择元件时要统筹考虑,权衡利弊,满足设计要求是主要目的,不要盲目追求某单一方面性能特别优秀,因为对于多数电子电路,当其某些方面性能改善时,另一方面的性能往往遭到破坏。其次能用通用元件实现的就不用专用型元器件。只有当系统电路结构正确,但性能不满足要求时才考虑更换所选的元器件。 0.5 其它 误差与估算:由于半导体器件性能参数的分散性和对温度的敏感性,精确的计算通常没有意义。所以通常要近似计算,但要近似的有道理。 估算不同的参数需采用不同的模型,模拟电子电路的特殊性表现在具有非线性特性的半导体器件,通常在求解模拟电子电路时需要将其转换为线性元件组成的电路(即等效电路),不同的条件、解决不同的问题,应构造不同的等效模型。 基本概念、基本电路、基本定律、基本分析方法。 从实际出发,没有最高的电路只有最合适的电路。当改善电路某些方面的性能而采取某些措施时要自问:这种措施还改变了什么?怎么变化?能容忍吗?因为一个电子电路是一个整体,各方面性能相互联系,通常“有一利将有一弊”,不能顾此失彼。 电路仿真辅助软件:SPICE Chapter 1: 常用半导体器件 半导体器件是构成电子电路的基本元件,所用材料是经过特殊加工的、性能可控的半导体材料。 1.1.1 本征半导体 纯净的,具有晶体结构体的半导体称为本征半导体。 物质的导电性能决定于原子结构,导体一般为低价元素(最外层电子数一般小于4),其最外层电子容易脱离原子核束缚成为自由电子并在外电场的作用下产生定向移动进而形成电流。高价元素或高分子物质其最外层电子受原子核束缚力很强,很难成为自由电子,导电性极差,所以称为绝缘体(最外层电子数一般大于4)。 注:原子结构、物质导电能力等知识可以在化学课本中找到答案 常用的半导体材料Si硅和Ge锗都是四价元素,最外层电子受原子核的束缚力介于导体和绝缘体之间,导电性能也介于两者之间,因此通过向其晶体中掺入特定的杂质元素可以使其导电性可控,那么就容易形成开关(1或0),因此半导体可以制作成各种电子器件。 本征半导体晶体形成稳定的共价键结构,具有很强的结合力,受温度影响下有少数电子因热运动而获取足够能量挣脱原子核束缚成为自由电子,自由电子的挣脱导致对应的原子带正电,被挣脱的位置称为“空穴”,电子带负电、空穴带正电,在本征半导体中空穴和电子成对出现。 如果此时在半导体两端加一个电场,则在电场力的作用下,电子产生定向移动,另一方面由于空穴的存在,价电子会依次添补空穴,这就相当于空穴在反向移动,本征半导体中的电流是两种电流的和。 o->o->o->o->o->o->o-> o->o->o->o->o->o->o-> o->o->o->o->o->o->o-> o->o->o->o->o->o->o-> o->o->o->o->o->o->o-> o->o->o->o->o->o->o-> o->o->o->o->o->o->o-> 电子电流 + 空穴电流 运载电荷的粒子称为载流子,本征半导体中的两种电子和空穴都参与导电 本征半导体在热激发下产生自由电子和空穴的现象称为本征激发,电子在运动过程中遇到空穴就会添补,这种现象称为复合,在一定温度下,本征激发所产生的自由电子与空穴对,与复合的自由电子与空穴对数相等,达到动态平衡。即一定温度下本征半导体的载流子浓度一定,并且电子与空穴浓度相等。 如果温度升高则浓度增加,反之降低,本征半导体载流子浓度是环境温度的函数:Ni=Pi=f(t); 本征半导体的导电性能差,且与温度密切相关,利用半导体材料性能对温度的敏感性可以用来制作热敏和光敏元件,这也是造成半导体器件温度稳定性差的原因。 1.1.2 杂质半导体 通过扩散工艺在本征半导体中掺入少量的杂质元素即可得到杂质半导体,按参入杂质元素不同可形成N(negative)和P(positive)型半导体。控制参入杂质的浓度就可控制杂质半导体的导电性。 N型半导体 在本征半导体中掺入最外层有5个电子的磷元素,这样磷元素容易和晶体形成共价键而多出一个自由电子,磷原子因与晶体形成共价键而成为不能移动的正离子,N型半导体中自由电子数量大于空穴数量,自由电子称为多数载流子(多子)、空穴称为少数载流子(少子)。由于杂质原子可以提供电子故称之为施主原子,参入杂质越多,多子浓度越高,导电性能越强。 P型半导体 在本征半导体中掺入最外层有3个电子的硼元素,这样硼元素容易和晶体形成共价键而多出一个空位,晶体原子添补该空位后就形成了空穴。硼元素因与晶体形成共价键而成为不能移动的负离子,P型半导体中空穴数量大于自由电子数量,空穴为多子,自由电子为少子,硼为受主原子,参入杂质越多,多子浓度越高,导电性越强。 结论 P和N型半导体,杂质使多子浓度大大增加,从何与少子复合的几率就增加,因此对于杂质半导体,多子的浓度越高,少子的浓度就越低,多子的浓度约等于所掺入杂质原子的浓度,多子受温度影响很小,而少子是本征激发形成的,尽管浓度很低却对温度非常敏感,这将影响半导体性能。 PN结 物质总是从高浓度的地方向低浓度的地方扩散(扩散运动),当把P和N型半导体制作在同一块硅片上时,它们的交界面就形成PN结,在交界面处两种载流子的浓度差很大,因而P区的空穴和N区的自由电子必然向对方扩散,因扩散运动导致交界面处的多子浓度下降,又因P区硼原子成为了不能移动的负离子、N区的磷原子成为了不能移动的正离子,因此交界面处形成内电场,称为空间电荷区,随着扩散运动的进行,空间电荷区加宽,同时内电场加强,内电场力刚好与自由电子方向相反,进而阻止了扩散运动的进行, 在内电场的作用下,P区的少子-自由电子(实际上是从N区扩散来的比较多)与N区的少子-空穴做反向运动(漂移),如此往复最终达到动态平衡,形成PN结。扩散电流等于漂移电流(因为实际上就是自由电子的往复运动,同一批自由电子当然电流相同) 空间电荷区的电压为Uho,电流为0,空间电荷区内正负离的电量相等,当P区域N区的杂质浓度相等时,负离子与正离子区宽度也相等,即电荷数量相等,称这种PN结为对称PN结,如果暂支浓度不等,则称为不对称PN结,这两种结对外的特性是相同的。 绝大部分空间电荷区内的自由电子和空穴都非常少,在分析PN结时常忽略载流子的作用而只考虑离子区电荷,这种分析方法称为“耗尽层近似”,故空间电荷区称为耗尽层。 PN结的单向导电性 如果在PN结两端施加电压就会破坏PN结的动态平衡,因为外电压(电压的本质是电流,电流的本质是电子的移动)存在,导致电子数增多,所以漂移电流不再等于扩散电流,施加外电压的极性不同导致PN结的单向导电性。 当给PN结P区接电源正极、N区接电源负极时(这时称“正向偏置”或正向接法),由于电源电子流是从负极流出,那么N区的自由电子将增多,扩散运动加剧,PN结耗尽层变窄(或消失?),打破原来的动态平衡,由于电源的作用,扩散运动源源不断的进行,PN结将导通。 从电场的角度讲,PN结接入电源后外电场的力大于内电场,导致导通(我不喜欢这种说法,如果只从电场角度说,那么扩散运动不管怎么加剧,PN结自由电子数量都是有限的) PN结导通时压降只有零点几伏(可见阻抗非常小),所以在回路中要注意使用电阻以限制回流电流,避免PN结(和电源)烧毁。 当给PN结N区结电源正极、P区接电源负极,(这时称“反向偏置”或反向接法),由于电源电子流是从负极流出,那么P区的空穴就会减少,同时N区的自由电子流向电源正极,N区的自由电子也减少,这时扩散运动减小(直到停止),PN结的耗尽区变宽, PN结处于截止状态。 PN结电流方程 TBD PN结伏安特性 通过PN结电流与加在两端的电压的曲线特性:PN结的伏安特性。u>0的部分称正向特性、u TBD PN结电容效应 分为扩散电容和势垒电容 势垒电容Cb:PN结的外加电压变化时,耗尽区宽度变化,耗尽层电荷量发生变化,这与电容充放电过程相同,称为势垒电容,电容大小与结面积、耗尽层宽度、半导体介质常数、外加电压等都有关系。 反向电压,对(高掺杂)PN结的耗尽区变化控制更为明显,因此可以制作成各种变容二极管。 扩散电容Cd:PN结外加正向电压时,耗尽层宽度变化,P区和N区的剩余宽度也在变化,其电荷量也在发生变化(非平衡少子浓度),这与电容充放电过程相同,称为扩散电容,电容大小与电流、电压、费平衡少子寿命等有关。 Cb和Cd一般很小,(结面积小的为1pF左右,大的有几十到几百pF。 1F=1000mF=1000 000uF=1000 000 000nF= 1000 000 000 000pF)只有高频信号才考虑结电容的作用,低频可忽略不计。 1.1.3 二极管 将PN结用外壳封装起来,加上电极引线就成为二极管,P区引出阳极、N区引出阴极。 将PN结结点做小,结面积小,结电容就小,就可以制作成适用于高频电路、小电流的二极管(高频电路、脉冲开关、小功率整流)。 将PN结结点做大,结面积大,结电容就大,就可以制作成适用于低频电路、大电流的二极管(低频电路、大功率整流)。 二极管伏安特性 [关于电阻的思考:电阻是耗能元件,而电压的本质是电源所连接的电路中所测量的两个点之间的电子数量差,将电阻与电源串联,那么将有一部分电子被电阻消耗,电阻另一端的电子数量就会变少,电源与该点开始存在电压差,该点的电压降低,所以说串联电阻分压了] [给电源串联一个电阻通常是有必要的,如果没有用电器那一定要串联,设想一个电源的正负极用几乎没有电阻的导线相连,那么电子无限的从负极流向正极,电流相当于无限大(欧姆定律可知),大电流会击穿电源烧毁电路] concept 模拟电子技术(Analog Electronics Tec.)是以半导体为基础材料、以电荷移动为基本原理的模拟信号放大技术。本质是研究能量的控制,结果是功率(不失真)的放大 电子技术的发展 关键词:电子管-晶体管-集成电路-大规模-超大规模 ---------------------------------------------- 1947 晶体管 - 贝尔实验室 1958 集成电路 1969 大规模集成电路 1975 超大规模集成电路 第一片集成电路只有4个晶体管,1997年有40亿个 预计2020年达饱和 模拟信号与模拟电路 关键词:连续/时间&空间有意义/放大(能量控制)/有源元件/功能和性能(细节)分析 --------------------------------------------------------------------------- 重点:基本概念/基本电路/基本分析方法/全面分析(副作用分析),适用的才是最好的 -------------------------------------------------------------------------- 四个会:会看(读图/分析)/会算/会选(电路 器件 参数)/会调 ----------------------------------------------------- 数字信号:离散性(时间和数值) 模拟信号:连续性(时间和数值),几乎所有物理量都是模拟信号,如温度 压力等,任何瞬间的任何值都有意义 模拟电路:最基本的处理是对信号的放大,放大的本质是能量的控制 传感器/AD转化的信号基本上都是小信号,它们不足以驱动负载/传输/转化,所以要进行放大 有源元件:能够控制能量的元件 常用半导体器件 半导体基础知识 本征半导体 半导体:绝缘体 mid 导体 导体的最外层电子容易脱离原子核束缚(通过电场/温度等), 最外层电子4 半导体-四价元素,Si Ge,电子被束缚力介于导体与绝缘体之间 最外层电子=4 原子核:正电 电子:负电 关键词:原子结构(核正子负,最外2/8稳定,4为半导体,其它结构易失/得)/Si Ge/本征无杂质-共价键 拓展 : 化学-原子 ---------------- 关键词:少子/多子 载流子 自由电子/空穴 热运动 (绝对温度0度不导电) 拓展:物理 - 热力学 ------------------ 本征半导体受温度影响 自由电子脱离共价键束缚成为自由电子 形成空穴 在温度一定下,自由电子浓度一定 温度升高,热运动加剧 杂质半导体 本征半导体受电场和温度影响,载流子很少,导电性很差 参如3价和5价的元素掺入本征半导体,将改善导电性能 N型半导体:本征加入P磷,破坏共价键,增加一个P就增加一个自由电子,此时自由电子成为多数载流子,空穴为少数 P : B硼, 吸收电子 , 空穴成为多数载流子,自由电子为少数 关键词:5价/P磷/3价/B硼/N型半导体(Negative -)/P型半导体(Positive +) 杂质半导体,仍然受温度变化,但受温度变化自由电子和空穴浓度仍然一定,重要的是在N中空穴比例小,温度变化 后对空穴比例浓度影响最大,P中自由电子比例小,温度变化后自由电子比例浓度影响较大 重点:少数载流子是影响半导体器件温度稳定性的主要因素 关键词:温度/比例浓度 PN结的形成及其单向导电性 在一块本征半导体基片上,做成PN结(两端根据扩散原理掺入不同杂质),注意,不是将一个P半导体和N半导体按压到一起!! ,这样它们的交界界面就形成空间电荷区,成为PN结 制作成的PN结,仍然受扩散运动的影响,P区的空穴向N区扩散,N区的自由电子向P区扩散, (实际上空穴是假想,实际是电子运动) NONE P N ----------- | +++++++++ | |-----------| ----------- | +++++++++ | |-----------| ----------- | +++++++++ | |-----------| N区电子运动到P区与空穴复合,因为复合后P区接触面开始带负电,N区开始带正电,导致PN结形成内电场 内电场将组织自由电子的复合,并且反向运动,如此反复以形成稳定的区域 NONE P N ----------- | +++++++++ | |-----------| ----------- | +++++++++ | |-----------| ----------- | +++++++++ | |-----------| 在空间电荷区(接触面)N区的自由电子向 关键词:空间电荷区/PN结-扩散运动-内电场-漂移运动-动态平衡 -------------------------------------------------------- 拓展:物理-热力学 ---------------- 给PN结通电,会打破动态平衡,释加正电压会削弱内电场(耗尽层变窄),进而扩散运动加剧,PN导通 正电压是指P区接正极,N接负极,因为电流的流动实际是电子的移动,即从电池的负极流出电子,而 负极接N区,导致N区电子增多,进而削弱了内电场,最后导通PN结 如果反向给电,效果相反,即电池的电子流向了P区,使得复合了很多空穴,增加了内电场,使得耗尽区变大,PN不通 关键词:外电场/削弱-增强/导通-截止/耗尽区/正向-加剧扩散/反向-加剧漂移 --------------------------------------------------------------------- 拓展:物理 - 电荷运动 -------------------- PN结的电容效应 势垒电容 : PN结外加电压时 空间电荷区宽度变化,有电荷积累和释放过程,与电容充放电向相同,其等效电容为//// 扩散电容: PN结外加正电压时,在扩散过程中在刘子浓度和梯度都有变化,也有电荷累积和释放,其等。。。。 结电容 =势垒电容 + 扩散电容 结电容不是常量,PN结外加电压频率到一定程度将失去单向导电性 关键词:势垒电容 扩散电容 结电容 限制电压频率 总之,pn结的扩散电容与其势垒电容不同。前者是少数载流子引起的电容,对于pn结的开关速度有很大影响,在正偏下起很大作用、在反偏下可以忽略,在低频时很重要、在高频时可以忽略;后者是多数载流子引起的电容,在反偏和正偏时都起作用,并且在低频和高频下都很重要 二极管 单向导通性 伏安特性 非发光二极管在电路中的电压在1V~2V之间,当电流在5~20mA时会发光,否则不发光 发光二极管在电路中的电压为0.7V 当二极管两端的电压小于0.5(约)时不导通,达到O.5V之后导通 当二极管两端电压反向,且大于击穿电压时导通 Tips:伏安特性曲线 ------ 稳压二极管 反向连接,且反向电压大于稳压电压时,该稳压二极管具有稳定电压的作用 Tips:稳压二极管电路 : 二极管 + 电阻的串连电路 (其中二极管反向连接) 稳压二极管利用了二极管的伏安特性中的反向性质:当反向电流达到一定值时,(反向)电压是稳定的。 要注意的是,反向电流一定在Max和Min之间,Min是二极管反向时刚刚导通时的电流,Max是二极管刚好击穿时的电流 Tips : 两种稳压电路的区别(二极管+电阻 VS 电阻+二极管) 整流二极管 用于将交流电变成(脉动)直流电 利用到了二极管的单向导通特性 当交流电的正弦波通过二极管时,每个正弦波的180~360度的相位被过滤掉,即变成了脉动直流电 开关二极管 利用到了二极管的单向导通特性 这种二极管比普通二极管的开关速度快(即 导通-截止 状态切换快) 用于器件的保护,防止反向电流的通过 散装知识点 去耦电容/退耦电容 https://www.youtube.com/watch?v=KKjHZpNMeik 位置 : 放在元器件连接VCC电源之间 和 元器件信号输出端, 去耦电容和旁路电容(放在元器件的信号输入端)相对应 耦合-辞海 : 两个元素/量之间,其中一个量的变化,导致另一个元素/量的变化的一种关系 噪声-辞海 :信号中 随机变化的 无用的 信号成分。 电路中安装在元件的电源端的电容,此电容可以提供比较稳定的电源,同时也可以降低元件耦合到电源端的噪声,间接可以减少其他元件受此元件噪声的影响 去耦电容,是影响了 电源 和 元件 之间的耦合,滤除了电源上的干扰信号,使电源信号稳定, 继而是连通该电源的元器件用电稳定 Q&A: 为什么要去耦? A:当一个电源端连接多个元器件供电时,每个元器件的工作都要动态的吸收电流,时多时少,多个元器件一起工作更会影响电源的稳定(直流的波形开起来像交流),这不但会影响元器件的供电, 也会产生电磁噪声影响周围系统,是元器件和周围系统产生错误的信号,所以在电源向元器件的输出端加上一个电容(称为去耦电容),用来减小或消除影响。 B: 当元器件输出信号时 为什么电容能去耦? 去耦原理 :因为电容是储能元件,当电压突变高时电容吸收多余电量,当电压突变低时电容释放存储电量补充 选型与放置 基本原则:最小化电阻(ESR)、最小化电感(ESL) 电容还具有阻抗和电感属性,对于电阻而言无论频率如何都呈固定阻抗,对于电感而言随着频率的增加而增强 容量选型: 电容式储能元件,当在电源端用作去耦功能时,还可以实现“蓄能”功能,即用来补偿电源的长期偏差(长期偏差可能是开关电源到PCB电源的距离较远,且负载较大,导致长期供电不足) ,如果需要补偿电源的长期偏差,则需要大量存储电荷,即选择大容量去耦电容 种类选型: 陶瓷电容 具有很小的阻抗和电感,其次是钽电容 , 另外贴片电容的效果更好 放置 : 电源 - 去耦电容 - 地,三点一线,呈最佳效果 去耦电容可以并联使用(相同/不同容值),已达到更好的去耦效果 牛屎芯片/牛屎封装 DICE: DICE 也叫 CHIP 或裸片,是没有封装的芯片 (常见芯片是黑色的矩形外壳,四周或者下面会引出许多金属脚,这种芯片就是标准封装。标准 封装已经规定好引脚的位置和大小,这样进行产品开发时候只要知道用的是什么封装就知道电路板 应该怎么布线) 这种芯片需要通过一种叫 BONDING(邦定)的方法将芯片上的引脚用非常细的线连出来,,再点上胶直接固定在电路板上 另外有的时候担心产品的程序被人复制,这样比用标准封装程序被复制的难度要大许多,标准封装只能依赖单片机 自身的防复制功能和把上面的丝印磨掉不让别人知道是什么型号的单片机来进行 现代诸多电子产品的 PCB 板上看到纽扣大小的黑色芯片,大家管它叫做“牛屎” 。其实它真正的学名叫 做绑定(bonding ),也就是芯片打线,芯片覆膜,音译为邦定, 是“ bonding ”的音译,是芯片生产工艺 中一种打线的方式,一般用于封装前将芯片内部的电路用金线与封装管脚连接。一般 bonding 后(即电路与 管脚连接后)用黑色胶体将芯片封 装, 同时采用的外封装技术 COB(Chip On Board),这种工艺的流程是将 已经测试好的晶圆植入到特制的电路板上, 然后用金线将晶圆电路连接到电路板上,再将融化后具有特 殊保护功能 的有机材料覆盖到晶圆上来完成芯片的后期封装。 使用邦定技术的芯片又叫 “裸芯” , 即半成品芯片。 由于本身已经具备了最基本的控制功能, 所以在 刚开始使用时与封装芯片并没有什么不同, 但由于省去了很多后续工序, 如没有增加 必要的保护电路,它 的使用寿命与稳定性都要比最终完工的封装 IC 集成芯片低很多,一旦坏了没得维修,一般只有整个报废, 其成本也只有硬封装 IC 集成芯片的 1/2到 1/3。 第一,牛屎芯片的封装工艺环境天生就不够塑料封装好,起码滴胶工艺的净度就绝对比不上正规硬封装厂家 的芯片。 第二,牛屎芯片的缺点,底衬不能很好的焊接或者是焊接不牢靠、受热受潮或者是受冷冻之后底衬可能会接触不 良、黑胶密封性差、对潮湿环境和静电抑制能力差、易老化、损坏无法维修。 第三,牛屎芯片的优点就是开发周期短、封装成本低、适用于比较简单的电路。 第四,同一个等级的芯片,用牛屎封装同用塑料封装,肯定是塑封好。牛屎的故障率肯定比正常的塑料封 装要高 逆变器 逆变器一般有6个功率晶体管(q1~q6)组成,分为上臂/上桥(q1、q2、q3)和下臂/下桥(q4、q5、q6) 它有将直流转换为三相交流 和 控制电流导通的开关功能。 缓冲器 缓冲器分输入缓冲器和输出缓冲器两种。前者的作用是将外设送来的数据暂时存放,以便处理器将它取走,后者的作用是用来暂时存放处理器送往外设的数据。有了数控缓冲器,就可以使高速工作的CPU与慢速工作的外设起协调和缓冲作用,实现数据传送的同步。由于缓冲器接在数据总线上,故必须具有三态输出功能。 74HC244是缓冲器的一种 该芯片用于数据同步以解决MUC与外设速度不匹配的问题,同时增强MCU的负载能力以驱动更多外设,又因其具有三态门,故还有隔离保护功能。 继电器 光电耦合器 optical coupler 简称OC 又叫光电隔离器,简称光耦 它将发光器和受光器封装在一个管壳内,来实现无接触式/绝缘式的 电 - 光 - 电 的转换 发光器通常是一个发光二极管、受光器为一个光敏半导体管 拥有体积小、寿命长、无触点、抗干扰强、输入输出绝缘等优点 MOC3020 是其中一款产品。 触发器 在实际的数字系统中往往包含大量的存储元件, 且经常要求它们同一时刻同步动作,为达到这个目的,在 每个存储单元电路上引入一个时钟脉冲(CLK)作为控制信号,只有CLK到来时电路才被“触发”而动作,并根据输入 信号改变输出状态。 这种在时钟信号触发时才能动作的存储单元电路,称为触发器,以区别没有时钟信号控制的锁存器。 D触发器是触发器的一种,它在时钟脉冲CP的前沿(正跳变0-1)发生翻转。D触发器的应用很广,如数字信号的 寄存、移位寄存、分频和波形发生器等。 74HC574是D触发器中的一种芯片 存储器 KEY: RAM ROM 存储阵列 行列译码 简介 存储器是计算机的数据记忆存储设备,用具有两种稳定状态的物理器件来存储信息(二进制数据)。按存储介质可分为半导体存储器和磁表面存储器,按功能作用可分为主存储器、辅存储器、高速缓冲存储器、控制存储器等。 半导体存储器由半导体芯片制成,可存在于片内(如CPU内部)、片上(板载)或成为独立设备(如内存条),可用作主存储器、高速缓冲存储器和控制存储器,如ROM、RAM、Register,也可用作辅助存储器,如FLASH。磁表面存储器由载体和磁性材料组成,常用作辅助存储器,如磁盘、光盘、磁带等。 半导体存储器 根据摩尔定律,半导体芯片每2~3年革新换代一次,从1970年至今半导体芯片晶体管集成度已达数十亿级别,其中半导体存储器占芯片的大部分面积。主要分为四大类:只读存储器ROM、随机存取存储器RAM、寄存器Register和闪存Flash ROM - Read-Only Memory,只读存储器,又称程序存储器。ROM在制作时或制作后写入数据,在工作时只能进行读操作,断电后数据不丢失,通常只有几十k或几百k的存储容量,常用于存储固件。按制作工艺可分为掩膜ROM-MROM(制作时形成数据)、可编程ROM-PROM(制作后一次性写入)、可擦可编程ROM-EPROM(紫外线照射擦除,可多次写入)、电可擦可编程ROM-EEPROM(电擦除,可多次写入)。 RAM- RAM - Random Access Memory,随机存取存储器,又称数据存储器。RAM可以随机存取,速度快,但断电后数据丢失,通常有几M、几百M或几G的存储容量,用于操作系统下的数据的临时存储。RAM分为静态RAM(Static RAM - SRAM)和动态RAM(Dynamic RAM - DRAM) A: SRAM SRAM分为MOS型SRAM(NMOS、CMOS)和双极型SRAM(TFT),由于SRAM的复杂电路结构,使得成本要比DRAM高很多,而且集成度低,一般只有几十K~几百K或几M存储容量。 SRAM读写速度极快,功耗低,常用作高性能微处理器中的高速缓存(Cache)。SRAM在工作时电路不需要刷新,只要供电就会一直存储数据,断电后数据消失。SRAM由三部分组成:存储单元阵列、(行/列)地址译码器、读写电路。 存储容量常写为乘法形式,如:“2Kx8位”,表示存储容量为16Kbit或2KByte,并可推导该芯片的地址总线数:“2K=2^11,有11根地址总线”;8位表示有8根数据总线,8个存储元视为一个存储单元。同一容量的SRAM有不同的存储实现方式,如:“1Kx16位、2Kx8位、4Kx4位、8Kx2位、16Kx1位等”;并可以是单片形式,或者通过其它存储阵列并联组成。 FLASH 闪存是EEPROM的发展,又兼具RAM的特性,其集成度高、功耗低 、体积小 ,又能在线快速擦除 Flash可归属ROM家族,因其特性单独讨论,安卓手机上常提到的ROM通常指FLASH,而不是MROM、PROM、EPROM或EEPROM等。 EEPROM 及 存储保护 1.软件 A.上电延时 B.存储备份和恢复 2.硬件 A.MCU自带功能,如AVR的BOD功能 B.大电容防止存储掉电 PAGE / BANK PAGE/BANK一般出现在简单的单片机中,PAGE对应于ROM,BANK对应于RAM,作用基本一致 BANK这里当做“储存块”来讲 有些指令只能操作很小的地址范围,通过BANK的方法(通过寄存器配置选中哪一部分来操作)可以将指令寻址大大增加,BANK 也同时增加了程序复杂性 CISC/RISC 复杂指令集与精简指令集 CISC具有大量的指令集,并增加硬件复杂性以满足用户的需求 RISC则反之,只拥有较少的指令,而把复杂性嫁接到软件复杂性上 一般CISC有几百条指令,而RISC只有几十条指令 目前PC机的CPU基本上都还是CISC指令集的, RISC 和CISC 的区别: ①RISC 指令系统较小,种类的数量较少,只提供简单指令。CISC 指令系统大,种类的数量多, 提供各种指令。 ②RISC 指令长度、寻址方式、格式都整齐划一,这样可以充分利用流水线,基本上可实现一个 时钟脉冲执行一条指令。CISC 指令长度、寻址方式、格式不一,难通过流水线方式提升指令执行效 率,无法做到一个时钟脉冲执行一条指令。 ③RISC 的函数调用将现场状况保存在专用寄存器中来提升效率,参数也使用寄存器传递。CISC 的函数调用一般通过堆栈保存现场,需要内存操作,效率要低 专用单片机的辉煌与落寞 冯·诺依曼结构与哈弗结构 冯诺依曼结构(也称普林斯顿结构)是计算机的启蒙结构,也是使用了相当长一段时间、并且现在计算机仍然在采用的计算机体系结构, 冯诺依曼提出 程序(指令)和数据 共用同一组地址总线和数据总线,这样 读取程序代码和数据就不能同步运行 哈弗结构将 程序(指令) 和 数据 分开存储, 使用两条独立的总线,如此哈弗结构单片机片内至少存在4套总线:指令数据总线、指令地址总线、数据的数据总线、数据地址总线 ,显然,哈弗结构可以同时获取指令和数据,互不干扰,效率更高 这就是冯诺依曼结构和哈弗结构的主要区别:哈弗结构少了一次总线切换。 DSP DSP就采用了哈弗结构,但只是采用哈弗结构不能显著提示单片机效率,于是DSP增加了很多硬件设备,如乘法器,对于没有乘法器硬件的单片机来说,实现一个乘法可能需要几十条 、上百条的指令,而有了乘法器,一个指令周期就将乘法搞定。 同时DSP还使用了流水线设计,使得原来的\"取指、译码、执行“三步在一个信号周期内就完成了,即在执行指令的同时对下一条指令译码并同时取得下一条指令,真正的流水线更加复杂 会有很多的优解。 DSP是专门对数字信号处理作出的设计,在处理数字信号时会比冯诺依曼结构快很多,但如果用DSP实现简单的逻辑控制并不一定比冯诺依曼结构快 不是所有的单片机都是冯·诺依曼结构,在移动数字通讯刚刚兴起的年代,DSP 那是望尽春色, 近年来随着技术的发展单片机的速度是越跑越快,有一些单片机也开始采用哈佛结构,少数单片机 内部甚至会加上一个小的DSP 核,使得DSP 在数字处理速度方面的优势逐步变小,加上一些专用器 件内部采用硬内核进行数据处理,这些变化恐怕让DSP 难以再现昔日辉煌。 这不仅仅是DSP的过程,也将是许多专用单片机的故事,将来或者是现在,一个ARM-A9或许可以把所有单片机都替代了 术语 MIPS : 百万指令每秒 74系列芯片 74系列芯片是TI德州仪器、NXP恩智浦、ST意法半导体等半导体公司生产的中小规模TTL集成电路芯片,主要用于计算机数据的输入、输出、锁存等处理,工作温度在-40~85℃之间。该系列芯片以74开头,连接字母或数字以标识不同功能。 例:74XXX 标准型TTL、电压2.4V、传递延迟9ns、功耗10mW。74LXXX低功耗TTL、电压2.4V、传递延迟33ns、功耗1mW。74HXXX高速型TTL、电压2.4V、传递延迟6ns、功耗23mW。 芯片最后的一个或几个字母,表示封装方式,不同厂家有不同标记方法,一般D表示SOP封装,如74HC138D 74或74+字母之后的数字表示该芯片的逻辑功能,不同的字母,相同的逻辑数字,其逻辑功能一样: 如:74LS224与74HC224的逻辑功能是一样的 附: 秒 1s = 1000ms 毫秒 1ms = 1000us 微秒 1us = 1000ns 纳秒 ADC 简介 ADC(Analog to Digital Converter)也称A/D,即模/数转换器,是将外界连续变化的模拟信号转换为离散的数字信号的电子元件。ADC最早用于无线电台中无线信号向数字信号的转换。与ADC对应的电子元件为DAC数模转换器 分类 有多种ADC类型:并行、逐次逼近型、积分型、∑-Δ型、流水线性,低功耗、高速、高分辨率是ADC的发展方向。其中并行ADC是当今速度较快的模数转换器。 AVRATMEGA128集成逐次逼近型ADC 指标 ADC 采样率和分辨率 是两个重要的参数 分辨率 - 模拟量量化为数字量的精度 - 量化精度(也称ADC精度,位数) 采样率 - 模拟量量化为数字量的速率 - 量化速率(单位SPS,或b/s或Hz) 采样个数/采样时间 - 单位时间内采样个数 显然采样率与分辨率有关,- 分辨率越高,样本数量越大,单位时间内采样数量越大,采样率越高 如果采样率可配置,则分辨率固定的情况下,增大采样率,同一时间内可采样更多样本 采样率是与分辨率有关联的,ADC手册经常看到的参数描述如:\"8位分辨率下采样率79kSPS , 最高分辨率时采样率高达15 kSPS\" 因为采样率表示数字量 ,数字量量化为模拟量的速率 ,ADC精度高,则代表的数值范围越大,数字量变多,所以相同时间内采样速度变慢 所以分辨率越高,采样率越小。它们之间可能没有固定比例关系,应该跟不同的ADC有关。 有些ADC的采样率和分辨率是可配置的。有些则不能,如ATMEGA128,分辨率固定为10位,采样率为15kb/s 采样率与奈奎斯特频率:采样率应至少为采样信号频率的两倍,(从这个角度讲,ATMEGA128不能对信号频率大于7.5kHz的进行采样??), 如果低于这个频率,采样信号失真. 基准电压 基于参考电压来将模拟量转换为数字码,因为数字电路只认高低电平,所以如果没有参考电压ADC读取来的电压值将是无意义的,(数字信号本身不具实际意义,仅表示相对大小1/0)而这参考电压又称基准电压,其指标是温漂,一般用ppm/K表示。 假设ADC的基准电压为5V、输入电压3V,则输入电压/基准电压=60%,对于8位ADC而言,该模拟量代表256X60%=153(0X99)。 公式:Dadc = 2n X ( Vadc / Vref ),其中n为ADC精度。 可见输入电压大于基准电压时ADC达满精度(满量程),输入电压为0V时,ADC为最小精度0。再设计上,基准电压最高值应该等于参考电压,如果基准电压不够,则可以使用功率放大器放大或使用ADC自带的增益。 单端与差分输入通道 单端输入是指被测电压从某个引脚输入,其参考电压是内部电压或GND。差分输入需要两个输入引脚,其参考电压时两个引脚彼此之间的相对电压。其中单端输入方式较为常见。 单端方式适用于传感器到ADC的线距离较短(5m以下),且所有输入信号要共用一个基准地。差分输入适用于更长距离的数据传输,更适用于噪声较大的使用场景。 如图所示,单端输入只有一个输入引脚ADCIN,使用公共地GND作为电路的返回端,ADC的采样值=ADCIN - GND(0V)。这种输入方式优点就是简单,缺点是如果VIN受到干扰,由于GND电位始终是0V,所以最终ADC的采样值也会随着干扰而变化。 而差分输入比单端输入多了一根线,最终的ADC采样值=(ADCIN+) - (ADCIN-),由于通常这两根差分线会布在一起,所以他们受到的干扰是差不多的,输入共模干扰,在输入ADC时会被减掉,从而降低了干扰,缺点就是接线复杂一些。而且需要VIN+和VIN-两路反相的输入信号。 其它术语参考:https://www.maximintegrated.com/cn/app-notes/index.mvp/id/641 https://zh.wikipedia.org/wiki/%E9%A1%9E%E6%AF%94%E6%95%B8%E4%BD%8D%E8%BD%89%E6%8F%9B%E5%99%A8 ---------------------------实验记录 热敏电阻测温实验, 设置ADC时钟分频为2(CPU时钟16MHz),时钟频率为8MHz,发现Vadc = 4.99,Dadc = 1023。 设置为4分频时,时钟频率 = 4MHz,Vadc和Dadc的值正常。 设置8分频、16、32、64、128分频都正常。 原因未知。 ------------------------------ Other ADC串联电阻的意义:关键词:数字电源、模拟电源、隔离、去耦、ADC性能、数字瞬态电流 TTL与CMOS电平 TTL电平:晶体管-晶体管逻辑电平,是计算机电路中的标准电平,它使用+5v=逻辑1、0V=逻辑0。 TTL与CMOS TTL电路速度快、延迟小、功耗高、抗噪声能力差 CMOS电路速度慢、延迟高、功耗低、抗噪声能力强 TTL电平的实际标准 输出: 高电平 - >2.4V 低电平 - 2.0V 低电平 - 0.7 * Vcc 输出 - >0.9 * Vcc 可见CMOS电平的高低电平取值是依电源电压而定的 ,高电平接近电源电压,低电平接近0 晶振 晶振是单片机系统的指挥家,它发布统一的工作节奏,注意,是统一而不是同一,统一意味着A吹两下笛子,B就得拉四次小提琴,这样不同的乐器 在统一的指挥下才能演奏出动听的交响曲。 晶振 就是 晶体振荡器,或 石英晶体振荡器, 石英这个东西就厉害了,他就是二氧化硅,天下物料之集大成者:玻璃、光纤、玛瑙、水晶、单片机等等。 石英晶体具有压电效应:给晶体薄片施加电场,晶体会形变,当移除电场时,晶体恢复形变并释放电场,如此往复形成固定的震动频率 RC振荡器(电容和电阻组成的振荡器)也可以作为触发信号源,但稳定性比晶振差、如果产品对时间精度要求不严格(比如一种按键发光的儿童玩具)就可以用RC 振荡器来节约成本 选多快的晶振?是不是单片机要跑多快就用多大的晶振? NO!频率越快,越容易产生电气噪声干扰,越难以控制,并且晶振对电路要求很高(在距离和走线上等等),如果放置不当还不会正常工作。 晶振作为一个外部器件,要提供的频率应该越稳定越好,而不是越快越好,那单片机需要更快的振荡频率怎么办呢? 这就需要锁相环 PLL 技术来解决,该技术可以将晶振频率加倍(N倍),进而实现更高的振荡频率 另外PLL还具有动态改变工作频率的能力 此外,还有分频器,即将晶振频率(或其它频率)分解的更小来使用 通过上述知识可知,通过晶振振荡可将震动传递给单片机内部,单片机内部可以通过倍频或分频技术来利用,无论倍N频还是分N频,显然都必须具备N是整数 ,通过将外部晶振 倍频和分频得到的震动频率,就是系统时钟 I/O复用技术 为了单片机增加I/O功能,又不能增加I/O管脚数量,只能将IO做成复用的,即一个接口可以有多种功能 不同的功能配置,通过单片机寄存器配置来完成 IO与GPIO IO就是输入输出,在单片机中代表输入输出接口,GPIO是近来兴起的说法,意为“通用IO”,都是一样的,叫法不同而已 上拉电阻 将不确定的信号接口,通过一个电阻拉在高电平,这个电阻就是上拉电阻,电阻同时起到限流的作用 下拉电阻就是将不确定的信号接口,通过一个电阻拉在低电平,这个电阻就是下拉电阻 PWM PWM即脉宽调制,其本质原理是“恒流斩波”:改变负载开关的开关频率或直流电流的接通和通断时间,就可以改变加载到负载上的电压和电流的平均值。从这个意义上说,PWM类似与负载串联的可调电阻。 (具数据统计,使用直流斩波器代替变阻器可节约电能约25%,利用直流斩波原理制作的器件角DC/DC,这一原理还实现了PWM技术。) PWM可以用软件模拟,也可以用硬件实现,在计算机中通常使用定时器来产生PWM。通过软件模拟,即通过延时来调整高低电平的输出时间,进而调整脉宽。脉宽即脉冲宽度,脉冲与脉宽是两个概念。 While(1) { PORTA = 0XFF; DELAY(1); PORTA = 0X00; DELAY(1); } 该代码可产生占空比为50%的方波,占空比表示一个PWM周期内有效电平所占时间与整个周期的比值,有效电平通常指高电平,在一些应用中也可能是低电平。 上述图示PWM占空比为50%,红色部分表示PWM一个周期。 高峰表示Vcc,低谷表示GND 实际产生的电压值为(Vcc - 0v)x50% PWM占空比为100%时的情况,此时负载电压为Vcc,以最高能量工作。 PWM占空比为0%的情况,此时负载电压为0v,不工作。 PWM可以用来驱动电机以,通过调整占空比,进而调整步进电机电压,从而控制其转速。 PWM也可以驱动LED灯,通过调整占空比,进而调整LED电压,让其产生“呼吸”效果。 可见要产生PWM,就必须实现快速的开关通断,这个速度是如此之快,以至于手工和机械都是完成不了的,所以必须使用继承电路IC实现。 PWM作为一种波形,携带这两种信息,一个是脉宽->占空比,另一是频率,前者是主要信息,是PWM的本质,后者是任何波形都携带的信息。脉宽信息决定着实际输出电压,频率信息决定着脉宽信息的改变速度。比如,当PWM用于驱动LED呼吸时,PWM脉宽决定了LED的呼吸(脉宽从0%~100%~0%改变),而PWM频率信息决定了LED的呼吸速度。又比如,当PWM用于驱动电机时,PWM脉宽决定了电机速度,而PWM频率决定了电机切换速度的速度。 附:PWM波是非正玄波,这使得输出的能量不能得到充分利用,于是产生了正玄波脉宽调制SPWM、SVPWM。 附:简易的呼吸灯设计 整个程序分两段,在死循环中,前段为PWM产生代码,后段为闪烁方向设计。闪烁方向设计让呼吸灯从”亮到灭到亮”变化,否则“从亮到灭,从亮到灭”变化。 要注意,上述程序延时使用微秒,而不是毫秒或秒,微秒级别的延时让人的眼睛看不到灯闪烁的过程(为了产生PWM只能让让灯亮灭),这里也利用了人类的视觉暂留原理,实际上灯是在飞速的闪烁,要看到这个效果,只需把微秒改成毫秒即可。 还有,数值一定要连续,才能使PWM模拟从0~5V的持续电压变化,如果给定数组查表,而不是从0累加,那么数组值一定要密集(采样足够多),否则也会产生毫秒级别的闪烁。(也可以理解为,要使尽量使PWM接近正弦波) 最后,改变微秒级别的闪烁值(setTimeCount),就可以改变灯的呼吸速度,从上述程序中也可以看到,一定要保证PWM周期固定,然后改变亮与灭的占空比即可。 附:通过示波器测量,上述程序产生的是方波,PWM本质就是方波,所以测量无误,即便程序模拟使PWM近似正玄波,但结果还是方波。 测量晶振结果为正弦波(晶振产生的是正弦波,通过电路滤波后形成供电路系统使用的方波) PWM恒流斩波效果的实现需要PWM周期足够小 (一般刷新频率子60Hz以上就可以了,这个跟电脑显示器的刷新频率一致,一般PC机显示屏的最低刷新频率是60Hz,即1秒刷新60次[即16.7ms/次]) 如果一定要使用较大周期怎么办呢? 比如1s为周期可以实现恒流斩波效果 10s呢? 10s就必须将其均匀化! 如果在1s时使用的是50%方波,则在10s周期时,每1s都分为两部分,这样10s就被分为20个部分,其中10个部分为50% HIGH level,另外10个部分为50% LOW LEVEL 如此就在比较大的周期中实现PWM效果了! 如果在1s时实现的是20% · 80% 同样在10s周期中将每1s都实现20%~80% 这样,无论在多长的周期中,都可以实现PWM效果 代码 // 20% 占空比 PWM周期1s delay(0.2) PORTA = 0X00; delay(0.8) PORTA = 0XFF; // 20% 占空比 PWM周期5s 1s均化 for(int i=0; i{ delay(0.2) PORTA = 0X00; delay(0.8) PORTA = 0XFF; } 占空比才是真正PWM应用的,其实就是开关的打开和关断的时间比值,这个比值在宏观上可以欺骗人眼,于是形成和电位器一样的作用。比如对一个电灯来说,你在1秒内,打开开关0.5秒,再关闭0.5秒,如此反复,那么电灯就会闪烁,但是如果是1毫秒内,0.5毫秒打开,0.5毫秒关闭,由于视觉暂留作用,也可能由于灯光的亮灭速度赶不上开关速度(还没全亮就又没电了),于是人眼不感觉电灯在闪烁,而是感觉灯的亮度少了一半。同理,如果是0.1毫秒开,0.9毫秒灭,感觉灯的亮度就只有1/10了。对于电机的原理也差不多,开关开时电机加速,关闭时电机减速,根据是加速时间多还是减速时间多,我们感觉总体的转速就是快了或慢了。当然,具体分析时还需考虑电机的电感作用,电感有滤波效果,但是用这个方式去理解也是成立的。 回到前面的频率问题,就如刚才说的,1秒内,0.5秒开,0.5秒灭,占空比是50%对吧?那么,1毫秒内,0.5毫秒开,0.5毫秒灭,占空比也是50%,对吧?如果是1秒呢,频率就是1HZ,如果是1毫秒,频率就是1KHZ,显然,同样是50%占空比,如果频率是1HZ,那电机肯定是跳着走的,灯光肯定闪得可以跳舞,不具有调速和调光的意义。 PWM 主要用途是通过对一个的电源开关控制可以得到输出电压大小和占空比成正比的电源,虽 然DAC 也可以输出与数字对应的电压,但这个电压驱动能力很弱,要想提供比较大的驱动能力实现 起来很难,但PWM 很简单,只要用三极管等做为开关控制元件向后面的大负载提供电源。对电源的 控制实际上也是对输出功率的控制,所以PWM 在马达转速、灯光亮暗这类控制上有着广泛的应用。 一周搞定系列 之 模电 第一章 基本元器件 二极管 二极管就是 把PN结封装起来 然后在P和N两端加个引线 特性: 单项导电性、伏安特性 属性: 1. 普通二极管导通后的电压值是(约)0.7V,0.5V时开始导通 2. 发光二极管导通后的电压值是(约)1~2V,电流范围是5~20mA,电流和电压不在此范围时,发光二极管不导通、不发光 3. 二极管反向不导通,但当反向电压足够大时也会导通,此时称为反向击穿 稳压二极管 具有稳压作用的二极管,用到了二极管的伏安特性。 在给二极管施加反向电压时,电流值处于 导通与击穿之间时,二极管电压处于稳定区域,此时二极管具有稳定(与其并联的)器件电压的功能。 要注意的是要选择合适二极管,给其施加的反向电压不能太小,太小将不能导通,太大将击穿二极管 稳压二极管的使用形式为:电阻和二极管的串联,二极管反向接入电压 整流二极管 用于把交流电编程脉动直流电 交流电是正弦波,将正弦波反向部分切除(即180到360的相位切除,因为二极管反向不导通),得到的即是脉动直流电,类似PWM方波,所以称为脉动 开关二极管 导通 和 截止 两种状态的切换时间比普通二极管快,使得其在电路中有开关作用,用于保护反向电流损坏所保护的器件 电容 电极板+中间介质封装而成。 电容具有旁路(支路)、去耦、滤波、和储能的作用 旁路 1)使输入电压均匀化,减少噪声对后级系统的影响 来自于电源的电压不保证是稳定的,或不保证一直是稳定的,不稳定的直流电压将影响数字电路系统的逻辑判定,这将导致致命的做错。 不稳定的直流电压的波形类似周期多变的交流电,而电容具有“通交流,隔直流\"的功能 ,在电源接入器件之间 并联旁路电容于GND,当有不稳定的直流电通过时将通过旁路电容过滤到GND 旁路电容应接到离器件较近的位置,而不是离电源较近的位置 2)进行储能,当信号变化过快时进行电压补偿 器件的高低电平快速切换可能导致输入电压供应不及时,此时旁路电容可将存储的电能及时释放补充给器件使用 去耦(退耦) 去耦电容和旁路电容类似,区别是旁路电容用于输入信号、去耦电容用于输出信号. 耦合-辞海 : 两个元素/量之间,其中一个量的变化,导致另一个元素/量的变化的一种关系 去耦连接器件输出信号,减少了输出信号不稳定信号对周围/下级器件的耦合作用 去耦电容一般相对较大,如10uF、旁路电容较小,如0.1uF 0.01uF 滤波 去耦/旁路电容的容值选择与滤波电路有关 这也与信号频率相关,因为大电容用于滤除低频噪声,而小电容用于滤除高频噪声 注意 铝解电容 连接分正负极,磁片、独石电容不分正负极 三极管 PNP 或 NPN结组成的晶体管 三极管具有三个极:b-basic基极 c-collector集电极 e-emit发射极 定义:称b-c之间的结为集电结、称b-e之间的结为发射结 三极管是利用“输入电流”控制“输出电流“的元件 即使用b基极的电流来控制e发射极的电流,可以把三极管类比一个水桶,c是储水区、b是开关区、e是流水区, b同样需要使用水流来控制开关的大小,b没有水流入时开关闸门关闭,C的水留不下来,e流不出来水,这种情况称为三极管的 “截止”状态 b给一定的水流,闸门开一定大小,此时c流下水,并且流下的水是b的倍数,此时称为三极管的“放大状态” b继续增大输入水流,闸门开到了最大,此时称为三极管的“饱和状态” 将水流依次比作电流,则有:Ie = Ib + Ic。Ic = βxIb ,即Ie = (1+β)xIb 定义:设b c e的电压为Ub Uc Ue Ub > Uc 称为集电结正偏,反之为集电结反偏 Ub > Ue 称为发射结正偏,反之为发射结反偏 要使三极管工作在截止状态,使Ue > Ub,即发射结反偏,或三极管电压为0 放大 ,使Uc > Ub, Ub > Ue, 即集电极反偏,发射极正偏 饱和 ,使Ub > Ue, Ub > Uc,即发射极和集电极都正偏 处于截止状态时,集电极与发射极之间相当于开路。 处于放大状态时,Ic由Ib控制 处于饱和状态时,集电极与发射极之间电压很小,相当于导线 工程上认为饱和时Uce=0.3V(硅)或0.1V(锗) 饱和状态时,Ic不再由Ib控制 附:三极管的特征频率 三极管工作也受(脉冲)频率的限制,但基本上可以满足大部分单片机,如9013为150MHz 场效应管 类似三极管,也是PN结构造的晶体管,三个电极为G-栅极、D-漏极、 S-源级 (类比三极管中的b、c、e) 不同于三极管的是场效应管是利用“输入电压”控制”输出电流“的元件 控制的电流为Id,Id受Uds和Ugs影响, 当Uds很小时,Id随Ugs的增大而增大、减小而减小,约成线性关系,称该区域为场效应管的可变电阻区 当Uds在X范围时,Id随Ugs变化,此时不受Uds影响,该居于称为场效应管的恒流区 当Uds小于1.5V时,Id=0,场效应管不导通,该区域为截止区 当Uds大于Y时,场效应管被击穿,Id突然增大,注意要对场效应管击穿做Id限制,否则管子将被烧坏,该区域称为击穿区 在横流区与击穿区之间的区域称为“过损耗区“,长期间在该区域工作会导致场效应管过热,为此要做好散射措施,如加散热片 VS 场效应管和三极管实现的功能类似,目的是控制输出电流,三极管的特点为: 1)电流控制器件,利用基极电流来控制晶体导电能力 2)输入阻抗不高 3)噪声大 4)反应速度快 场效应管的特点为: 1)电压控制器件,利用电压产生的电场来控制导电能力 2)输入阻抗极高(这意味着较小电流将产生较大电压,适合电压控制器件) 3)噪声小 4)反应速度慢 光耦 光耦实现了 “电-光-电”的转换,有发光二极管和光敏三极管组成 信号输入 发光二极管发光,光被光敏三极管接收,三极管决定电路通断 光耦又称光电耦合器(耦合见辞海),是小电流控制大电流或小电压控制大电压器件的一种安全方式,因为这是一种“无接触、无反弹”式电路控制 发声器件 喇叭、蜂鸣器等 喇叭为无极性器件,即没有正负之分 蜂鸣器分为有源和无源的,无源蜂鸣器内部没有震荡源,直接用直流不能驱动,需要2KHZ-5KHZ的方波才能驱动 ,有源蜂鸣器内部含有震荡源,直接输入(1.5V-15V)直流就可以发出声响 继电器 类似光耦,用低电压小电流去控制高电压大电流 继电器常用在开关速度不高的场合,否则使用光耦 光耦vs继电器 光耦 :无触点、开关速度快、寿命长、负载能力小 继电器 :有触点、开关速度慢、寿命短、负载能力大 所以,要求大负载能力且开关速度较慢的场合使用继电器,而小负载能力且开关速度较快的场合使用光耦 PS 电流与感觉 交流电 直流电 数码管 通过控制不同的LED灯来显示所需要的字符0~F 瞬态高压抑制器 TVS 二极管封装形式的高效保护器,放置瞬时高能量冲击,保护精密器件被各种浪涌脉冲破坏 1、加在信号和电源线上,能防止微处理器,人体 静电、交流浪涌或噪声,导致处理器的失灵。 2、能释放超过10000V,60A以上的脉冲,并能持 续10ms,而一般的TTL器件,遇到30ms的10V脉 冲时,便会导致损坏,所以利用TVS是既可以防止 器件损坏,也可以防止总线之间开关引起的干扰。 3、将TVS放置在信号线和地之间,能避免数据及 控制总线受到不必要噪声的影响。 一周搞定系列 之 模电 第二章 基本电路验证与分析 基本放大电路 基本放大电路的核心是三极管,电阻和电容辅助 三极管放大电路是小信号的放大,常用器件最大通过电流也只有几百毫安,所以输入信号不能太大 反馈 凡是将放大电路输出端的信号(电压、电流)的一部分或全部引回到输入端,与输入信号叠加,称为反馈 负反馈 - 引回的信号削弱了输入信号 正反馈 - 引回的信号增强了输入信号 电源电路 由整流桥、电容、二极管组成的电路 开关电源 集成运算放大器 具有很高放大倍数的多级 直接耦合的 运算放大电路 是发展最早、应用最广泛的 模拟集成电路 特点: 高增益、高可靠性、低成本、小尺寸 一周搞定系列 之 模电 第三章 仪表放大电路 积分运算电路 微分运算电路 有源滤波电路 采样保持电路 文氏桥振荡电路 功率放大器 功率放大电路是一种以输出较大功率为目的的放大电路 特点: 输出信号电压大 输出信号电流大 放大电路的输出电阻与负载匹配 电压放大器与功率放大器的区别 电压 - 不失真的提高输入信号的幅度,通常工作在小信号状态 功率 - 不失真或轻度失真的条件下提高输出功率,通常工作在大信号状态 一周搞定系列 之 模电 第四章 实际电路应用 多路稳压电源 数控恒流源 电子及其运动 是电子学的核心,是解释所有有关电的现象的原理 电流的本质是电子的运行,电压是导体两点之间的电流不平衡导致的,本质是导体两点之间电子多少导致的 场效应管+三极管驱动电路 1KHz脉冲测试没有问题 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/hardware/Digital.html":{"url":"pages/hardware/Digital.html","title":"Digital Elec","keywords":"","body":"芯片及相关术语 缓冲器 74HC244是8路正相缓冲器/线路驱动器 芯片用于数据同步以解决MUC与外设速度不匹配的问题,同时增强MCU的负载能力以驱动更多外设,又因其具有三态门,故还有隔离保护功能。 总线驱动器: 一.解释 MCU具有一定的负载能力,如果外设过多或所需驱动电流/电压导致MCU负载能力不够,就需要驱动器来提升驱动能力。总线驱动器具有很大的扇出系数,可将输入逻辑信号进行功率提升送到输出端。总线驱动器一方面可实现对总线的驱动,另一方面也可实现对总线的隔离,隔离的能力还是来自于三态门。 功率提升的本质是电流的提升。 二.应用 在屏幕显示及大部分消费类电子产品中常需要驱动器。 译码器: 译码是编码的反过程,是将二进制代码翻译成特定的输出信号。 分类: 二进制译码器 又称n->2ⁿ线译码器,即将n种二进制输入组合翻译成2ⁿ种高低电平信号。 74HC138是二进制译码器中的一种 二 - 十进制译码器 将二进制代码翻译成十进制数。这种译码器有4个输入端10个输出端。 显示译码器 将二进制代码翻译成显示器可显示的数字或文字。 时钟 时钟 = 协调 协调系统部件工作节奏 各干各的是不行的 必须有统一的节奏(注意是统一而不是同一,如:部件A的工作节奏[频率]是1秒中100次,部件B的节奏为2倍的A ,这是统一的节奏,也可以说是所有部件/器件的工作频率是可以相互逻辑推算的) 它的角色像人体的心脏,像乐队的指挥家 三态门 概念 TTL电路只有高电平(1)和低电平(0)两种状态,而三态门(TSL)具有高电平、低电平和高阻态(Z)三种状态,故称三态。三态门的核心就是高阻态的应用,在半导体电路结构中不可能使用闸门开关来闭合电路(设计上和速度响应上都是不现实的),而高阻态(电阻无穷大)可以被认为是开路状态,起到了半导体电路的开关作用 - 半导体电路控制开关。 符号 应用 1. 总线的分时复用 三态门主要用于TTL电路与总线间的接口电路,如果一个设备要挂到总线上,则必须要经过三态门,因为总线上一个时刻只能与一个设备通信,此时其它设备要呈高阻态 2. 数据的双向传输 通过两个三态门的设计可实现一根线路的双线传输 一周搞定系列 之 数电 第一章 逻辑门 逻辑门的电路分类 按功能 与 或 非 异或 与非 或非 与或非 跟数学上的与或非一样,如,与:一假则假,在C语言中就是 && 或:一真则真,在C语言中就是 || 非:反之 ,在C语言中就是 ~ 异或:同假亦真 只不过表达式不太一样:如,与:Y = AB 或:Y = A+B 非:Y = 非A 异或:Y = A 圈加 B 按电路结构 TTL集成门电路 输入端和输出端都用三极管的逻辑门电路 COMS集成门电路 用互补对称MOS管构成的逻辑门电路 按功能特点 普通门,推拉式输出 输出 开路门 三态门 COMS 传输门 高电平和低电平 高低电平是在某一范围内的电位值,非固定值,也非固定范围 正逻辑: 高电平 3.5~5V 低电平 0~0.3V 负逻辑: 高电平 0~0.3V 低电平 3.5~5V OC门 - Open collector gate (三极管的)集电极开路的门电路 1. 自己加上上拉电阻和电源可以增加驱动能力 2. 实现“线与”逻辑 OD门 - 漏极开路的门电路,功能类似OC 三态门 具有三种状态的门电路,分别为高电平、低电平、高阻态 TTL电路只有高电平(1)和低电平(0)两种状态,而三态门(TSL)具有高电平、低电平和高阻态(Z)三种状态,故称三态。三态门的核心就是高阻态的应用,在半导体电路结构中不可能使用闸门开关来闭合电路(设计上和速度响应上都是不现实的),而高阻态(电阻无穷大)可以被认为是开路状态,起到了半导体电路的开关作用 三态门的应用 总线的分时复用 三态门主要用于TTL电路与总线间的接口电路,如果一个设备要挂到总线上,则必须要经过三态门,因为总线上一个时刻只能与一个设备通信,此时其它设备要呈高阻态。 数据的双向传输 通过两个三态门的设计可实现一根线路的双线传输。 COMS传输门 COMS门电路 VS TTL门电路 1. 功耗极低 2. 抗干扰能力强 3。电源电压范围宽 4. 输出信号摆动幅度大 5. 输入阻抗高 6. 扇出系数大(带负载能力强) 7. TTL门比COMS门电平反转速度快一些 TTL电平:晶体管-晶体管逻辑电平,是计算机电路中的标准电平,它使用+5v=逻辑1、0V=逻辑0。 TTL与CMOS TTL电路速度快、延迟小、功耗高、抗噪声能力差 CMOS电路速度慢、延迟高、功耗低、抗噪声能力强 TTL电平的实际标准 输出: 高电平 - >2.4V 低电平 - 2.0V 低电平 - 0.7 x Vcc 输出 - >0.9 x Vcc 可见CMOS电平的高低电平取值是依电源电压而定的 ,高电平接近电源电压,低电平接近0 一周搞定系列 之 数电 第二章 组合逻辑电路 由逻辑门电路组合而成的电路 一周搞定系列 之 数电 第三章 编码器和译码器 二进制代码与某种编码的相互转换 编码器的类型 1. 二进制编码器 用N位二进制对2^n个输入信号进行编码的电路 2. 2-10进纸编码器 将0~9十个十进制数转换成二进制的译码电路 3. 优先编码器 一周搞定系列 之 数电 第四章 触发器 数字电路分为 组合逻辑电路 和 时序逻辑电路 两类 组合逻辑电路的基本单位是 门电路 时序逻辑电路的基本单位是 触发器 门电路在某一时刻的输出信号完全取决于该时刻的输入信号,没有记忆功能 触发器具有记忆功能,能够在无输入信号的时候,保持上一次输入信号的状态 触发器:每个存储单元电路上引入一个时钟脉冲(CLK)作为控制信号,只有CLK到来时电路才被“触发”而动作,并根据输入 信号改变输出状态,这种在时钟信号触发时才能动作的存储单元电路,称为触发器. 触发器的现态和次态 现态Qn ---- 触发器接收输入信号之前的状态 现态Qn+1 ---- 触发器接收输入信号之后的状态 分类 从电路结构不同分:基本触发器、同步触发器、边沿触发器 基本触发器: 输入信号直接加到输入端,是触发器的基本电路结构,是构成其它触发器的基础 同步触发器: 输入信号经过控制门输入,控制门受时钟信号CP控制 边沿触发器: 只在时钟信号CP的上升下降沿时刻输入信号才能被接收 从逻辑功能不同分:RS触发器、JK触发器、 D触发器、T触发器、T‘触发器 一周搞定系列 之 数电 第五章 计数器 用来统计输入计数脉冲个数的电路 计数器由触发器构成,因为触发器具有记忆功能,1个触发器单元能存储一位二进制数 应用:计数、定时、分频 一周搞定系列 之 数电 第六章 电路设计 (无程序控制的,纯电路设计,如简易秒表、抢答器等等) ----- IO扩展的方法:① 逻辑芯片 ② FPGA/CPLD Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 14:41:02 "},"pages/expansions/XML.html":{"url":"pages/expansions/XML.html","title":"XML","keywords":"","body":"1 XML Base 1.1 Introduction XML - EXtensible Markup Language 可扩展标记语言,由W3C开发,用于传输和存储数据,是互联网进行数据传输的最常用的信息传输工具。 [info] VS HTML XML是HTML语言的扩展,遵循DOM模型,其标签可自定义,具有自我描述性。XML不是HTML的替代,其焦点是数据的内容而非外观,旨在信息的存储和传递。 1.2 Feature XML文档内容是纯文本,仅作为树型结构体的信息包装载体,能处理纯文本的软件都可以处理XML文档,没有任何行为的XML是不作为的。生成和解析程序可以针对性的处理XML标签,标签的功能性意义依赖于应用程序的实现。 1.3 Structure XML文档中一切皆节点(Node),分为元素节点(Element Node)、属性节点(Attribute Node)和文本节点(Text Node),元素节点是一对封闭的标签...,可嵌套,属性节点是元素节点标签中的属性,文本节点是元素节点标签之间的文本内容。 Harry Potter 2005 29.99 [info] 文档节点 整个XML文档也被视作一个节点,称为“文档节点”。 1.4 Grammer 1.4.1 Declaration XLM声明定义在文档首行,用于指示该文档版本、编码等信息。XML声明是可选的,但属于W3C推荐规范。 [info] standalone 'yes' 表示该文档独立存在,即不引用外部Schema进行内容校验,'no' 表示不独立存在,即要引用外部Schema进行内容校验。 1.4.2 Lable XML标签大小写敏感,所有标签必须成对存在(大小写要对应),XML标签必须正确嵌套。 [info] Singal lable 单标签是合法标签,如 1.4.3 Attribute XML中的属性用于提供关于元素的额外(附加)信息,XML标签的属性值必须加引号(单引号或双引号,当属性值中有双引号时需要用单引号,也可以使用引用代替内部引号)。为扩展和维护,应尽量使用元素来描述数据,而使用属性来提供与数据无关的信息。多个属性值之间用空格分隔。 1.4.4 Quote Quote Character Description < 小于 > > 大于 & & 和 &apos ' 单引号 " \" 双引号 1.4.5 Comment/Space/Line break 注释与HTML相同,在HTML中连续的空格会被合并成一个,在XML中这样的空格会被保留,XML在Unix中新行以LF字符存储、在Mac中以CR字符存储、在Windows中以LF或CR存储。 1.4.6 Name 元素和属性名由字母、数字和下划线组成,以字母和下划线开头,不能使用屏蔽字“xml”(或XML、Xml等)。 [info] 经验 作为数据存储语言,XML文档经常有一个对应的数据库,其中的字段会对应XML文档中的元素。有一个实用的经验,即使用数据库的名称规则来命名XML文档中的元素。 2 XML Advanced 2.1 XML DOM DOM - Document Object Model文档对象模型,定义了XML、HTML等文档元素的对象和属性,以及操作和访问它们的方法(接口)。 2.1.1 Feature DOM结构以数据结构中的树泛型来组织,当处理XML时会将整个XML文档读入内存,因此支持应用程序通过操作树的方法(增、删、改、查、遍历等)来操作DOM。 2.1.2 DOM Parse 浏览器解析:所有现代浏览器都内建了用于读取和操作XML的解析器。解析器把XML读入内存,并把它转换为可被JavaScript访问的XML DOM对象。除了DOM之外,还有SAX、JDOM、DOM4J等不同的基于浏览器的解析技术。 函数库解析:XML作为跨平台的存储和传输信息的工具,更多的应用在应用程序中,不同于浏览器的是应用程序并不集成XML解析器,因此要编程实现应用程序对XML文档的解析。 目前已经有很多成熟且开源的XML函数库可以使用,如miniXML、Xerces-C、libxml等。 2.2 XML SAX SAX - Simple APIs for XML, XML简单应用程序接口,由XML-DEV邮件列表开发。SAX将XML视为数据流处理,并使用事件驱动方法,实时、高效、节省空间。SAX的出现是为了解决一些不适用的DOM接口,它不是W3C推荐标准,但拥有广泛支持API标准的接口规范,并已成为“非官方”的事实标准。 2.2.1 Feature 因DOM的内存处理方式,当处理大规模文档时会造成内存空间不足、速度慢、效率低等情况。SAX以数据流的方式实时解析XML文档,并在读取到任何节点时以事件(回调)的方式调用代码,因此更适合处理大规模XML文档。SAX的缺点是只具备读取XML的能力,在内容处理上要在编程实现(自定义回调函数),另外因为不建立内存模型,所以不能随机访问。 2.2.2 SAX Parse SAX Timing 2.3 namespace XML标签是自定义的,解析两个或多个具有相同标签的XML文档就会产生歧义,XML解析器对此的表现是未定义的。有两种方式解决冲突:前缀和命名空间。命名空间类似面向对象语言中的命名空间,在XML文档根元素节点中声明为“xmlns=URL”,其中URL仅作为唯一标识,可以不具备实际意义。前缀的本质是合法的标签,在命名空间中扩展为共享命名空间的标识。 Coffee table Apples 90 Bnanas 120 100 Coffee table Apples 90 Bnanas 120 100 Coffee table Apples 90 Bnanas 120 100 2.3.1 Expansion namespace 扩展命名空间格式为“xmlns:namespace-prefix”,任何使用'namespace-prefix'的节点都共享所声明的同一命名空间。 Coffee table Apples 90 Bnanas 120 100 Coffee table Apples 90 Bnanas 120 100 2.4 Validation 一份XML文档是否合格要满足两个层面:XML语法规范和XML自我描述规范;前者是最基本前提,后者表现在实际应用支持上,如节点名是否正确、节点组成是否完整、属性节点的值是否在枚举之内、值类型是否正确等等。 2.4.1 Technology 验证的方法是通过一份已准备好的验证文件来描述合格的XML文档,以约束其格式和内容。有两种验证技术:DTD(对应文件扩展名'.dtd')和Schema(对应文件扩展名'.xsd');Schema是基于XML技术的DTD替代者。 2.4.2 xsi and schemaLocation 使用哪个约束文档对当前XML文档进行验证是自定义的,但一般要选用根元素节点中链接的验证文档(如果存在的话),在XML文档的根元素节点中链接验证文档的方法是使用xsi扩展命名空间和schemaLocation属性。 ... [info] XSI and XSD \"xmlns:xsi\"表示涉及到xsi项目的内容都来自该扩展命名空间,\"xsi:schemaLocation\"表示使用xsi扩展命名空间中的schemaLocation属性。 2.5 CDATA XML文档中所有的文本数据都会被解析器解析,只有CDATA(Character data)区段会被解析器忽略。在XML中使用“”等字符是非法的,如需使用必须转义为“<”/“>”,但有些文本内容必须显示使用这些字符(如文本内容为Javascript代码),这就需要使用CDATA区段。 3 XML Technology 3.1 XPath 3.1.1 Introduction XPath是使用路径表达式遍历XML文档的语言,内置函数库,Javascript、Python等都实现了XPath功能及其函数。 3.1.2 运算符 运算符 描述 示例 返回值 | 计算两个节点集 //book | //cd 返回所有拥有 book 和 cd 元素的节点集 + 加法 6 + 4 10 - 减法 6 - 4 2 * 乘法 6 * 4 24 div 除法 8 div 4 2 = 等于 price=9.80 true/false != 不等于 price!=9.80 true/false 小于 price true/false 小于或等于 price true/false > 大于 price>9.80 true/false >= 大于或等于 price>=9.80 true/false or 或 price=9.80 or price=9.70 true/false and 与 price>9.00 and price true/false mod 计算除法的余数 5 mod 2 1 3.1.3 路径表达式 表达式 描述 示例 nodename 相对路径-选取此节点的所有子节点 bookstore / 绝对路径-选取根节点 /bookstore // 无视路径-选择根和所有后代节点 book . 当前路径-选取当前节点 .. 上级路径-选取当前节点的父节点 @ 选取属性 /bookstore/book/@lang * 匹配任何元素节点 /bookstore/* @* 匹配任何属性节点 node() 匹配任何节点 Table 3.1.3.1 谓语 描述 示例 [X] 用于定位,X为等式、不等式、数值和函数等谓语 /bookstroe/book[1] Table 3.1.3.2 轴(Axis) 描述 示例 ancestor 选取当前节点的所有先辈(父、祖父等) ancestor::book ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 attribute 选取当前节点的所有属性 attribute::lang child 选取当前节点的所有子元素 child::text() descendant 选取当前节点的所有后代元素(子、孙等) descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身 following 选取文档中当前节点的结束标签之后的所有节点 namespace 选取当前节点的所有命名空间节点 parent 选取当前节点的父节点 preceding 选取文档中当前节点的开始标签之前的所有节点 preceding-sibling 选取当前节点之前的所有同级节点 self 选取当前节点 Table 3.1.3.3 [info] Note 完整的路径表达式是由“轴::节点[谓语]”组成的,但通常只使用“表达式”或“表达式” + “谓语”的方法。 [info] Example /bookstore//book[2]/child::title[text()],选取根节点下的bookstore节点下的所有book元素中的第二个下的所有子元素中的title子元素的文本。 4 XML Parse 4.1 MiniXML Mini XML是一个小型、开源的XML解析库,采用C语言开发,支持 UTF-8/UTF-16 编码(写UTF-8编码的XML文件和字符串、读UTF-8/UTF-16的文件和字符串)。Mini XML设计的初衷是为了替换大而笨重的libxml2库,它很容易移植到嵌入式系统当中,但不进行错误恢复及校验。Official website。 4.2 Xerces-C++ Xerces-C++是大型、功能丰富、开源的XML解析库,包含JAVA、C++、PERL等多种版本,支持SAX和DOM,它对XML进行基本解析外还进行语法检查。Official website。 Xerces类与XML文档对象的对应: 类 对应 DOMNode 文档的所有节点 DOMDocument 文档节点 DOMElement 文档的元素节点 DOMAttr 文档的属性节点 Appendix-A:XML Version and Specification W3C XML规范声明:如果 XML 文档存在错误,那么程序就不应当继续处理这个文档。理由是,XML 软件应当轻巧,快速,具有良好的兼容性。目前XML最新版本为1.0第五版。XML规范和时间线参看https://www.w3school.com.cn/w3c/w3c_xml.asp和https://www.w3.org/TR/xml/。 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/expansions/JDF.html":{"url":"pages/expansions/JDF.html","title":"JDF","keywords":"","body":" p{word-wrap:break-word; word-break:break-all;} 1 Introduction CIP4 (International Cooperation for Integration of Processes in Prepress, Press and Postpress) is committed to building CIMS (Computer Information Management System) of printing industry for prepress, press and postpress. And JDF (used as data carrier) and JMF (used as info carrier) are applied. CIP4 Official Website. JDF (Job Definition Format) is superset of JDF, JMF (Job Messaging Format) and ICS (Interoperability Conformance Specification), based on XML (EXtensible Markup Language) technology. [warning] XML vs JDF JDF applies only Element Node and Attribute Node, not Text Node (except ). And DOM (document OBJ model), xmlns (namespace), XPath (path expression) and Schema (verification) Tech are used. More. 1.1 Workflow Components Roles ATTR Description Machine bare metal prepress, press or postpress machines without JDF integrated Device software interprets JDF and executes the instructions, MAY controls a Machine Agent software create, modify, read and write JDF Controller software initiates Devices and routes JDF MIS (Management Information System) software master controller Components Roles [info] Note Low-level Agent and Controller SHALL implement Device functions. 1.2 Components interactions Components interactions [info] Note Components interactions by JDF as Data Flow and JMF as Info Flow, and JDF is created by top-level Controller/Agent, modified, spwan and merged by intermidiate Controller/Agent, and finally executed by Device. 1.3 Components communication Components communication [info] Note HotFolder via network MAY supported by FTP, SOAP, etc. 2 Data Flow - JDF Jobs are organized in the XML DOM Tree (JDF Instance or Job Ticket) by JDF and recursive nesting element nodes which describes Processes and Resources necessary to complete the job. JDF Node Diagram Job Hierarchy 2.1 Processes Product Nodes with JDF/@Type=\"Product\" describes the job intent. Process Group Nodes with JDF/@Type=\"ProcessGroup\" describes the job processes group. Process Nodes with JDF/@Type=\"[Predefined Process]\" or JDF/@Type=\"Combined\" with JDF/@Types=\"[Predefined Process List]\" describes the specific job process. Classic Processes Model [info] Note Combined nodes are designed for multi-function devices that can excute multi processes. 2.2 Resouces JDF/ResoucePool contains various resources and implemented in current or root process node in each processes described upon. And JDF/ResouceLinkPool describes the usage (Input/Output) of resources and implemented in current process node. JDF/ResoucePool/ResouceRef is used to including resources from other resource pool. Classic Resouces Model [info] Gray Box JDF/@Type=\"ProcessGroup\" with JDF/@Types=[Predefined Porcess List] is deformed node that lacks resources and SHALL NOT BE EXCUTED BY DEVICE. More. 2.3 Job's History JDF/AuditPool stores the Job’s history and can support daily quality control and troubleshooting management reporting needs. And the history SHALL place in output folder after the job ends (when HotFolder communication method is used). [info] Spawn and Merge Jobs may be spawned by Controller/Agent from a complete instance due to purpose of parallel execution, and JDF/AncestorPool stores these info for merge later. 3 Info Flow - JMF Job Messaging Format, based on XML, take HTTP(s) as the communication carrier, used for communication between JDF workflow components. JMF Node Diagram Family Description Query client Query server for messages Command client sends Command to the server Response server sync Response for client Query or Command. Or client sync Response for server Signal Signal server push Signal to the client Acknowledge server async Response for client Query/@AcknowledgeURL='True' or Command/@AcknowledgeURL='True' JMF Family [info] Acknowledge When the server cannot output the result in time, return the Response first and then return the Acknowledge. 3.1 Queue The sets of queue operation is core of JMF/Command to scheduling jobs, and each job is a QueueEntry identified by JMF/Command/@QueueEntryID, and supports priority (0[Low]~100[High]) adjustment. Queue and QueueEntry QueueEntry Lifecycle [info] For Programming The program can provide a memory map with the same status as the queue to synchronize the changes of the queue. [warning] About QueueEntry Sort QueueEntry/@Status=\"Running\" sort before other status, and QueueEntry/@Status=\"Waiting\" watting in Queue with priority sort (DSC 100~0). 3.2 Persistent Channel If the client sends Query/Subscription/@URL, the server will push Signal to the client when the subscribed event occurs, util the server recives the client's Command/StopPersistentChannel. Persistent Channel The server can send Signal to clients (Select from the list of configured URLs) actively without any subscription, to broadcast device functions. That is Hard-Wired. [info] Reliable Signal If the server sends Signal/@ChannelMode='Reliable', the client SHALL do Response with non-empty body. If the client do not response or Response/@ReturnCode!=0, the server SHALL retry until the client do response and Response/@ReturnCode=0. [warning] Note The Signal message a combination of Query and Response messages, and the Query part tells subscribers what to subscribe at that time, and the Response part tells the subscribers what specific events happened. 3.3 Error handling When the JMF message family cannot be processed correctly by the server, Response/@ReturnCode=ERR CODE SHALL be returned. and Response/Notification SHOULD implement. 4 System Building Classes Num Process Result Note Software 11 JDF&JMF CIP4-APP - 10 Xerces-C - 9 HTTP(s) HotFolder - 8 Socket - 7 Modbus InterCom Optional 6 Device drivers Linux - 5 Linux kernel&File system - 4 uboot - Hardware 3 PCBA PCB - 2 Layout - 1 Schematic design - CIP4 Proj development framework [info] Note PCB (1/2/3), Linux (4/5/6) and InterCom (7) are omitted. 4.1 Packaging JDF (and digital assets which it refers) and/or JMF MAY be exist standalone or packaged as MIME and sent to Device from Controller/Agent. MIME Headers Values Description Content-Type application/vnd.cip4-jdf+xml JDF entity application/vnd.cip4-jmf+xml JMF entity multipart/related mixed entity Content-ID US-ASCII character refer to 'cid:' Content-Transfer-Encoding 8bit - binary - base64 - MIME entity used in CIP4 [info] Suffix *.mjd suffix is used when JDF is the first entity of MIME, and *.mjm suffix is used when JMF is the first entity of MIME. The first body part of the MIME 'Content-Type:multipart/related' message SHALL be the JMF Message. Internal links are defined using the cid URL (which corresponding Content-ID without ''). Subsequent sections are the JDF Jobs followed by the linked entities. [info] Note Only one JMF can exsit (if it must exist) and but multi JDF and digital assets can exsits in mixed entity. 4.2 Communication HotFolder and HTTP(s) are used to exchange data and info between Controllers/Agents and Devices. 4.2.1 File Based Portocol (JDF) HotFolder is a directory that is monitored by OS in real-time, once a file is entered, it will be processed immediately. An Input HotFolder and Output HotFolder (which provides for opposite system) SHALL be implemented. Communication by HotFolder JDF instance with element node SHALL be written to Output HotFolder when Devices finishes processing, for Controllers/Agents polling. [info] Note *.jdf/*.mjd reference files MAY be written into a exsiting directory of the Input HotFolder, or a new directory 'D' which created by Controllers/Agents in Input HotFolder. 4.2.2 HTTP Based Protocol (JDF+JMF) HTTP is a stable protocol with a well defined query-response mechanism, and only post method is used for CIP4, the content is MIME package. Communication by HTTP(s) [info] Note Controllers/Agents implements HTTP Server and Devices implements HTTP Client. 5 Development 5.1 Library Building Linux based and gcc (including cross-compilation toolchains) and cmake SHALL BE up to date, 5.1.1 Packages JDFLibC-sources-b11.tar.gz (depend on : curl, xerces-c++), and syswatcher, superline, httpcd (depend on : libmime + socketcd). [info] Note In fact, zlib and libpng are also required, but are usually included in cross-compilation toolchains or system environments. 5.1.2 Building 5.1.2.1 xerces-c $ tar -xvf xerces-c-3.2.2.tar.gz && cd xerces-c-3.2.2 $ ./configure --host=[HOST] CFLAGS=-fPIC CXXLAGS=-fPIC //Alter macro 'XERCES_XMLCH_T' with value 'wchar_t' for ./configure and ./src/xercesc/util/Xerces_autoconf_config.hpp. $ make $ mkdir ./lib/[Linux]/[BITW] $ cp ./src/.libs/* ./lib/Linux/[BITW] [info] Note [HOST ] : if the format is A-B-C-XXX, then A-B-C is host name, such as 'arm-linux-gnueabihf'. If it's the host, the --host option can be ignored. [BITW ] : x86 or x64. [Linux] : Windows, MacOS or Linux 5.1.2.2 curl $ tar -xvf curl-7.55.1.tar.gz && cd curl-7.55.1 $ mkdir ./install $ ./configure --host=[HOST] --prefix=`pwd`/install $ make && make install [info] Note The library SHALL copy into somewhere where the compiler can be detected. 5.1.2.3 JDF $ mkdir JDFLibC $ tar -xvf JDFLibC-sources-b11.tar.gz -C ./JDFLibC $ cd JDFLibC $ mkdir ./external/Xerces-C $ cp -rf ../xerces-c-3.2.2/* ./external/Xerces-C $ chmod +x build_[linux].sh && ./build_[linux].sh $ ls ./bin/[Linux]/[x64] AddJDF BookJDF CheckJDF libJDFTools.so libJDFToolsWrapper.so MergeJDF SpawnJDF SpecJDF [info] Note libJDF*.so is dynamic library for development, and others is command line program for JDF test. 5.2 Programming IT INVOLVES COMPANY SECRETS, SO IGNORE. Appendix-A : Interoperability Conformance Specification ICS defines the minimum set of JDF with multi parts. Base ICS defines the most basic functions that any JDF products should implement. Other ICSs are based on the Base ICS and describes the minimum implementation in different aspects. ICS Classes Appendix-B : Predefined Processes [info] Note Prepress and Press processes are omitted. B.1 Postpress Processes Processes Translation Description BlockPreparation BoxFolding - 定义了将坯料折叠并粘合到折叠的扁平盒中进行包装的过程 BoxPacking 装箱 - Bundling 捆绑 把书芯压紧并扎成捆 CaseMaking - (硬)封面的制作过程 CasingIn - 将书芯装入封面的过程 ChannelBinding 螺旋装订 - Collecting 配帖 将书帖或多张散印书页按照页码的顺序配集成书 CoverApplication - 定义了将软封面应用到书芯的过程 Creasing 压痕 - Cutting 裁切 - DieMaking 模具制造 - Embossing 印花 使用浮雕模具压印图形的过程 EndSheetGluing Feeding Folding 折叠 Gathering Gluing 涂胶 在书皮贴紧书脊处涂胶 HeadBandApplication HoleMaking 制孔 - Inserting Jcketing 护套/书皮 书本外层的保护材料 Labeling 标签 标签可以包含收件人、产品、产品数量等信息 Laminating 层压 泛指覆膜的过程 Plletizing 托盘 - Perforating 打孔 描述组件打孔的过程 PlasticCombBinding 塑料梳齿装订 - PrintRolling RingBinding 圆环装订 - SaddleStitching 骑马订 ShapeCutting ShapeDefProduction Shrinking 收缩 SpinePreparation - 书芯脊柱的生产的准备过程 SpineTaping - 书芯脊柱贴胶带(和牛皮纸等)的过程 Stacking 堆叠 - StaticBlocking Stitching 装订 - Strapping StripBinding ThreadSealing ThreadSewing Trimming 三面裁切 - WebInlineFinishing Winding WireCombBinding 线梳齿装订 - Wrapping 包裹 将捆扎物、托盘等物体打包的过程 B.2 General Processes Processes Translation Description Approval Buffer 缓冲 用于资源缓冲,如管道资源等 Combine 合并 将多个物理资源(PhysicalResource)或逻辑资源(如RunList)合并 Delivery 递送 描述物理资源(PhysicalResource)的传送过程 ManualLabor - 描述任何情况下资源被手动处理的过程 QualityControl 质量控制 - ResourceDefinition 资源定义 - Split 分割 将多个物理资源(PhysicalResource)或逻辑资源(如RunList)分割 Verification 验证 Appendix-C : Predefined Resources [info] Note Prepress and Press resources are omitted. C.1 Intent Resources Resources Description BindingIntent - Component 组件,用于描述(印前和印后)中间件或成品的组成部分 DeliveryIntent 交付,物力资源、中间产品等交付 EmbossingIntent 压花、烫金 FoldingIntent - HoleMakingIntent - InsertingIntent - LaminatingIntent 层压 LayoutIntent 记录产品组件的完成页面的大小 MediaIntent 描述用于产品组件的媒介 PackingIntent - PublishingIntent - ShapeCuttingIntent - JDF/ResoucePool/[Resources]/@Class=\"Intent\" C.2 Parameter Resources Resources Description ApprovalParams - ApprovalSuccess - Assembly - BinderySignature 一套印刷好的纸张 BoxFoldingParams - BoxPackingParams - BufferParams - BundlingParams - ByteMap - CaseMakingParams - CasingInParams - ChannelBindingParams - CoilBindingParams - CollectingParams - Company 描述公司、联系人和地址等信息 Contact 人或地址的联系 ContentList - CoverApplicationParams 定义将封面应用到书块的参数 CreasingParams 定义了纸张折痕或刻槽的参数 CustomerInfo - CutBlock - CutMark - CuttingParams - DeliveryParams - DensityMeasuringField 定义密度测量领域的信息 EmbossingParams - Employee 关于设备或机器操作员的信息 EndSheetGluingParams - FeedingParams - FileSpec 文件或一组文件的说明 FoldingParams 描述了折叠参数,包括折叠步骤、顺序 GatheringParams - GlueApplication 硬皮书和软皮书的胶水应用 GluingParams - HeadBandApplicationParams - HoleList - HoleMakingParams - InsertingParams - InsertSheet - JacketingParams - LabelingParams - LaminatingParams - Layout 布局结构的根元素 ManualLaborParams 手工工作参数的限定 NodeInfo 包含关于计划的调度和消息路由的信息 PalletizingParams - PerforatingParams - PlasticCombBindingParams - PrintRollingParams - ProductionPath - QualityControlParams - QualityControlResult - ResourceDefinitionParams - RingBindingParams - Shape - ShapeCuttingParams - ShapeDef 描述二维曲面的结构设计,其路径描述了不同的加工操作,如切割、压痕、穿孔等 ShapeDefProductionParams 结构设计参数 ShrinkingParams - SpinePreparationParams - SpineTapingParams - StackingParams - StaticBlockingParams - StitchingParams - StrappingParams - StripBindingParams - ThreadSealingParams - ThreadSewingParams - TrimmingParams - VarnishingParams - WebInlineFinishingParams - WindingParams - WireCombBindingParams - WrappingParams - JDF/ResoucePool/[Resources]/@Class=\"Parameter\" C.3 Consumable Resources Resources Description Media 物理媒介 MiscConsumable - Pallet 用于装货的托盘 RegisterRibbon - Strap - JDF/ResoucePool/[Resources]/@Class=\"Consumable\" C.4 Handling Resources Resources Description PrintRolling - Tool - UsageCounter 用于跟踪设备的使用情况 JDF/ResoucePool/[Resources]/@Class=\"Handling\" C.5 Implementation Resources Resources Description Device 关于特定设备的信息,如功能 JDF/ResoucePool/[Resources]/@Class=\"Implementation\" C.6 Quantity Resources Resources Description Bundle 用于描述各种Compnents的设置,该资源可被许多印前和印后过程创建 Component - JDF/ResoucePool/[Resources]/@Class=\"Quantity\" [info] Component Almost every post-press process contains one or more components resources (input and ouput). Appendix-D : Error Codes ReturnCode Description 0 Success ReturnCode Description 1 General error 2 Internal error 3 XML parser error (e.g., if a MIME file is sent to an XML Controller). 4 XML validation error 5 Query Message/Command Message not implemented 6 Invalid parameters 7 Insufficient parameters 8 Device not available (Controller exists but not the Device or queue) 9 Message incomplete. 10 Message Service is busy. 11 Synchronous mode not supported for message. No @ AcknowledgeURL is specified and the Message can only be processed asynchronously and was not processed. (Error) 12 Asynchronous acknowledge not supported for message. No @ AcknowledgeURL is specified and the Message was processed. The resulting Acknowledge can only be emitted asynchronously. (Warning) 13 Reliable Signals not supported. Subscription denied. Protocol errors ReturnCode Description 100 Device not running 101 Device incapable of fulfilling request (e.g., a RIP that has been asked to cut a Sheet). 102 No executable Node exists in the JDF 103 JobID not known by Controller 104 JobPartID not known by Controller 105 Queue entry not in queue 106 Queue request failed because the queue entry is already executing 107 The queue entry is already executing. Late change is not accepted 108 Selection or applied filter results in an empty list 109 Selection or applied filter results in an incomplete list. A buffer cannot provide the complete list queried for. 110 Queue request of a Job submission failed because the requested completion time of the Job cannot be fulfilled. 111 Subscription request denied. 112 Queue request failed because the Queue is \"Closed\" or \"Blocked\" and does not accept new entries. 113 Queue entry is already in the resulting status. 114 QueueEntry /@ Status is already \"PendingReturn\" , \"Completed\" or \"Aborted\" and therefore does not accept changes. Modification note: starting with JDF 1.4, \"PendingReturn\" added. 115 Queue entry is not running. 116 Queue entry already exists. Used when a QueueEntry with identical JobID , JobPartID and Part already exists. 120 Cannot access referenced URL. URI Reference cannot be resolved. Used when a referenced entity (e.g., a JDF in a SubmitQueueEntry cannot be found). 121 Unknown DeviceID . No Device is known with the DeviceID specified. 130 Ganging is not supported. A gang Job has been submitted to a queue that does not support ganging. 131 GangName not known. A Job has been submitted with an unknown GangName . Device and Controller errors ReturnCode Description 200 Invalid Resource parameters 201 Insufficient Resource parameters 202 PipeID unknown 203 Unlinked ResourceLink 204 Could not create new JDF Node. 300 Authentication denied. 301 Secure channel not supported - I don't support secure channel for this Message. 302 Secure channel required - I require secure channel for this Message. 303 Certificate expired (Some implementations might not be able to send this response because the SSL layer will reject the Message before passing it to the JMF implementation for parsing) 304 Authentication pending. 305 Authentication already established. 306 No authentication request in process 307 Certificate Invalid Job and pipe specific errors Appendix-T : JDF Tools CIP4 official JDF Tools, development by Java : Alces、Bambi、EasyXJDF、JDFEditor T.1 Alces Alces的角色是Manager,包含Test、Client、Server三个模块,它向Worker(eg.RIP、印刷系统、装订机等Controller设备)发送JDF/JMF消息,并接收和处理Worker的返回消息,同时验证消息是否合法(是否为正确的JDF/JMF文档、是否符合ICS规范、是否符合当前上下文),验证的结果将形成XML Log文件。 T.2 Bambi Bambi的角色是Controller,它被设计的初衷是为MIS系统开发提供测试框架,它有一个配置文件,通过配置文件可以将Bambi设定模拟为印刷、印后等设备。Bambi的另一个使用场景是“printing house”,同样通过适当的配置文件完成,这对高标准的生产线是非常有用的。 [info] Note Alces和Bambi的取名可能来自迪士尼著名动画片《小鹿斑比》. T.3 EasyXJDF EsayXJDF是生成XJDF文档的工具,目前它只能用于“WebToPrint”环境,以便于MIS对接。EsayXJDF同时提供HTTP发送接口,可以将XJDF文档发送给MIS. T.4 JDFEditor JDFEditor是JDF编辑器,它可以显示、修改和验证JDF文档和JMF消息,同时具有转换JDF文档和XJDF文档的功能。为操作遍历,JDFEditor提供HTTP接口,可以通过网络链接并操作JDF/JMF文档。 Appendix-U : JDF Instance Template ... --> --> U.1 JDF Instance TBD U.2 MJD Instance TBD Appendix-V : JMF Instance Template [info] Note This template is the superset of possible JMF instances. Only one Query/Response/Signal/Command/Acknowledge element can exist, and its attributes and child element nodes also exist under different conditions. V.1 JMF Instance V.1.1 Query V.1.2 Command V.1.3 Acknowledge V.1.4 Response StartJob unsuccessful - Device does not handle commands V.2 MJM Instance Message-ID: MIME-Version: 1.0 Content-Type: multipart/related; boundary=\"----=_Part_0_2409003.1131706449797\" ------=_Part_0_2409003.1131706449797 Content-Type: application/vnd.cip4-jmf+xml Content-Transfer-Encoding: 7bit ------=_Part_0_2409003.1131706449797 Content-Type: application/vnd.cip4-jdf+xml Content-Transfer-Encoding: 7bit Content-ID: ------=_Part_0_2409003.1131706449797 Content-Type: application/pdf; name=Alces-Figures.pdf Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=Alces-Figures.pdf Content-ID: JVBERi0xLjYNJeLjz9MNCjkgMCBvYmogPDwvTGluZWFyaXplZCAxL0wgMTg4NDcvTyAxMS9FIDY4 ODkvTiAyL1QgMTg2MjYvSCBbIDQ1NiAxNTldPj4NZW5kb2JqDSAgICAgICAgICAgICAgICAgICAg IA14cmVmDTkgOA0wMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDA2MTUgMDAwMDAgbg0KMDAwMDAw MDY3NSAwMDAwMCBuDQowMDAwMDAwODkzIDAwMDAwIG4NCjAwMD... ------=_Part_0_2409003.1131706449797-- Appendix-W : Gray Box Process Group Nodes MAY contain an OPTIONAL JDF/@Types Attribute that allows a Controller (e.g., an MIS system) to specify a minimum set of Processes to be executed without specifying the complete list of Processes or the exact structure or grouping of these Processes into individual JDF Nodes when the Controller can not find the resources of the processes. Process Group Nodes that contain a JDF/@Types Attribute are commonly referred to as Gray Boxes. Gray Boxes CAN NOT BE EXECUTED BY DEVICE and SHALL BE found and fixed by other level Controllers until JDF/@Types is empty and a normal JDF Node Structure is built. Appendix-X : JDF future - XJDF XJDF是JDF的全新升级协议,同样由CIP4维护,字母“X”表“Exchange”,仅用于区分JDF。XJDF可称之为“JDF2.0”,是更精简、高效的作业传票协议,同时JDF本身也在保持着自己的发展路线,目前最新版本为JDF1.6(2017.09.01日推出)。仍然保留JDF并保持JDF更新的原因有三点:一是XJDF是全新协议,不能做到向下兼容。二是许多厂商已经在JDF协议上花费太多时间和成本,虽然很复杂,但已开发出成熟的接口,在短时间内并不能兼容XJDF。三是XJDF并未经过实际测试,在一些方面尚不成熟。 Appendix-Y : JDF Market Y.1 JDF Job Ticket Job ticket standalone JDF编辑器。单纯地具有对JDF作业传票进行查看、检测和编写功能 电子商务&Web接口工具。具有兼容JDF的电子商务功能 资产转移工具。可实现PDF文件后额JDF作业传票的管理工作,如文件的输入和输出管理。 Job ticket embedded 文档创建&版面设计软件。可实现作业文档的制作(或文档的创意和编辑等),并存在创建文档或输出文档的同时创建相关的JDF作业传票 预飞工具。能够对PDF文件做到预飞检查,同时能够创建相关的JDF作业传票。 资产转移服务。可实现PDF文件和JDF作业传票的管理工作,如文件的输入和输出。 其它的一些内嵌的作业传票软件。将属于JDF作业传票软件的范围又不具备以前功能的软件都归属到这一类型。 Y.2 MIS-JDF system Y.2.1 MIS Management Information System,管理信息系统,由决策支持系统、工业控制系统、办公自动化系统以及库与外界信息交换接口组成,主要作用是最大限度利用计算机和网络来加强企业的信息管理,提高整体效益和效率。 Y.2.2 MIS With JDF 集成JDF的MIS系统能够提供作业流程控制、生产控制等功能,可以实现从作业接收、估价、报价、作业安排、作业分派和打样,最后到印刷生产的全过程的信息管理。Case : HP HIFLEX. Y.3 JDF compatible devices 印前设备:控制、打样、大幅面打印机、胶片输出、CTP、印前工作中心或软件、拼大版、版面设计、预飞、RIP、数字印刷等设备。 印刷设备:油墨系统、颜色控制、数字印刷、卷筒胶印、单张纸胶印等设备。 印后设备:裁切、配帖、折页、压痕、装订、覆膜等设备。 Y.4 JDF tools Development tools IDE/SDK, Provide programming env for JDF development SOAP/HTTP, Provide JMF env for JDF production, such as JMF creation, JMF send and recive etc. Test tools Validity test, Provide validity test for JDF file under JDF scheme that provide by CIP4. ICS test, Provide ICS test for JDF file under CIP4 ICS Y.5 JDF Serve JDF consulting and training serve etc. Appendix-Z : CIP4 Software License Copyright (c) 2001-2020 The International Cooperation for the Integration of Processes in Prepress, Press and Postpress (CIP4). All rights reserved. PREAMBLE This software license applies to all source code and compiled software products made available by International Cooperation for the Integration of Process in Prepress, Press and Postpress (CIP4) association, to include, but not limited to the C++ and Java Application Programming Interfaces (APIs), CheckJDF application, JDF Schema, JDF Editor, Online Documentation for C++ API, the Alces application, the Elk application, and any part or component thereof (hereinafter \"CIP4 Software\"). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: TERMS AND CONDITIONS FOR USE AND REDISTRIBUTIONS OF THE CIP4 SOFTWARE 1 USE AND REDISTRIBUTION 1.1 The CIP4 Software may only be copied, modified, sublicensed or distributed as expressly provided under this license. Any other use or attempt to otherwise copy, modify, sublicense or distribute the CIP4 Software is void and will automatically terminate licensee's rights under this license. 1.2 Redistributions of source code must retain this CIP4 Software License and the following copyright notice: \"Copyright (c) 2001-2006 The International Cooperation for the Integration of Processes in Prepress, Press and Postpress (CIP4). All rights reserved.\" 1.3 Redistributions in binary form, with or without modifications, including compiled applications, must reproduce this CIP4 Software License including the above copyright notice in the documentation and other materials provided with the distribution. Redistributions containing modifications must include a prominent modification notice stating that modifications have been made to the original CIP4 Software. 1.4 Any company that sells, markets, or attempts to sell software development kits or any development tools that include the redistribution of CIP4 Software, in whole or in part, must make clear which files, applications or components are derived from CIP4 sources and the license provided by such companies to their customers, suppliers, and business partners must include this License in whole. Such customer, suppliers, and business partners must acknowledge the terms of this License to the company providing said software development kits or development tools and are subject to all terms herein, including the membership requirement in paragraph 4 below. 2 DISCLAIMER OF WARRANTY Licensee of the CIP4 Software expressly acknowledges and agrees that any use of the CIP4 Software is at the sole and entire risk of the user. The CIP4 Software is provided \"as is\" without warranty, upgrades or support of any kind. CIP4 expressly disclaims any expressed or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement of third party rights. CIP4 does not warrant that the operation of the CIP4 Software will be error-free or that defects in the CIP4 Software will be corrected. 3 LIMITATION OF LIABILITY To the extent not prohibited by law, in no event shall CIP4, CIP4 trustees, directors, officers or employees, or contributors to the CIP4 Software be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of the CIP4 Software, even if advised of the possibility of such damage. 4 CIP4 MEMBERSHIP REQUIREMENT 4.1 Any company that sells, markets or attempts to sell redistributed CIP4 Software for profit or fee, or distributed as a free component of any commercial system or package, shall maintain either Full or Partner CIP4 membership status and be a member in good standing. Any such company that fails to maintain its Full or Partner membership status must cease selling, marketing, attempting to sell any products that redistribute CIP4 Software, in whole or in part, and may only provide fixes, updates, or upgrades to customers with installations if no portion of the updates, fixes or upgrades make use of the CIP4 Software. 4.2 Any affiliate company using a different name than the member that participates in the selling, marketing or attempts to sell redistributed CIP4 Software for profit or fee must either maintain its own CIP4 Full or Partner status membership as provided under paragraph 4.1 above, or the parent company, if it holds majority ownership of both companies, shall maintain CIP4 Full or Partner status membership as provided under paragraph 4.1 above. 4.3 Distributors, resellers, and integrators that sell products that include redistributed CIP4 Software, in whole or in part, that are produced by a third party are exempt from the membership requirement in paragraph 4.1 above, provided that they do not provide any value-added programming or modifications to said products. Any distributor, reseller, or integrator that sell products that include redistributed CIP4 Software, in whole or in part, that are produced by a third party are NOT exempt from the membership requirement in paragraph 4.1 above if they make any value-added modifications or alter the said products via programming or any method that changes the functionality of the CIP4 Software. Companies that are developing and testing products that make use of CIP4 Software, in whole or in part, to include beta and alpha testing where testing companies have not paid or committed to pay anything for the product being tested and under development are also exempt from the membership requirements in paragraph 4.1 above until they begin to sell, market or attempt to sell such products. 5 END USER DOCUMENTATION The end-user documentation included with the redistribution containing CIP4 Software, if any, must include the following acknowledgment: \"This product includes software developed by the The International Cooperation for the Integration of Processes in Prepress, Press and Postpress (www.cip4.org)\" Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 6 USE OF CIP4 NAMES, TRADEMARKS, LOGOS, ICONS 6.1 The names \"CIP4\" and \"The International Cooperation for the Integration of Processes in Prepress, Press and Postpress\" may be used by Full or Partner CIP4 members in good standing to promote products that are JDF-enabled. 6.2 This license does not grant any rights to use CIP4 and JDF trademarks, trade names logos, and icons. The use of and JDF trademarks, trade names logos, and icons must be in accordance with CIP4's Guidelines for Logo Usage as published on the CIP4 website. 6.3 CIP4 may audit the use by any licensee of the CIP4 Software, trademarks, logos, and icons to determine compliance with these terms and conditions. 7 LICENSE VERSIONS CIP4 retains the right to modify the terms applicable to the CIP4 Software under this CIP4 License. CIP4 may at any given time publish revised and/or new versions of this CIP4 License. Each version will be given a distinguishing version number and CIP4 Software that has been published under a particular version of this License may be used either under the terms of the original version or any subsequent version of this License. This software consists of voluntary contributions made by many individuals on behalf of the The International Cooperation for the Integration of Processes in Prepress, Press and Postpress and was originally based on software copyright (c) 1999-2001, Heidelberger Druckmaschinen AG and copyright (c) 1999-2001, Agfa-Gevaert N.V. For more information on The International Cooperation for the Integration of Processes in Prepress, Press and Postpress, please see http://www.cip4.org. Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/expansions/matlab.html":{"url":"pages/expansions/matlab.html","title":"MatLab","keywords":"","body":"附A:微积分基础 一.历史碎片 微积分学是古老的课题,古希腊的泰勒斯、阿基米德的相关著作中就已经有微积分的萌芽,三国时期的刘徽也有割圆术和求体积的思想出现。早在庄子的时代,就已经有了极限的概念“一尺之棰,日取其半,万世不竭”。 到了十七世纪,有许多问题需要解决,这些问题也就促成了微积分的产生因素。这些问题可归结为4类:第一类是求运动物体的即时速度、第二类是求曲线切线、第三类是求函数最大最小值、第四类是求曲线及曲面面积。 任何伟大的发明都要站在巨人的肩膀上,微积分的产生与发展经历了上千年,是许许多多数学家的贡献,到了十七世纪,出现了两位集大成者:牛顿、莱布尼茨。他们最主要的贡献是将一直独立的微分学(切线问题)和积分学(求积问题)联系到了一起,甚至他们所创建的微积分符号一直沿用至今。 科学上的巨大需要战胜了逻辑上的顾忌。他们需要做的事情太多了,他们急于去攫取新的成果,基本问题只好先放一放。所以在微积分一方面被快速投入应用,另一方面出现了越来越多的悖论,中心问题是无穷小量的问题,这引发了第二次数学危机,直到19世纪通过极限的概念才得以解决。 二.内容分支 微积分的基本内容包括微分学和积分学,微分学的主要内容包括“极限、导数、微分”,积分学的主要内容包括“定积分、不定积分”。现在,微积分已成了数学分析的代名词。 三.常用符号 数学当中的符号要从古希腊和罗马帝国说起,罗马文明是古希腊文明的延伸,罗马帝国曾统治亚欧非大陆长达一千多年,所以其文明影响着亚欧非大部分地区。罗马帝国以拉丁文为母语并传承者古希腊文明,而数学贡献多源于西方,他们以拉丁文、古希腊字母作为数学符号,这样即不会与流通语言产生冲突,又达到了可查找、可辨识的效果。 微分符号:dx, dy 其中d源自拉丁语“Differentia”(差);积分符号:ʃ 来源于拉丁语“Summa”(总和)。 四.运算 //TBD 五.应用 //TBD 附B:MATLAB 一.简介 MATLAB 是美国MathWorks公司出品的商业数学软件,用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLAB和Simulink两大部分。MATLAB技术代表了当今科学计算软件的先进水平。 二.自动控制与MATLAB MATLAB内置众多模块化工具,其中包括模糊逻辑工具箱和PID工具,通过simmulink模块还可以查看仿真图示,观察不同参数下的图像运行轨迹,通过工具的使用可以更清楚的了解PID等算法的运行机制。 三.MATLAB的使用 //TBD Matlab 命令行绘图 将数学公式输入到MATLAB,即可绘图,展现该公式的图像。 打开MATLAB即进入命令行模式 先输入X的值: >>X=0:0.1:5 表示X的值从0到5,步长为0.1 , 即X轴的值为(5-0)*0.1 => 0、0.5、1、1.5 。。。 >>Y=2*X 输入公式 >>plot(x,y,'-r') plot是matlab内置函数(英文意思为绘图),其中-r代表图像线条颜色即红色 再次回车即可看到图像。 需要注意 .* 与 * , ./ 与 / 的区别,前者是矩阵内容的组合乘法,后者是矩阵本身相乘 或者说.* ./才是相当于编程使用中的乘除法。 如何保持图(将多个曲线画在一张图中) plot(x,y,'-r') hold on //每次画图前,调用一次即可 plot(x1,y1,'-g') plot(x2,y2,'-b') ... 如何标注曲线 legend('曲线1的标注', '曲线2的标注','曲线3的标注'); Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/expansions/English.html":{"url":"pages/expansions/English.html","title":"English","keywords":"","body":"词来源 来自神话,如希腊神话 来自国家,如古罗马、日耳曼、斯拉夫、凯尔特、中国广东、日本、法国、德国、拉丁等等 词缀造词,前缀和后缀 罗马神话和希腊神话基本一致,只是在人物命名和一些细节有差异。 Mercury 墨丘利,是罗马神话中的众神信使,因为墨丘利的建议使得罗马繁荣,因此也被称为商业之神 对应希腊神话中的 信使之神Hermes 赫尔墨斯 Merc 就是许多与商业有关的词缀,如market、commercial、merchant 古希腊的 Jupitor 对应 希腊神话中的Zeus 宙斯,Juno对应赫拉Hera Statue (区别status)n 雕塑 雕像,与stand站立相关,指耸立的雕像 figure 动词 计算、认为 名词很多 基本词根是fig与fact相关,“做”, 当人物讲时,表示捏造、做出来的人,即人物 也有雕像的含义,也是捏造的 也可以当塑造的 身材、体型相关 2 Words 2.1 Source class 2.1.1 China ketchup [‘ketʃəp] n. 番茄酱 来自广东,广东称番茄酱为茄汁,粤语发音与英文类似 2.1.2 Japan 2.2 Affix class 2.2.1 Prefix class 2.2.1.1 con- & com- 表聚集 2.3 Suffix class 2.3 Myth class 2.3.1 Pro Aim : IELTS 7.5+ Teacher Yang 全民英语训练营 Day 29 The Picture of Dorian Gray -- 奥斯卡·王尔德(英) soul n.灵魂,心灵 和sea海洋相关,来自日耳曼传说:人的灵魂源于大海,也归于大海。 passion n.激情,热情 来自基督教,-pass-词根为痛苦之意,早期指耶稣被钉十字架时承受的巨大痛苦,后来衍生为一种强烈的情感-”热情、激情“ compassion n.同情,同情心 com前缀表聚合、共同,共同承担痛苦,能感受到彼此的痛苦,即同情,是较正式的词汇。 someone VS some one 都指”某个人“,前者泛指某个人,后者指代大家都知道的那一类/一个人。 virtue n.美德 美德是看不见的,本身是虚拟的事物,与Virtual相关,VR即Virtual reality Day 30 Animal farm -- 乔治·奥威尔(英) slave n.奴隶, slavery n.奴役、奴隶制度 来自古代欧洲人种“斯拉夫(Slavs)“人,在罗马帝国时期,日耳曼、斯拉夫和凯尔特人被称为欧洲三大蛮族,类似中国国代的蛮夷狄戎胡,在罗马与蛮族的交战之中斯拉夫人大量沦为奴隶,久而久之,斯拉夫人就成了奴隶的代名词. comrade n.同志 同源词camera相机,camera来自拉丁文,源意为房子,而古代相机类似一个小房子,故称相机为camera。在早期西班牙军队里comrade指同住一室的战友,后来在法国社会主义革命期间引用改词表示为了共同志向而战斗的人。 now 也用于吸引人注意力, 或者用于转义话题 Day 32 Mercedes-Benz - The best or nothing then as now 一如既往 satisfy vt.使满意,使满足 来自法语,名词satisfaction,形容词satisfied, satisfactory,satisfying. Day 33 IHG(InterContinental Hotels Group) deliver vt. 递送,发表,接生 de -> dis, liver -> Liber自由,即释放束缚,让其自由之意。Delivery n.快递 span n.跨度 vt.跨越 lifespan 寿命 luxury n.奢侈,奢华 Lux 品牌“力士”。形容词luxurious pure adj.纯的,纯粹的,纯洁的 来自拉丁文 distinct adj.明显的,明显不同的 dis - 分离, stinck -> stick 刺、戳,分开刺,即强调分开做标记,表示明显的、明显不同的 brand n.品牌,商标 vt.给...打烙印 bran 与 burn相关,用高温的工具在动物身上做标记、打烙印 provide vt.提供 pro表示向前,vid与vis看相关,向前看即表示能预见需求,即提供 community n.社区 commun 与 common相关,community强调的是一群人共同居住的地方,即社区 continent n.大陆 与continue相关,表示连接在一起的土地,也指不包括英国和爱尔兰的欧洲大陆 Day 34 Nick's Manhattan Beach Manhattan [mæn’hæt(ə)n] n. 曼哈顿(美国纽约辖区和中心区) cocktail [ˈkɑ:kteɪl] n. 鸡尾酒 cock + tail 公鸡 + 尾巴 wine 一般指葡萄酒,来自vine葡萄树 spacious 宽敞的 来自space crave vt/vi 渴望 比desire强烈,是desire strongly的感觉 patio 露台 exhibition 展览会 ex 表示向外,hib与hold拿相关,即表示将东西拿出去,即展览,动词exhibit inhibit 含义反之:印制、约束、阻碍等 beverage 饮品 bever 与beer啤酒相关 impeccable 无瑕疵的,无可挑剔的,无懈可击的 im pec - pick 无法 挑选 1 句子成分 主语 : 谓语的对称,谓语的陈述对象。 谓语 : 主语的对称,用于对主语加以陈述。 宾语 : 句子中受动词(含次动词)支配的成分,表示动作行为涉及的人或物。 定语 : 修饰和限定的成分,用于修饰和限定 名词等体词或体词性短语 前置定语 后置定语 状语 : 修饰和限定的成分,用于修饰和限定 动词、形容词等为此和谓词性短语 补语 : \"补足语\",动词或形容词后面的补充说明成分 Tips : 一个句子一定是主谓宾组成的,但通常有省略成分。主谓宾是一个集合、定状补是另一个集合,主谓宾和定状补在一个句子中呈交集存在,即主语可以是定状补、谓语也可以是定状补、宾语也可以是定状补。 2 词性 实词 名词 : 动词 : 形容词 : 量词 : 代词 : 虚词 介词 : 又称”次动词“或”副动词“,用于动词、名词和形容词等之前,表示方向和对象等 - 辞海 助词 : 附着在词、短语或句子,表示附加意义的词,包含结构助词、时态助词和语气助词等 拟声词 : - 副词 : 用于修饰动词、形容词等表示行为、发展变化、性质状态的词,一般不能修饰名词、不能充当谓语,常做状语和补语 Tips : 词 是 句子的组成成分,属于句子的子集。 HP销售文案示例 NPI - New product introduction 新产品介绍 如:HP SmartStream Direct-to-Finish NPI ,惠普 SmartStream Direct-to-Finish 新品介绍 Sales team 销售团队 bottleneck 瓶颈 : bottle + neck streamline n.流线 v.使流线, 简化...的过程 speed-to-market 加速上市,表示将产品加速的推向市场 Front End [计]前端 Pre- requirements 先决条件 APJ Asia Pacific Japan 亚太和日本地区 亚太 : 亚洲及太平洋地区,中国、中国接壤和附近间接接壤地区(俄罗斯远东地区、新加坡、文莱、柬埔寨、泰国、印度尼西亚、菲律宾、越南、朝鲜等等)、朝鲜、韩国、澳大利亚、新西兰等 世界三大字母体系:拉丁字母、阿拉伯字母、斯拉夫字母,西方大部分国家和地区使用拉丁字母,中国汉语拼音方案采用拉丁字母(1958)。中国哈萨克族、维吾尔族等伊斯兰教使用阿拉伯字母。 中文拼音、英语、法语、西班牙语、罗马尼日亚语、德语、瑞典语、荷兰语、意大语等都使用拉丁字母。 中文、西班牙语和英语为世界使用人数、范围和第一语言的前三 Mass 质量 inertia 惯性 payload 有效负载 efficiency 效率 torque 扭矩 alternating current 交流电 Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/automation/Motor.html":{"url":"pages/automation/Motor.html","title":"Motor","keywords":"","body":"1 Concept 电机(Electric Machine)是将电能与其它形式能进行相互转换的装置, 大部分电机应用电磁感应原理,机械能转换为电能的电机称为“发电机”,电能转换为机械能的电机称为“电动机” 新型超声波电机应用压电效应进行能量转换 主要有三种分类: 能量转化方向; 电动机、发电机 磁场方向;径向磁场电机、轴向磁场电机 电流形式:交流电机、直流电机 电机就是上述三种分类的交集 有刷直流电机 1.简介 有刷直流(BDC)电机是比较传统的电动机,其定子上是永磁体和电刷,转子上是线圈绕组和换向器,电能通过换向器、电刷进入电机(的转子),换向器与电刷接触以实现电流换向进而实现电机连续旋转。 有刷电机成本低,但因其电刷与换向器的接触式设计导致其可靠性差、寿命短、换向火花易产生电磁干扰等诸多缺点。 2.驱动 BDC电机一般不需要复杂的驱动电路,接通电源就可以旋转、关闭电源就可以(惯性)停止,但如果要实现双向旋转、速度控制、反馈电路等就需要设计驱动电路。 (1)BDC的启动 电机通电后,因电阻和电感较小且开始阶段反电动势很小,导致电流相对较大,最大可达到额定电流的15~20倍,这一电流会使电网受到扰动、机组受到机械冲击、换向器发生火花,因此直接合闸启动只适用于功率不大于4千瓦的电动机(启动电流为额定电流的6-8倍)。 (2)双向转动 BDC电机的双向转动硬件上需要H桥电路,软件上只需变换通电顺序,下图为简易的H桥电路模拟。也可使用MC33035芯片实现。 (3)PWM调速 BDC电机的速度由电压大小而定,一般有两种方式进行调速:①改变励磁电压,降压升速、升压降速。②改变电枢电压,升压升速、降压降速(常用)。 PWM是用数字方式控制模拟输出的电压调节手段,其调速就是改变上述某种方式的电压来进行调速。注:PWM调节BDC电机常用于智能小车的调速。 无刷直流电机 1.简介 无刷直流电机(BLCD)使用半导体开关器件来实现电子换向,成本相对较高,但有使用寿命长、易于控速等诸多优点。按电子换向器的实现方式可分为有位置/有霍尔传感器(参看附录A)无刷电机和无位置/无霍尔传感器无刷电机。 2.组成 无刷电机系统由电机本体和驱动器组成,电机本体由多极绕组定子、永磁体转子组成,通过改变定子绕组线圈的通电顺序即可驱动转子转动,通过控制定子绕组线圈的通电大小即可控制转子力矩,通过控制定子绕组线圈的通电频率即可控制转子的运转速度。 外转子无刷电机驱动系统 逆变器将直流电转变为三相交流电,PWM控制信号决定其6个功率晶体管的开关及频率从而控制流经定子线圈的电流变化。 3.驱动 无刷电机驱动电路可选专业驱动器或驱动芯片,如摩托罗拉生产的MC3303X系列芯片,控制部分只需给出使能、方向和刹车信号,其它逻辑都由芯片解决,这种方式控制的缺点是不能控制电机转速。 给定EN=1、DIR0/1、Brake=0/1,电机就转动/停止。 4.接线 无刷电机一共有八根引线,其中三根是信号线,五根是霍尔传感器接线,信号线接电机U/V/W,五根霍尔接线中有一个VCC一个GND,余下三个为SA/SB/SC。 步进电机 1.简介 步进电机是一种将电脉冲转化为角位移或线位移的执行机构,是现代数字程序控制系统中的主要执行元件,广泛应用于开环控制领域。 2.分类 步进电机分为反应式(VR)、永磁式(PM)和混合式(HS)。按定子绕组可分为二相(1.8°)、三相(1.2°)和五相(0.72°)等。反应式和永磁式步各有缺点,混合式集成了它们的优势,具有步距角小、转矩大等特点。目前最受市场欢迎的是二相混合式步进电机,约占市场份额的97%。 3.特点 步进电机的角位移与脉冲数成正比、速度和加速度与脉冲频率成正比、 步距角精度在3%~5%,且没有累积误差。 步进电机的频矩特性 由于反向电动势作用,步进电机的力矩与脉冲频率成反比。 多数步进电机在1KHz时转矩迅速衰减,在0.1KHz时达最高力矩,在5KHz~10KHz左右衰减为0(0~100Hz↑ 100~1000Hz↓)。 从曲线可看出,电机启动时不应高于最高启动频率,否则可能丢步、堵转;给定一个适当的启动频率而不是从零开始,以使步进较快进入到运行速度。 步进细分与转矩关系 在频率一定时,增大细分数将使转矩增大,在频矩特性曲线上表现为横向拉伸。 测试YOFO-42系列两相混合步进,频率为约10000Hz时,设置细分数为200、400时电机堵转,力矩很小,可以用手反向扭转。设置细分数为800、3200时力矩大,用手不能反转方向。 温度与转矩的关系 高温(>90°)将使转子退磁,进而导致电机力矩下降或丢步;高温可能来自环境温度或由电机高功率、大负载的持续输出引起。 电压电流与频矩特性 改变电压和电流都会影响电机的频矩特性,电压和电流增大会增加静力矩(正比)并同时增加转速(正比)。相对来说,在恒压下改变电流对电机力矩影响更突出、在恒流下改变电压对电机速度影响更突出。 在增压时可适当减少电流,以减少高功率输出导致高温引起的力矩下降,反之亦然 步进电机没有最低启动频率,可以今年给一个低电平,明年给另一个高电平,电机仍然能走一步,但有最高启动频率,超过最高启动频率步进电机将堵转(或出现不稳定现象),最高启动频率跟步进细分、电机大小、负载大小等有关。 细分越大,最高启动频率越大(这个没什么好说的,就是频矩特性)。电机越大转子越重,最高启动频率越低,比如同样是100Hz,在小电机上不用加速就能正常运行,换了一个大电机反而转不动了!。负载也是一样,负载变大,就需要加速曲线来启动。 4.组成 步进电机系统由电机本体和驱动器组成,电机本体由多相绕组定子、永磁体转子组成,定子绕组表面和转子表面都刻有相同尺寸的小齿,当转子小齿与一组定子绕组重合时,其它转子小齿刚好与其它组定子绕组错位,通过定子绕组换相即可驱动转子转动。 两相步进电机一般有八个定子绕组,间隔选取四个绕组成一相。 5.驱动 步进电机驱动电路可选专业驱动器(如:FYDH807T)或驱动芯片(如:Allegro A4982SLPT、达林顿驱动器ULN2003)。步进驱动器至少应具备功率放大能力,其次应具备脉冲分配和细分功能。 仅有电流放大能力的步进驱动器增加了编程的复杂性,如使用ULN2003驱动时,必须设定脉冲节拍以驱动步进电机转动方向和精度。而对于具备脉冲分配功能的步进驱动器,只需给定脉冲和方向即可。 一个步进电机驱动器/驱动芯片理论上可以驱动多个步进电机,但因电气和时序等问题影响会减少驱动器使用寿命、降低步进电机精度。 步进驱动器的细分功能是一种通过精确控制步进电机的相电流而提高步距角精度的电子阻尼技术,细分技术提高了步进电机分辨率、减弱或消除了步进电机固有的低频振荡、增大了步进电机(30-40%的)输出转矩。 6.接线 步进电机的外部引线数与相数没有必然的联系,许多二相步进电机有8根引线,这种电机既可以串联连接又可以并联连接。不同的接线方式并不影响驱动程序的编写。 串联连接的电机,电流较小,低频力矩较大(适用低速);并联连接的电机,电感较小,所以启动、停止速度较快,高频力矩有所增大(适用高速)。 步进电机与驱动器接线方式如下图:MP表示脉冲接线、DIR表示方向接线、MF表示使能接线(置低电平时脱机)。 其中VBB为+24V, PG为+24地。 7.加减速控制 加减速控制的目的是解决步进电机堵转(或失步)和过冲的现象。导致步进电机堵转(或失步)现象的原因:①启动频率:启动频率高于最高启动频率限制;②跳变频率:频率突变导致转矩瞬时下降。导致步进电机过冲的原因是步进电机在高频运行时瞬时停止。 常见的加减速方案有:梯形曲线、指数曲线、S曲线等;其中S型加减速曲线最为平滑,生成S型加减速曲线也可通过多种基本曲线,如正弦曲线、Sigmoid曲线等,其中Sigmoid曲线是标准S曲线函数,它在生物学和神经网络中有广泛应用。 (1)Sigmoid公式 公式:f(x) = 1/(1+e-x); 特点:x在(-10, 10)之间取值,f(x)在(0, 1)之间变化,曲线以(0,0.5)对称。 可以看出在[-5, 5]区间以外,其函数值变化非常小,所以可按实际情况裁剪使用。 (2)Sigmoid变换 坐标变换规则:①平移,左加右减,上加下减。②伸缩,X:压缩乘、拉伸除;Y:拉伸乘、拉伸除。注:伸缩表示伸缩为原值的多少倍。 Sigmoid函数是函数模型,需要在其基础上进行变换才能成为实际应用函数。使用Sigmoid曲线驱动步进电机,其Y轴变换为频率f,X轴变换为采样点,通过坐标变换可得 Y = (Fset-Fmin)/(1+exp(-Flexible*(x-num)/num)) + Fmin(加速曲线): 设FSet=100,Fmin=50,x∈[0,100] 注:①其中Fset为设置的运行频率、Fmin为设置的起始频率、flexible为压缩率(4~6)、num是x取值范围的一半;②加减速时间与取样·动频率成正比;③减速曲线公式为Y = Fset - (Fset-Fmin)/(1+exp(-Flexible*(x-num)/num))。 (3)Sigmoid使用 取适当数量样本,使用公式得到频率数组并转换为半周期数组或定时器计数器重载值数组,然后通过软件延时或定时器定时方式得到50%PWM方波来驱动步进电机。 设得到半周期数组int Tarr[] = {10, 11, 13, 18, 20, 30, 38, 45, 50, 53}、定时器计数器重载值数组int Carr[] = {}。 举例 - 软件延时方式: for (int i = 0; i int Countflag = 0; int i = 0; TCNT0 = Carr[0]; ISR(TIMER0) { if (i 举例 - 定时器定时方式: 附:定时器计数器重载值计算方法 通过定时器时钟Tclk,则计数一次的时间为1000/Tclk毫秒,计算Thalf/(1000/Tclk)得到计数次数(当次数小于255时采用8bit定时器,否则采用16bit定时器),于是得定时器计数器重载值TCNT = 255 - Thalf/(1000/Tclk)。 PS:步进电机不能突然换向,(当然也跟运行频率相关),突然换向可能导致失步,这是因为电机内部或驱动器的原因,所以换向之后要延时一点再给脉冲。 伺服电机 伺服电机 尾部具有(高精度)码盘,并在一侧接有两个接口,接入驱动器, 一个输入,一个输出, 输入:系统 -》 驱动器 -》伺服电机 系统 《- 驱动器 《- 伺服电机 : 输出 伺服电机通过码盘将运行数据实时传送给驱动器,由驱动器返回系统,系统进行反馈处理 并输出校正 步进电机没有配备码盘,输出默认是没有反馈的,输出精度与电机质量、负载、环境、电流电压等都有关系, 要使用步进电机组成伺服系统,则必须接入反馈装置 伺服电机 也不能完全取代步进电机, 伺服电机的反馈源是在伺服电机的本身上,所以不能适用所有场景,适用于直接输出而不考虑负载的复杂情况时很适用 相比这点,步进电机就比较灵活,因为可以将反馈系统放置到任何位置,比如步进电机驱动胶辊、胶辊下走纸张,我想要纸张定位的精度,而不是胶辊旋转的精度, 这样伺服电机就不适用了,因为胶辊带动纸张是会漂移的,所以不能对胶辊直接定位, 这时将反馈系统(如编码器)放到纸张运行的适当位置,就可以达到控制效果 https://www.youtube.com/watch?v=Gzo9m0tMD0A //TBD 伺服系统、伺服电机http://www.xfoyo.com/jishuhefuwu/jiejuefangan/267.html http://www.xfoyo.com/jishuhefuwu/jiejuefangan/320.html 减速电机 减速电机(齿轮电机)是减速机和电机的结合设备,目的是提高输出扭矩、降低负载惯量,常用于低转速、大扭矩的传动设备。 通过减速机中输入轴配有较少的齿轮来啮合输出轴上的大齿轮,大小齿轮的齿数之比就是传动比,减速机在原动机和执行机构之间起匹配转速和传递扭矩的作用 电机控制系统 //TBD 材料1:电动机的转速与力矩成反比,因此通常配合减速器(并集成)使用,如:减速步进电机、减速无刷电机等。 材料2:编码器、反馈、闭环、开环 材料3:伺服电机、伺服系统 材料4:步进、伺服:https://www.zhihu.com/question/37374664 附录A:霍尔效应与霍尔传感器 1.霍尔效应 洛伦兹力指出:在磁场中的通电导体其内部的载流子会因磁场而产生偏移;在洛伦兹力的作用下会使通电导体产生感应电动势,这就是霍尔效应。 2.霍尔传感器: 根据霍尔效应做成霍尔器件,就是以磁场为工作媒介将物体的运动参量转变为数字电压的输出,使之具备传感和开关的功能,这就是霍尔传感器、霍尔开关器件。 无刷电机的霍尔传感器通常以120°或60°的角度排列在定子绕组上,为控制部分提供相序控制的依据,同时也可以作为无刷电机的闭环反馈系统。 附录B:步进电机应用术语 步距角 对应一个脉冲信号,电机转子转过的角位移,一般二相步进电机步距角为1.8°、三相1.5°、五相0.72° 步距角精度 步进电机每转过一个步距角的实际值与理论值的误差。用百分比表示: (误差/步距角)× 100% 相数 步进电机内部线圈组数 转矩(扭矩) 使物体发生转动的特殊力矩 保持转矩(静力矩) 步进电机通以额定电流但没有转动时,定子锁住转子的力矩。它是步进电机最重要的参数之一,通常步进电机在低速时的转矩接近静力矩 定位转矩(定力矩) 步进电机没有通电的情况下,定子锁住转子的力矩 最大空载起动频率 电机在某种驱动形式、电压及额定电流下,在不加负载的情况下,能够直接起动的最大频率 最大空载运行频率 电机在某种驱动形式、电压及额定电流下,电机不带负载的最高运行频率 丢步(失步) 步进电机转动步距角个数小于给定脉冲数。一般当电机力矩偏小、加速度偏大、速度偏高、摩擦力不均匀等都会使丢步现象发生 拍数 完成一个磁场周期性变化所需脉冲数或导电状态,或指电机转过一个齿距角所需脉冲数。步距角=360/(拍数*齿数),二相电机步距角1.8°,齿数为50,则拍数为4,即工作节拍为二相四拍 径向间隙 径向负载时轴偏离距离(伸出食指与地面平行,向手指挂载重量会使手指偏移,这就是径向负载, 而负载时的偏移与原来位置间的距离就是颈项间隙) 轴向间隙 轴向负载时轴移动距离(伸出食指向下与地面垂直,向手指挂载重量会使手指关节脱离一定距离,这就是轴向负载,而负载时的关节偏移与关节原位置的距离就是轴向间隙) 法兰面 与轴垂直的电机前表面 径向负载 距离法兰面一定距离,径向所能承受的最大力 轴向负载 轴向所能承受最大力 附录C:步进电机计算公式 关系 公式 单位 频率与转速 f =(n S)/ 60 Hz或pps 线速度与转速 v = π D n m/min 步距角 θ = 360 / S 或 θ = 360 /(Z M) ° 推导公式 转速与频率 n = f 60 / S r/min或rpm 转速与线速度 n = v /(π D) r/min或rpm 线速度与频率 v = π D f 60 / S m/min 频率与线速度 f = v S /(π D 60) Hz或pps 说明:n为角速度,单位:r/min或rpm。S为步进一圈步数。D为步进同轴齿轮直径,单位:m 。Z为转子齿数,M为运行拍数。f为频率,单位Hz,即1秒所需脉冲数量。 注意:1.从公式可以看出,所需线速度固定时角速度不变,如果增加步进细分值则必须同时增大驱动频率。2.步进电机没有最低启动频率,脉冲之间时间间隔可以无限长。 实际使用电机,还是需要看转速,因为脉冲频率跟细分相关 所以不能直接表达运行速度(细分情况跟精度有关) 附录D:电机选型 TBD APPEND 同步异步指的是转子转速与定子旋转磁场转速是同步(相同)还是异步(滞后),因而只有交流能产生旋转磁场,只有交流电机有同步异步的概念 同步电机——原理:靠“磁场总是沿着磁路最短的方向上走”实现转子磁极与定子旋转磁场磁极逐一对应,转子磁极转速与旋转磁场转速相同。 特点:同步电机无论作为电动机还是发电机使用,其转速与交流电频率之间将严格不变。同步电机转速恒定,不受负载变化影响 异步电机——原理:靠感应来实现运动,定子旋转磁场切割鼠笼,使鼠笼产生感应电流,感应电流受力使转子旋转。转子转速与定子旋转磁场转速必须有转速差才能形成磁场切割鼠笼,产生感应电流。 区别:(1)同步电机可以发出无功功率,也可以吸收;异步电机只能吸收无功。(2)同步电机的转速与交流工频50Hz电源同步,即2极电机3000转、4极1500、6极1000等。异步电机的转速则稍微滞后,即2极2880、4极1440、6极960等。(3)同步电动机的电流在相位上是超前于电压的,即同步电动机是一个容性负载。同步电动机可以用以改进供电系统的功率因素。 同步电机无法直接启动:刚通电一瞬间,通入直流电的转子励磁绕组是静止的,转子磁极静止;定子磁场立即具有高速。假设此瞬间正好定子磁极与转子磁极一一对应吸引,在定子磁极在极短的时间内旋转半周的时间之内,会对转子产生吸引力,半周之后将会产生排斥力。由于转子有转动惯量,转子不会转动起来,而是在接近于0的速度下左右震动。因此同步电机需要鼠笼绕组启动。转速差使其产生感应电流,而感应电流具有减小转速差的特性(四根金属棒搭成井形,内部磁场变密会减小面积,变疏会增加面积,阻止其变化趋势),因而会使转子转动起来,直到感应电流与转速差平衡(没有电流就不会有力,因而不会消除转速差,猜测与旋转阻力有关) 有刷无刷电机都是针对直流电机而言的,为了直流电能产生使转子持续旋转的磁场才 需要刷结构 步进电机是有刷还是无刷? 首先步进电机是直流电机,但既不是有刷也不是无刷,步进的驱动不是靠电刷或霍尔的换向而产生的磁场来旋转的,步进电机的驱动是靠脉冲信号产生的磁场来旋转的 伺服电机与步进电机的区别? 控制器 -》 驱动器 -》 步进电机 控制器 -》 驱动器 -》 伺服电机 | | -- 控制器 -》 驱动器 -》 伺服电机 | | -- 最大的区别是在反馈上,步进电机是开环的,理论上发1个脉冲走一步,但发N个脉冲丢了多少步也不知道 伺服电机自带反馈系统,能让控制器和驱动器知道所走的精度 步进电机在精度要求较高的场合会使用编码器来反馈 控制器 -》 驱动器 -》 步进电机 -> 编码器 | | -- 实际上伺服电机的反馈原理与这种方式类似 另外,伺服电机的负载、转矩、启动/响应速度等性能都高于步进电机, 这是特殊内部结构和工艺等原因造成的,因此伺服电机也比较贵 伺服系统 servo system 就是指类似伺服电机这种反馈系统, 可以说凡是具有严格反馈的系统都可以成为伺服系统 电机选型 交流电机 主要分为 同步电机和异步电机 同步和异步是在交流电机上的分类 而不是直流电机上的分类 构造差异 constructional difference 同步电机: 定子具有轴向槽,该槽由定子绕组组成,用于特定数量的极 异步电机: 卷取作业 与 力矩电机 力矩电机的负载增大时,需求转矩增大,进而速度减小,这种特性非常适合卷曲作业. 卷取设备通常需求固定张力,固定速度。但进行卷取作业时,卷取侧的直径会逐步变大,受其影响每转一圈卷取的量也会逐步变多,并且需求更大的转矩。因此,为了保持固定张力和固定速度,电机有必要要在直径变大时逐步减速并增大转矩. Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "},"pages/automation/Sensor.html":{"url":"pages/automation/Sensor.html","title":"Sensor","keywords":"","body":"1 传感器 1.1 对射传感器 对射传感器又叫透射传感器,因常被做成凹槽式所以又称凹槽传感器。对射传感器由发射器接收器组成,通过发射器的光线直接进入接收器,当它们之间的光线被阻断时光电开关就产生开关信号。对射传感器的特点是可检测不透明物体或低透明度物体。 1.2 反射传感器 反射传感器也是由发射器和接收器组成,除此之外还可能有反射镜,发射器和接收器放置在一端,当有接近物体时或监测物体明暗变化时会通过漫反射(无反光镜)或镜面反射(有反光镜)使接收器接收光信号,从而触发开关信号。 要注意的是上述的光信号多指红外线,正常环境中也有一定量的红外线,所以接收器会检测红外线强度,进而判断是否触发开关信号。另外红外线也会被黑色物体吸收,或者说黑色物体是不反射或反射较少光线的,所以给待检测物体适当位置布置黑块也是一种反射传感器的检测方式。 1.3 常开与常闭 常开:常态下断路/断开/开路,信号/电平为0 常闭:常态下短路/闭合/闭路,信号/电平为1 如果传感器是运行决策设备,那么“不作为”通常不会使情况更糟,如果传感器损坏时的状态为A,则传感器要设置为A状态,并且执行机构执行时需要的决策应设计为!A。假设传感器损坏时为短路,呈高电平,则传感器设置为常闭,这样传感器未作决策和损坏时的状态相同,而执行机构执行时需要的决策是传感器为低电平,这样传感器损坏时使执行机构是“不作为”的,属于安全的设计。 如果传感器是精度检测设备,那么常开和常闭的选择没有很大的意义。 2 编码器 2.1 概念 编码器(encoder)是将光、磁或电刷等信号转换成电信号的用于角和线位移测量及反馈的设备,属运动控制类传感器。按信号读出方式分为接触式编码器和非接触式编码器,按工作原理分为增量式编码器和绝对式编码器。 2.2 增量式编码器 增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。 2.2.1 光电式增量编码器 光电式增量编码器利用光电转换原理输出A、B、Z或A、B、C、D、Z五组方波,除Z相外,其它各相的相位相差90°,通过相位差即可判定旋转方向,通过对任一项计数即可测量或反馈角位移或线位移。 带有C和D相的增量式编码器常用于伺服系统,将C和D相信号反向,叠加到A和B相中可增强信号的稳定性。Z相在编码器每旋转一圈时(在特定位置)输出一个脉冲,用于基准点定位。另外部分增量式编码器还具有A-、B-、(C-、D-)Z-相,形成差分对形式输出信号以增强抗干扰能力。 增量式编码器机械寿命长、抗干扰、可靠性高,适合长距离传输。缺点是没有转轴的绝对位置信息。最高精度可达10000P/R(脉冲/转)。 2.2.2 编码器开关 编码器开关又称为数字电位器,精度一般为10~20P/R,常作为功率调节器件、广泛应用于智通家居、多媒体音响、仪器仪表、家用电器等设备。 通过调节编码器开关旋钮即可输出相位,通过程序计数读取和方向判定即可输出决策信号以控制输出系统。 2.3 绝对式编码器 绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。 绝对式编码器的码盘均分为若干弧段,每个弧段拥有同样数量的扇区,同一弧段的扇区进行二进制编码器以形成该扇区的码值,这样就可以输出转轴的绝对位置。格雷码码盘(又称循环码盘)设计为相邻弧段之间只相差一个扇区,使得读出误差减小。 IPC standards tree 如图是精度为4位的绝对式编码器,共2^4=16个弧段,位数越高、弧段越多,精度越高,目前有16位的绝对式编码器。 2.4 电路连接(增量式) 增量式编码器有A、B或A、B、C、D相位各差90°的脉冲输出线,可单向和双向计数,各相接线可连接至单片机外部中断或GPIO(中间可能需要滤波、退耦和放大等电路),单向计数时任选一相接口即可。 开环与闭环 开环系统与闭环系统最重要的区别是反馈系统。 开环系统是没有反馈系统的,其控制机构发出命令后,执行机构开始执行,而执行机构的结果是未知的。比如步进电机 闭环系统拥有反馈系统,其控制机构发出命令后,执行机构开始执行,并有监测机构检测并反馈执行结果告知控制机构执行机构的执行状态,进而以此为依据进行进一步调整。比如伺服电机 动力系统+反馈系统 = 闭环。如果给步进电机的执行机构在适当位置放置(高精度)编码器,那么这就是一个闭环,也就是常说的\"伺服系统“ Copyright © Jim 2019-2020 all right reserved,powered by GitbookRevision time: 2021-08-30 10:19:58 "}}