C语言基础

一:C语言特点

C 语言程序采用函数结构, 每个 C 语言程序由一个或多个函数组成, 在这些函数中至少应包含一个主函数 main(), 也可以包含一个 main()函数和若干个其它的功能函数。 不管 main()函数放于何处, 程序总是从 main()函数开始执行,执行到 main()函数结束则结束。 在 main()函数中调用其它函数, 其它函数也可以相互调用, 但 main()函数只能调用其它的功能函数, 而不能被其它的函数所 调用。 功能函数可以是 C 语言编译器提供的库函数, 也可以是由用户定义的自定义函数。 在编制 C 程序时, 程序的开始部分一般是预处理命令、 函数说明和变量

二:C51与C的区别

  1. C51 中定义的库函数和标准 C 语言定义的库函数不同。 标准的 C 语言定义的库函数是按通用微型计算机来定义的,而C51 中的库函数是按 51 单片机相应情况来定义的

  2. C51 中还增加了几种针对 51 单片机特有的数据类型

  3. C51 变量的存储模式与标准 C 中变量的存储模式不一样, C51 中变量的存储模式是与 51 单片机的存储器紧密相关

  4. C51 与标准 C 的输入输出处理不一样, C51 中的输入输出是通过 51 串行口来完成的, 输入输出指令执行前必须要对串行口进行初始化

  5. C51 与标准 C 在函数使用方面也有一定的区别, C51 中有专门的中断函数

三:基础知识

基本数据类型
  • 基本数据类型

    C51语言基础_寄存器

     

     

  • 指针型

    指针型本身就是一个变量, 在这个变量中存放的指向另一个数据的地址

  • 寄存器型

    这是 C51 扩充的数据类型, 用于访问 51 单片机中的特殊功能寄存器数据,分 sfr 和 sfr16 两种类型,在 C51 中对特殊功能寄存器的访问必须先用 sfr 或 sfr16 进行声明

  • 位类型

    这也是 C51 中扩充的数据类型, 用于访问 51 单片机中的可寻址的位单元。分为bit 型和 sbit 型。它们在内存中都只占一个二进 制位, 其值可以是“1” 或“0” 。

  • KEIL C51 编译器能够识别的基本数据类型:

基本数据类型 长度 取值范围
unsigned char 1 字节 0~255
signed char 1 字节 -128~+127
unsigned int 2 字节 0~65535
signed int 2 字节 -32768~+32767
unsigned long 4 字节 0~4294967295
signed long 4 字节 -2147483648~+2147483647
float 4 字节 1.175494E-38~3.402823E+38
bit 1 位 0 或 1
sbit 1 位 0 或 1
sfr 1 字节 0~255
sfr16 2 字节 0~65535
  • 隐式转换的优先级顺序与强制转换 Bit→char→int→long→float→signed→unsigned

    通过强制类型转换符“() ” 对数据类型进行强制转换

  • C5l 编译器除了能支持以上这些基本数据类型之外, 还能支持一些复杂的组合型数据类型, 如数组类型、 指针类型、 结构类型、 联合类型等这些复杂的数据类型

变量
  • 变量名

    变量名是 C51 区分不同变量, 为不同变量取的名称。 在 C51 中规定变量名可以由字母、 数字和下划线三种字符组成, 且第一个字母必须为字母或下划线。 变量名有两种: 普通变量名和指针变量名。 它们的区别是指针变量名前面要带“*”号。

  • 存储种类

    存储种类是指变量在程序执行过程中的作用范围。 C51 变量的存储种类有四种, 分别是自动(auto)、 外部(extern)、 静态(static)和寄存器(register) 。

  • 存储器类型

    存储器类型 描 述
    data 直接寻址的片内 RAM 低 128B, 访问速度快
    bdata 片内 RAM 的可位寻址区(20H~2FH) , 允许字节和位混合访问
    idata 间接寻址访问的片内 RAM, 允许访问全部片内 RAM
    pdata 用 Ri 间接访问的片外 RAM 的低 256B
    xdata 用 DPTR 间接访问的片外 RAM, 允许访问全部 64k 片外 RAM
    code 程序存储器 ROM 64k 空间
  • 特殊功能寄存器变量

    51 系列单片机片内有许多特殊功能寄存器, 通过这些特殊功能寄存器可以控制 51 系列单片机的定时器、 计数器、 串口、 I/O 及其它功能部件, 每一个特殊功能寄存器在片内 RAM 中都对应于一个字节单元或两个字节单元。

    在 C51 中, 允许用户对这些特殊功能寄存器进行访问, 访问时须通过 sfr 或sfr16 类型说明符进行定义, 定义时须指明它们所对应的片内 RAM 单元的地址。 格式如下:sfr 或 sfr16 特殊功能寄存器名 = 地址; sfr PSW=0xd0;

  • 位变量

    格式:bit 位变量名;

           sbit 位变量名=位地址;   sbit LED=P1^0;
  • 在 C51 中, 为了用户处理方便, C51 编译器把 51 单片机的常用的特殊功能寄存器和特殊位进行了定义, 放在一个“reg51.h” 或“reg52.h” 的头文件中, 当用户要使用时, 只须要在使用之前用一条预处理命令#include <reg52.h>把这个头文件包含到程序中, 然后就可使用殊功能寄存器名和特殊位名称 。

