1. <em id="3qmea"><ol id="3qmea"></ol></em>
    2. <em id="3qmea"></em>
      (玩电子) 电子技术学习与研究
      当前位置单片机教程网 >> 基础教程 >> 浏览文章

      第十五课 C51数组的使用

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

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

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

      数据类型

      数组名

      [常量表达式];

      数据类型

      数组名

      [常量表达式 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]就会有错误出现了还有一点要 注意的就是在程序中只能逐个引用数组中的元素不能一?#25105;?#29992;整个数组但是字符型的数 组就能一?#25105;?#29992;整个数组

      数组也是能赋初值的在上面介绍的定义方式只适用于定义在内存  DATA  存储器使 用的内存有的时候我们需要把一些数据表存放在数组中通常这些数据是不用在程序中改 变数值的这个时候就要把这些数据在程序编写?#26412;?#36171;给数组变量因为  51  芯片的片内  RAM 很有限通常会把 RAM ?#25351;?#21442;与运算的变量或数组而那些程序中不变数据则应存放在片 内的 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 区

      下面的一个简单例子是对数组中的数据进行排序使用的是冒泡法一来了解数组的使 用二来掌握基本的排序算法冒泡排序算法是一种基本的排序算法它?#30475;?#39034;序取数组中 的两个数并按需要按其大小排?#26657;?#22312;下一次循环中则取下一次的一个数和数组中下一个数 进行排序直到数组中的数据全部排序完成


      #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 开?#25216;?#25968;

      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);

      }

      例子中能看出数组同样能作为函数的参数进?#20889;?#36882;数组做参数时是用数组名进

      ?#20889;?#36882;的一个数组的数组名表示该数组的首地址在用数组名作为函数的调用参数时它 的传递方式是采用了地址传递就是将实际参数数组的首地址传递给函数中的形式参数数 组这个时候实际参数数组和形式参数数组实际上是使用了同一?#25991;?#23384;单元当形式参数数组在 函数体中改变了元素的值同时?#19981;?#24433;响到实际参数数组因为它们是存放在同一个地址的 上面的例子同时还使用到字符数组字符数组中每一个数据都是一个字符这样一个一 维的字符数组就组成了一个字符串在  C  语言中字符串是以字符数组来表达处理的为了 能测定字符串的长度C 语言中规定以\o来做为字符串的结束标识编译时会自动在字 符串的最后加入一个\o那么要注意的是如果用一个数组要保存一个长度为 10 字节的字 符串则要求这个数组至少能保存 11 个元素\o是转义字符它的含义是空字符它的 ASCII 码为 00H也就是说当每一个字符串都是以数据 00H 结束的在程序中操作字符数 据组时要注意这一点字符数组除了能对数组中单个元素进行访问还能访问整个数组 其实整个访?#39318;址?#25968;组就?#21069;?#25968;组名传到函数中数组名是一个指向数据存放空间的地址指 针函数根据这个指针和/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.15888691.com"};

      unsigned char code email[] = {"[email protected]"};

      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); //显示模式设置,开始要求?#30475;?#26816;测忙信号

      WriteCommandLCM(0x08,1); //关闭显示 WriteCommandLCM(0x01,1); //显示清屏 WriteCommandLCM(0x06,1); //  显示光标移动设置 WriteCommandLCM(0x0C,1); //  ?#20801;究?#21450;光标设置

      }


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

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

      {

      Y &= 0x1;

      X &= 0xF; //限制 X 不能大于 15Y 不能大于 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 不能大于 15Y 不能大于 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--);

      };

      }

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

      文章评论

      相关文章

      ຣ11ѡ5app

        
        
        1. <em id="3qmea"><ol id="3qmea"></ol></em>
        2. <em id="3qmea"></em>

            
            
            1. <em id="3qmea"><ol id="3qmea"></ol></em>
            2. <em id="3qmea"></em>