基于IAR编译器DS80C400的开发

发布者:as233632621最新更新时间:2018-03-24 来源: eefocus关键字:IAR编译器  DS80C400 手机看文章 扫描二维码
随时随地手机看文章

    DS80C400微控制器ROM的功能可由8051汇编语言、C或Java?编写的程序访问。通过使用ROM功能和由Maxim开发的软件库能够构建多种应用程序。本应用笔记阐述了如何使用8051 IAR Embedded Workbench?来建立DS80C400的C语言应用程序。通过一个简单的HTTP服务器示例来演示DS80C400的ROM功能。

    DS80C400微控制器的ROM包含多种功能,可通过由8051汇编语言、C或Java编写的程序访问。DS80C400的ROM功能提供成熟的MxTNI?网栈、进程调度和存储器管理,是开始构建C和汇编程序的最佳选择。对于简单程序,可以用汇编语言轻松实现。对于更复杂的程序,C语言可以充分利用Dallas SEMIconductor提供的ROM组件和软件库。这些软件库帮助您利用Keil ?Vision2?、SDCC和IAR 8051编译器构建应用程序。

    本应用笔记阐述了如何开始使用8051 IAR Embedded Workbench?来创建DS80C400的C语言应用程序。通过一个简单的HTTP服务器演示如何使用DS80C400的ROM功能。所有开发都采用TINIm400验证模块和包含6.11A版本C编译器的8051 IAR Embedded Workbench.

    从8051 IAR Embedded Workbench开始

    本节阐述如何使用IAR Embedded Workbench套件创建一个C语言编写的Hello World程序,即您的第一个DS80C400 C应用程序。

    1.安装IAR Embedded Workbench

    2.选择File→New→WorksPACe,在工作空间窗口,输入workspace名称appnote

    3.选择Project→Create New Project.在出现的对话框中,输入项目名称hellowworld,并确定选择了8051作为工具链

    4.当左侧的项目窗口打开时,选择Project→Add Files…在弹出的对话框中,将files of type改为汇编程序文件。添加文件Cstartup.s51,该文件可在Download的zip文件中找到

    5.双击并打开文件Cstartup.s51.找到程序段声明RSEG CSTART:CODE:ROOT(0)。这是代码段的开始。变量段的起始地址在link51ew_400.xcl中声明。代码的开始在文件中的0x400000h进行声明。另外,应有一个DB 'TINI'行,后跟另一个DB, high(?INIT)',带有注释Target Bank.这样就可以确保应用程序对应于TINIm400 flash的起始地址

    6.建立新文件main.c.在该文件中写入如下代码:

    #include

    #include

    void main ()

    {

    printf("Test program using IAR compiler");

    while (1)

    {

    }

    保存文件内容。通过选择Project→Add Files,然后在文件对话框中选择main.c,这样就把刚建立的文件加入到项目hellowworld中。确定加入的文件就是您建立的文件main.c;因为在默认目录中很有可能存在另一个具有相同名字的文件

    7.同样,将文件low_level_init.s51和putchar.c加入到项目中。low_level_init.s51文件包含初级DS80C400初始化程序;putchar.c文件包含将字符输出至默认控制台的初级程序

    8.从ftp://ftp.dalsemi.com/pub/tini/ds80c400/c_libraries/iar/bin/init.zip复制ROM initialization库文件,并将其解压缩到相同目录下。将rominit.r51库文件添加到项目中

    9.在编译Hello_World应用程序之前,我们需要配置IAR工具链来满足DS80C400的目标要求

    1)。选择Project→Options→General

    单击Target标签并浏览,在Derivative中选择DS80C400.将Extended stack at:对应的地址值改为0xFFDC00.这是因为IAR起始代码重新定位DS80C400硬件堆栈至0xFFDC00.对应这些设置请参考图1.

    单击Data Pointer标签。选择Number of DPTRs = 1.这是因为由Dallas SemIConductor所提供的库文件是在该选项下产生。

