DS80C400的Keil C语言编程

发布者:TechVoyager最新更新时间:2012-02-01 来源: Maxim中文网站关键字:DS80C400  Keil  C语言编程 手机看文章 扫描二维码
随时随地手机看文章
可以被视作一个构建C或汇编程序的起跑架,它提供TINI®经过验证的网栈、进程调度器和存储器管理器。简单程序,如网络扬声器,可以用汇编语言轻松实现,更复杂一点的,如HTTP服务器这种需要与文件系统交互的程序,可以使用C语言。

文中介绍了如何从Keil的uVision2开发套件着手构建一个DS80C400的C语言应用程序,通过实现一个简单的HTTP服务器演示如何使用DS80C400的ROM功能。所有开发都采用了TINIm400验证模块和包含7.05版C编译器'C51'的Keil uVision2 2.37。

从Keil的uVision2开始
你可以使用Keil uVision2开发套件,构建一个简单的HelloWorld型C语言程序。按照以下步骤完成你的第一个用于DS80C400的C语言应用程序。

选择Project-->Create New Project。 输入项目名称。

屏幕上将出现Select Device for Target对话框。在Data base中选择Dallas Semiconductor和DS80C400。选择Use Extended Linker和Use Extended Assembler。点击OK继续。图1所示为该对话框的正确配置。


图1. 为一个新的Keil uVision2项目选择

将有对话框提示:Copy Dallas 80C390 Startup Code to Project Folder and Add File to Project?选择No。我们将提供自己的启动代码。

当项目窗口在左侧打开时,打开Target 1。右击Source Group 1,并选择Add files to group 'Source Group 1'。在弹出的文件对话框中,将files of type改为Asm Source file。添加文件startup400.a51。该文件可以在http://files.dalsemi.com/tini/ds80c400/c_libraries/HelloWorld.zip上的zip文件中找到。

双击打开文件startup400.a51。找到段声明?C_CPURESET?0。确保代码段声明为400000h。

      C_CPURESET?0        SEGMENT CODE AT 400000h
另外,应有一个"DB 'TINI'"行,后跟另一个DB行,带有注释"Target bank"。这样就可以确保应用建立地址为400000h,对应于TINIm400上flash的起始地址。请确认该行为: 
      DB     40h           ; Target bank