C51运算符
  1. 赋值运算符 格式:变量=表达式;

  2. 算术运算符 + - * / %

  3. 关系运算符 > < >= <= == !=

  4. 逻辑运算符 || && !

  5. 位运算符 & | ~ ^ << >>

    位运算是按位对变量进行运算, 但并不改变参与运算的变量的值。 如果要求按位改变变量的值, 则要利用相应的赋值运算。

    C51 中位运算符只能对整数进行操作

  6. 复合赋值运算符

    += -= *= /= %=

    |= &= ^= ~= >>= <<=

  7. 逗号运算符

    在 C51 语言中, 逗号“, ” 是一个特殊的运算符, 可以用它将两个或两个以上的表达式连接起来, 称为逗号表达式。 逗号表达式的一般格式为:表达式 1, 表达式 2, ……, 表达式 n

    按从左至右的顺序依次计算出各个表达式的值, 而整个逗号表达式的值是最右边的表达式( 表达式 n) 的值。

    例如:x=(a=3,6*3)结果 x 的值为 18。

  8. 条件运算符

    条件运算符“? : ” 是 C51 语言中唯一的一个三目运算符

    条件表达式的一般格式为:逻辑表达式? 表达式 1: 表达式 2 ;

  9. 指针与地址运算符

    指针是 C51 语言中的一个十分重要的概念, 在 C51 中的数据类型中专门有一种指针类型。 指针为变量的访问提供了另一种方式, 变量的指针就是该变量的地址, 还可以定义一个专门指向某个变量的地址的指针变量 。

    * 指针运算符 & 取地址运算符

C51基本结构和语句
  • 基本结构

    1. 顺序结构

    2. 选择结构

    3. 循环结构

  • 基本语句

    1. if 语句

      ①if (表达式) {语句; }
      ②if (表达式) {语句 1; } else {语句 2; }
      ③if (表达式 1) {语句 1; }
      else if (表达式 2(语句 2
      else if (表达式 3(语句 3
      ……
      else if (表达式 n-1(语句 n-1
      else {语句 n}
      /* 单分支,双分支,多分支(else if)*/
    2. switch/case 语句

      switch (表达式)
      {case 常量表达式 1: {语句 1; }break;
      case 常量表达式 2: {语句 2; }break;
      ……
      case 常量表达式 n: {语句 n; }break;
      default: {语句 n+1; }
      /*当该表达式的值与某一“case” 后面的常量表达式的值相等时, 就执行该“case” 后面的语句, 然后遇到 break 语句退出 switch 语句。 若表达式的值与所有 case 后的常量表达式的值都不相同, 则执行 default 后面的语句, 然后退出 switch 结构。*/
    3. while 语句 do...while 语句

      while(表达式)
      {语句; } /*循环体*/

      do
      {语句; } /*循环体*/
      while(表达式)
    4. for 语句

      for(表达式 1表达式 2表达式 3
      {语句; } /*循环体*/
      /*
      在 for 循环中, 一般表达式 1 为初值表达式, 用于给循环变量赋初值; 表达式 2 为条件表达式, 对循环变量进行判断; 表达式 3 为循环变量更新表达式, 用于对循环变量的值进行更新, 使循环变量能不满足条件而退出循环。
      */
    5. 循环的嵌套

      void delay(unsigned int x)
      {
      unsigned char j;
      while(x--)
      {for (j=0;j<125;j++);}
      }
      /*用内循环构造一个基准的延时, 调用时通过参数设置外循环的次数,这样就可以形成各种延时关系。*/
    6. break 和 continue 语句

    7. return 语句

函数
  • 函数的定义

    函数类型 函数名(形式参数表) [reentrant][interrupt m][using n]
    形式参数说明
    {
    局部变量定义
    函数体
    }
    /*
    1. 函数类型
    函数类型说明了函数返回值的类型。
    2. 函数名
    函数名是用户为自定义函数取的名字以便调用函数时使用。
    3. 形式参数表
    形式参数表用于列录在主调函数与被调用函数之间进行数据传递的形式参数。
    4. reentrant 修饰符
    这个修饰符用于把函数定义为可重入函数。 所谓可重入函数就是允许被递归调用的函数
    5. interrupt m 修饰符
    interrupt m 是 C51 函数中非常重要的一个修饰符, 这是因为中断函数必须通过它进行修饰。m 的取值为 0~31, 对应各种中断情况
    */
  • 函数的调用

    //函数调用的一般形式
    函数名(实参列表)
    //函数调用方式有以下三种: 函数语句 函数表达式, 函数参数
  • 自定义函数的声明

    //在 C51 中, 函数原型一般形式如下:
    [extern] 函数类型 函数名(形式参数表);
    //函数的声明是把函数的名字、 函数类型以及形参的类型、 个数和顺序通知编译系统, 以便调用函数时系统进行对照检查
    //如果声明的函数在文件内部, 则声明时不用 extern, 如果声明的函数不在文件内部, 而在另一个文件中, 声明时须带 extern
构造数据类型
  • 数组

    格式:数据类型说明符 数组名 [常量表达式]={初值, 初值……} 数组有两种定义方法

    1. unsigned char x[5];

    2. unsigned int y[3]={1,2,3};

  • 字符数组

    用来存放字符数据的数组称为字符数组, 它是 C 语言中常用的一种数组 ,定义时把数据类型定义为 char 型。 例如: char string[10];

    在 C51 语言中, 字符数组用于存放一组字符或字符串, 字符串以“\0” 作为结束符, 只存放一般字符的字符数组的赋值与使用和一般的数组完全相同。 对于存放字符串的字符数组。 既可以对字符数组的元素逐个进行访问, 也可以对整个数组按字符串的方式进行处理。