logo资料库

几个简单例子教你学会msp430的单片机c语言编程.doc

第1页 / 共13页
第2页 / 共13页
第3页 / 共13页
第4页 / 共13页
第5页 / 共13页
第6页 / 共13页
第7页 / 共13页
第8页 / 共13页
资料共13页,剩余部分请下载后查看
MSP430 单片机 C 语言的基本结构 王晓宁 2013/1/28 随着单片机处理速度的加快和存储容量的加大以及相应的开发软件中增强的代码优化功能,用 C 语言 编写的程序其代码效率和运行速度已堪与汇编程序相媲美,而且 C 语言程序因其平易性、结构化、易维护 性和可移植性而日益广泛地应用于单片机的开发中。用 C 语言编程时必须结合单片机的特点,不同品牌、 不同系列或不同型号的单片机其内部资源、寄存器名称等都会不同,因此其软件的开发必须结合实际的硬 件来进行。但 C 语言的程序结构还是有许多共性的,下面结合 MSP430 单片机大致说一下 C 程序的基本结 构。 C 语言的程序结构还是比较规范的,一般包括头文件、宏定义、变量定义、函数定义、一个主函数 main( )、以及中断处理函数等。在多文件的管理中,还包括自定义的头文件等。根据不同的情形,一个完 整的 C 程序可以有不同的具体结构,但其框架基本上还是固定的。下面通过几个简单的小例子来看一下 C 程序的几种结构。 在此之前,先说一下 C 中的赋值方式。很多情况下,C 程序就是在那儿完成一些赋值操作。|= 是“或” 运算,&=是“与”运算,^= 是“异或”运算。比如 BIT0 已经在 430 的头文件里定义为:BIT0=0x0001, 0x0001 是 16 进制计数,转成 2 进制就是 00000001(低八位),那么 P1OUT|=BIT0,是一个什么结 果?这是一个“或”运算(英文称 or)。首先 P1OUT 是一个在头文件中定义好的寄存器,是 8 位的,因 此,我们可以把 P1OUT 就当成一个变量名好了,只不过这个变量是在头文件中定义的,我们直接拿来用 即可。P1OUT 的取值就是在 00000000~11111111 之间(二进制)。因此不管 P1OUT 原先的值是多少, P1OUT|=BIT0 就是(设 P1OUT 原先的值为 xxxxxxxx)xxxxxxxx 跟 00000001 进行或运算,最低位 (即 BIT0)的值肯定是 1 的,而对其它位没有影响。,因此这样赋值后 P1OUT=xxxxxxx1,达到了让 BIT0 位等于 1(称为“置 1”)的目的。P1OUT&=~BIT0 的结果呢?首先,这是一个“与”运算(英文 称 and),而“~”在 C 中是一个求反的符号(即 1 变 0,0 变 1),则~BIT0=11111110,也即把 BIT0 原来各位的值全求反了。那么不论 P1OUT 原来的值是多少,就假设为 xxxxxxxx,则 xxxxxxxx 跟 11111110 相“与”的结果就是 xxxxxxx0,也就是 BIT0 这一位肯定是 0 的(称为“清 0”或“置 0”), 而 对 其 它 位 没 有 影 响 。 P1OUT^=BIT0 呢 ? 这 称 为 “ 异 或 ” 运 算 ( 英 文 称 为 xor ) (1^0=1,0^1=1,0^0=0,1^1=0 ) ,BIT0=00000001 , 设 P1OUT=xxxxxxx1 , 则 (xxxxxxx1 ) ^(00000001)=xxxxxxx0;若 P1OUT=xxxxxxx0,则(xxxxxxx0)^(00000001)=xxxxxxx1,因此 不管 P1OUT 的值原先是多少,经过 P1OUT^=BIT0 的运算后,BIT0 这一位总是取反的(原先是 1 变为 0, 原先是 0 变为 1)。综上,P1OUT|=BIT0 是赋 1 运算,P1OUT&=~BIT0 是赋 0 运算,P1OUT^=BIT0 是 求反运算,而且都是只对 BIT0 位产生影响,对其它位是没有影响的(其它位还保留它们原先的值)。这 是一种很好的处理方法,因为单片机的寄存器,其每一位都是有控制作用的,我们只改变我们想赋值的那 一位,而对其它位不造成影响。当然其它一些赋值方法也是可以的,如:WDTCTL=WDTPW+WDTHOLD 等。 另 外 BIT6+BIT0 是 互 不 影 响 的 , 因 为 BIT6=01000000 , BIT0=00000001 , 因 此 BIT6+BIT0=01000001 , 各 位 之 间 互 不 干 扰 ( 或 称 为 互 不 打 架 ) 。 很 多 位 相 加 也 是 同 理 : BIT7+BIT6+BIT3+BIT1=10000000+01000000+00001000+00000010=11001010,各位互不影响。 因此,可以有这样的赋值运算:P1DIR|=BIT6+BIT0,P1OUT&=~(BIT7+BIT5+BIT1)等等。其它的 运算就是加减乘除了。这些事情在许多单片机的书及资料中都有叙述,可能没有讲得这么细。 第 1页/共 13 页
例 1:C 程序的基本结构。 图 1 的例子基本说明了 C 程序的基本结构,不论你的程序是大还是小,头文件、主函数总是需要的。 注意图中红色的标注,可以帮助我们理解在程序中每条语句是怎样被执行的。 图 1. C 程序的基本结构 如果要打一个比较形象的比喻,上面这个小例子的基本结构就是通过 while(1)语句让 CPU 在那儿不停 地跑圈,一直不停地依次执行相同的任务:间隔地点亮红色和绿色 LED。如果画一张图的话,应该像图 2 所示。 图 2. CPU 在跑圈,周围有一些可以产生中断的事件,但 CPU 不一定理会 第 2页/共 13 页
例 2:C 程序的宏定义。 图 3 示例了宏定义的方法,通过宏定义可以把许多操作和语句定义为有字面含义的名称,如图 3 程序 中的 Red_On_Green_Off,一读就知道是让红色 LED 点亮,绿色 LED 熄灭。有人说过:用 C 语言编程, 无论变量、语句还是函数都是可以念出来并像让人听起来就懂的。因此给变量命名、函数命名、宏定义等, 都要起一些一看就知其意的名字,读起来可以朗朗上口的,有助于程序的可读性和相互交流,也有助于你 自己事后的修改和维护。 图 3. C 程序中的宏定义和引用 第 3页/共 13 页
例 3:C 程序中函数的定义和调用。 定义函数和调用函数是 C 语言最突出的特点之一,也最有挑战性,函数的英文名称是 Function,字面 意义上就是一个功能,数学里的函数不就是一个功能吗? y  )( xf  26 x ,就是完成了一个功能,一个抛物 线的功能。C 语言中,通过定义函数完成相应的功能,并通过在主函数 main( )中调用函数来实现其功能。 在函数定义中还可以给函数传递参数(形参),函数中还可以有复杂的数学运算及逻辑处理。函数可以有 返回值,也可以没有返回值(只完成某些操作)。在图 4 的示例中只定义了几个简单的函数,没有传递参 数,没有复杂的数学或逻辑运算,也没有返回值。很多情况下,有些函数定义了,但在主函数中没有调用 它,则这个函数是不起作用的。 图 4. 函数的定义和调用 第 4页/共 13 页
例 4:多文件管理和头文件。 如 果 程 序 很 大 , 则 可 以 进 行 功 能 划 分 , 把 它 模 块 化 。 如 图 5 的 工 程 中 , 有 Blink_and_Delay.c, Blink_and_Delay.h, Lighting Two LEDs with Multi C files.c 三个文档。 图 5. 多文档的管理 图 6. 文档 1 第 5页/共 13 页
图 7. 文档 2 图 8. 文档 3 第 6页/共 13 页
例 5.中断及其处理。 图 9 示例了中断及其中断服务程序的编写方法。 图 9. 中断及其处理,本例中运用了低功耗模式 0 中断是控制器或处理器为了快速响应及处理外部事件(如按键、触摸屏、AD 转换结束、定时器计时 到、以及与外部模块接口等等)而采取的一种应对机制。中断就是一种临时打断,如图 2 中所示,CPU 本 来在那儿跑圈,如果我们的程序中允许了某些中断并开启了总中断,则当这些中断事件发生时,CPU 就会 响应这些中断,也就是 CPU 先去处理这些中断事件(或称突发事件),处理完后,CPU 再返回到原来的被 中断点,继续处理它原来的事情。这个过程会涉及到 PC(程序计数器)值的变化及 SP(堆栈指针)的改 变等等,不过 PC 和 SP 的变化在我们的 C 程序中是不可见的,或者说是我们不需要关心的,我们只要写 好我们的 C 语言就一切 OK 了。 第 7页/共 13 页
以下各图示例了 430 的头文件中的宏定义,包括各寄存器的定义,寄存器中各位的定义等等。这些头 文件中的内容千万不要动,不要改变,否则会很麻烦的。除非你很清楚你在干什么。(后面还有一些文字, 请耐心看到最后一页) 第 8页/共 13 页
分享到:
收藏