图1. 选择新的IAR 8051项目Target选项

    图1. 选择新的IAR 8051项目Target选项

    2)选择Project-Options→Options→ICC8051

    单击Code标签。选择Optimizations下的Size和None.

    单击List标签。选择Output List File和Output assembler File.

    单击Preprocessor标签。在include路径中放入以下程序:

    $TOOLKIT_DIR$INC

    $TOOLKIT_DIR$INCCLIB

    $TOOLKIT_DIR$SRClib

    $TOOLKIT_DIR$srclibclib

    include

    上面最后一行是库的头文件(*.h)所处的include路径。确定头文件在上面指定的路径中。$TOOLKIT_DIR$与IAR安装路径有关(例如,c:/program files/iar systEMS/embedded workbench 3.n/8051)。

    3)选择Project→Options→A8051

    单击List标签。选中Output List File.

    单击Preprocessor标签,在include路径中放入以下程序:

    $TOOLKIT_DIR$INC

    $TOOLKIT_DIR$srclib

    include

    上面最后一行是库的头文件(*.h; *.inc)所处的include路径。确定头文件在上面指定的路径中。

    4)。选择Project-→Options→XLINK

    单击Output标签

    在Output file中,选择Override default,并将文本文件名改为hello_world.hex.

    在Format中,选择Other,并从选项中选择Intel Extended.详情请参考图2.

    单击List标签。选择Generate Linker Listing.

    单击include标签,参考图3.

    选择Ignore CSTARTUP in Library.

    单击Override default,将文件名改为$TOOLKIT_DIR$configlnk51ew_400.xcl. $TOOLKIT_DIR$与IAR安装路径有关(例如,c:/program files/iar systems/embedded workbench 3.n/8051)。确定文件lnk51ew_400.xcl和lnk_base_400.xcl在指定的路径中。可在zip文件Download中找到这些文件。

图2. 选择新的IAR 8051项目的XLINK Output选项

图2. 选择新的IAR 8051项目的XLINK Output选项。

图3. 选择新的IAR 8051项目的XLINK Include选项

图3. 选择新的IAR 8051项目的XLINK Include选项。

    建立Hello_World应用程序。如果正确完成了每一步,建立过程应不会出现错误或警告信息;之后会在/debug/exe目录中产生hello_world.hex.如果你的项目配置为Release,那么hex文件将在/release/exe目录中产生。

    现在已经生成了可执行文件,我们需要将应用程序装载到TINIm400模块中并运行。

    将示例应用程序装载到TINIm400模块:

    本节说明如何使用Maxim/Dallas Semiconductor提供的Microcontroller Tool Kit (MTK)工具将IAR编译器生成的hex文件装载到TINIm400验证模块中。目前可用的MTK版本仅支持Windows.如果您的开发环境不是Windows?,需要使用JavaKit应用程序来装载和执行应用程序。要使用JavaKit,您必须具备Java Runtime Environment? (版本至少为1.2),并且安装了Java Communications API?.JavaKit工具包含在MxTNI软件开发包中。请下载MxTNI SDK.在撰写本文时,发布的最新固件版本是1.15.运行JavaKit的指导说明可在TINI SDK docs目录下的Running_JavaKit.txt文件中找到。如果您在运行MTK或JavaKit时遇到问题,可能其他人已经遇到过类似问题并已在Dallas Semiconductor讨论组公布。您可以在讨论组搜索现有文章(和新发表的文章)。

    在此可下载最新版本的应用程序。要安装MTK,请运行安装文件并按照提示操作。成功安装后,将会添加一个新的菜单组:Start→All Programs→Dallas Semiconductor MTK.MTK启动后,会出现图4. 所示的对话框。

图4. 启动时 MTK选项

