This is just an essay on my study of the MSP430, a 16-bit ultra-low power microcontroller produced by TI. I hope it can be of some reference to other friends. Please feel free to point out any mistakes.
Reference address:My opinion on 430 study notes
There are many books explaining 430 now, but most of them describe the underlying hardware structure in detail, which makes them seem empty and boring. I think to understand the operation of an MCU, we must first understand its basic characteristics, and then carefully study the functions of each module.
1. First, you need to know the memory structure of msp430. There are two typical microprocessor structures: von Neumann structure - program memory and data memory are uniformly encoded; Harvard structure - program memory and data memory; MSP430 series microcontrollers belong to the former, while the commonly used mcs51 series belong to the latter.
0-0xf special function register; 0x10-0x1ff peripheral module register; 0x200-? According to different models, the address is extended from low to high; 0x1000-0x107f seg_b0x1080_0x10ff seg_a is used for flash information storage
The rest start from 0xffff and extend downwards according to different capacities, for example, 149 is 60KB, 0xffff-0x1100
2. The reset signal is the starting point of the MCU. There are two types of reset types for 430: the power-on reset signal POR and the power-on clear signal PUC. The POR signal is only used when the power is on and the RST/NMI reset pin is set to the reset function, and the system is reset when the level is low. The PUC signal is generated by the POR signal, as well as other signals such as watchdog timer overflow and security key value errors. However, no matter which signal triggers the reset, the MSP430 will read the reset interrupt vector at address 0xffff, and then the program will start executing from the address pointed to by the interrupt vector. I will not write about the state after the reset, please refer to the reference book for details, hehe.
3. The system clock is the commander of a program, and the timing and interrupts are also the core and central axis of the entire program. 430 has up to three oscillators, DCO internal oscillator; LFXT1 external low-frequency oscillator, common 32768HZ, no external load capacitor; can also connect to high-frequency 450KHZ-8M, need to connect to load capacitor; XT2 connects to high-frequency 450KHZ-8M, plus external capacitor.
430 has three clock signals: MCLK system master clock, which can be divided into 1 2 4 8 and is used by the CPU. Other peripheral modules can also use it when they have the option; SMCLK system sub-clock, which is used by peripheral modules and can be a clock signal generated by different oscillators; ACLK auxiliary clock, which can only be generated by LFXT1 and is used by peripheral modules.
4. Interrupts are a major feature of the 430 processor, because almost every peripheral module can generate them. The 430 can enter a low-power state when there is no task, and wake up the CPU when there is an event, and enter a low-power state again after the processing is completed.
The entire interrupt response process is as follows: when there is an interrupt request, if the CPU is in active state, complete the current command first; if it is in low power consumption, exit first and push the PC value of the next instruction into the stack; if there are multiple interrupt requests, respond to the one with the highest priority first; after execution, wait for the interrupt request flag to be reset. Note that the interrupt request flag of a single interrupt source is automatically reset, while the flag of multiple interrupts requires software reset; then the system general interrupt enable bit SR.GIE is reset, the corresponding interrupt vector value is loaded into the PC, and the program continues to execute from this address.
Here we should pay attention to the interrupt enable bit SR.GIE and interrupt nesting. If you want to respond to a higher-level interrupt request during the execution of the interrupt program, you must set SR.GIE when entering the first interrupt.
In fact, the clocks of other peripheral modules are executed along the core of clock and interrupt. I will not elaborate on the specific structure, you can refer to the 430 series manual.
I want to write about the overall structure of C language programming for 430. Basically, it belongs to the framework structure, that is, the overall modular programming, which is actually the basic rule of hardware programming (not the rule I set).
First, the program header file includes #include , which is the 14 series, because 149 is commonly used; other models can be modified by yourself. You can also include #include "data.h" and other database header files, or function variable declaration header files, which are all defined by you.
Next is the declaration of functions and variables void Init_Sys(void); system initialization
System initialization is an overall concept, which generally includes the initialization of all peripheral modules. You can write the sub-functions of peripheral module initialization into Init_Sys(), or you can write the initialization of each module separately. However, for the sake of simplicity, it is best to initialize other modules here after initializing the system clock.
void Init_Sys()
{
unsigned int i;
BCSCTL1&=~XT2OFF; //Turn on XT2 oscillator
do
{
IFG1 &= ~OFIFG; // Clear oscillator failure flag
for (i = 0xFF; i > 0; i--); // Delay, wait for XT2 to start oscillating
}
while ((IFG1 & OFIFG) != 0); // Determine whether XT2 is oscillating
BCSCTL2 =SELM_2+SELS; //Select MCLK, SMCLK as XT2
//The following initializes various modules, interrupts, peripherals, etc.
........................................
_EINT(); //Open global interrupt control
}
This involves the clock issue. Usually we choose XT2 as the 8M crystal oscillator, that is, the system main clock MCLK is 8M, and the CPU executes commands based on this clock; but other peripheral modules can select other clocks, ACLK, in the corresponding control registers; when you have very low speed requirements and a large timing time interval, you can choose ACLK, for example, set it in the initialization of timer Timea.
Main program: void main( void )
{
WDTCTL = WDTPW + WDTHOLD; // Turn off the watchdog
InitSys(); //Initialization
//Other functions in your own task
. . . . . . . . . . . . . . . . . . . . .
while(1);
}
After the main program, I will talk about the interrupt function. Interrupt is an indispensable part of your microcontroller tasks, and it can also be said to be the soul (exaggeration?).
/****************************************************** ******************************
Each interrupt function can be written in order of priority
*************************************************** *********************/
Here is an example of a timed interrupt:
Initialize void Init_Timer_A(void)
{
TACTL = TASSEL0 + TACLR; // ACLK, clear TAR
CCTL0 = CCIE; // CCR0 interrupt enable
CCR0=32768; //timing 1s
TACTL|=MC0; //Increment counting mode
}
Interrupt service #pragma vector=TIMERA0_VECTOR
__interrupt void TimerA0()
{
// You request to interrupt the execution of the task
}
Of course, there are other timings and multiple interrupts, and the number of interrupt vectors in each series of chips is also different.
This is the simple overall program framework. It is written simply. Please forgive me for forgetting to understand. Tomorrow I will learn in detail about the initialization and functions of each peripheral module. Good night.
The overall programming structure includes all peripheral modules and the initialization of internal clocks, interrupts, and timings. You can add or reduce them according to your needs. Remember, modular design is the most powerful weapon.
This is a classic that I personally summarized. Thank you for your support. Because 149 is often used, this is the structure of 149. Others can be changed according to personal needs.
/****************************************************** ******************************
File name: main.c
Description: MSP430 framework program. Applicable to MSP430F149, other models need to be changed appropriately.
Unused interrupt functions can be retained or deleted, but if retained, make sure not to enable unnecessary interrupts.
*************************************************** ***************************/
//head File
#include
// Function declaration
void InitSys();
int main( void )
{
WDTCTL = WDTPW + WDTHOLD; // Turn off the watchdog
InitSys(); //Initialization
start:
//Fill in the following user code
LPM3; //Enter low power mode n, n: 0~4. If you do not want to enter low power mode, disable this sentence
goto start;
}
[page]
/****************************************************** ******************************
system initialization
*************************************************** ****************************/
void InitSys()
{
unsigned int iq0;
//Use XT2 oscillator
BCSCTL1&=~XT2OFF; //Turn on XT2 oscillator
do
{
IFG1 &= ~OFIFG; // Clear oscillator failure flag
for (iq0 = 0xFF; iq0 > 0; iq0--); // Delay, wait for XT2 to start oscillating
}
while ((IFG1 & OFIFG) != 0); // Determine whether XT2 is oscillating
BCSCTL2 =SELM_2+SELS; //Select MCLK, SMCLK as XT2
//Fill in user code below to initialize various modules, interrupts, peripherals, etc.
_EINT(); //Open global interrupt control. If you don't need to open it, you can shield this sentence
}
/****************************************************** ******************************
Port 2 interrupt function
*************************************************** ****************************/
#pragma vector=PORT2_VECTOR
__interrupt void Port2()
{
//The following is a reference processing program. The judgment of the interrupt source should be deleted for unused ports.
if((P2IFG&BIT0) == BIT0)
{
//Handle P2IN.0 interrupt
P2IFG &= ~BIT0; // Clear interrupt flag
//Fill in the following user code
}
else if((P2IFG&BIT1) == BIT1)
{
//Handle P2IN.1 interrupt
P2IFG &= ~BIT1; // Clear interrupt flag
//Fill in the following user code
}
else if((P2IFG&BIT2) == BIT2)
{
//Handle P2IN.2 interrupt
P2IFG &= ~BIT2; // Clear interrupt flag
//Fill in the following user code
}
else if((P2IFG&BIT3) == BIT3)
{
//Handle P2IN.3 interrupt
P2IFG &= ~BIT3; // Clear interrupt flag
//Fill in the following user code
}
else if((P2IFG&BIT4) == BIT4)
{
//Handle P2IN.4 interrupt
P2IFG &= ~BIT4; // Clear interrupt flag
//Fill in the following user code
}
else if((P2IFG&BIT5) == BIT5)
{
//Handle P2IN.5 interrupt
P2IFG &= ~BIT5; // Clear interrupt flag
//Fill in the following user code
}
else if((P2IFG&BIT6) == BIT6)
{
//Handle P2IN.6 interrupt
P2IFG &= ~BIT6; // Clear interrupt flag
//Fill in the following user code
}
else
{
//Handle P2IN.7 interrupt
P2IFG &= ~BIT7; // Clear interrupt flag
//Fill in the following user code
}
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
USART1 send interrupt function
*************************************************** ****************************/
#pragma vector=USART1TX_VECTOR
__interrupt void Usart1Tx()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
USART1 receive interrupt function
*************************************************** ****************************/
#pragma vector=USART1RX_VECTOR
__interrupt void Ustra1Rx()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Port 1 interrupt function
Multiple interrupt sources: P1IFG.0~P1IFG7
After entering the interrupt, the interrupt source should be determined first, and the interrupt flag should be cleared before exiting the interrupt, otherwise the interrupt will be triggered again.
*************************************************** ****************************/
#pragma vector=PORT1_VECTOR
__interrupt void Port1()
{
//The following is a reference processing program. The judgment of the interrupt source should be deleted for unused ports.
if((P1IFG&BIT0) == BIT0)
{
//Handle P1IN.0 interrupt
P1IFG &= ~BIT0; // Clear interrupt flag
//Fill in the following user code
}
else if((P1IFG&BIT1) == BIT1)
{
//Handle P1IN.1 interrupt
P1IFG &= ~BIT1; // Clear interrupt flag
//Fill in the following user code
}
else if((P1IFG&BIT2) == BIT2)
{
//Handle P1IN.2 interrupt
P1IFG &= ~BIT2; // Clear interrupt flag
//Fill in the following user code
}
else if((P1IFG&BIT3) == BIT3)
{
//Handle P1IN.3 interrupt
P1IFG &= ~BIT3; // Clear interrupt flag
//Fill in the following user code
}
else if((P1IFG&BIT4) ==BIT4)
{
//Handle P1IN.4 interrupt
P1IFG &= ~BIT4; // Clear interrupt flag
//Fill in the following user code
}
else if((P1IFG&BIT5) == BIT5)
{
//Handle P1IN.5 interrupt
P1IFG &= ~BIT5; // Clear interrupt flag
//Fill in the following user code
}
else if((P1IFG&BIT6) ==BIT6)
{
//Handle P1IN.6 interrupt
P1IFG &= ~BIT6; // Clear interrupt flag
//Fill in the following user code
}
else
{
//Handle P1IN.7 interrupt
P1IFG &= ~BIT7; // Clear interrupt flag
//Fill in the following user code
}
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
[page]
/****************************************************** ******************************
Timer A interrupt function
Multiple interrupt sources: CC1~2 TA
*************************************************** ****************************/
#pragma vector=TIMERA1_VECTOR
__interrupt void TimerA1()
{
//The following is a reference handler. Unused interrupt sources should be deleted.
switch (__even_in_range(TAIV, 10))
{
case 2:
//Capture/compare 1 interrupt
//Fill in the following user code
break;
case 4:
//Capture/compare 2 interrupt
//Fill in the following user code
break;
case 10:
//TAIFG timer overflow interrupt
//Fill in the following user code
break;
}
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Timer A interrupt function
Interrupt source: CC0
*************************************************** ****************************/
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA0()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
AD converter interrupt function
Multiple interrupt sources: analog 0~7, VeREF+, VREF-/VeREF-, (AVcc-AVss)/2
ADC12TOV and ADC12OV interrupt flags are not processed
*************************************************** ****************************/
#pragma vector=ADC_VECTOR
__interrupt void Adc()
{
//The following is a reference handler. Unused interrupt sources should be deleted.
if((ADC12IFG&BIT0)==BIT0)
{
//Channel 0
//Fill in the following user code
}
else if((ADC12IFG&BIT1)==BIT1)
{
//Channel 1
//Fill in the following user code
}
else if((ADC12IFG&BIT2)==BIT2)
{
//Channel 2
//Fill in the following user code
}
else if((ADC12IFG&BIT3)==BIT3)
{
//Channel 3
//Fill in the following user code
}
else if((ADC12IFG&BIT4)==BIT4)
{
//Channel 4
//Fill in the following user code
}
else if((ADC12IFG&BIT5)==BIT5)
{
//Channel 5
//Fill in the following user code
}
else if((ADC12IFG&BIT6)==BIT6)
{
//Channel 6
//Fill in the following user code
}
else if((ADC12IFG&BIT7)==BIT7)
{
//Channel 7
//Fill in the following user code
}
else if((ADC12IFG&BIT8)==BIT8)
{
//VeREF+
//Fill in the following user code
}
else if((ADC12IFG&BIT9)==BIT9)
{
//VREF-/VeREF-
//Fill in the following user code
}
else if((ADC12IFG&BITA)==BITA)
{
//temperature
//Fill in the following user code
}
else if((ADC12IFG&BITB)==BITB)
{
//(AVcc-AVss)/2
//Fill in the following user code
}
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
USART0 send interrupt function
*************************************************** ****************************/
#pragma vector=USART0TX_VECTOR
__interrupt void Usart0Tx()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
USART0 receive interrupt function
*************************************************** ****************************/
#pragma vector=USART0RX_VECTOR
__interrupt void Usart0Rx()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Watchdog timer interrupt function
*************************************************** ****************************/
#pragma vector=WDT_VECTOR
__interrupt void WatchDog()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Comparator A interrupt function
*************************************************** ****************************/
#pragma vector=COMPARATORA_VECTOR
__interrupt void ComparatorA()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
[page]
/****************************************************** ******************************
Timer B interrupt function
Multiple interrupt sources: CC1~6 TB
*************************************************** ****************************/
#pragma vector=TIMERB1_VECTOR
__interrupt void TimerB1()
{
//The following is a reference handler. Unused interrupt sources should be deleted.
switch (__even_in_range(TBIV, 14))
{
case 2:
//Capture/compare 1 interrupt
//Fill in the following user code
break;
case 4:
//Capture/compare 2 interrupt
//Fill in the following user code
break;
case 6:
//Capture/compare 3 interrupt
//Fill in the following user code
break;
case 8:
//Capture/compare 4 interrupt
//Fill in the following user code
break;
case 10:
//Capture/compare 5 interrupt
//Fill in the following user code
break;
case 12:
//Capture/compare 6 interrupt
//Fill in the following user code
break;
case 14:
//TBIFG timer overflow interrupt
//Fill in the following user code
break;
}
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Timer B interrupt function
Interrupt source: CC0
*************************************************** ****************************/
#pragma vector=TIMERB0_VECTOR
__interrupt void TimerB0()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Non-maskable interrupt function
*************************************************** ****************************/
#pragma vector=NMI_VECTOR
__interrupt void Nmi()
{
//The following is a reference handler. Unused interrupt sources should be deleted.
if((IFG1&OFIFG)==OFIFG)
{
//Oscillator failure
IFG1 &= ~OFIFG;
//Fill in the following user code
}
else if((IFG1&NMIIFG)==NMIIFG)
{
//RST/NMI non-maskable interrupt
IFG1 &= ~NMIIFG;
//Fill in the following user code
}
else //if((FCTL3&ACCVIFG)==ACCVIFG)
{
// Illegal access to memory
FCTL3 &= ~ACCVIFG;
//Fill in the following user code
}
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
/****************************************************** ******************************
Basic timer interrupt function
*************************************************** ****************************/
#pragma vector=BASICTIMER_VECTOR
__interrupt void BasTimer()
{
//Fill in the following user code
LPM3_EXIT; //Exit low power mode after exiting interrupt. If you want to keep low power mode after exiting interrupt, shield this sentence
}
Previous article:My opinion on MSP430 introduction
Next article:SD16 module in MSP430
Recommended ReadingLatest update time:2024-11-16 19:50
Multi-channel resistance measurement system based on MSP430F169
Aiming at the problem of multi-channel resistance measurement difficulty often encountered in actual measurement work, a new multi-channel resistance measurement system is designed. The system uses two MSP430F169 microcontrollers to coordinate work, which improves the accuracy and stability of measurement. The slave i
[Microcontroller]
Some issues with MSP430
1-Q: MSP430 pin multiplexing between JTAG and I/O functionsA
: Four pins, P1.7 - P1.4, have both I/O and JTAG functions on the 20 and 28-pin MSP430F1xx devicesThe default function of these pins is to have I/O function when the device is poweredOnly when the test pin is pulled high will select these pins as JTAGWhen u
[Microcontroller]
Characteristics and Application of Flash Memory in MSP430 Microcontroller
Overview
Instruments with single-chip microcomputer as the core often need to consider the problem of data preservation in the event of a sudden power failure. Generally, there are two countermeasures: one is to use a backup power supply to keep the single-chip microcomputer working continuously, which is called har
[Microcontroller]
Design and production of sine wave signal source based on MP430 control
This system uses MSP430 as the control core to design and produce a sine wave and pulse wave signal source. This experiment is divided into four major modules, namely keyboard scanning module, sine wave generation module, pulse wave generation module and LCD display module. The sine generation part uses the DDS chip
[Microcontroller]
Design of portable blood pressure monitor based on MSP430 microcontroller and USB bus
At present, most of the sphygmomanometers on the market are still mercury sphygmomanometers. Electronic sphygmomanometers have been widely used abroad, but they have just begun to be used in my country. The doctor must wear a stethoscope to measure each time with a mercury sphygmomanometer. The measurement process
[Microcontroller]
MSP430 MCU FLASH read and write operation examples
//******************************************************************************
// MSP430F149
// M. Mitchell
// Texas Instruments Inc.
// Feb 2005
// Built with IAR Embedded Workbench Version: 3.21A
//******************************************************************************
#include MSP430x14x.h
char
[Microcontroller]
Design of portable blood pressure monitor using MSP430 microcontroller and USB bus ch375
This paper uses the low-power MSP430 microcontroller to collect human blood pressure signals, and stores these data in a USB flash drive through the USB control chip CH375. The changes in blood pressure during the day can be analyzed through PC software.
Electronic sphygmomanometers have been widely used abroad, but
[Microcontroller]
How important is the memory allocation of MSP430?
In a project I did before, I had no problem running the program when the emulator was plugged in. However, after unplugging the emulator, the program always ran to the alarm state after powering off and then on. First, I suspected that it was a problem with the reset circuit. After checking the information, I found th
[Microcontroller]
Latest Microcontroller Articles
He Limin Column
Microcontroller and Embedded Systems Bible
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
MoreSelected Circuit Diagrams
MorePopular Articles
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
MoreDaily News
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
Guess you like
- About the difference between CC1312R LAUNCHPAD versions
- About the signal input mode of the power amplifier
- My Journey of MCU Development (Part 1)
- How to understand the accuracy parameter (1.5% + 3) of the Fluke F17B+ multimeter?
- Another bottleneck.
- Easy-to-use and cheap microcontroller is here
- Inverting proportional operational amplifier circuit
- Upper computer displays waveform acquisition
- Evaluation Weekly Report 20211129: There are 4 days left for Anxinke NB-IoT and domestic FPGA applications, and the wireless charging mouse pad is waiting to be disassembled (Extra)
- Are there any pmos and nmos tubes with working current |Ids|=1.2A;|Vds|<0.2V, which don't matter if they are enhanced or not, and have low leakage current when turned off?