C语言嵌入式系统编程修炼之内存操作

C语言笔记——第二篇 数据的存储,附练习题详解 这是我在学习过程中的笔记,总结的经验,踩过的坑。希望能对你有所帮助。持续缓慢更新...... 阅读详情

  数据指针

  在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:

  (1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;

  (2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断;

  (3) 读取在ROM或FLASH的特定单元所烧录的汉字和英文字模。

  譬如:

unsigned char *p = (unsigned char *)0xF000FF00;
*p=11;

  以上程序的意义为在绝对地址0xF0000+0xFF00(80186使用16位段地址和16位偏移地址)写入11。

  在使用绝对地址指针时,要注意指针自增自减操作的结果取决于指针指向的数据类别。上例中p++后的结果是p= 0xF000FF01,若p指向int,即:

int *p = (int *)0xF000FF00;

  p++(或++p)的结果等同于:p = p+sizeof(int),而p-(或-p)的结果是p = p-sizeof(int)。

  同理,若执行:

long int *p = (long int *)0xF000FF00;

  则p++(或++p)的结果等同于:p = p+sizeof(long int) ,而p-(或-p)的结果是p = p-sizeof(long int)。

  记住:CPU以字节为单位编址,而C语言指针以指向的数据类型长度作自增和自减。理解这一点对于以指针直接操作内存是相当重要的。

  函数指针

  首先要理解以下三个问题:

  (1)C语言中函数名直接对应于函数生成的指令代码在内存中的地址,因此函数名可以直接赋给指向函数的指针;

  (2)调用函数实际上等同于"调转指令+参数传递处理+回归位置入栈",本质上最核心的操作是将函数生成的目标代码的首地址赋给CPU的PC寄存器;

  (3)因为函数调用的本质是跳转到某一个地址单元的code去执行,所以可以"调用"一个根本就不存在的函数实体,晕?请往下看:

  请拿出你可以获得的任何一本大学《微型计算机原理》教材,书中讲到,186 CPU启动后跳转至绝对地址0xFFFF0(对应C语言指针是0xF000FFF0,0xF000为段地址,0xFFF0为段内偏移)执行,请看下面的代码:

typedef void (*lpFunction) ( ); /* 定义一个无参数、无返回类型的 */
/* 函数指针类型 */
lpFunction lpReset = (lpFunction)0xF000FFF0; /* 定义一个函数指针,指向*/
/* CPU启动后所执行第一条指令的位置 */
lpReset(); /* 调用函数 */

  在以上的程序中,我们根本没有看到任何一个函数实体,但是我们却执行了这样的函数调用:lpReset(),它实际上起到了"软重启"的作用,跳转到CPU启动后第一条要执行的指令的位置。

  记住:函数无它,唯指令集合耳;你可以调用一个没有函数体的函数,本质上只是换一个地址开始执行指令!

  数组vs.动态申请

  在嵌入式系统中动态内存申请存在比一般系统编程时更严格的要求,这是因为嵌入式系统的内存空间往往是十分有限的,不经意的内存泄露会很快导致系统的崩溃。

  所以一定要保证你的malloc和free成对出现,如果你写出这样的一段程序:

char * function(void)
{
 char *p;
 p = (char *)malloc(…);
 if(p==NULL)
  …;
  … /* 一系列针对p的操作 */
 return p;
}

  在某处调用function(),用完function中动态申请的内存后将其free,如下:

char *q = function();
…
free(q);

  上述代码明显是不合理的,因为违反了malloc和free成对出现的原则,即"谁申请,就由谁释放"原则。不满足这个原则,会导致代码的耦合度增大,因为用户在调用function函数时需要知道其内部细节!

  正确的做法是在调用处申请内存,并传入function函数,如下:

char *p=malloc(…);
if(p==NULL)
…;
function(p);
…
free(p);
p=NULL;

  而函数function则接收参数p,如下:

void function(char *p)
{
 … /* 一系列针对p的操作 */
}

  基本上,动态申请内存方式可以用较大的数组替换。对于编程新手,笔者推荐你尽量采用数组!嵌入式系统可以以博大的胸襟接收瑕疵,而无法"海纳"错误。毕竟,以最笨的方式苦练神功的郭靖胜过机智聪明却范政治错误走反革命道路的杨康。

  给出原则:

  (1)尽可能的选用数组,数组不能越界访问(真理越过一步就是谬误,数组越过界限就光荣地成全了一个混乱的嵌入式系统);

  (2)如果使用动态申请,则申请后一定要判断是否申请成功了,并且malloc和free应成对出现!
  关键字const

  const意味着"只读"。区别如下代码的功能非常重要,也是老生长叹,如果你还不知道它们的区别,而且已经在程序界摸爬滚打多年,那只能说这是一个悲哀:

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

  (1) 关键字const的作用是为给读你代码的人传达非常有用的信息。例如,在函数的形参前添加const关键字意味着这个参数在函数体内不会被修改,属于"输入参数"。在有多个形参的时候,函数的调用者可以凭借参数前是否有const关键字,清晰的辨别哪些是输入参数,哪些是可能的输出参数。

  (2)合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改,这样可以减少bug的出现。

  const在C++语言中则包含了更丰富的含义,而在C语言中仅意味着:"只能读的普通变量",可以称其为"不能改变的变量"(这个说法似乎很拗口,但却最准确的表达了C语言中const的本质),在编译阶段需要的常数仍然只能以#define宏定义!故在C语言中如下程序是非法的:

const int SIZE = 10;
char a[SIZE]; /* 非法:编译阶段不能用到变量 */

  关键字volatile

  C语言编译器会对用户书写的代码进行优化,譬如如下代码:

int a,b,c;
a = inWord(0x100); /*读取I/O空间0x100端口的内容存入a变量*/
b = a;
a = inWord (0x100); /*再次读取I/O空间0x100端口的内容存入a变量*/
c = a;

  很可能被编译器优化为:

int a,b,c;
a = inWord(0x100); /*读取I/O空间0x100端口的内容存入a变量*/
b = a;
c = a;

  但是这样的优化结果可能导致错误,如果I/O空间0x100端口的内容在执行第一次读操作后被其它程序写入新值,则其实第2次读操作读出的内容与第一次不同,b和c的值应该不同。在变量a的定义前加上volatile关键字可以防止编译器的类似优化,正确的做法是:

volatile int a;

  volatile变量可能用于如下几种情况:

  (1) 并行设备的硬件寄存器(如:状态寄存器,例中的代码属于此类);

  (2) 一个中断服务子程序中会访问到的非自动变量(也就是全局变量);

  (3) 多线程应用中被几个任务共享的变量。

  CPU字长与存储器位宽不一致处理

  在背景篇中提到,本文特意选择了一个与CPU字长不一致的存储芯片,就是为了进行本节的讨论,解决CPU字长与存储器位宽不一致的情况。80186的字长为16,而NVRAM的位宽为8,在这种情况下,我们需要为NVRAM提供读写字节、字的接口,如下:

typedef unsigned char BYTE;
typedef unsigned int WORD;
/* 函数功能:读NVRAM中字节
* 参数:wOffset,读取位置相对NVRAM基地址的偏移
* 返回:读取到的字节值
*/
extern BYTE ReadByteNVRAM(WORD wOffset)
{
 LPBYTE lpAddr = (BYTE*)(NVRAM + wOffset * 2); /* 为什么偏移要×2? */

 return *lpAddr;
}

/* 函数功能:读NVRAM中字
* 参数:wOffset,读取位置相对NVRAM基地址的偏移
* 返回:读取到的字
*/
extern WORD ReadWordNVRAM(WORD wOffset)
{
 WORD wTmp = 0;
 LPBYTE lpAddr;
 /* 读取高位字节 */
 lpAddr = (BYTE*)(NVRAM + wOffset * 2); /* 为什么偏移要×2? */
 wTmp += (*lpAddr)*256;
 /* 读取低位字节 */
 lpAddr = (BYTE*)(NVRAM + (wOffset +1) * 2); /* 为什么偏移要×2? */
 wTmp += *lpAddr;
 return wTmp;
}

/* 函数功能:向NVRAM中写一个字节
*参数:wOffset,写入位置相对NVRAM基地址的偏移
* byData,欲写入的字节
*/
extern void WriteByteNVRAM(WORD wOffset, BYTE byData)
{
 …
}

/* 函数功能:向NVRAM中写一个字 */
*参数:wOffset,写入位置相对NVRAM基地址的偏移
* wData,欲写入的字
*/
extern void WriteWordNVRAM(WORD wOffset, WORD wData)
{
 …
}

  子贡问曰:Why偏移要乘以2?

  子曰:请看图1,16位80186与8位NVRAM之间互连只能以地址线A1对其A0,CPU本身的A0与NVRAM不连接。因此,NVRAM的地址只能是偶数地址,故每次以0x10为单位前进!


图1 CPU与NVRAM地址线连接

  子贡再问:So why 80186的地址线A0不与NVRAM的A0连接?

  子曰:请看《IT论语》之《微机原理篇》,那里面讲述了关于计算机组成的圣人之道。

  总结

  本篇主要讲述了嵌入式系统C编程中内存操作的相关技巧。掌握并深入理解关于数据指针、函数指针、动态申请内存、const及volatile关键字等的相关知识,是一个优秀的C语言程序设计师的基本要求。当我们已经牢固掌握了上述技巧后,我们就已经学会了C语言的99%,因为C语言最精华的内涵皆在内存操作中体现。

  我们之所以在嵌入式系统中使用C语言进行程序设计,99%是因为其强大的内存操作能力!

  如果你爱编程,请你爱C语言;

  如果你爱C语言,请你爱指针;

  如果你爱指针,请你爱指针的指针!

第一讲:halcon模板匹配捆绑测量矩形检测芯片针脚 使用halcon模板匹配捆绑测量矩形,检测位置发生变换的芯片针脚缺陷。 阅读详情

相关推荐

南京邮电大学电工电子实验(二)复习一

本文给电工电子实验(二)的复习进行一些知识点的提醒

YOUXISUN的博客 2958

C语言基础篇

1.C语言概述 1.1为什么要学习C语言 1.1.1 C语言的特点 1)优点: 代码量小 执行速度快 功能强大 编程自由 2)缺点: 写代码实现周期长 可移植性较差 过于自由,经验不足易出错 对平台库依赖较多 1.1.2 C语言的简洁 C语言仅有32个关键字,9种控制语句,34种运算符,却能完成无数的功能: 1.2第一个C语言程序 1.2.1编写C语言代码:hello.c #include <stdio.h> int main() { //这是第一个C语言代码 printf