创建一个新的文件,以"main.c"为文件名来保存。在该文件中写入如下代码:
      #include 

      void main()
      {
             printf("Test 400 Program\r
");
             while (1)
             {
             }
      }
保存文件内容。右击Source Group 1,并添加源文件main.c。现在就将该源文件添加到项目中了。

右击左侧的Target 1。选择Options for target 'Target 1'打开选项对话框。第一个选择标签应该为Target。将Memory Model改为Large: variables in XDATA。将Code Rom Size改为Contiguous Mode: 16MB program。选中检查框Use multiple DPTR registers和far memory type support。在Off-chip Code memory项目下加入第一个入口:Start:0x400000,Size:0x80000。在Off-chip XData memory项目下加入一个入口:Start:0x10000,Size:0x4000。图2所示为配置完成的对话框。确认检查框Use On-Chip Arithmetic Accelerator被清除--多线程应用很难共用算术累加器。


图2. setp 7目标选项对话框(注意,'Eprom:start' 应为0x400000,最后一个'0'未显示)。

选择Output标签。点击Create HEX File,并在下拉框中选择HEX-386。按F7键建立应用程序。如果每一步都正确完成,建立过程应不产生错误或警告信息。之后会生成一个hex文件。现在就可以将该应用程序装载到你的电路板上了。

将应用实例装载到TINIm400模块
这部分介绍如何使用JavaKit工具将Keil编译器生成的hex文件装载到TINIm400验证模块中。使用JavaKit之前,必须首先安装Java Runtime Environment2 (1.2版以上)和Java Communications API3。JavaKit包含在TINI软件开发包中(TINI Software Development Kit),http://files.dalsemi.com/tini/tini1_11.tgz上提供下载。运行JavaKit的说明可以在TINI Software Development Kit的docs目录下的Running_JavaKit.txt文件中找到。如果你在运行JavaKit时遇到任何技术问题,很可能其他人曾经遇到过类似的问题,这些问题被收集在TINI主题列表中。你可以在http://lists.dalsemi.com/search/search.html上搜索有关该列表的文档。

通过以下命令行建立JavaKit与TINIm400的通话。

      java JavaKit -400 -flash 40
图3显示了JavaKit窗口。


图3. JavaKit界面。

运行JavaKit后,选择用来与TINIm400进行通信的串口。使用'Open Port'按钮打开该串口。然后按Reset按钮。DS80C400装载器将提示如下信息:

     DS80C400 Silicon Software - Copyright (C) 2002 Maxim Integrated Products
     Detailed product information available at http://www.maxim-ic.com

     Welcome to the TINI DS80C400 Auto Boot Loader 1.0.1
     >
在JavaKit顶部的'File'菜单中,选择Load HEX File as TBIN。找到并选择我们已经创建的helloworld.hex文件。Load HEX File as TBIN选项先将输入的hex文件转换为TBIN文件,然后装载。这样的操作比直接装载hex文件速度快,因为对于同样的数据,ASCII编码的hex文件的尺寸是二进制文件的二倍多。
用户程序装载后,有两种执行方法。由于程序装载到存储区40中,所以你可以直接键入:
      > B40
      > X
要选择存储区40,并在运行这里的代码,也可以键入:
      > E
这将使ROM查找可执行代码,有一个特殊标记符用来表示当前存储区中有可执行代码。该标记符由字符'TINI'和紧随其后的当前区号组成。它位于当前区的地址0002处。我们的HelloWorld程序对于此标记符的声明在startup400.a51文件中如下所示: [page]
      C_STARTUP:   SJMP   STARTUP1
                    DB     'TINI'               ; Tag for TINI Environment 1.02c
                                                ; or later (ignored in 1.02b)
                    DB     40h                  ; Target bank
注意SJMP STARTUP1语句位于40区的地址0000处。由于sjmp语句占两个字节,所以紧随其后的执行标记{'T', 'I', 'N', 'I', 40h}位于地址0002。当键入'E'时,ROM在FEh存储区中向下查找可执行代码。如果键入'E'后执行了其他代码,就说明ROM在高于 400000h (装载你的代码的位置)的地址处找到了执行标记,你可能需要找到该标记,并删除该存储区中的内容。

接口至ROM和ROM库
从C中调用ROM函数比较复杂(调用ROM函数的步骤参见High-Speed Microcontroller User's Guide supplement for the DS80C4004)。必须将Keil C编译器规范的参数转换成ROM所使用的规范。Keil编译器以XDATA地址和寄存器组合的方式传递参数。而ROM函数采用不同的方式接收参数。例如,套接字函数接受存放在单个参数缓冲器中的参数,而许多其他应用函数接受特殊功能寄存器或直接存储器地址传来的参数。Dallas Semiconductor编写了访问ROM函数的库,可完成Keil调用规范与ROM参数规范间的翻译工作。

要在你的C程序中使用ROM函数,只需要导入相应的库,并包含一个头文件。为了在你的项目中导入一个库,在Keil项目窗口中右击Source Group 1,并选择Add Files to Group 'Source Group 1'。将文件过滤器改为‘*.lib’,选择你需要的库。然后在源代码顶部加入头文件。你可以使用任何一个库函数。这些ROM库可支持:
ROM初始化
DHCP客户端操作
进程管理
套接字函数(TCP、UDP、Multicast)
TFTP客户端操作
一些实用函数(CRC和伪随机数产生等)

使用扩展库
除了ROM库,还有许多其他库(还有更多正在编写中)提供了很多ROM中没有的实用功能。这些库包括:

- 文件系统,改编自TINI文件系统,实现stdio.h中声明的方法。
- DNS客户端实现。
- 1-Wire®,采用Public Domain Kit (参见www.ibutton.com.cn/software/1wire/wirckit.html)中定义的API。
- I2C,实现一个类似于TINI中所用的设计。
- CAN,实现一个类似于TINI中所用的设计。

为DS80C400提供的C库项目(包括文档、应用实例和发行说明)可以在http://files.dalsemi.com/tini/ds80c400/c_libraries/index.html上找到。

一个简单的HTTP服务器和SNTP客户端应用
Dallas Semiconductor编写了一个小的应用程序来演示这些库的功能,特别是文件系统、套接字、进程调度器和TFTP库等。应用实例中包括一个SNTP 客户端和一个只响应'GET'请求的HTTP服务器。它使用Dallas Semiconductor提供的核心库调用套接字和调度器函数。它还使用文件系统保存了几个网页。该应用由两个进程组成:(1) HTTP服务器作为一个新进程被创建并用来处理端口80上的连接,以及(2)主进程位于一个循环中,约每60秒尝试进行一次时间同步。

文件系统的初始化
启动HTTP服务器之前,必须初始化文件系统。演示程序确保两个静态文件,主页(index.html)和程序源码(source.html),在服务器启动之前已位于文件系统中。 可以用多种方法将这些文件安装到文件系统。方法之一是在程序代码数据中包含这些文件的文本,然后,在启动时将文件数据写到文件系统。这是最简单的方法,而且我们的演示程序也有空闲的代码空间可供使用。

本演示程序通过TFTP服务器查找它所需要的文件并初始化其文件系统。这是一种更为有趣、并且更能展示DS80C400内置功能的方法。在我们这个实例中,TFTP服务器在一个已知的IP地址上运行。文件index.html和source.html由TFTP服务器获得,然后被写入文件系统。

      void initialize_filesystem()
      {
             struct sockaddr address;
             unsigned int i;
             unsigned int result;
             void* start = (void*)FS_START;

             // initialize the file system
             int x = finit(FOPEN_MAX, FS_BLOCKS, start);
             printf("Result of FS init: %d \r
", x);

             if ((x==0) && (fexists("index.html")==0) && (fexists("source.html")==0))
             {
                    printf("File system OK, skip TFTP init.\r
");
                    return;
             }

             // lets get the files we want off a TFTP server
             // initialize TFTP server setting
             for (i=0;i<18;i++)
                    address.sin_addr[i] = 0;

             // since the DS80C400 supports Ipv6, the address is 16 bytes long
             // however, since we are only using Ipv4 addresses, only the last
             // 4 bytes are meaningful
             address.sin_addr[12] = TFTP_IP_MSB;
             address.sin_addr[13] = TFTP_IP_2;
             address.sin_addr[14] = TFTP_IP_3;
             address.sin_addr[15] = TFTP_IP_LSB;

             result = settftpserver(&address, sizeof(struct sockaddr));
             printf("Set TFTP server to selected server, result: %u\r
", result);
             result = tftp_init();
             printf("Result of TFTP init: %u \r
", result);

             get_tftp_file("source.html");
             get_tftp_file("index.html");
      }

      void get_tftp_file(char* filename)
      {
             unsigned int result;
             unsigned char* TFTP_MSG;
             FILE* file;

             printf("Free FS RAM: %ld\r
", getFreeFSRAM());
             TFTP_MSG = getTFTPData();
             file = fopen(filename, "w");
             result = tftp_first(filename);
             if (result==0xFFFF)
             {
                    printf("Error in TFTP_FIRST...\r
");
                    return;
             }
             printf("Result of first segment: %u\r
", result);
             fwrite(TFTP_MSG, 1, result, file);

             while (result >= 512)
             {
                    result = tftp_next(TFTP_MORE_DATA);
                    if (result==0xFFFF)
                    {
                           printf("Error in TFTP_NEXT...\r
");
                           return;
                    }
                    printf("Result of next segment: %u\r
", result);
                    TFTP_MSG[result] = 0;
                    fwrite(TFTP_MSG, 1, result, file);
             }
             tftp_next(TFTP_LAST_SEGMENT);

             fclose(file);
             printf("Done with TFTP server.\r
");
      }[page]
注意在每次启动应用时都须调用finit函数,以确保文件系统已正确安装并能正常工作。如果文件系统已正确初始化(返回0),并且我们所要的文件已全部到位,则函数直接退出,不去尝试下载文件。否则,它会尝试从TFTP服务器下载文件,并将它们写入文件系统,正如函数get_tftp_file中所显示的。

SolarWinds为Windows (平台提供了一个免费的TFTP服务器,它被应用于该演示程序的开发中。在SolarWinds网站(www.solarwinds.net),跟随Downloads - Free Software菜单可找到TFTP服务器下载。安装以后,使用File菜单下的Configure选项来配置现有文件。确保程序使用你的TFTP服务器IP地址(TFTP_IP_MSP, TFTP_IP_2,TFTP_IP_3和TFTP_IP_LSB)。

简单的HTTP服务器
该应用中的HTTP服务器是RFC 2068所描述的HTTP服务器的一个简化版实现。在该版本下,只支持'GET'方法。输入头被忽略,只给出很少的输出头。

服务器套接字通过调用Berkley型套接字函数来创建,这样使得服务器套接字容易建立。以下代码说明了这个简单的HTTP服务器是如何创建、邦定并接受新连接的。

      struct sockaddr local;
      unsigned int socket_handle, new_socket_handle, temp;

      socket_handle = socket(0, SOCKET_TYPE_STREAM, 0);
      local.sin_port = 80;
      bind(socket_handle, &local, sizeof(local));
      listen(socket_handle, 5);

      printf("Ready to accept HTTP connections...\r
");

      // here is the main loop of the HTTP server
      while (1)
      {
             new_socket_handle = accept(socket_handle, &address, sizeof(address));
             handleRequest(new_socket_handle);
             closesocket(new_socket_handle);
      }
请注意,接受了新的套接字后,这个简单的应用并不启动新的线程或进程来处理请求。而是在同一进程中处理该请求。任何非演示版的HTTP服务器都会在新的线程中处理收到的请求,这样就允许多个连接出现并被同时处理。请求处理完后,关闭套接字,等待另一个收到的连接。

handleRequest方法从收到的请求中解析出一个文件名,并确定该方法是'GET'。其它方法(甚至是'POST','HEAD'或'OPTIONS')均不被接受。两个文件名被作为特例处理。当请求文件为time.html时,服务器动态产生一个响应,其中包含来自timeserver的最新结果,以及自上一次查询时间服务器以来的秒数。当请求文件为stats.html时,将显示服务器的正常运行时间和请求次数统计结果。

如果找不到文件或发出的是无效的请求方法,HTTP服务器报告错误码。

SNTP客户端
第二个主要部分是Simple Network Time Protocol客户端,参见RFC 1361的描述。它是Network Time Protocol (RFC 1305)的一个版本。SNTP要求UDP从一个侦听端口123的服务器请求时戳。我们的timeserver使用以下代码周期性地与服务器time.nist.gov同步。请注意,在写这篇文章时,DNS检索还不被支持,因此服务器的IP地址须手动设置。DNS现已被添加到了C库网站,以下代码更新后可通过检索获得IP地址。

      socket_handle = socket(0, SOCKET_TYPE_DATAGRAM, 0);

      // set a timeout of about 2 seconds
      buffer[0] = 0x0;
      buffer[1] = 0x0;
      buffer[2] = 0x8;
      buffer[3] = 0x0;
      setsockopt(socket_handle, 0, SO_TIMEOUT, buffer, 200);

      buffer[2] = 0;                            // reset since we used this in call to setsockopt
      buffer[0] = 0x23;                         // No warning/NTP Ver 4/Client

      address.sin_addr[12] = TIME_NIST_GOV_IP_MSB;
      address.sin_addr[13] = TIME_NIST_GOV_IP_2;
      address.sin_addr[14] = TIME_NIST_GOV_IP_3;
      address.sin_addr[15] = TIME_NIST_GOV_IP_LSB;
      address.sin_port = NTP_PORT;

      sendto(socket_handle, buffer, 48, 0, &address, sizeof(struct sockaddr));
      recvfrom(socket_handle, buffer, 256, 0, &address, sizeof(struct sockaddr));

      timeStamp = *(unsigned long*)(&buffer[40]);
      timeStamp = timeStamp - NTP_UNIX_TIME_OFFSET;
      // now we have time since Jan 1 1970

      formatTimeString(timeStamp, "London", last_time_reading_1);
      last_reading_seconds = getTimeSeconds();
      closesocket(socket_handle);
首先生成一个数据报套接字,并给定一个约2秒的超时(0x800==2048ms)。这样可以确保在与我们选择的服务器通信失败时,不必无限期地等待下去。

下一行设定请求选项。关于这些位的描述参见RFC 1361第三节。值0x23要求闰秒时无需告警,要求采用NTP版本4,并声明模式为'Client'。当我们使用公共数据报函数sendto和recvfrom发出请求并收到回答后,时戳的秒部被赋给变量timeStamp,然后调整到参考时间1970年1月1日。formatTimeString函数将时戳转换为易读的字符串,如“In London it is 15:37:37 on March 31, 2003”。

getTimeSeconds函数以DS80C400内部时钟为基础确定上一次更新。由于该程序大约每60秒才更新一次,HTML页time.html使用这个数值来报告自上次更新以来的时间间隔。最后,关闭套接字,SNTP客户端在下面的60秒内进入休眠。

有关同步的说明
在LARGE存储模式下,Keil编译器将通过在进程交换中非安全的存储器传递有限数量的参数。这就意味着有些函数不能由多个程序同时调用。尽管已专为 400开发了C库,其中的所有变量都通过在进程交换中安全的直接存储器传递,有些函数仍然是危险的。例如,Berkeley式的套接字header要求一些较长的方法签名,它会涉及到一些通过非安全存储器传递的数据。因此,针对套接字有两个库:

一个库(rom_sock.lib)遵循Berkeley式的header。但是,两个进程同时用这个库调用某个函数是不安全的。不过,如果一个进程正在使用UDP函数而另一个正在使用TCP函数就不会有问题。为了对并发访问非安全存储器提供真正的保护,开发了另外一个套接字库(rom_sock.lib)。该库中的函数类似于Berkeley型函数,但具有更少或重新安排的变量,以使Keil编译器通过安全存储区传递参数。无论何种情况,请参考相关文档,以确认函数是否为多进程安全的。[page]

有关指针传递的说明
Keil文档提供了用8051汇编自己编写可从你的C程序中调用的方法的途径。如果你选择这样做,请注意,由C程序传递到8051汇编的指针在 DS80C390和DS80C400中不是立即可用的。因为传统的8051架构是16位的,Keil指针由两字节的指针和一字节的存储类型组成。当采用 Dallas的24位8051微控制器时,存储类型字节为指针高字节所用,但采用一种变化的形式。在当前版本的Keil编译器中,高指针字节有其高位设置并被递增1。以下来自rom_offsets.inc的宏在Dallas Semiconductor库中被用于纠正被更改的指针。

      FIXKEILPOINTER  MACRO DIRECT_DPX
             LOCAL  must_be_null
             mov    a, DIRECT_DPX
             jz     must_be_null
             dec    a

             anl    a, #7Fh
             mov    DIRECT_DPX, a
     must_be_null:
             ENDM
Keil编译器通过寄存器r3:r2:r1 (r3是存储类型字节) 或XDATA存储区传递指针。该宏将工作于任何寄存器或其他直接存储器值,传给它存储类型字节,它会在同一位置返回高指针字节。以下代码演示了它的用法:
      ;
      ; Keil passes pointers as r3:r2:r1...
      ;---- Variable 'buffer1?972' assigned to Register 'R1/R2/R3' ----
      ;
      FIXKEILPOINTER r3
      ;
      ; r3:r2:r1 is now usable as a pointer value.
      ;

      ;
      ; ...or in XDATA.
      ;---- use dpx1:dph1:dpl1 for buffer pointer ----
      ;
      mov     dptr, #buffer2?1078
      GETX
      mov     dpx1, a
      inc     dptr
      GETX
      mov     dph1, a
      inc     dptr
      GETX
      mov     dpl1, a
      FIXKEILPOINTER   dpx1
      ;
      ; Data pointer 1 is now usable as a pointer.
      ;
注意,还有一种与FIXKEILPOINTER宏相反的情况,可以使函数将其所需的指针转换为Keil编译器生成代码可以理解的形式。在此情况下,可以用UNFIXKEILPOINTER宏。这个宏的用法和FIXKEILPOINTER宏相同。一点不同是,当你从一个用汇编写的方法中返回一个指针时,指针必须保存在寄存器r3, r2和r1中,高指针字节在r3中。因此,在退出一个需要返回指针的函数前,它必须调用宏:
      UNFIXKEILPOINTER r3
      ret
      ; End of the assembly function
保持你的Keil为最新版本
Keil会随时发布对其uVision2工具套件的更新版本。网站http://www.keil.com/update/上有关于最新版本的C51编译器和uVision2 IDE的信息。从该网页你可以选择你需要的下载,并看到所发生的变化。

更新应该是一个可执行的InstallShield。应用将显示一个标题为Setup uVision2的窗口。选择Update Current Installation选项执行更新。程序可以检测你当前的安装目录,点击Next继续。在下一屏上选择是否要保留原来的uVision2配置,并再次点击Next。最后,确认你选择的选项并开始安装。

结论
Keil C编译器和Dallas Semiconductor提供的库允许用C编写的应用也可方便地使用以前只能通过TINI的Java环境访问的功能和函数。C语言程序现在可以访问网栈、存储管理器、进程调度器、文件系统,以及DS80C400网络微控制器的许多其他特性。另外,与TINI运行环境相比,用C语言编写的应用程序为用户代码和数据提供了更多的空间。使用C语言的DS80C400开发者可轻易编写出极为精简的应用,有充裕的速度速度、能力、代码空间来应付各种问题。

参考文献
1 App Note 609: Internet Speaker with the DS80C400 Silicon Software

2 Download at http://java.sun.com/j2se/downloads.html

3 Download at http://java.sun.com/products/javacomm/

4 The High-Speed Micro User's Guide Supplement for the DS80C400 can be found at http://pdfserv.maxim-ic.com/arpdf/Design/DS80C400UG.pdf

关键字:DS80C400  Keil  C语言编程 引用地址:DS80C400的Keil C语言编程

上一篇:采用ST72F651实现的安全U盘
下一篇:基于单片机的智能无功补偿仪的设计

推荐阅读最新更新时间:2024-03-16 12:52

keil 中调用printf 的使用 在软件调试下 serial windows 下显示打印信息
1.软件编程内容 printf 要包含C的头文件#include stdio.h 标准的输入输出; printf 在调用的时候要先重写(不知道是不是重写)putchar 函数,在单片机中用下面的函数, char putchar(char s) { SBUF=s; while(TI==0) { _nop_(); } TI=0; } 在stm32 中用要写fputc 函数 int fputc(int ch, FILE *f) { while((USART1- SR&0X40)==0);//循环发送,直到发送完毕 USART1- DR = (u8) ch; r
[单片机]
<font color='red'>keil</font> 中调用printf 的使用 在软件调试下 serial windows 下显示打印信息
Arm设计思想与高效C语言编程联系
一.RISC设计思想 ARM内核采用RISC体系结构。RISC是一种设计思想,其目标是设计出一套能在高时钟频率下单周期执行,简单而有效的指令集。RISC的设计重点在于由硬件执行的指令的复杂度,这是因为软件比硬件容易提供更大的灵活性和更高的智能。因此,RISC设计对编译器有更高的要求;相反,传统的复杂指令集的计算机(CISC)则更侧重于硬件执行指令的功能性,使CISC变得更复杂。 RISC设计思想主要由下面4个设计准则来实现: ▇ 指令集 RISC处理器减少了指令种类,每条指令的长度都是固定的,允许流水线在当前指令译码阶段去取其下一条指令;而CISC处理器中,指令的长度通常不固定,执行也需要多个周期。 ▇ 流水线 在理
[单片机]
Hash查找法在Keil C51中的实现
摘要:散列(hash)是一种重要的存储方法,也是一种常见的查找方法。它是指在记录的存储位置和它的关键字之间建立一个确定的对应关系。本文以射频卡门禁控制器为例,说明用射频卡卡号作为关键字,用Hash查找法确定此卡能否开门,并给出对应的Keil C51程序。 单片机应用系统中,经常要涉及到数据的存储和查找。以射频卡门禁系统为例,见图1。系统由51系列单片机、射频卡(RF卡)读卡电路、存储单元24C256、继电器等部分组成。其基本原理为:用户刷卡后,RF卡读卡电路读出卡号,通过I/O口线送入单片机。单片机收到卡号后,在存储单元中查找此卡是否允许开门。如允许,则命令继电器动作,打开电磁门锁:如不允许,则返回。 iframe id="
[单片机]
Hash查找法在<font color='red'>Keil</font> C51中的实现
Keil c51的应用及特性解析
Keil c51号称作为51系列单片机最好的开发环境,大家一定都很熟悉。它的一些普通的特性大家也都了解,(书上也都说有)如:因为51内的RAM很小,C51的函数并不通过堆栈传递参数(重入函数除外),局部变量也不存储在堆栈中,而是存在于固定的RAM中及寄存器中。那么看一下下面的程序。 void fun1(unsigned char i) { } 正常情况参数i通过R7传入函数,那么它的实际地址在什么地方呢?就是R7吗?回答这个问题之前我们先来了解keil c51的几个有趣的特性(不考虑重入函数)。 一、函数在调用前定义与在调用后定义产生的代码是有很大差别的(特别是在优化级别大于3级时)。(本人也不太清楚为什么,大概因为在
[单片机]
创建keil工程并点亮STM32板子的LED灯
打开之前创建的工程,如下图所示(keil工程的创建在之前的文章中有,不了解的同学可以翻一下上一篇文章。) (上图是已经建立完成的工程) 然后,再次打开我们之前下载的对应开发板版本的例程包中的点亮LED灯的例程 (路径为:en.stsw-stm32077 \STM32L1xx_StdPeriph_Lib_V1.3.1 \project\STM32L1xx_StdPeriph_Examples \GPIO \IOToggle) 找到mian.c文件打开,全选复制里面的内容 再回到我们之前已经创建完毕的工程中,打开mian.c文件清空,并将GPIO文件中的main.c里面的内容粘贴到我们工程的mian.c中。 此时可以看到有很多
[单片机]
KEIL调试错误信息提示
1.warning: #1295-D: Deprecated declaration UART1_sendIMU_data - give arg types 不赞成这样声明函数;; 解决:多半是在h文件中声明函数是,形参没有写。eg:void UART1_sendIMU_data();形参中的void没写 2、error: #18: expected a ) 如果是出现在c文件中, 多半是因为少了一个 ) ,或者错误行有编译器不识别的字符 如果出现在头文件中,错误行又是一个函数声明,多半是因为在函数声明中有编译器不认识的字符. 还有一种可能是,你传递的形参中的变量,在c文件中已经定义过或者define过。。
[单片机]
关于keil MDK 的配置文件Configuration Wizard
在keil MDK自带的启动代码有一个优势就是可视化的配置选项,就是Configuration wizard选项,这样就省去了我们手动输入配置的问题。比如下面对于Memory的设计的Configuration界面: 而在启动代码中的这个Configuration的程序为: // e Watchdog Timer Setup // h Watchdog Timer Control Register (WTCON) // o1.8..15 Prescaler Value 0-255 // o1.5 Watchdog Timer Enable // o1.3..4 Clock Divis
[单片机]
关于<font color='red'>keil</font> MDK 的配置文件Configuration Wizard
Keil C51 总线外设操作问题的深入分析
阅读了《单片机与嵌入式系统应用》2005年第10期杂志《经验交流》栏目的一篇文章《Keil C5l对同一端口的连续读取方法》(原文)后,笔者认为该文并未就此问题进行深入准确的分析。文章中提到的两种解决方法并不直接和简单。笔者认为这并非是Keil C51中不能处理对一个端口进行连续读写的问题,而是对Keil C51的使用不够熟悉和设计不够细致的问题,因此特撰写本文。 本文中对原文提到的问题,提出了三种不同于原文的解决方法。每种方法都比原文中提到的方法更直接和简单,设计也更规范。(无意批评,请原文作者见谅) 1 问题回顾和分析 原文中提到:在实际工作中遇到对同一端口反复连续读取,Keil C5l编译并未达到预期的结果。原文作
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved