- 基础知识
- 数据类型
- const 用法
- 作用域与 static 用法
- extern 用法
嵌入式C语言和普通C语言在语法上几乎没有差别,其主要差别在于普通C语言的运行环境是OS之上,有很多的标准库函数支撑调用,分配的内存是电脑的内存,其处理器就是电脑的CPU;而在嵌入式环境中,会涉及到底层的硬件,而硬件本身是没有标准库可以调用的,因而就需要开发者使用C语言编程调试硬件,使其可以工作,对于开发某一款芯片,有针对的编译器(或者交叉编译环境),可以分配的内存则是芯片的RAM、Flash,处理器则是芯片自身带的MCU,例如ARM、DSP等。
例如C语言编程的入门课:打印“Hello World!”,在普通C语言编程中,直接调用printf()函数即可在PC上打印出;而在嵌入式中,则需要开发者使用C语言去将芯片的串口调试成功,然后将printf()函数重新实现,方可调用打印。
嵌入式C语言的基本结构及其特点:
- 所有的C语言程序都需要包含main()函数,代码从main()函数开始执行;这一条在嵌入式中不一定完 全正确,在执行main()函数之前也有开发者可以操纵的空间,因而开始函数可以不是main(),例如 也可以是myMain()这样的函数,而这所涉及到的知识已经超过基础知识的范围,会在后续详细说 明;
- C语言的语句以用分号“;”结束;
- C语言的注释有行注释(“//”)和段注释(“/…/”);
- 函数是C语言的基本结构,每个C程序都是由至少一个函数组成;
- C语言的文件有两种格式:源文件.c文件和头文件.h文件,通常.c文件用于功能函数的实现,而.h文 件用于预处理、宏定义和声明等;在嵌入式中,通常将某个硬件模块的功能实现函数及其声明和包 含的全局变量声明分别处理到一个.c和.h文件中,例如led.c、hello.c和led.h、hello.h就分别对应于LED 灯的功能函数及其声明和hello的功能函数及其声明;
- 我们将这种基于某个模块的独立设计称之为模块化设计,在一个系统中通常是由许许多多的模块 共同组成的,因而模块化设计是一个非常科学且非常值得学习的程序设计方法;
- 除了模块化设计,通常嵌入式的编程设计还有层次化设计。在一个工程系统中,硬件驱动仅仅只是 第一步,对硬件的应用则是一个功能丰富的系统的更进一步的设计,通常在这一块会设计到例如图 像处理、数据处理等算法;我们可以笼统的将一个嵌入式工程系统分为驱动层和应用层。
在C语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统,变量的类型决定了变量存储占用的空间以及如何解释存储的位模式。
在嵌入式系统中,芯片的容量是有限的,且对比于PC机容量通常都是比较小的,因而了解变量所占用的存储空间是嵌入式开发者应当掌握的一项技能,所以对于不同数据类型在不同位数的芯片中(例如STM32xxx就表示此款芯片是32bit的芯片,STM8xxx表示此款芯片是8bit的芯片)的长度开发者也应该掌握。
C语言中的数据类型有以下几种: 就以STM32F103ZE这一款芯片为例,这是一块32bit的MCU,基本数据类型在此款芯片中的数据长度,以及在HAL库函数中的定义(stdint.h文件中的定义,采用C99标准)如图 5.3.2 所示。这里建议开发者在开发过程中使用库定义的数据类型,来定义变量或函数,比如unsigned char a,使用uint8_t a。
C语言中const关键字是constant的缩写,译为常量、常数等,但const关键字不仅仅是用于定义常量,还可以用于修饰数组、指针、函数参数等。
修饰变量 C语言中使用const修饰变量,功能是对变量声明为只读特性,并保护变量值以防被修改。例如:
const int i = 5;
这个例子表明整形变量i具有只读性,不能够被修改;若想对其重新赋值,例如i=10则是错误的用法。需 要注意的是,const定义变量的同时还必须对其初始化,const可以放在数据类型的前面或者后面,比如上述 例子也可以写成:
int const i = 5;
此外,const修饰变量还起到了节约空间的目的,通常编译器并不给普通const只读变量分配空间,而是将它们保存在符号列表中,无需读写内存操作,程序执行效率也会提高。
修饰数组 C语言中const还可以修饰数组,例如:
const int array[5] = {0, 1, 2, 3, 4};
// 或
int const array[5] = {0, 1, 2, 3, 4};
const关键字修饰数组与修饰变量类似,表明此数组具有只读性,不可修改,一旦被更改程序会出错,例 如上述例子如果:
array[1] = 10;
则程序将会提示错误。
修饰指针 C语言中const修饰指针需要特别注意,共有两种形式,一种是用来限定指向空间的值不可修改;另一种 是限定指针不可修改,例如:
int i = 5;
int k = 10;
int const *p1 = &i;
int * const p2 = &k;
对于指针p1,const修饰的是*p1,即p1指向的空间的值不可改变,例如*p1 = 20;就是错误的用法;但是p1的值是可以改变的,例如p1 = &k;则没有任何问题。
对于指针p2,const修饰的是p2,即指针本身p2不可更改,而指针指向空间的值是可以改变的,例如*p2 = 15;是没有问题的,而p2 = &i;则是错误的用法。
修饰函数参数 在C语言中const修饰函数参数对参数起限定作用,防止其在函数内部被意外修改,所限定的参数可以是 普通变量也可以是指针变量,如:
void fun(const int x)
{
...
x = 10; // 对 x 的值进行了修改,错误
}
void fun1(const int *p)
{
...
(*p)++; // 对 p 指向空间的值进行了修改,错误
}
作用域与 static 用法
在了解static关键字的用法之前,我们需要先了解C语言中的作用域、局部变量和全局变量的概念。
一个C变量的作用域可以是块作用域、函数作用域、函数原型作用域或文件作用域。
块是用一对花括号“{}”括起来的代码区域,定义在块中的变量具有块作用域。块作用域的可见范围是从定义处到包含该定义的块的末尾。以前,具有块作用域的变量都必须声明在块的开头,C99标准放宽了这一限制,允许在块中的任意位置声明变量。例如不支持C99标准的的for循环需要这样写:
void fun1(void) {
int i = 0;
for(i=0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?