永远相信美好事情都会发生的博客 4525

深入解析JESD204B Subclass 1中的SYSREF与LMFC同步机制

本文深入解析了JESD204B Subclass 1协议中的核心同步机制,重点阐述了SYSREF信号如何作为系统级参考,对齐所有设备内部的本地多帧时钟(LMFC),从而实现高速多通道数据采集系统中的确定性延迟。文章结合实战经验,详细说明了硬件设计、时序要点及软件配置流程,是解决多ADC芯片同步对齐问题的关键指南。

weixin_29271263的博客 398

嵌入式 C语言实现在0x1000地址处写入一个单字节的整数

char a=2;*(char *)0x1000=a; Memset((char *)0x1000,2,1);

skdkjxy的专栏 2430

基于STM32的智能台灯PWM调光与人体感应融合设计

本文详细介绍了基于STM32单片机的智能台灯设计方案,重点讲解了PWM调光技术与人体感应模块的融合实现。通过STM32的高级定时器产生精准PWM信号控制LED亮度,结合红外传感器实现人来灯亮、人走灯灭的智能体验,同时集成光敏传感实现环境自适应调光,打造高效节能的智能照明解决方案。

threejs5artist的博客 823

Qcom camera hal简介

Qcom camera hal简介

weixin_42136255的博客 7764

