Practical C language programming for MSP430 series microcontrollers[Copy link]
1. asm can also be written as __asm. Its function is to embed assembly language directly in C program. Syntax: asm("string"); string must be a valid assembly statement. 2. __interrupt is placed before the function to mark the interrupt function. The following program is the receive interrupt function of asynchronous serial port UART0. UART0RX_VECTOR is the receive interrupt vector of asynchronous serial port UART0. Example: #pragma vector=UART0RX_VECTOR __interrupt void UART0_R(void) { TXBUF0=RXBUF0; } 3. __monitor is placed before the function, and its function is to automatically disable interrupts when this function is executed. Such functions should be shortened as much as possible, otherwise, interrupt events cannot be responded to in time. 4. __no_init is placed before global variables, and its function is to prevent variables from being assigned initial values when the program starts. 5. __raw When compiling an interrupt function, the compiler will automatically generate a section of code that first saves the contents of the CPU registers used at the time, and then restores them when exiting the interrupt program. Placing __raw before the interrupt function can prohibit the process of saving the CPU registers, and of course it will not be restored when exiting. Whether to use this keyword for an interrupt function depends on the needs. //UART0 receives interrupt 6. __regvar is placed in front of a variable to declare the variable as a register variable. It can be used for integers, pointers, 32-bit floating-point numbers, and structures and unions with only one element. The address of a register variable can only be R4 or R5, and a pointer cannot be used to point to this register variable, and __no_init must be used to prohibit initialization. For example: __regvar __no_init unsigned char q0 @ __R4; Other uncommon keywords include: __data16, __intrinsic, __noreturn, __root, __task, __word16. Internal Functions This section introduces the prototypes and functions of internal functions. 1. __bcd_add_short unsigned short __bcd_add_short(unsigned short, unsigned short); Function: Add two 16-bit BCD format numbers and return the sum. 2. __bcd_add_long unsigned long __bcd_add_long(unsigned long, unsigned long); Function: Add two 32-bit BCD format numbers and return the sum. 3. __bcd_add_long_long unsigned long long __bcd_add_long_long(unsigned long long, unsigned long long); Function: Add two 64-bit BCD format numbers and return the sum. 4. __bic_SR_register void __bic_SR_register(unsigned short); Function: Clear some bits in the SR register in the CPU to 0. Its parameter is a mask code, and the bits that need to be cleared to 0 are 1. 5. __bic_SR_register_on_exit void __bic_SR_register_on_exit(unsigned short); Function: When an interrupt function or a non-interruptible function (flag is __monitor) returns, the CPU clears some bits in the internal SR register to 0. Its parameter is a mask code, and the bits that need to be cleared to 0 are 1. 6. __bis_SR_register void __bis_SR_register(unsigned short); Function: Set some bits in the SR register in the CPU to 1. Its parameter is a mask code, and the bits that need to be set to 1 are 1. 7. __bis_SR_register_on_exit void __bis_SR_register_on_exit(unsigned short); Function: When an interrupt function or a non-interruptible function (flag is __monitor) returns, the CPU sets some bits in the internal SR register to 1. Its parameter is a mask code, and the bits that need to be set to 1 are 1. 8. __disable_interrupt void __disable_interrupt(void) Function: Disable global interrupts. Execute the DINT command first to disable global interrupts, and then execute the NOP command. The null instruction is to ensure that the following program is executed after the global interrupt is disabled. 9. __enable_interrupt void __enable_interrupt(void) Function: Use the NINT instruction to enable global interrupts. 10. __even_in_range void __enable_in_range(unsigned short value, unsigned short upper_limit) Function: Can only be used in conjunction with the switch statement to determine whether value is an even number and less than or equal to upper_limit. Example: unsigned int MoonRiver, iq0; iq0=2; switch(__even_in_range(iq0,4)) { case 0: MoonRiver=0; break; case 2: MoonRiver=2; } Result: Assuming the value of iq0 is 2, MoonRiver=2 when the execution is completed. Otherwise, just like the normal switch statement, skip the case part and execute the following program directly. The advantage of using __even_in_range is that it can generate more efficient code. This function can be used when determining the source of multiple interrupt sources. 11. __get_interrupt_state istate_t __get_interrupt_state(void) Function: Returns the current interrupt status. The return value isate_t is a structure. Through this function, the current interrupt status can be obtained and saved. In the future, the interrupt status can be restored using __set_interrupt_state. 12. __get_R4_register unsigned short __get_R4_register (void); Function: Returns the value of register R4, which is only valid when R4 is locked. 13. __get_R5_register unsigned short __get_R5_register (void); Function: Returns the value of register R5, which is only valid when R5 is locked. 14. __get_SP_register unsigned short __get_SP_register (void); Function: Returns the value of stack pointer register SP. 15. __get_SR_register unsigned short __get_SR_register (void); Function: Returns the value of status register SR in CPU. 16. __get_SR_register_on_exit unsigned short __get_SR_register_on_exit (void); Function: Returns the value of status register SR when an interrupt function or non-interruptible function (flag is __monitor) returns. Only valid in interrupt functions or non-interruptible functions. 17.__low_power_mode_n void __low_power_mode_n(void); Function: Enter low power mode 0~4. 18. __low_power_mode_off_on_exit void __low_power_mode_off_on_exit(void); Function: Exit low power mode when returning from an interrupt function or a non-interruptible function (flag is __monitor). Only valid in interrupt functions or non-interruptible functions. 19. __no_operation void __no_operation(void); Function: Execute NOP instruction. 20. __op_code __op_code(unsigned short); Function: Insert a constant into the instruction stream. 21. __segment_begin void *__segment_begin(segment); Function: segment is the name of the segment and must be a string. Returns the address pointing to the segment segment. The segment here is the data segment, code segment, stack segment, etc. defined in the program. Generally, users can use the default settings of the compiler. 22. __segment_end void *__segment_end(segment); Function: segment is the name of the segment and must be a string. Returns the first word address after the end of segment. 23. __set_interrupt_state void __set_interrupt_state(istate_t); Function: Restore the interrupt state saved in isate_t. 24. __set_R4_register void __set_R4_register(unsigned short); Function: Assign unsigned short value to register R4, which is only valid when R4 is locked. 25. __set_R5_register void __set_R5_register(unsigned short); Function: Assign unsigned short value to register R5, which is only valid when R5 is locked. 26. __set_SP_register void __set_SP_register(unsigned short); Function: Assign value to stack pointer register SP. 27. __swap_bytes unsigned short __swap_bytes(unsigned short); Function: A 16-bit unsigned integer, the upper 8 bits are swapped with the lower 8 bits. For example, 0x1234 is swapped to 0x3412. Extended definition For ease of use, EW430 also makes some definitions, some of which are not part of the C language, but a secondary packaging, such as the packaging of internal functions. Their functions can be completely implemented by other functions or expressions, and users can also redefine them by themselves, but using them will make programming easier to understand. The following 1 to 4 items are defined in the header files of different types of CPUs, such as msp14x.h, which has detailed definitions of various registers and module working modes in the CPU, and should be used as much as possible when programming. 1. PxIN, PxOUT, PxDIR, PxSEL x is the port number. IN is the port input register, OUT is the port output register, DIR is the port direction control register, and SEL is the port second function selection register. For example: Moon = P1IN; //Read the value of port P1 and assign it to the variable Moon P3Out = 5; //P3 port outputs 5 P2DIR = 0xF0; //The upper 4 bits of port P2 are output, and the 4th bit is input P6SEL = 0xF; //The upper 4 bits of port P6 are used as I/O ports, and the lower 4 bits are used for the second function 2. The value range of BITx x is 0~F. It represents a bit of the register. Its definition is: #define BIT0 #define BIT1 … #define BITE #define BITF (0x4000) (0x8000) (0x0001) (0x0002) BIT0 is the lowest bit, and BITF is the highest bit. MSP430 does not support bit operations. If you want to operate on bits, the best way is to implement it through bit masking. Example: P1OUT | = BIT0; P1OUT &= ~BIT7; 3. LPMx x: 0~4. Enter 0~4 low power mode. Its definition is: #define LPM0 … #define LPM4 Example: LPM0; LPM4; //Enter low power mode 0 //Enter low power mode 4 _BIS_SR(LPM4_bits) //Enter low power mode 4 From the above code, we can see that the extended definition is the second packaging of the internal function. _BIS_SR(LPM0_bits) //Enter low power mode 0 //Set the lowest bit output of P1 port to 1 //Clear the highest bit output of P1 port, P1 port has only 8 bits 4. LPMx_EXIT x: 0~4. Exit +0~4 low power mode. Its definition is: #define LPM0_EXIT … #define LPM4_EXIT Example: LPM0_EXIT; LPM4_EXIT; 5. _EINT() Turn on global interrupt control and make GIE=1. 6. _DINT() Turn off global interrupt control and make GIE=0. Execute the __disable_interrupt instruction. 7. _NOP() No operation. Execute the __no_operation instruction. 8. _OPC(x) Insert a constant into the instruction. x is of type unsigned char. Execute the __op_code instruction. 9. _SWAP_BYTES(x) x is a 16-bit unsigned integer, and the upper 8 bits are swapped with the lower 8 bits. Execute __swap_bytes //Exit low power mode 0 //Exit low power mode 4 _BIC_SR_IRQ(LPM4_bits) //Enter low power mode 4 _BIC_SR_IRQ(LPM0_bits) //Enter low power mode 0 instruction. 10. __no_init [Data type] Variable name @ address Define a variable without initialization at a fixed address. The address can be in RAM or FLASH. If the variable defined in RAM using this method needs to be assigned a value, it must be defined first and then assigned a value. /* Allocate variable MoonRiver at RAM address 0x210*/ __no_init unsigned int MoonRiver @ 0x210; MoonRiver = 100; /* Allocate variable MoonRiver at FLASH address 0xFFC0*/ __no_init float MoonRiver @ 0xFFC0; /* Allocate variable MoonRiver[3] at FLASH address 0x200*/ __no_init char MoonRiver[3] @ 0xFF00; /* Allocate structure sMoonRiver at RAM address 0x200*/ Typedef struct { unsigned char q0; unsigned int iq0; } sMoonRiver; Type is sMoonRiver MoonRiver.q0 = 100; MoonRiver.iq0 = 1000; 11.const [data type] //Assign an initial value to MoonRiver variable name @ address //Define a structured data type, named sMoonRiver __no_init sMoonRiver MoonRiver @ 0x200; //Declare the variable MoonRiver, whose data type //is not initialized //Initialize MoonRiver to 100 Define a read-only variable at a fixed address, and only assign an initial value when defining it. This way of defining variables is very useful when allocating variables at fixed addresses in FLASH. Example: /* Allocate variable MoonRiver at RAM address 0x210*/ const unsigned int MoonRiver @ 0x210 = 100; /* Allocate variable MoonRiver at FLASH address 0xFFC0*/ const float MoonRiver @ 0xFFC0 = 32.5; /* Allocate variable MoonRiver[3] at FLASH address 0xFF00*/ const char MoonRiver[3] @ 0xFF00 = {0, 1, 2}; /* Allocate structure sMoonRiver at RAM address 0xFFD0*/ Typedef struct // Initialize MoonRiver to 32.5 // Initialize MoonRiver to 100 { unsigned char q0; unsigned int iq0; }sMoonRiver; // Define a structure data type named sMoonRiver // Declare variable MoonRiver, const sMoonRiver MoonRiver @ 0xFFD0 = {2, 500}; Its data type is sMoonRiver If you do not need to determine the address and just want to allocate a variable in FLASH, the format is: const Example: const unsigned int MoonRiver = 100; [Data type] variable name;