图4. 启动时 MTK选项。

    选择TINI选项,以操作TINIm400评估板。

    选择了TINI之后,会打开MTK主窗口。从Options→Configure Serial Port菜单选项中选择您用来与TINIm400通信的串口。然后,选择Tini→Tini Options 菜单,就会出现下面的对话框。选择DSTINIm400按钮,配置MTK用于和TINIm400板通讯。图5显示了带有DSTINIm400按钮的对话框。图5. 选择TINIm400配置选项

图5. 选择TINIm400配置选项。

    选择Tini→Open COMx在xxx baud菜单选项打开串口。接着选择Tini→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

    >

    从File菜单中选择Load HEX File.找到并选择我们刚才生成的hello_world.hex文件。加载程序后,有两种方法运行它。因为我们将程序加载到40区,您可以输入:

    > B40

    > X

    要选择40区并运行那里的代码,您也可以输入:

    > E

    这会使ROM查找可执行代码。它查找一个标识当前区具有可执行代码的特定标签。此标签由文本'TINI'和随后的当前区号码组成,并位于当前区的0x0002地址。应用程序的起始代码采用下面几行声明该标签:

    ?VECTOR_TABLE:

    sjmp ?INIT

    DB      'TINI'           ; Tag for TINI Environment 1.02c

    ; or later (ignored in 1.02b)

    DB      high(?INIT)      ; Target bank

    注意sjmp ?INIT语句位于0x40区的0x0000地址。其后紧跟着可执行标签{ 'T', 'I', 'N', 'I', 0h},由于sjmp语句为两个字节,所以该标签地址位于0x0002处。当您键入E时,ROM从C0h区开始向下搜索可执行代码。如果您键入E时,执行了其它代码,则意味着ROM在一个比您的代码装载位置0x400000更高的地址找到了一个可执行标签。如果出现这种情况,您可能需要找到此标签的位置,并删除那个区的内容。

    与ROM以及IAR ROM库接口

    在高速微控制器用户指南DS80C4003补充资料中说明了在汇编语言中调用ROM函数的过程。但是,在C中调用这些ROM函数会复杂一些。必须将参数从IAR C编译器的规则转换成ROM使用的规则。IAR编译器通过硬件堆栈和寄存器相结合的方式传递参数。ROM函数以多种不同方式接受参数。例如,socket函数接收存储在一个参数缓冲器中的参数。相反,许多功能函数接收由特殊功能寄存器或堆栈存储器传递的参数。为了从IAR调用方式转换为ROM参数方式,Dallas Semiconductor已经编写了访问ROM函数的库。

    在您的C程序中使用ROM函数只需包含一个头文件并与相应的库文件连接即可。用于IAR编译器的ROM库包括:

    ROM初始化程序

    DHCP客户端

    进程调度

    Sockets (TCP、UDP和Multicast)

    TFTP客户端

    功能函数(CRC16, 随机数)

    在撰写本文时,还没有为IAR编译器提供包括文件系统、邮件客户端和HTTP服务器之类的扩展库。请关注IAR库主页上的DS80C4004升级信息,我们会添加更多支持IAR的库。

    简单应用: HTTP服务器

    这里编写了一个简单的http服务器说明如何使用一些ROM库函数,特别是socket和进程调度库。该示例应用程序由两个模块组成:一个HTTP服务器和一个SNTP客户端。主程序生成一个新的子任务来运行http服务器,用于处理80端口上的客户连接。父任务每60秒会试图通过时间服务器同步当前时间。

    SNTP客户端模块

    以下代码实现SNTP客户端模块的核心功能。

    socket_handle = socket(0, SOCKET_TYPE_DATAGRAM, 0);

    for (i=0;i<256;i++)

    buffer[i] = 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 = htons(NTP_PORT) // port number

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

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

    //IAR uses little Endian for storing data, so reorganize the data before   //converting it to long

    buffer[0]=buffer[43];

    buffer[1]=buffer[42];

    buffer[2]=buffer[41];

    buffer[3]=buffer[40];

    timeStamp = *(unsigned long *)(&buffer[0]);

    formatTimeString(timeStamp, "London", last_time_reading_1);

    formatTimeString(timeStamp - (6 * SECONDS_PER_HOUR), "Dallas",                    last_time_reading_2);

    formatTimeString(timeStamp + (5 * SECONDS_PER_HOUR) + (30 * SECONDS_PER_MINUTE), "Bangalore", last_time_reading_3);

    formatTimeString(timeStamp - (10 * SECONDS_PER_HOUR), "Honolulu",

    last_time_reading_4);

    last_reading_seconds = getTimeSeconds();

    closesocket(socket_handle);

    SNTP客户端模块是通过RFC 1361实现的。SNTP模块通过使用UDP协议和time.nist.gov通信,并请求一个时间标记。需注意撰写本应用笔记时还不能提供DNS查找支持,因此time.nist.gov的IP地址是人工设定的。

    首先,创建一个数据包socket并分配一个大约2秒(0x800==2048毫秒)的超时。这样会保证如果和我们选中的服务器通信失败,我们不会无休止地等待响应。

    接下来的一行用来设置请求选项。在RFC 1361的第3节对这些位进行了说明。0x23在一个闰秒不产生告警,要求使用版本4 NTP,并声明模式为Client.我们使用普通数据包函数sendto和recvfrom请求发送并接收响应后,将时间标记的秒赋予变量timeStamp,然后调整至参考日期1970年1月1号。用函数formatTimeString将时间标记转换成一个可读字符串,比如说"In London it is 05:33:19 on May 11, 2005".

    用函数getTimeSeconds 确定基于DS80C400内部时钟的最后一次更新时间。由于程序大约每60秒更新一次,HTML网页time.html将会使用该数值来报告上一次时间更新后已经过了多长时间。最后,关闭socket,SNTP客户端进入另一个60秒的休眠期。

    简单HTTP服务器

    这个时间服务器应用程序的另一个子模块为web服务器。此应用程序中的HTTP服务器实现了一个RFC 2068中描述的HTTP服务器简易版本。在我们的版本中,仅支持GET方法,忽略输入头文件,并且几乎不给出输出包头。在撰写这篇应用笔记时尚未提供文件系统库,因此示例应用程序动态地生成HTML网页。

    通过调用Berkley-style socket函数来创建服务器socket.这使得建立一个服务器socket十分容易。以下代码给出我们的简易HTTP服务器的创建、绑定和接受新连接。

    struct sockaddr LOCal;

    unsigned int socket_handle, new_socket_handle, temp;

    socket_handle = socket(0, SOCKET_TYPE_STREAM, 0);

    local.sin_port = htons(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);

    }

    注意当接收到一个新的socket时,这一简易应用程序不会启动一个新的线程或进程处理该请求,而是在同一进程中处理请求。任何优于该演示的HTTP服务器都会在一个新的线程中处理到来的请求,允许同时发生多个连接并能进行处理。请求处理完毕后我们关闭socket并等待下一个到来的连接。

    handleRequest方法从接入的请求中解析出文件名并且验证请求方法为GET.不允许使用其它方法(即使是POST、HEAD或OPTIONS)。

    为IAR编译器编写DS80C400汇编函数的注意事项

    IAR文档提供了在8051汇编中编写程序,可从C程序中调用的方法。若8051汇编函数由IAR编译器编写的C程序来调用,在编写这些汇编语言时需切记以下几点。如果没有可用的寄存器传递变量时,会将这些变量以Little Endian顺序压入堆栈。

    1.函数参变量传递约定

    下表说明了变量的传递方式。

 

