1. asm 也可以写成__asm。功能是在 C 程序中直接嵌入汇编语言。 语法:asm(“string”);其中 string 必须是有效的汇编语句。 2. __interrupt 放在函数前面,标志中断函数。下面这段程序是异步串行口 UART0 的接收中断 函数。UART0RX_VECTOR 为异步串行口 UART0 的接收中断向量。 举例: #pragma vector=UART0RX_VECTOR __interrupt void UART0_R(void) { TXBUF0=RXBUF0; } 3. __monitor 放在函数前面, 功能是但这一函数执行的时候自动关闭中断。应该尽量缩短这样 的函数,否则,中断事件无法得到及时的响应。 4. __no_init 放在全局变量前面,功能是使程序启动时不为变量赋初值。 5. __raw 编译中断函数时,编译器会自动生成一段代码,首先保存当时所用到 CPU 内寄 存器的内容,退出中断程序时再进行恢复。将__raw 放在中断函数前可以禁止保 存 CPU 内寄存器的过程,当然退出时也不会恢复。是否为中断函数使用此关键 字要根据需要而定。 //UART0 接收中断
6. __regvar 放在变量前面,作用是声明变量为寄存器变量。可以用于整数、指针、32 位浮 点数以及只含有一个元素的结构和联合。 寄存器变量的地址只能为 R4 或者 R5, 也不能用指针指向这个寄存器变量,而且必须用__no_init 禁止初始化。如: __regvar __no_init unsigned char q0
@ __R4; 其他不常用的关键字还有: __data16、 __intrinsic、 __noreturn、 __root、 __task、 __word16。
内部函数
本节将介绍内部函数的原型和功能。 1. __bcd_add_short unsigned short __bcd_add_short(unsigned short, unsigned short); 功能:两个 16 位 BCD 格式的数相加,返回和。 2. __bcd_add_long unsigned long __bcd_add_long(unsigned long, unsigned long); 功能:两个 32 位 BCD 格式的数相加,返回和。 3. __bcd_add_long_long unsigned long long __bcd_add_long_long(unsigned long long, unsigned long long); 功能:两个 64 位 BCD 格式的数相加,返回和。 4. __bic_SR_register void __bic_SR_register(unsigned short); 功能:将 CPU 中 SR 寄存器中的某些位清 0。其参数为屏蔽码,需要清 0 的位 为 1。 5. __bic_SR_register_on_exit void __bic_SR_register_on_exit(unsigned short); 功能: 用于一个中断函数或者不可中断函数 (标志为__monitor) 返回时, CPU 将 内 SR 寄存器中的某些位清 0。其参数为屏蔽码,需要清 0 的位为 1。
6. __bis_SR_register void __bis_SR_register(unsigned short); 功能:将 CPU 中 SR 寄存器中的某些位置 1。其参数为屏蔽码,需要置 1 的位 为 1。 7. __bis_SR_register_on_exit void __bis_SR_register_on_exit(unsigned short); 功能: 用于一个中断函数或者不可中断函数 (标志为__monitor) 返回时, CPU 将 内 SR 寄存器中的某些位置 1。其参数为屏蔽码,需要置 1 的位为 1。 8. __disable_interrupt void __disable_interrupt(void) 功能:关闭全局中断。先执行 DINT 命令,关闭全局中断,然后再执行 NOP 命 令。空指令是为了确保关闭了全局中断之后再执行下面的程序。 9. __enable_interrupt void __enable_interrupt(void) 功能:使用 NINT 指令打开全局中断。 10. __even_in_range void __enable_in_range(unsigned short value, unsigned short upper_limit) 功能:只能与 switch 语句结合使用,判断 value 是否为偶数且小于等于 upper_limit。 举例: unsigned int MoonRiver, iq0; iq0=2; swich(__even_in_range(iq0,4)) { case 0: MoonRiver=0; break; case 2: MoonRiver=2; }
结果:假设 iq0 的值为 2,执行完毕时 MoonRiver=2。否则,与普通的 swich 语 句一样,跳过 case 部分,直接执行下面的程序。使用__even_in_range 的好处 是可以生成效率比较高的代码,在判断多中断源的来源时可以使用此函数。 11. __get_interrupt_state istate_t __get_interrupt_state(void) 功能:返回当前的中断状态。返回值 istate_t 为一结构,通过此函数可以获得当 前的中断状态并保存,将来可以使用__set_interrupt_state 恢复中断状态。 12. __get_R4_register unsigned short __get_R4_register (void); 功能:返回寄存器 R4 的值,只在 R4 被锁定时有效。 13. __get_R5_register unsigned short __get_R5_register (void); 功能:返回寄存器 R5 的值,只在 R5 被锁定时有效。 14. __get_SP_register unsigned short __get_SP_register (void); 功能:返回堆栈指针寄存器 SP 的值。 15. __get_SR_register unsigned short __get_SR_register (void); 功能:返回 CPU 中状态寄存器 SR 的值。 16. __get_SR_register_on_exit unsigned short __get_SR_register_on_exit (void); 功能:用于一个中断函数或者不可中断函数(标志为__monitor)返回时,返回 状态寄存器 SR 的值。只在中断函数或者不可中断函数中有效。 17. __low_power_mode_n void __low_power_mode_n(void); 功能:进入低功耗模式 0~4。
18. __low_power_mode_off_on_exit void __low_power_mode_off_on_exit(void); 功能:从一个中断函数或者不可中断函数(标志为__monitor)返回时退出低功 耗模式。只在中断函数或者不可中断函数中有效。 19. __no_operation void __no_operation(void); 功能:执行 NOP 指令。 20. __op_code __op_code(unsigned short); 功能:在指令流中插入一个常数。 21. __segment_begin void *__segment_begin(segment); 功能:segment 是段的名字,必须是字符串。返回指向 segment 段的地址。此 处的段是程序中定义的数据段、代码段、堆栈段等,一般用户可以使用编译器的 默认设置。 22. __segment_end void *__segment_end(segment); 功能:segment 是段的名字,必须是字符串。返回指向 segment 段结束后的第 一个字地址。 23. __set_interrupt_state void __set_interrupt_state(istate_t); 功能:恢复 istate_t 中保存的中断状态。 24. __set_R4_register void __set_R4_register(unsigned short); 功能:将 unsigned short 值赋给寄存器 R4,只在 R4 被锁定时有效。 25. __set_R5_register
void __set_R5_register(unsigned short); 功能:将 unsigned short 值赋给寄存器 R5,只在 R5 被锁定时有效。 26. __set_SP_register void __set_SP_register(unsigned short); 功能:给堆栈指针寄存器 SP 赋值。 27. __swap_bytes unsigned short __swap_bytes(unsigned short); 功能:一个 16 位的无符号整数,高 8 位与低 8 位进行交换。如 0x1234 交换后 为 0x3412。
扩展定义
为了使用方便, EW430 还作了一些定义, 有些定义不属于 C 语言的一部分, 而是一种二次包装, 如对内部函数的包装。它们的功能完全可以用其他函数或者 表达式实现, 用户也可以自己重新定义, 但使用它们会使编写程序更加简单易懂。 下面 1~4 项都是在不同类型 CPU 的头文件中定义的,如 msp14x.h,其中 对 CPU 内的各寄存器和模块的各种工作模式都作了详尽的定义,编程时应尽可 能地利用。 1. PxIN、PxOUT、PxDIR、PxSEL x 为端口号。IN 为端口输入寄存器,OUT 为端口输出寄存器,DIR 为端口方向 控制寄存器,SEL 为端口第二功能选择寄存器。 举例: Moon=P1IN; //读端口 P1 的值,赋给变量 Moon P3Out = 5; //P3 端口输出 5 P2DIR = 0xF0; //P2 端口的高 4 位为输出,第 4 位为输入 P6SEL = 0xF; //P6 端口的高 4 位用作 I/O 端口,低 4 位用于第二功能 2. BITx x 的取值范围为 0~F。代表寄存器的某一位。其定义为: #define BIT0 #define BIT1 … #define BITE #define BITF (0x4000) (0x8000) (0x0001) (0x0002)
BIT0 为最低位, BITF 为最高位。 MSP430 是不支持位操作的, 如果想对位操作,
最好的方法就是通过位屏蔽来实现。 举例: P1OUT | = BIT0; P1OUT &= ~BIT7; 3. LPMx x:0~4。进入 0~4 低功耗模式。其定义为: #define LPM0 … #define LPM4 举例: LPM0; LPM4; //进入低功耗模式 0 //进入低功耗模式 4 _BIS_SR(LPM4_bits) //进入低功耗模式 4 从以上代码可以看出扩展定义是对内部函数的第二次包装。 _BIS_SR(LPM0_bits) //进入低功耗模式 0 //将 P1 口的最低位输出置 1 //将 P1 口的最高位输出清 0,P1 口只有 8 位
4. LPMx_EXIT x:0~4。退出+0~4 低功耗模式。其定义为: #define LPM0_EXIT … #define LPM4_EXIT 举例: LPM0_EXIT; LPM4_EXIT; 5. _EINT() 打开全局中断控制,使 GIE=1。 6. _DINT() 关闭全局中断控制,使 GIE=0。执行__disable_interrupt 指令。 7. _NOP() 空操作。执行__no_operation 指令。 8. _OPC(x) 在指令中插入一个常数。x 为 unsigned char 类型。执行__op_code 指令。 9. _SWAP_BYTES(x) x 是一个 16 位的无符号整数,高 8 位与低 8 位进行交换。执行__swap_bytes //退出低功耗模式 0 //退出低功耗模式 4 _BIC_SR_IRQ(LPM4_bits) //进入低功耗模式 4 _BIC_SR_IRQ(LPM0_bits) //进入低功耗模式 0
指令。 10. __no_init [数据类型] 变量名 @ 地址
在某一固定地址处定义一个不进行初始化的变量,地址可以在 RAM 或 FLASH 内。如果使用此方式定义在 RAM 内的变量需要赋值,那么必须首先定义,然后 才能赋值。 /*分配变量 MoonRiver 在 RAM 地址 0x210*/ __no_init unsigned int MoonRiver @ 0x210; MoonRiver = 100; /*分配变量 MoonRiver 在 FLASH 地址 0xFFC0*/ __no_init float MoonRiver @ 0xFFC0; /*分配变量 MoonRiver[3]在 FLASH 地址 0x200*/ __no_init char MoonRiver[3] @ 0xFF00; /*分配结构 sMoonRiver 在 RAM 地址 0x200*/ Typedef struct { unsigned char q0; unsigned int iq0; }sMoonRiver; 型为 sMoonRiver MoonRiver.q0 = 100; MoonRiver.iq0 = 1000; 11. const [数据类型] //为 MoonRiver 赋初值 变量名 @ 地址 //定义一个结构型的数据类型,取名为 sMoonRiver __no_init sMoonRiver MoonRiver @ 0x200; //声明变量 MoonRiver, 其数据类 //没有初始化 //初始化 MoonRiver 为 100
在某一固定地址处定义一个只读变量,并且只能在定义的时候赋初值。这种定义 变量的方式在 FLASH 的固定地址处分配变量时非常有用。 举例: /*分配变量 MoonRiver 在 RAM 地址 0x210*/ const unsigned int MoonRiver @ 0x210 = 100; /*分配变量 MoonRiver 在 FLASH 地址 0xFFC0*/ const float MoonRiver @ 0xFFC0 = 32.5; /*分配变量 MoonRiver[3]在 FLASH 地址 0xFF00*/ const char MoonRiver[3] @ 0xFF00 = {0, 1, 2}; /*分配结构 sMoonRiver 在 RAM 地址 0xFFD0*/ Typedef struct //初始化 MoonRiver 为 32.5 //初始化 MoonRiver 为 100
{ unsigned char q0; unsigned int iq0; }sMoonRiver; //定义一个结构型的数据类型,取名为 sMoonRiver //声明变量 MoonRiver, const sMoonRiver MoonRiver @ 0xFFD0 = {2, 500}; 其数据类型为 sMoonRiver 如果不需要确定地址,只想在 FLASH 中分配一个变量,则形式为: const 举例: const unsigned int MoonRiver = 100; [数据类型] 变量名;