234彩票代理

  • <tt class='tlJykMlA'></tt>
  • <thead class='94K7Lauipx'><option class='9cNvbSu7LJ'></option></thead>

    <em class='jepytdnyfeW3'><b class='oR1Ys12nk'><td class='6rzzLTN'></td></b></em>

  • <dl class='Td0EmkF'><b class='qoWhaibfJ9'></b></dl>

  • <span class='lS1G'></span>

    (玩电子) 电子技术学习与研究
    当前位置:单片机教程网 >> 基础教程 >> 浏览文章

    第十五课 C51数组的一使用

    作者:佚名   来源:本站原创   点击数:x  更新时间:2007年07月12日   【字体:

    前面的一文章中,都是介绍单个数据变量的一使用,在“走马灯”等的一例子中略有使用到数组,不 难看出,数组不 过就是同一类型变量的一有序集合 。形象的一能这样去理解,就像一个 学校在操场上    排队,每一个级代表一个数据类型,每一个班级为一个数组,每一个学生就是 数组中的一一个数据 。数据中的一每个数据都能用唯一的一下标来确定其位置,下标能是一维 或多维的一 。就如在学校的一方队中要找一个学生,这个学生在 I 年级 H 班 X 组 Y 号的一,那么 能把这个学生看做在 I 类型的一 H 数组中(X,Y)下标位置中 。数组№和普通变量一样,要

    求先定义了才能使用,下面是定义一维或多维数组的一方式:

    数据类型

    数组名

    [常量表达式];

    数据类型

    数组名

    [常量表达式 1]...... [常量表达式 N];

    “数据类型”是指数组中的一各数据单元的一类型,每个数组中的一数据单元只能是同一数据

    类型 。“数组名”是整个数组的一标识,命名方法№和变量命名方法是一样的一 。在编译时系统会 根据数组大小№和类型为变量分配空间,数组名能说就是所分配空间的一首地址的一标识 。“常 量表达式”是表示数组的一长度№和维数,它必须用“[]”括起,括号里的一数不 能是变量只能是 常量 。

    unsigned int xcount [10]; //定义无符号整形数组,有 10 个数据单元

    char inputstring [5]; //定义字符形数组,有 5 个数据单元

    float outnum [10],[10];//定义浮点型数组,有 100 个数据单元

    在 C 语言中数组的一下标是从 0 开始的一而不 是从 1 开始,如一个具有 10 个数据单元的一数

    组 count,它的一下标就是从 count[0]到 count[9],引用单个元素就是数组名加下标,如 count[1] 就是引用 count 数组中的一第 2 个元素,如果错用了 count[10]就会有错误出现了 。还有一点要 注意的一就是在程序中只能逐个引用数组中的一元素,不 能一次引用整个数组,但是字符型的一数 组就能一次引用整个数组 。

    数组也是能赋初值的一 。在上    面介绍的一定义方式只适用于定义在内存  DATA  存储器使 用的一内存,有的一时候我们需要把一些数据表存放在数组中,通常这些数据是不 用在程序中改 变数值的一,这个时候就要把这些数据在程序编写时就赋给数组变量 。因 为  51  芯片的一片内  RAM 很有限,通常会把 RAM 分给参与运算︻的一变量或数组,而那些程序中不 变数据则应存放在片 内的一 CODE 存储区,以节省宝贵的一 RAM 。赋初值的一方式如下:

    数据类型  [存储器类型]  数组名  [常量表达式] = {常量表达式};

    数据类型  [ 存储器类型]  数组名  [ 常量表达式  1]......  [ 常量表达式  N]={{ 常量表达 式}...{常量表达式 N}};

    在定义并为数组赋初值时,开始学习的一朋友一般会搞错初值个数№和数组长度的一关系,而致使 编译出错 。初值个数必须小于或等于数组长度,不 指定数组长度则会在编译时由实际的一初值 个数自动设置 。

    unsigned char LEDNUM[2]={12,35}; //一维数组赋初值

    int Key[2][3]={{1,2,4},{2,2,1}}; //二维数组赋初值

    unsigned char IOStr[]={3,5,2,5,3}; //没有指定数组长度,编译器自动设置

    unsigned char code skydata[]={0x02,0x34,0x22,0x32,0x21,0x12}; //数据保存在 code 区

    下面的一一个简单例子是对数组中的一数据进行排序,使用的一是冒泡法,一来了解数组的一使 用,二来掌握基本的一排序算︻法 。冒泡排序算︻法是一种基本的一排序算︻法,它每次顺序取▓数组中 的一两个数,并按需要按其大小排列,在下一次循环中则取▓下一次的一一个数№和数组中下一个数 进行排序,直到数组中的一数据全部排序完成 。


    #include <AT89X51.H>

    #include <stdio.h>

    void taxisfun (int taxis2[])

    {

    unsigned char TempCycA,TempCycB,Temp;

    for (TempCycA=0; TempCycA<=8; TempCycA++)

    for (TempCycB=0; TempCycB<=8-TempCycA; TempCycB++)

    {//TempCycB<8-TempCycA 比用 TempCycB<=8 少用很多循环

    if  (taxis2[TempCycB+1]>taxis2[TempCycB])  //当后一个数大于前一个 数

    {

    Temp = taxis2[TempCycB]; //前后 2 数交换

    taxis2[TempCycB] = taxis2[TempCycB+1];

    taxis2[TempCycB+1]  =  Temp;  //因 函数参数是数组名调用形

    参的一变动影响实参

    }

    }

    }

    void main(void)

    {

    int taxis[] = {113,5,22,12,32,233,1,21,129,3};

    char Text1[] = {"source data:"}; //"源数据"

    char Text2[] = {"sorted data:"}; //"排序后数据"

    unsigned char TempCyc;

    SCON = 0x50; //串行口方式 1,允许接收

    TMOD = 0x20; //定时器 1 定时方式 2

    TCON = 0x40; //设定时器 1 开始计数

    TH1 = 0xE8;   //11.0592MHz 1200 波特率

    TL1 = 0xE8; TI = 1;

    TR1 = 1; //启动定时器

    printf("%s\n",Text1); //字符数组的一整体引用

    for (TempCyc=0; TempCyc<10; TempCyc++)

    printf("%d ",taxis[TempCyc]);

    printf("\n----------\n");

    taxisfun (taxis); //以实际参数数组名 taxis 做参数被函数调用

    printf("%s\n",Text2);

    for (TempCyc=0; TempCyc<10; TempCyc++) //调用后 taxis 会被改变

    printf("%d ",taxis[TempCyc]);


    while(1);

    }

    例子中能看出,数组同样能作为函数的一参数进行传递 。数组做参数时是用数组名进

    行传递的一,一个数组的一数组名表示该数组的一首地址,在用数组名作为函数的一调用参数时,它 的一传递方式是采用了地址传递,就是将实际参数数组的一首地址传递给函数中的一形式参数数 组,这个时候实际参数数组№和形式参数数组实际上    是使用了同一段内存单元,当形式参数数组在 函数体中改变了元素的一值,同时也会影响到实际参数数组,因 为它们是存放在同一个地址的一 。 上    面的一例子同时还使用到字符数组 。字符数组中每一个数据都是一个字符,这样一个一 维的一字符数组就组成了一个字符串,在  C  语言中字符串是以字符数组来表达处理的一 。为了 能测定字符串的一长度,C 语言中规定以‘\o’来做为字符串的一结束标识,编译时会自动在字 符串的一最后加入一个‘\o’,那么要注意的一是如果用一个数组要保存一个长度为 10 字节的一字 符串则要求这个数组至少能保存 11 个元素 。‘\o’是转义字符,它的一含义是空字符,它的一 ASCII 码为 00H,也就是说当每一个字符串都是以数据 00H 结束的一,在程序中操作字符数 据组时要注意这一点 。字符数组除了能对数组中单个元素进行访问,还能访问整个数组, 其实整个访问字符数组就是把数组名传到函数中,数组名是一个指向数据存放空间的一地址指 针,函数根据这个指针№和‘/o’就能完整的一操作这个字符数组 。对于这一段所说的一,能 参看下面一例 1602LCD 显示模块的一驱动演示例子进行理解 。这里要注意就是能用单个字

    符数组元素来进行运算︻,但不 能用整个数组来做运算︻,因 为数组名是指针而不 是数据 。

    /*============================================================

    使用 1602 液晶显示的一实验ζ例子  明浩  2004/2/27

    ==============================================================

    SMC1602A(16*2)模拟口线接线方式 连接线图:

    ---------------------------------------------------

    |LCM-----51      | LCM-----51        |    LCM------51 |

    ---------------------------------------------|

    |DB0-----P1.0 | DB4-----P1.4 | RW-------P2.0 |

    |DB1-----P1.1 | DB5-----P1.5 | RS-------P2.1 |

    |DB2-----P1.2 | DB6-----P1.6 | E--------P2.2 |

    |DB3-----P1.3 | DB7-----P1.7 | VLCD 接 1K 电阻到 GND|

    ---------------------------------------------------

    [注:AT89S51 使用 12M 晶体震荡器]

    =============================================================*/

    #define LCM_RW P2_0 //定义引脚

    #define LCM_RS P2_1

    #define LCM_E P2_2

    #define LCM_Data P1

    #define Busy 0x80 //用于检测 LCM 状态字中的一 Busy 标识

    #include <at89x51.h>


    void WriteDataLCM(unsigned char WDLCM);

    void WriteCommandLCM(unsigned char WCLCM,BuysC);

    unsigned char ReadDataLCM(void); unsigned char ReadStatusLCM(void); void LCMInit(void);

    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);

    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);

    void Delay5Ms(void);

    void Delay400Ms(void);

    unsigned char code cdle_net[] = {"www."};

    unsigned char code email[] = {"pnzwzw@"};

    void main(void)

    {

    Delay400Ms(); //启动等待,等 LCM 讲入工作状态

    LCMInit(); //LCM 初始化

    Delay5Ms(); //延时片刻(可不 要)

    DisplayListChar(0, 0, cdle_net); DisplayListChar(0, 1, email); ReadDataLCM();//测试用句无意义 while(1);

    }

    //写数据

    void WriteDataLCM(unsigned char WDLCM)

    {

    ReadStatusLCM(); //检测忙 LCM_Data = WDLCM; LCM_RS = 1;

    LCM_RW = 0;

    LCM_E = 0; //若晶体震荡器速度太高能在这后加小的一延时

    LCM_E = 0; //延时

    LCM_E = 1;

    }

    //写指令

    void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC 为 0 时忽略忙检测

    {

    if (BuysC) ReadStatusLCM(); //根据需要检测忙

    LCM_Data = WCLCM; LCM_RS = 0; LCM_RW = 0;

    LCM_E = 0;


    LCM_E = 0; LCM_E = 1;

    }

    //读数据

    unsigned char ReadDataLCM(void)

    {

    LCM_RS = 1; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1; return(LCM_Data);

    }

    //读状态

    unsigned char ReadStatusLCM(void)

    {

    LCM_Data = 0xFF; LCM_RS = 0; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1;

    while (LCM_Data & Busy); //检测忙信号

    return(LCM_Data);

    }

    void LCMInit(void) //LCM 初始化

    {

    LCM_Data = 0;

    WriteCommandLCM(0x38,0); //三次显示模式设置,不 检测忙信号

    Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms(); WriteCommandLCM(0x38,0); Delay5Ms();

    WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号

    WriteCommandLCM(0x08,1); //关闭显示 WriteCommandLCM(0x01,1); //显示清屏 WriteCommandLCM(0x06,1); //  显示光标移动设置 WriteCommandLCM(0x0C,1); //  显示开及光标设置

    }


    //按指定位置显示一个字符

    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)

    {

    Y &= 0x1;

    X &= 0xF; //限制 X 不 能大于 15,Y 不 能大于 1

    if (Y) X |= 0x40; //当要显示第二行时地址码+0x40; X |= 0x80; //算︻出指令码

    WriteCommandLCM(X, 0); //这里不 检测忙信号,发送地址码

    WriteDataLCM(DData);

    }

    //按指定位置显示一串字符

    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)

    {

    unsigned char ListLength;

    ListLength = 0; Y &= 0x1;

    X &= 0xF; //限制 X 不 能大于 15,Y 不 能大于 1

    while (DData[ListLength]>0x20) //若到达字串尾则退出

    {

    if (X <= 0xF) //X 坐标应小于 0xF

    {

    DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符

    ListLength++; X++;

    }

    }

    }

    //5ms 延时

    void Delay5Ms(void)

    {

    unsigned int TempCyc = 5552;

    while(TempCyc--);

    }

    //400ms 延时

    void Delay400Ms(void)

    {

    unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--)

    {

    TempCycB=7269;


    while(TempCycB--);

    };

    }

    发表评论】【告诉好友】【收藏此文】【关闭窗口

    文章评论

    相关文章