(a), IO port module,
1. The MSP430G2553 we use has two groups of IO ports, P1 and P2.
2. The registers of the IO port are: direction selection register PxDIR, output register PxOUT, input register PxIN, IO port internal pull-up or pull-down resistor enable register PxREN, IO port function selection registers PxSEL and PxSEL2, IO port interrupt enable register PxIE, interrupt edge selection register PxIES, IO port interrupt flag register PxIFG.
3. All IOs have interrupts, among which all P1 ports share one interrupt vector, and all P2 ports share one interrupt vector. Therefore, when using interrupts, after entering the interrupt, it is also necessary to determine which IO port generated the interrupt. The determination method can be to determine the level of each IO port.
4. The interrupt flag PxIFG needs to be cleared by software, but can also be set by software to trigger an interrupt.
Note: When setting PxIESx, the corresponding PxIFGx may be set according to PxINx (see the user guide for details), so after initializing the IO port interrupt, the corresponding PxIFGx must be cleared before officially using the IO interrupt. The procedure is as follows:
void IO_interrupt_init() //IO interrupt initialization function
{
P1REN |= BIT4+BIT5+BIT6+BIT7; // pullup internal pull-up resistor enabled
//When using interrupts, enable the internal pull-up resistor so that when the pin is left floating, the level will not jump, to prevent the level from jumping and constantly triggering interrupts when it is left floating
P1OUT = BIT4+BIT5+BIT6+BIT7; // When the pull-up or pull-down resistor on the pin is enabled, PxOUT selects whether to pull up or down
//0: pull down, 1: pull up
P1IE |= BIT4+BIT5+BIT6+BIT7; // interrupt enabled P13 interrupt enabled
P1IES |= BIT4+BIT5+BIT6+BIT7; // Hi/lo edge falling edge interrupt
//P1IES &= ~BIT3; //Rising edge triggers interrupt
P1IFG &= ~(BIT4+BIT5+BIT6+BIT7); // Clear interrupt flag
}
5. PxOUT: If the pin selects the internal pull-up or pull-down resistor to be enabled, PxOUT sets the resistor to be pull-up or pull-down, 0: pull-down, 1: pull-up
6. When the IO port is not used, it is best not to set it as input and to float (this is the default state of the IO port), because when the input is floating, the input voltage may be between VIL and VIH, which will produce breakdown current. Therefore, the unused IO port can be set as output, or set as input but connected to VCC or GND through peripheral circuits, or connected to a pull-up/pull-down resistor.
7. When using the IO port of msp430g2553, please pay attention to the operation of the IO port register of g2553, unlike 51, it cannot operate on a single bit, but must operate on the entire register. So unlike 51, g2553 cannot define bit-type data. So when using the IO port of msp, please pay attention to the operation of the required bit, and do not affect other irrelevant bits. You can use symbols such as | & ^ for bitwise operations. When using IO to control other peripheral modules, you must also pay attention to the definition of the IO port to be used. You can use the following definition method:
#define CLR_RS P2OUT&=~BIT0; //RS = P2.0
#define SET_RS P2OUT|=BIT0;
#define CLR_RW P2OUT&=~BIT1; //RW = P2.1
#define SET_RW P2OUT|=BIT1;
#define CLR_EN P2OUT&=~BIT2; //EN = P2.2
#define SET_EN P2OUT|=BIT2;
#define DataPort P1OUT
8. The P27 and P26 pins of g2553 are connected to the output and input pins XOUT and XIN of the external crystal respectively. By default, they are automatically set to the crystal oscillator pin function. However, if you want to use them as ordinary IO, you can also set the corresponding SEL to ordinary IO, as follows:
P2DIR |= BIT6+BIT7; //Configure P26 and P27 as common IO and output pins. The default is the input and output pins of the crystal oscillator.
P2SEL &= ~(BIT6+BIT7); //cs and wr control terminals
P2SEL2 &= ~(BIT6+BIT7);
(ii) Clock system
1. The ultra-low power consumption of msp430 is largely due to the reasonable clock module. However, the powerful clock module is relatively complicated to set up.
2. The clock sources of msp430 are:
(1) External low-frequency crystal oscillator LFXT1CLK: low-frequency mode connects to watch crystal 32768Hz, high-frequency mode 450KHz~8MHz;
(2) External high-speed crystal oscillator XT2CLK: 8MHz;
(3) Internal digital controlled oscillator DCO: It is a controllable RC oscillator with a frequency of 0~16MHz;
(4) Ultra-low power low frequency oscillator VLO: uncontrollable, 4~20KHz, typical value is 12KHz;
3. Clock module: The clock modules of 430 include MCLK SMCLK ACLK:
(1) Main system clock MCLK: The CPU clock provided to MSP430. It can come from LFXT1CLK XT2CLK DCO VLO is optional, and the default is DCO.
(2) Subsystem clock SMCLK: Provided to high-speed peripherals. Can come from LFXT1CLK XT2CLK DCO VLO optional, default is DCO.
(3) Auxiliary system clock ACLK: Provided to low-speed peripherals. Can come from LFXT1CLK VLO.
4. The clock frequency provided by the internal oscillators DCO and VLO is not very accurate and varies greatly with the external environment.
The default frequency of DCO is about 800KHz, but I observed it with an oscilloscope and it was about 1.086MHz. When the DCO is set too high, the waveform is no longer a square wave, but a sine wave. DCO can be set relatively accurately using the macro definition provided by CCS, as follows:
DCOCTL = CALDCO_12MHZ; //DCO is set to 12MHz. This method is more accurate in setting the DCO frequency. The actual measured value is about 12.08MHz. Sine wave
BCSCTL1 = CALBC1_12MHZ;
This method can be used to set 1, 8, 12, 16MHz
The macro definition is as follows:
#ifndef __DisableCalData
SFR_8BIT(CALDCO_16MHZ);
SFR_8BIT(CALBC1_16MHZ);
SFR_8BIT(CALDCO_12MHZ);
SFR_8BIT(CALBC1_12MHZ);
SFR_8BIT(CALDCO_8MHZ);
SFR_8BIT(CALBC1_8MHZ);
SFR_8BIT(CALDCO_1MHZ);
SFR_8BIT(CALBC1_1MHZ);
#endif
5. Using ultra-low power low frequency oscillator VLO can greatly reduce system power consumption. The following example sets ACLK to VLO and MCLK to 8 divided by VLO:
#include
//1 delay
//#define CPU_F ((double)16000000)//cpu frequency16000000
#define CPU_F ((double)1630) //cpu frequency1630 //The actual MCLK of the CPU is about 13.05/8=1.63KHz
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
void main(void)
{
volatile unsigned int i; // Volatile to prevent removal
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO Low frequency clock is selected as VLO ACLK is selected as VLO
IFG1 &= ~OFIFG; // Clear OSCFault flag Clear oscillator error interrupt flag
__bis_SR_register(SCG1 + SCG0); // Stop DCO SCG1 disables SMCLK SCG0 disables DCO
BCSCTL2 |= SELM_3 + DIVM_3; // MCLK = LFXT1/8
//Since LFXT1 = VLO has been selected before, MCLK is selected as VLO 8-division, so the CPU's MCLK is about 1.5KHz
P1DIR = 0xFF; // All P1.x outputs
P1OUT = 0; // All P1.x reset
P2DIR = 0xFF; // All P2.x outputs
P2OUT = 0; // All P2.x reset
P1SEL |= BIT0+BIT4; // P10 P14options function selection is peripheral module
//p10 outputs ACLK, which comes from VLO, and p14 outputs SMCLK. Because SMCLK is disabled, there is no waveform output on the P14 pin
//The typical value of VLO is 12KHz. The actual value measured by oscilloscope is: 13.05KHz.
//So the actual MCLK of the CPU is about 13.05/8=1.63KHz
for (;;)
{
P1OUT ^= BIT6; // P1.6 flashes
delay_ms(1000);
}
}
6. As shown in the above program, the delay function uses that method, using the system delay cycle function __delay_cycles(int n); to achieve a more accurate delay, as follows:
//more_
//1 delay
//#define CPU_F ((double)16000000)//cpu frequency16000000
#define CPU_F ((double)12000000)//cpu frequency12000000
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
//2 empty function
#define nop() _NOP();
7. After the system is powered on, the DCO clock is used by default. The default frequency of DCO is about 800KHz, but I observed it with an oscilloscope and it was about 1.086MHz. When the DCO is set too high, you can see with an oscilloscope that the waveform is no longer a square wave, but a sine wave.
(III) Timer_A
1. MSP430g2553 has two 16-bit timers: Timer0_A and Timer1_A. Each has three capture/compare registers, with input capture and output compare functions. It can generate timing interrupts and PWM.
2. Generate PWM, the example is as follows:
#include
void Timer_A0_1_init() //TA0.1 outputs PWM
{
TACTL|= TASSEL_1+MC_1; //ACLK, count up
CCTL1=OUTMOD_7; //Output mode is reset/set
CCR0=328; //Clock frequency is 32768HZ, 100HZ
//CCR1=164; //Clock frequency is 32768HZ, duty cycle CCR1/CCR0=50%
CCR1=109; //Duty cycle CCR1/CCR0=1/3 TA0.1 is output by P1.2 P1.6
}
void Timer_A1_2_init() //TA1.2 outputs PWM
{
TA1CTL|= TASSEL_1+MC_1; //ACLK, count up
TA1CCTL2=OUTMOD_7; //Output mode is reset/set, note that CCTL2 should be written as TA1CCTL2
TA1CCR0=164; //Clock frequency is 32768HZ, waveform 32768/CCR0=199HZ
TA1CCR2=41; //Duty cycle CCR2/CCR0=1/4, note that CCR2 should be written as TA1CCR2 TA1.2 is output by P2.4 P2.5
}
void Timer_A1_1_init() //TA1.1 outputs PWM
{
TA1CCTL1=OUTMOD_7;
TA1CCR1=123; //Duty cycle CCR1/CCR0=3/4, note that CCR1 should be written as TA1CCR1 TA1.1 is output by P2.1 P2.2
}
void IO_init()
{
P1SEL|=BIT2+BIT6;
P1DIR|=BIT2+BIT6; //P1.2 P1.6 output TA0.1 OUT1
P2SEL|=BIT4+BIT5;
P2DIR|=BIT4+BIT5; //P2.4 P2.5 output TA1.2 OUT2
P2SEL|=BIT1+BIT2;
P2DIR|=BIT1+BIT2; //P2.1 P2.2 output TA1.1 OUT1
}
void main(void) {
WDTCTL=WDTPW+WDTHOLD;
IO_init();
Timer_A0_1_init();
Timer_A1_2_init();
Timer_A1_1_init();
_BIS_SR(CPUOFF); // Enter LPM0 Enter low power mode 0 SMCLK ON, ACLK ON
}
3. Timer_A capture/compare register
The TAR register is the 16-bit count register of Timer_A. TACCRx is the capture/compare register of Timer_A. When in capture mode: when capture occurs, the value of TAR is loaded into TACCRx. When in compare mode: TACCRx is loaded with the value to be compared with the TAR register.
4. Capture Mode
Capture the rising edge or falling edge or both the rising and falling edges of the external input signal. When the capture occurs, the value of TAR is loaded into TACCRx. At the same time, the interrupt can be entered to perform the corresponding operation. In this way, by capturing the rising edge or falling edge, the period of the external input signal can be calculated to obtain the frequency. By capturing the rising edge and falling edge, the duration of the high or low level of the input signal can be obtained. The duty cycle can also be calculated. The following is an example of the program for capturing and initializing Timer_A:
void timer_init() //When using Timer1_A, pay special attention to the writing of each register, because the registers of Timer0_A are abbreviated, so when writing
//When reading the registers of Timer1_A, pay special attention to the differences from Timer0_A
{
P1SEL |= BIT2; //Select P12 as the capture input terminal Timer0_A
//TACCTL1 |=CM_3+SCS+CAP+CCIE; //Both rising and falling edges trigger capture, used to measure pulse width, synchronous mode, and time interrupt CCI1A
TACCTL1 |=CM_1+SCS+CAP+CCIE; //Rising edge trigger capture, synchronous mode, time interrupt CCI1A
TACTL |= TASSEL1+MC_2; //Select SMCLK clock as the counting clock source, without frequency division. The increment counting mode is not possible, and the continuous counting mode is required.
P2SEL |= BIT1; //Select P21 as the capture input terminal Timer1_A
//TA1CCTL1 |=CM_3+SCS+CAP+CCIE; //Both rising and falling edges trigger capture, used to measure pulse width, synchronous mode, and time interrupt CCI1A
TA1CCTL1 |=CM_1+SCS+CAP+CCIE; // rising edge trigger capture, synchronous mode, time interrupt CCI1A
TA1CTL |= TASSEL1+MC_2; //Select SMCLK clock as the counting clock source, without frequency division. The increment counting mode is not possible, and the continuous counting mode must be used.
}
The corresponding interrupt functions are as follows:
#pragma vector=TIMER0_A1_VECTOR //Timer0_A CC1 interrupt vector
__interrupt void Timer_A(void)
{
// The capture compare register used by CCI0A is TA0CCR0, which is allocated to a
//Interrupt vector TIMER1_A0_VECTOR, so after entering the interrupt, it is directly the interrupt generated by Timer0_A CC0, without going through similar
//The following method determines the interrupt source.
//Timer0_A CC1-4, TA0 share an interrupt vector TIMER0_A1_VECTOR, so after entering the interrupt, you need to use the following
//Method to determine which interrupt source caused the interrupt
switch(TAIV) //If it is an interrupt generated by Timer0_A CC1
{
case 2:
{
flag=1;
LPM1_EXIT; //Exit low power mode
// _BIC_SR_IRQ(LPM1_bits);
//_bic_SR_register_on_exit(LPM1_bits);
break;
}
case 4: break;
case 10:break;
}
}
#pragma vector=TIMER1_A1_VECTOR //Timer1_A CC1 interrupt vector
__interrupt void Timer_A1(void)
{
// P1OUT|=BIT0; //For LED debugging
// LPM1_EXIT; // Exit low power mode Because CCI0A is used, the capture compare register used is TA1CCR0, which is allocated to a separate
//Interrupt vector TIMER1_A0_VECTOR, so after entering the interrupt, it is directly the interrupt generated by Timer1_A CC0, without going through similar
//The method commented out below is used for judgment.
//Timer1_A CC1-4, TA1 share an interrupt vector TIMER1_A1_VECTOR, so after entering the interrupt, you need to use the following
//Method to determine which interrupt source caused the interrupt
switch(TA1IV) //If it is an interrupt generated by Timer1_A CC1
{
case 2:
{
flag=2;
LPM1_EXIT; //Exit low power mode
// _BIC_SR_IRQ(LPM1_bits);
//_bic_SR_register_on_exit(LPM1_bits);
break;
}
case 4:break;
case 10:break;
}
}
//If you want to measure a lower frequency signal, you can determine the number of overflow interrupts in the interrupt, so that you can get the number of overflows and measure a higher frequency signal.
//Low frequency signal
5. Counting mode of Timer_A
The counting modes include: up counting mode, continuous counting mode and up/down counting mode. For detailed explanation of each mode, please refer to the user guide.
6. Timer interrupt
When using the timer's timing interrupt, pay attention to the selection of the timer counting mode. When using the interrupt, pay attention to the use of the interrupt vector and the judgment of the interrupt source. Here is an example with detailed comments:
#include
unsigned int t=0;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
CCTL0 = CCIE; // CCTLx is the capture/compare control register interrupt enabled CCIE=0x0010 enables timer A interrupt
CCR0 = 50000; //Capture/compare register Set the initial value of counter CCR0 16-bit register, the maximum value is 65535
//The default SMCLK uses DCO, the default DCO is about 800KHz, and CCR0=50000, so the frequency of interrupt generation is about 16Hz
TACTL = TASSEL_2 + MC_2; // SMCLK, contmode continuous counting mode from 0 to 0FFFFh
//TACTL = TASSEL_2 + MC_1; // SMCLK, upmode count up mode from 0 to CCR0
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt Enter low power mode 0, enable interrupts
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void) //After the CCIFG interrupt is responded, this flag is automatically cleared
{
//P1OUT ^= 0x01; // Toggle P1.0
t++;
if(t==5)
{
P1OUT ^= BIT0; // Toggle P1.0
t=0;
}
CCR0 += 50000; // Add Offset to CCR0
//The timer always counts up from 0 until it is full and then starts again from 0. In continuous counting mode, when the timer value is equal to CCR0, an interrupt is generated.
//Increase CCR0 by 50000 in the interrupt, so that the interval from the current value to the next moment when the timer is equal to CCR0 again is 50000, constant
//This way the time intervals between interrupts are equal
//So in the continuous counting mode, if you want to make the interrupt time interval constant, you need to have CCR0 += n;
//CCR0 does not need to be reassigned during interruption, which is different from 51
}
Note on the use of interrupts: Let's take an example:
#include
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
TACTL = TASSEL_2 + MC_2 + TAIE; // SMCLK, contmode, interrupt TAIE enables timer overflow interrupt
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt GIE enables interrupt
}
// Timer_A3 Interrupt Vector (TA0IV) handler
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
switch(TA0IV) //TAIV interrupt vector register used for
{
case 2: break; // CCR1 not used Capture/Comparator 1
case 4: break; // CCR2 not used Capture/Comparator 2
case 10: P1OUT ^= 0x01; // overflow timer overflow
break;
}
}
7. Note: The clock of timer Timer0_A can be selected as external clock input TACLK (P10), so when an external signal is connected, timer Timer0_A is equivalent to a counter. In this way, you can use Timer0_A to connect to external signals, and Timer1_A to connect to standard clocks such as 32768Hz crystal oscillators, and you can achieve equal precision frequency measurement. In fact, the clock of Timer1_A can also be external, but there is no external pin (P37) in g2553, so you can only choose the normal clock.
The setting of the external clock input TACLK (P10) of Timer0_A is as follows: The following is the initialization procedure of the two timers when I implement equal-precision frequency measurement:
void timer0_init()
{
TACTL |= TASSEL_0+MC_2+TACLR; //Select TACLK clock as the counting clock source, no frequency division, must be continuous counting mode
P1SEL |= BIT0; //P10 is the clock TACLK input of Timer0_A, which is connected to the external signal to be tested, so that Timer0_A can be used as a counter
}
//Timer1_A uses ACLK as the clock source for counting, so ACLK is equivalent to a standard signal, so both timers are equivalent to working in counter mode.
//ACLK 32768Hz is used as the standard signal, so that the frequency measurement with equal accuracy can be achieved
void timer1_init()
{
TA1CCTL0 = CCIE;
TA1CCR0 = 32768; //1s timing
TA1CTL |= TASSEL_1+MC_2+TACLR; //Select ACLK clock as the counting clock source, no frequency division, must be continuous counting mode
}
8. DAC can be realized using timers and comparators
Serial communication can also be achieved using a timer
Previous article:msp430 working notes 2
Next article:Wind-solar inverter grid-connected system based on MCU-FPGA architecture
Recommended ReadingLatest update time:2024-11-15 15:22
- Learn ARM development(14)
- Learn ARM development(15)
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- I drew a draft of the micro-bit
- Lead Angle/Conduction Angle of Brushless DC Motor
- [Bluesun AB32VG1 RISC-V board "meets" RTT] + unpacking and environmental installation
- Analog electronics elective test + DC and AC parameters
- The ADC example of the underlying driver code of esp32 is added to my own project and compiled unsuccessfully
- [Evaluation of EVAL-M3-TS6-665PN development board] Hardware introduction and features
- Read the good book "Electronic Engineer Self-study Handbook" - First Look
- Can anyone confirm what device this is? Thanks!
- Renesas RL78 D1A has an error when assigning an unsigned short type variable to a floating point number
- Source code of FFT transform IP core.zip