mtk 中 nvram 的读写操作

定义NVRAM 数据有三种方式: (一)、在nvram_editor_data_item.h、nvram_data_item.h、nvram_data_item.c三个文件中添加。 1、在nvram_editor_data_item.h文件中定义自己保存在nvram 中的结构体数据类型。       例如:  typedef struct                  

玉凌风 5897

Typora绘制思维导图

我们观察一下,其实思维导图就是树状结构的数据嘛,作为程序员,拿语言写树状结构的数据是很平常的事情。而且写代码可比画图省事多了,查阅资料可以知道,有一种`mermaid`语法,就是做这件事情的,支持 UML,甘特图,流程图等。

Peter Cheung的博客 7933

第一章 用C语言操作内存

课堂随笔: 计算机的程序=代码+数据 计算机程序运行完成后得到一个结果 代码+数据(经过运行)=结果 从宏观的角度来说,代码就是动作,就是加工数据的动作,;数据就是数字,就是被代码所加工的东西。 结论:程序运行的目的就是–“结果”和“过程” 用函数类比: 函数的形参数就是待加工的数据(函数内还需要一些临时数据,就是局部变量) 函数本体就是代码 函数的返回值就是结果 函数体的执行就是过程 例...

weixin_29547033的博客 862

【RT-DETR实战】117、华为昇腾CANN部署探索:从模型转换到推理踩坑实录