下表显示了函数返回值的规则。

函数int foo(int x, int y,void* ptr);的变量和返回值的传递如下:

 

2.数据类型存储规则

  IAR遵循Little Endian存储规则。注意,IAR使用最低有效字节在前的二进制数据存储格式。

  例如,一个4字节长的数值0xDEADBEEF,将会按如下方式存储:

    3.一个简单的汇编程序与'C'接口

    本节演示如何编写一个汇编程序并用IAR Embedded Workbench与'C'程序接口。应用程序交换16位和32位字节,并将交换后的字节输出到默认的控制台。C的可调用函数原型是int ltob( int *shortptr , long *longptr)。

    本示例程序由两个文件组成:main.c和eswap.s51.main.c调用我们用汇编语言编写的示例函数ltob()。创建一个新项目,命名为endian;添加cstartup.s51、low_level_init.s51、putchar.c文件以及Dallas Semiconductor ROM初始化库rominit.r51.详细资料请参考上述从8051 IAR Embedded Workbench开始。

    用以下内容来创建一个新的main.c文件,并将该文件添加到项目endian中。在C中,必须声明一个函数,以便让编译器知道如何调用它。ltob()函数在main()之前声明。注意在成功运行后函数ltob()会返回'0',而且,如果任一指针为NULL则返回非零值。程序应向控制台输出以下结果:

    创建一个新文件eswap.s51,输入以下汇编代码,并将它加入到项目endian中。这个汇编程序将我们的函数ltob()声明为PUBLIC,因此它能够由'C'程序调用。ltob()的第一个参数是指针,并通过DS80C400控制器的寄存器r3:r2:r1来传递。第二个参数也是一个指针,由IAR编译器压入偏移3至5堆栈(偏移3含有最低有效字节,偏移5含有最高有效字节)。首先,函数重新找到堆栈中存储的指针(指向一个32位值),交换它所指向的值,将交换后的字节存储在相同位置。同样,16位值也被字节交换并存储在交换前的同一位置。注意,通过汇编函数来保留寄存器r6和r7.这是因为IAR编译器将这些寄存器视为永久寄存器,意味着任何函数调用都不应修改这些寄存器。

    #include "reg400.inc"

    r0_b0     equ 0                         ; Register bank 0 equates.

    r1_b0     equ 1

    r2_b0     equ 2

    r3_b0     equ 3

    r4_b0     equ 4

    r5_b0     equ 5

    r6_b0     equ 6

    r7_b0     equ 7

    PROGRAM ENDIAN_SWAP

    PUBLIC ltob

    RSEG FAR_CODE:CODE:NOROOT(0)

    ; ********************************************************************

    ;

    ; int ltob(unsigned int* shortptr, unsigned long* longptr)

    ;

    ; ********************************************************************

    ltob:

    // shortptr is in r3:r2:r1

    // longptr is in stack at offset 5

    ; get the longptr stored in the stack

    mov a,SP

    clr c

    subb a,#5

    mov b,a

    mov a,esp

    anl a,#0x3

    orl a,#0xDC       ; extended stack is at 0xff dc00

    subb a,#00        ; subtract 0x0005 to point to MSB of 2 nd argument

    mov DPX,#0xFF

    mov DPH,a

    mov DPL,b

    push r6_b0        ; save r6:r7 for the compiler

    push r7_b0

    movx a,@DPTR

    mov r4,a          ;store least signifiCANt byte of 'longptr' in r4

    inc DPTR

    movx a,@DPTR

    mov r5,a          ;store middle byte of 'longptr' in r5

    inc DPTR

    movx a,@DPTR

    mov r6,a          ;store most significant byte of 'longptr' in r6

    mov a,r4_b0

    orl a,r5_b0

    orl a,r6_b0

    jz ltob_err       ; is (longptr == NULL)?

    mov dpx,r6_b0     ; point to the memory where 'longptr' is pointing to

    mov dph,r5_b0

    mov dpl,r4_b0

    pop r6_b0         ; restore r6:r7 for the compiler

    pop r7_b0

    push dpx

    push dpl

    movx a,@dptr      ; get the long value (in r4:r3:r2:r1) from the memory

    mov r4,a

    inc dptr

    movx a,@dptr

    mov r5,a

    inc dptr

    movx a,@dptr

    mov r6,a

    inc dptr

    movx a,@dptr

    mov r7,a

    inc dptr

    pop dpl

    pop dph

    pop dpx

    mov a,r7_b0         ; swap the long value bytes and store it in memory

    movx @dptr,a

    inc dptr

    mov a,r6_b0

    movx @dptr,a

    inc dptr

    mov a,r5_b0

    movx @dptr,a

    inc dptr

    mov a,r4_b0

    movx @dptr,a

    mov a,r1_b0        ; is (shortptr == NULL)?

    orl a,r2_b0

    orl a,r3_b0

    jz ltob_err

    mov dpx,r3_b0      ; point to a memory where the 'shortptr' is pointing to

    mov dph,r2_b0

    mov dpl,r1_b0

    push dpx

    push dph

    push dpl

    movx a,@DPTR        ; get the integer value from memory

    mov r2,a

    inc dptr

    movx a,@dptr

    mov r1,a

    inc dptr

    pop dpl

    pop dph

    pop dpx

    mov a,r1_b0         ; swap the integer bytes

    movx @dptr,a

    inc dptr

    mov a,r2_b0

    movx @dptr,a        ; bytes of an integer are swapped and stored in memory

    mov r3,#00          ; return 'success'

    mov r2,#00

    sjmp ltob_exit

    ltob_err:

    mov r3,#00          ; return 'error'

    mov r2,#01

    ltob_exit:

    ret

    END                 ; end of assembly program

    局限性以及开发问题

    以下是使用6.11A版的IAR编译器时发现的局限性:

    IAR编译器用堆栈存储本地变量。在DS80C400中,堆栈限制为1024字节。DS80C400库的默认堆栈交换为384字节(ROM_SAVESIZE) .如果您的程序声明了多个堆栈变量,确保该限制也适当地变化。要改变默认任务的交换大小,使用Dallas Semiconductor的task_genesis(unsigned int savesize)库或rom400_task.h中定义的task_fork(unsigned char priority, unsigned int savesize),并给savesize参数提供正确的值。

    printf、sprintf等函数存在一些问题:只有选择了'lowest optimization level'函数才能正常工作。要选择优化等级,找到project→options→ICC8051,并选择Code标签中的'None'.

    IAR printf, sprintf的默认库不能正常工作。要使它们正常工作,您的C程序应包含IAR提供的C文件(如#include )。

    结论

    Dallas Semiconductor为IAR编译器提供支持C程序访问DS80C400 ROM软件的函数。用C程序能够访问网栈、存储管理器、进程调度器以及DS80C400的其它许多函数。使用C语言的DS80C400微控制器开发者能够编写出更精简的应用程序,赋予系统足够的速度、能力和代码空间。Dallas Semiconductor正致力于将所有目前工作与Keil编译器的DS80C400库移植到IAR.请经常访问DS80C400 IAR库主页获得升级。


关键字:IAR编译器  DS80C400 引用地址:基于IAR编译器DS80C400的开发

上一篇:基于ATT7022A和AVR单片机的无功补偿控制器设计
下一篇:基于Atmega8的PID控制策略的车辆稳定行驶及加速、减速控制

推荐阅读最新更新时间:2024-03-16 15:58

采用DS80C400建立网络多媒体应用
  随着电子信息技术日新月异的高速发展,令人振奋的多媒体应用,包括有线扩音系统(PA-Public address system)、网络门、MP3播放器以及安全摄像机等需求也是与日俱增。在网络技术发展的今天,可以采用一种低成本的网络型微处理器DS80C400来建立与实现。其特点是无需任何硬件的图像压缩,便可每秒传输4帧原始的黑白图像,而分辨率可达240180像素。   新型DS80C400是具有高性能结构和多层网络节点和I/O口及稳定的ROM固件的网络微控制器,它广泛应用于工业控制/自动化、数据转换器、远距离数据采集设备、环境监测、家庭/办公室自动化、交易/支付终端及网络传感器等领域。本文对如何在音视频范例网络多媒体系统中应用D
[工业控制]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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