单片机中常用的C语言编程

  单片机内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能,其任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED等)的控制。在给单片机输入灵魂时常使用C语言进行编程,本文以keil uVision5的编译过程为例作个人在编程过程中的总结。

一、进制换算

  通过了解单片机的使用手册,可以发现每个寄存器有特定的地址编号,如C51中P0引脚的地址编号是0x80,SCON(Serial Control)的地址编号是0x98。在电平触发式发送指令或者数据时,用与运算可以实现十六进制转换成二进制一位位地传送,如定义变量Data,i,则可以用for(i=0;i<8;i++){Data&(0x80>>i);}进行传送,0x80用二进制表示是1000 0000,Data也是十六进制数据,把1进行移位,若Data对应位是1则为1,否则是0。

下面是进制间的数据转换:

  1. 十进制转二进制是除以2取余即除以2取余后的商重复步骤,将余数倒序写就是结果
  2. 二进制转十进制是从右到左按2的n次幂(n=0,左移一位n加1)乘以二进制对应位上的0或1,将积相加;
  3. 二进制转十六进制是取四合一法,即从二进制数据向左每四位取成一位按二进制转十进制的方法算出,从右到左组合即可;
  4. 十六进制转二进制反之。

e、BCD码(Binary Coded Decimal‎),用4位二进制数来表示1位十进制数。BCD码转十进制:DEC=BCD/16*10+BCD%16(2位BCD);十进制转BCD码:BCD=DEC/10*16+DEC%10(2位BCD)。与二进制转十六进制相似,但是二进制换算结果超过10是不合法的,如0001 0001表示11,0001 1010不合法。与八进制有关的换算就不赘述了,在单片机编译过程中很少涉及。

二、数据类型

类型

符号

     关键字

   所占位数

数的表示范围

(signed) int

     16

-32768~32767

(signed) short

     16

-32768~32767

(signed) long

     32

-2147483648~2147483647

unsigned int

     16

0~65535

unsigned short int

     16

0~65535

unsigned long int

     32

0~4294967295

float

     32

3.4e-38~3.4e38

  double

     64

1.7e-308~1.7e308

  char

     8

-128~127

unsigned char

     8

0~255

注意:

’a’表示字符常量,”a”表示字符串常量。每个字符串结尾,编译器会自动的添加一个结束标志位’\0’,即”a”包含两个字符’a’和’\0’。

  在函数外定义的变量是全局变量,所有函数都可以调用;加上static(静止的)是静态全局变量,如果不赋初值,它的值是0。在函数内定义的变量是局部变量,只能在函数内部调用;加上static是静态局部变量,如果不赋初值,它的值是0;定义普通局部变量,如果不赋初值,它的值是随机的。

三、数据运算符

  类别

运算符

意义

类别

运算符

意义

    

 算术

     +

    加

  判断

    !=

  不等于

     -

    减

     *

    乘

   

  逻辑

    &&

  逻辑与

     /

    除

    ||

  逻辑或

     %

    取余

    !

  逻辑非

     =

    赋值

   

  位运算

    <<

 按位左移

     ++

i++(先用后加)

++i(先加后用)

    >>

 按位右移

     --

i--(先用后减)

--i(先减后用)

    &

按位与

判断

     >

    大于

    |

按位或

     >=

 大于等于

    ^

按位异或

     <

    小于

    ~

按位取反

     <=

 小于等于

  变量

【】

数组下标

     ==

    等于

    *

定义指针,指针取值

注意:/是整除;逻辑是判断真假的,0即为假,非0即为真;按位是对位数据进行运算。

补充:

四、常用基本语句

      语句

      解释

      语句

       解释

if(逻辑表达式)

{

    语句体1;

}

else

{

    语句体2;

}

如果逻辑表达式成立

  执行语句体1

否则

执行语句体2

(else可以不写)

for(初始化;逻辑表达式;更改条件)

{

    循环体;

}

先执行初始化

再判断逻辑表达式

若成立则执行循环体

执行后更改条件

再判断逻辑表达式

直到表达式不成立

while(逻辑表达式)

{

    循环体;

}

如果逻辑表达式成立

  执行循环体

执行后再次判断

若还成立则继续执行

直到表达式不成立

switch(变量)

{

case 常量1:语句体1;break;

case 常量1:语句体2;break;

(...)

default:语句体1;break;

}

将变量与case后的各个变量对比

若有相等,则执行相应的语句体

若没有一个相等,则执行default后的语句体

(default可以不写)

注意:所有需要运行的程序都只能放在main()函数中执行,Project只能有一个main()函数。

五、数组

  数组是若干个相同类型的变量在内存中有序存储的集合,可以通过数组名+索引号简单快捷的操作大量数据。如

int i[3];     //定义一组变量(3个)

i[0] //引用数组的第0个变量

i[1] //引用数组的第1个变量

i[2] //引用数组的第2个变量

int i[]={1,2,3}; //定义一组变量并初始化,此定义方法可以省去统计定义的变量个数。

引用i[3]时,数组越界,读出的数值不确定,应避免这种操作。

六、模块化函数

  模块化函数是把不同模块的函数放在不同的源文件里,在头文件里声明外部可调用函数,其它源文件可以通过头文件使用其中的代码,使用模块化函数可极大的提高代码的可阅读性、可维护性、可移植性等。以C语言编程为例,main()函数所在的.c文件除外的其他.c文件中可以定义和编写不同功能的函数,建立相应的.h文件,在.h文件中声明自定义的函数,其他.c文件可以通过#include “~~~.h”进行函数调用。

注意:

a、任何自定义的变量、函数在调用前必须有定义或声明,即函数名+()+;

b、使用到的自定义函数的.c文件必须添加到Project参与编译

c、使用的.h文件必须放在编译器可寻找到的地方,如工程文件夹根目录、安装目录、自定义

预编译:(以C语言编译为例)

               预编译

                 意义

#include <~~~.H>

#include “~~~.h”

头文件的内容替换预编译的语句,从而展开头文件

        #define PI 3.1415926

定义PI,PI替换2.1415926

        #define A

定义A

        #ifndef __~~_h_

如果没有定义__~~_h_

        #endif

与#ifndef,#if匹配,组成“括号”

为防止头文件重复定义,造成代码错乱,可以使用以下的方法:

#ifndef _DS1302__h_     //如果没有宏定义_DS1302__h_,则执行下面的语句

#define _DS1302__h_     //宏定义_DS1302__h_ 

外部可调用函数声明     //函数声明

如(void DS1302_Init(void);)

#endif                 //与#ifndef,#if匹配,组成“括号”

你可能感兴趣的:(单片机,c语言)