本文总结了RT-DETR模型在昇腾310B芯片上部署的关键挑战与解决方案。主要遇到四大问题:1)模型转换时需注意ONNX导出设置,建议先固定尺寸验证;2)内存布局差异导致推理异常,需精确匹配NHWC/NCHW格式;3)流水线并发优化中内存复用和异步处理是关键;4)调试阶段需利用专用工具逐层比对。作者提出六条实用建议,包括小尺寸验证、预处理对齐、内存池设计等,强调部署是持续适配过程,需建立完整的测试体系应对工具链迭代。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 191

Esp32蓝牙Hid调用方案 http执行设备、鼠标、键盘相关操作

本文主要介绍 Esp32 蓝牙 Hid 相关的多种操作方式,详细的设备、鼠标、键盘相关操作的 http 调用方法。下面是整理出的所有 http 调用方法和 rhino 引擎方式。本机调用的话直接使用http://localhost:8080 如果是局域网调用则使用软件里的地址 比如我的是http://192.168.1.5:8080。文件地址: https://www.123865.com/s/Qtm4jv-xyZbd?使用前需要一块烧录好的ESP32板子并在手机安装好embedded软件用于蓝牙通信。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 569

C语言嵌入式系统编程修炼之道——内存操作篇

 C语言嵌入式系统编程修炼之道——内存操作篇1.数据指针在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:(1)   某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对

sunewer的专栏 1986

linux安装配置Mysql详细步骤

下载Mysql rpm包 官网下载:https://dev.mysql.com/downloads/mysql/ 如果你到了这里,本地应该有了如下四个rpm包: mysql-community-client-5.7.26-1.el6.x86_64.rpm mysql-community-common-5.7.26-1.el6.x86_64.rpm mysql-community-libs-5...

🏆 前端领域优质创作者 7万+

C语言嵌入式系统编程修炼之三:内存操作

数据指针  在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:  (1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;  (2) 两个CPU之间以双端

我的嵌入式 1249

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C语言嵌入式系统编程修炼之内存操作 [转]

 数据指针  在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:  (1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;  (2) 两个CPU之间以双

听风的专栏 1156

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

c语言中那些指令是申请内存的,C语言嵌入式系统编程修炼之内存操作

C语言嵌入式系统编程修炼之内存操作tongxin | 2009-03-20 17:34:58 阅读:734 发布文章数据指针%A%A   在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作...

weixin_33196555的博客 300

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

c语言中函数体在内存中的位置,[转]C语言嵌入式系统编程修炼之内存操作

数据指针在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指 令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能 力。以指针直接操作内存多发生在如下几种情况:(1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;(2) 两个CPU之间以双端口RAM...

weixin_30488835的博客 1650

c语言嵌入式系统编程修炼之道pdf,C语言嵌入式系统编程修炼之内存操作.pdf

C语言嵌入式系统编程修炼之内存操作.pdfC 语言嵌入式系统编程修炼之内存操作 C 语言嵌入式系统编程修炼之内存操作 数据指针 数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应 的 MOV 指令, 而除 C/C以外的其它编程语言基本没有直接访问绝对地址的能力。 在嵌入式系统的实际调试中, 多借助 C 语言指针所具有的对绝对地址单元内容的 读写能力。以指针直接操作内存多发...

weixin_33344147的博客 340
上一篇: C++ Templates 中的一个例子
下一篇: Visual C++实现定制标题栏
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值