中断优先级
- MSP430共有69个中断向量,可以分为不同优先级:
- 最高优先级:RESET (复位)
- 次高优先级:NMI (非屏蔽中断)
- 高优先级组(可配置优先级):
1) PMM 电源管理模块
2) PORT1 端口中断
3) PORT2 端口中断
4) ADC10 ADC转换完成中断
5) USCI A0/B0 UART/SPI中断
6) TIMER0_A0/A1/B0 定时器中断
7) TIMER1_A0/A1/B0 定时器中断
8) FLASH 控制器中断 - 中优先级组(可配置优先级):
1) COMPARATOR_A 比较器中断
2) TIMER0_B1 定时器中断
3) TIMER1_B1 定时器中断
4) USCI A1/B1 UART/SPI中断
5) USCI A2/B2 UART/SPI中断
6) I2C I2C中断 - 低优先级组:
1) DMA 数据传输控制器中断
2) AES 加密模块中断
3) RTC 实时时钟中断
4) LCD 驱动器中断
5) MPY乘法器中断
6) BSL 启动加载程序中断
- 可通过编辑器的都中断管理器配置优先级,也可以通过代码设置每个中断的组优先级。
外部中断
void main()
{
GPIO_setAsInputPin (GPIO_PORT_P1, GPIO_PIN1);//设置为输入模式
GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P1, GPIO_PIN1);//设置为输入上拉电阻
GPIO_enableInterrupt (GPIO_PORT_P1, GPIO_PIN1);//启用引脚上的中断
GPIO_selectInterruptEdge(GPIO_PORT_P1,GPIO_PIN1,GPIO_LOW_TO_HIGH_TRANSITION);//设置中断触发方式
GPIO_clearInterrupt (GPIO_PORT_P1, GPIO_PIN1);//清除中断标志
__enable_interrupt();//打开总中断
//For debugger
__no_operation();
}
//中断处理函数
#pragma vector=PORT1_VECTOR// P1口中断源
__interrupt void Port_1(void)//声明一个中断服务程序,名为Port_1()
{
GPIO_toggleOutputOnPin (GPIO_PORT_P4, GPIO_PIN7);
GPIO_clearInterrupt (GPIO_PORT_P1, GPIO_PIN1);
}
timer
差异
msp430单片机有4个定时器,它们之间有以下区别:
- 定时器模块基地址不同:
- Timer_A0 - 0x0340
- Timer_A1 - 0x0380
- Timer_A2 - 0x0400
- Timer_A3 - 0x0440
- 中断向量不同:
- Timer_A0 - TIMER0_A0_VECTOR, TIMER0_A1_VECTOR
- Timer_A1 - TIMER1_A0_VECTOR, TIMER1_A1_VECTOR
- Timer_A2 - TIMER2_A0_VECTOR, TIMER2_A1_VECTOR
- Timer_A3 - TIMER3_A0_VECTOR, TIMER3_A1_VECTOR
- 捕获/比较寄存器CCRx不同:
- Timer_A0 - CCR0, CCR1, CCR2
- Timer_A1 - CCR0, CCR1, CCR2
- Timer_A2 - CCR0, CCR1, CCR2
- Timer_A3 - CCR0, CCR1, CCR2
- 输入/输出管脚映射不同:
每个Timer_Ax有自己唯一的I/O口映射关系。 - 是否支持双模模式:
- Timer_A0和Timer_A1支持双模块模式
- Timer_A2和Timer_A3只支持单模块模式
- 是否支持分割模式:
- Timer_A1和Timer_A3支持分割模式
- Timer_A0和Timer_A2不支持分割模式
产生PWM
#define TIMER_PERIOD 511//预装载值
#define DUTY_CYCLE 350//占空比
void main (void)
{
//Stop WDT
WDT_A_hold(WDT_A_BASE);
//定时器TA0.1
Timer_A_outputPWMParam htim = {0};
//P1.2复用输出
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2);
//时钟源选为SMCLK = 25MHz
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
//分频系数设为40
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_5;
//装载值设为12500 - 1
htim.timerPeriod = TIMER_PERIOD - 1;
//P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1
htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;
htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;
//初始比较值为装载值的一半 即初始占空比为50%
htim.dutyCycle = pwm_zkb;
//P1.2 对应 TA0.1 为TIMER_A0_BASE
Timer_A_outputPWM(TIMER_A0_BASE, &htim);
//定时器TA0.2
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN3);
htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;
htim.dutyCycle = 250;
Timer_A_outputPWM(TIMER_A0_BASE, &htim);
//定时器TA2.1
GPIO_stAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4);
//时钟源选为SMCLK = 25MHz
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
//分频系数设为40
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_5;
//装载值设为12500 - 1
htim.timerPeriod = TIMER_PERIOD - 1;
//P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1
htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;
htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;
//初始比较值为装载值的一半 即初始占空比为50%
htim.dutyCycle = 200;
//P1.2 对应 TA0.1 为TIMER_A0_BASE
Timer_A_outputPWM(TIMER_A2_BASE, &htim);
__enable_interrupt();//打开总中断
//For debugger
__no_operation();
}
修改占空比
Timer_A_setCompareValue (TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1, pwm_zkb);//设置占空比,1.定时器基地址2.比较寄存器3.比较值
定时器中断
简介
16位定时器Timer_A具有两个中断向量,分别如下:
- TAxCCR0的中断向量CCIFG0;
- TAxCCR0中断标志位CCIFG0在Timer_A中断中具有最高的中断优先级。当相应的TAxCCR0中断请求被响应后,TAxCCR0中断标志位CCIFG0自动复位
- 具有其余TAxCCRn的中断标志CCIFGn及TAIFG的中断向量TAIV
- TAxIV中断主要包括TAxCCRn的中断标志CCIFGn和TAIFG中断标志。中断向量寄存器可被用来判断当前被挂起的Timer_A中断,之后通过查中断向量表得到中断服务程序的入口地址,并将其添加到程序计数器中,程序将自动转入中断服务程序。禁用Timer_A中断功能并不影响TAxIV中断向量寄存器的值。
- 对TAxIV中断向量寄存器的读或写,都将自动清除挂起的最高优先级中断标志位。如果同时也置位了其他中断标志位,在当前中断服务程序执行完毕后,将自动立即响应新的中断请求。
CCR0中断
void Timer_A0_Init(void)
{
//timer0 CCR0中断延时10ms,
Timer_A_initUpModeParam htim = {0};
htim.clockSource = TIMER_A_CLOCKSOURCE_ACLK; //时钟源选为ACLK = 32768Hz
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_5; //5分频
htim.timerPeriod = 66- 1; //计数值设为512 - 1
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;// 禁止了定时器溢出中断(TAIE),只启用了CCR0的中断
htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE; //使能CCR0中断
htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
htim.startTimer = true; //初始化后立即启动定时器
Timer_A_initUpMode(TIMER_A0_BASE, &htim);
//配置定时器A0为增计数模式
}
//中断服务函数
#pragma vector=TIMER0_A0_VECTOR
__interrupt
void TIMER0_A0_ISR (void)
{
GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN7); //翻转P4.7
}
TAIE中断
void Timer_A_Init(void)
{
//5ms延时
Timer_A_initUpModeParam htim = {0};
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 25MHz
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_5; //5分频
htim.timerPeriod = 25000 - 1; //计数值设为25000 - 1
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TALE中断
htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
htim.startTimer = true; //初始化后立即启动定时器
Timer_A_initUpMode(TIMER_A0_BASE, &htim);
//配置定时器A为增计数模式
}
//中断服务函数
#pragma vector=TIMER0_A1_VECTOR
__interrupt
void TIMER0_A1_ISR (void)
{
switch(TA0IV)
{
case TA0IV_NONE:
break;
case TA0IV_TACCR1:
break;
case TA0IV_TACCR2:
break;
case TA0IV_TACCR3:
break;
case TA0IV_TACCR4:
break;
case TA0IV_5:
break;
case TA0IV_6:
break;
case TA0IV_TAIFG:
GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN2);
break;
default:
break;
}
}
测量脉宽长度
void Ch_Sr04_Init()
{
Timer_A_initContinuousModeParam htim = {0};//把定时器TIMER_A2配置为连续模式运行。这是为了提供时钟和计数基础。
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;//选择定时器时钟源为SMCLK,系统主时钟
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;//时钟不分频,用于提供高精度计数时钟
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;//使能定时器溢出中断TAIE
htim.timerClear = TIMER_A_DO_CLEAR;//初始化时清空定时器计数器。
htim.startTimer = true;//配置完成后启动定时器。
Timer_A_initContinuousMode(TIMER_A2_BASE, &htim);//调用初始化函数配置定时器CONT模式
//TA2.2对应TIMER_A2_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_2
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5);//设置P2.5作为定时器辅助功能输入引脚
Timer_A_initCaptureModeParam capture_htim = {0};
capture_htim.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;//选择使用捕捉/比较寄存器2,即CCR2进行输入捕捉
capture_htim.captureMode = TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE;//配置为上升沿和下降沿都可以触发捕捉
capture_htim.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA;//选择CCIxA作为输入捕捉的信号源,在本例中CCIxA映射到P2.5
capture_htim.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS;//配置为同步捕捉模式
capture_htim.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;//使能CCR2中断
capture_htim.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;//输出模式配置为输出PWM波形
Timer_A_initCaptureMode(TIMER_A2_BASE,&capture_htim);//调用函数初始化捕捉模式
}
//计数一次1us
#pragma vector=TIMER2_A1_VECTOR
__interrupt
void TIMER2_A1_ISR (void)
{
static uint16_t Overflow_Times = 0;
static uint16_t Sign_Begin = 0, Sign_End = 0;
switch(TA2IV)
{
case TA2IV_TACCR2://CCR2捕捉中断
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5))//如果是上升沿,记录当前计数值到Sign_Begin
{
Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
}
else//如果是下降沿,记录到Sign_End
{
Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);
if(!Overflow_Times)
Sign_Counts = Sign_End - Sign_Begin;
else
{
Sign_Counts = (uint32_t)65536 * Overflow_Times + Sign_End - Sign_Begin;//计算脉冲宽度计数Sign_Counts
Overflow_Times = 0;
}
}
Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);// 清除CCR2中断标志
break;
case TA2IV_TAIFG:// case TA2IV_TAIFG: 溢出中断
if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5))// 根据当前电平判断是否发生溢出
{
++Overflow_Times;// 更新溢出次数变量Overflow_Times
}
else
Overflow_Times = 0;
Timer_A_clearTimerInterrupt(TIMER_A2_BASE);//清除溢出中断标志
break;
default:
break;
}
}
ADC
msp4305529内置12位ADC
单通道中断转换
void adc_init()
{
//将P6.0引脚设置为ADC外设输入引脚
GPIO_setAsPeripheralModuleFunctionInputPin(
GPIO_PORT_P6,
GPIO_PIN0
);
/*
初始化ADC12_A,设置采样保持信号源为SC时钟,时钟源为内部ADC12OSC,时钟预分频为1
*/
ADC12_A_init(ADC12_A_BASE,
ADC12_A_SAMPLEHOLDSOURCE_SC,
ADC12_A_CLOCKSOURCE_ADC12OSC,
ADC12_A_CLOCKDIVIDER_1);
ADC12_A_enable(ADC12_A_BASE);//使能ADC12_A模块
/*
配置采样定时器,缓冲区0-7的采样保持时间为64个时钟周期,缓冲区8-15默认为4个时钟周期,关闭多次采样模式
*/
ADC12_A_setupSamplingTimer(ADC12_A_BASE,
ADC12_A_CYCLEHOLD_64_CYCLES,
ADC12_A_CYCLEHOLD_4_CYCLES,
ADC12_A_MULTIPLESAMPLESDISABLE);
//Configure Memory Buffer
/*
* Base address of the ADC12_A Module
* Configure memory buffer 0
* Map input A0 to memory buffer 0
* Vref+ = AVcc
* Vr- = AVss
* Memory buffer 0 is not the end of a sequence
*/
ADC12_A_configureMemoryParam param = {0};
param.memoryBufferControlIndex = ADC12_A_MEMORY_0;//配置内存缓冲区0
param.inputSourceSelect = ADC12_A_INPUT_A0;//映射到输入通道A0
param.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
param.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;//设置正负参考电压源为AVCC和AVSS
param.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;//设置内存缓冲区0不是序列结束,连续转换不用
ADC12_A_configureMemory(ADC12_A_BASE ,¶m);
//使能内存缓冲区0的中断ADC12IE0
ADC12_A_clearInterrupt(ADC12_A_BASE,
ADC12IFG0);
ADC12_A_enableInterrupt(ADC12_A_BASE,
ADC12IE0);
}
uint16_t result0;
int main(void) {
WDT_A_hold(WDT_A_BASE);
SystemClock_Init();
UART_Init(USCI_A1_BASE, 115200);
OLED_Init();
OLED_Clear();
adc_init();
_EINT();//打开总中断
while(1)
{
/*第一个参数ADC12_A_BASE:ADC模块的基地址。- 第二个参数ADC12_A_MEMORY_0:指定使用内存缓冲区0来保存转换结果。- 第三个参数ADC12_A_SINGLECHANNEL:指定单通道单次转换模式。1. 单次单通道转换:ADC12_A_SINGLECHANNEL
每次启动转换时只采集1个通道的样本,转换一次后就停止。
2. 重复单通道转换:ADC12_A_REPEATED_SINGLECHANNEL
连续重复转换单通道,直到被停止。
3. 单次多通道转换:ADC12_A_SINGLECHANNEL
每次启动转换时依次采集多个通道的样本,每通道转换一次后就停止。
4. 重复多通道转换:ADC12_A_REPEATED_SEQOFCHANNELS
连续重复扫描转换多个通道,像轮询一样循环转换。
5. 环形缓冲区转换:ADC12_A_AUTOSCAN
将多个通道采样数据依次存入同一个环形缓冲区中,缓冲区满后从头再存。
6. 随机通道转换:ADC12_A_RANDOM
*/
ADC12_A_startConversion(ADC12_A_BASE,
ADC12_A_MEMORY_0,
ADC12_A_SINGLECHANNEL);//启动ADC转换
}
}
#pragma vector=ADC12_VECTOR
__interrupt
void ADC12_A_ISR (void)
{
switch (__even_in_range(ADC12IV,34)){
case 0: break; //Vector 0: No interrupt
case 2: break; //Vector 2: ADC overflow
case 4: break; //Vector 4: ADC timing overflow
case 6: //Vector 6: ADC12IFG0
//Is Memory Buffer 0 = A0 > 0.5AVcc?
result0 = ADC12_A_getResults(ADC12_A_BASE,ADC12_A_MEMORY_0);
//Exit active CPU
//_DINT();
case 8: break; //Vector 8: ADC12IFG1
case 10: break; //Vector 10: ADC12IFG2
case 12: break; //Vector 12: ADC12IFG3
case 14: break; //Vector 14: ADC12IFG4
case 16: break; //Vector 16: ADC12IFG5
case 18: break; //Vector 18: ADC12IFG6
case 20: break; //Vector 20: ADC12IFG7
case 22: break; //Vector 22: ADC12IFG8
case 24: break; //Vector 24: ADC12IFG9
case 26: break; //Vector 26: ADC12IFG10
case 28: break; //Vector 28: ADC12IFG11
case 30: break; //Vector 30: ADC12IFG12
case 32: break; //Vector 32: ADC12IFG13
case 34: break; //Vector 34: ADC12IFG14
default: break;
}
}
多通道中断转换
void adc_init()
{
//将P6.0引脚设置为ADC外设输入引脚
GPIO_setAsPeripheralModuleFunctionInputPin(
GPIO_PORT_P6,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2
);
/*
初始化ADC12_A,设置采样保持信号源为SC时钟,时钟源为内部ADC12OSC,时钟预分频为1
*/
ADC12_A_init(ADC12_A_BASE,
ADC12_A_SAMPLEHOLDSOURCE_SC,
ADC12_A_CLOCKSOURCE_ADC12OSC,
ADC12_A_CLOCKDIVIDER_1);
ADC12_A_enable(ADC12_A_BASE);//使能ADC12_A模块
/*
配置采样定时器,缓冲区0-7的采样保持时间为64个时钟周期,缓冲区8-15默认为4个时钟周期,关闭多次采样模式
*/
ADC12_A_setupSamplingTimer(ADC12_A_BASE,
ADC12_A_CYCLEHOLD_64_CYCLES,
ADC12_A_CYCLEHOLD_4_CYCLES,
ADC12_A_MULTIPLESAMPLESDISABLE);
ADC12_A_configureMemoryParam param = {0};
param.memoryBufferControlIndex = ADC12_A_MEMORY_0;//配置内存缓冲区0
param.inputSourceSelect = ADC12_A_INPUT_A0;//映射到输入通道A0
param.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
param.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;//设置正负参考电压源为AVCC和AVSS
// param.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;//设置内存缓冲区0不是序列结束,连续转换不用
ADC12_A_configureMemory(ADC12_A_BASE ,¶m);
param.memoryBufferControlIndex = ADC12_A_MEMORY_1;//配置内存缓冲区1
param.inputSourceSelect = ADC12_A_INPUT_A1;//映射到输入通道A1
ADC12_A_configureMemory(ADC12_A_BASE ,¶m);
param.memoryBufferControlIndex = ADC12_A_MEMORY_2;//配置内存缓冲区2
param.inputSourceSelect = ADC12_A_INPUT_A2;//映射到输入通道A2
ADC12_A_configureMemory(ADC12_A_BASE ,¶m);
//使能内存缓冲区0,1,2的中断ADC12IE0,ADC12IE1,ADC12IE2
ADC12_A_clearInterrupt(ADC12_A_BASE, ADC12IFG0);
ADC12_A_clearInterrupt(ADC12_A_BASE, ADC12IFG1);
ADC12_A_clearInterrupt(ADC12_A_BASE, ADC12IFG2);
ADC12_A_enableInterrupt(ADC12_A_BASE, ADC12IE0);
ADC12_A_enableInterrupt(ADC12_A_BASE, ADC12IE1);
ADC12_A_enableInterrupt(ADC12_A_BASE, ADC12IE2);
}
#pragma vector=ADC12_VECTOR
__interrupt
void ADC12_A_ISR (void)
{
switch (__even_in_range(ADC12IV,34)){
case 0: break; //Vector 0: No interrupt
case 2: break; //Vector 2: ADC overflow
case 4: break; //Vector 4: ADC timing overflow
case 6: //Vector 6: ADC12IFG0
//Is Memory Buffer 0 = A0 > 0.5AVcc?
result0 = ADC12_A_getResults(ADC12_A_BASE,ADC12_A_MEMORY_0);
break;
case 8:
result1 = ADC12_A_getResults(ADC12_A_BASE,ADC12_A_MEMORY_1);
break; //Vector 8: ADC12IFG1
case 10:
result2 = ADC12_A_getResults(ADC12_A_BASE,ADC12_A_MEMORY_2);
break; //Vector 10: ADC12IFG2
case 12: break; //Vector 12: ADC12IFG3
case 14: break; //Vector 14: ADC12IFG4
case 16: break; //Vector 16: ADC12IFG5
case 18: break; //Vector 18: ADC12IFG6
case 20: break; //Vector 20: ADC12IFG7
case 22: break; //Vector 22: ADC12IFG8
case 24: break; //Vector 24: ADC12IFG9
case 26: break; //Vector 26: ADC12IFG10
case 28: break; //Vector 28: ADC12IFG11
case 30: break; //Vector 30: ADC12IFG12
case 32: break; //Vector 32: ADC12IFG13
case 34: break; //Vector 34: ADC12IFG14
default: break;
}
}
//启动转换,得加入延时,等待转换
delay_us(75);
ADC12_A_startConversion(ADC12_A_BASE,ADC12_A_MEMORY_0,ADC12_A_REPEATED_SEQOFCHANNELS);//启动ADC转换
delay_us(75);
ADC12_A_startConversion(ADC12_A_BASE,ADC12_A_MEMORY_1,ADC12_A_REPEATED_SEQOFCHANNELS);
delay_us(75);
ADC12_A_startConversion(ADC12_A_BASE,ADC12_A_MEMORY_2,ADC12_A_REPEATED_SEQOFCHANNELS);
Comments NOTHING