Switch 没有break和default位置乱放情况分析

package flowcontrol;

public class SwitchCase {
// first default
public static void testFirst(int i) {
switch (i) {
default:
System.out.println("default");// first default
case 1:
System.out.println("one");
case 2:
System.out.println("two");
case 3:
System.out.println("there");
}
}

// last default
public static void testLast(int i) {
switch (i) {
case 1:
System.out.println("one");
case 2:
System.out.println("two");
case 3:
System.out.println("there");
default:
System.out.println("default");// last default
}
}

// middle default
public static void testMiddle(int i) {
switch (i) {
case 1:
System.out.println("one");
case 2:
System.out.println("two");
default:
System.out.println("default");// middle default
case 3:
System.out.println("there");

}
}

public static void main(String[] args) {
// first default
testFirst(2);
System.out.println("------------------");
testFirst(9);

System.out.println("|||||||||||||||||||||||||||||||||||");

// last default
testLast(2);
System.out.println("----------------");
testLast(9);

System.out.println("|||||||||||||||||||||||||||||||||||");
// middle default
testMiddle(2);
System.out.println("----------------");
testMiddle(9);

}

}



输出结果是什么呢,看了结果,我是这么理解的:
(1)switch语句关键地方是进入点,有了进入点没有break的情况下会执行到底
(2)没有匹配值的时候default就是进入点,进入default以后会和普通进入点一样,如果没有break继续执行下面语句
two
there
------------------
default
one
two
there
|||||||||||||||||||||||||||||||||||
two
there
default
----------------
default
|||||||||||||||||||||||||||||||||||
two
default
there
----------------
default
there
#include <msp430f5438a.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #define CPU_F (1045000UL) #define Delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define uchar unsigned char unsigned char duty_cycle_value = 75; // 初始占空比值 char data[20] = {0}; char datapro[5]={0}; char hex[10]={0}; volatile uint8_t id_index = 0; // 数据索引 volatile uint8_t id_ready = 0; // 数据准备标志 volatile uint8_t jiebo = 0; //几阶波的标志 volatile uint8_t sanjie =0; volatile uint8_t jie =0; char e=0; int i=0; int m=0; int s=0; void XT2(); char five_code[32]={1,1,1,1,1,1,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0};//五阶码 char three_code[8]={1,1,1,0,1,0,0,0};//三阶码 char seven_code[128]={1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,1,1,1, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; char nine_code[512]={1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,0, 1,1,1,0, 1,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0 ,0,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,1,0, 1,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; int main (void) { WDTCTL = WDTPW | WDTHOLD; XT2(); P3SEL |= 0x30; // 设置P3.4/P3.5为UART模式 // 配置UART UCA0CTL1 |= UCSWRST; // 进入复位状态 UCA0CTL1 |= UCSSEL_1; // 使用ACLK (32768 Hz) UCA0BR0 = 0x03; // 波特率设置: 32768 / 9600 ≈ 3.41 UCA0BR1 = 0x00; UCA0MCTL = UCBRS_3; // 调制参数 UCA0CTL1 &= ~UCSWRST; // 退出复位状态 UCA0IE |= UCRXIE; // 使能接收中断 __bis_SR_register(GIE); while(1){ if(id_ready==1){ //数据提取并处理,ASCLL码转十进制数 int shu1 = data[10]-'0'; int shu2 = data[11]-'0'; int shu3 = data[12]-'0'; //端口配置 int v = shu1*100 + shu2*10 + shu3*1; //端口配置 P4DIR |= BIT1 ; P4DIR |=BIT2; P4OUT &=~ BIT1 ; P4OUT &=~BIT2; //运算求周期 int c= sizeof(three_code); int b=c*v*8; int a =1000000/b ; //TIMER_B配置 TB0CCR0 = a ; TB0CCTL0 = CCIE; TB0CTL = TBSSEL_2 | MC_3 | TBCLR ;//SMCLK;增减计数;清零; id_ready=0; //清除标志 //运行结束更新标志位 } /*if((e==1)&&){ if((three_code[i-1]!=three_code[i])&&(jie==1)) { P4OUT &=~BIT2; P4OUT &=~BIT1; __delay_cycles(10); m=0; } }*/ } } //目前适用于100-999频率,可改进(if语句判别数据长度) #pragma vector=USCI_A0_VECTOR __interrupt void USCI_A0_ISR(void) { switch (__even_in_range(UCA0IV, 4)) { case 0: break; // 无中断 case 2: // 接收中断 data[id_index++] = UCA0RXBUF; // 修正寄存器名 //判断数据帧尾 AA 55 E7 if((data[id_index-1]==0xE7)&&(data[id_index-2]==0x55)&&(data[id_index-3]==0xAA)){ if(data[2]==0x07){ //只接收数据data[2]=07的数据 if((data[6]==0x02)&&(data[4]==0x03)){ id_ready = 1;//标志更新 sanjie=1; } if((data[6]==0x0B)&&(data[4]==0x03)){//标志分辨是几阶波 //三阶波 if(data[10]==0x33){ jiebo = 1;//标志更新 jie=1; } //五阶波 if(data[10]==0x35){ jiebo = 2;//标志更新 jie=1; } } } else { id_ready=0; id_index=0; return;//退出中断 } break; } case 4: break; // 发送中断 default: break; } } //定时器B中断 高低电平转换 #pragma vector=TIMER0_B0_VECTOR __interrupt void TIMER0_B0_ISR(void) { // 根据数组设置输出 switch(m=0){ case 0: if(three_code[i]==1) { P4OUT |= BIT1; // 数组为1 高电平 P4OUT &=~ BIT2; } else { P4OUT &= ~BIT1; // 数组为0 低电平 P4OUT |= BIT2; } /* if(three_code[i]==0) { P4OUT |= BIT2; // 数组为0 高电平 } else { P4OUT &=~ BIT2; // 数组为1 低电平 } */ i++; if(three_code[i-1]!=three_code[i]) { m=1; } if(i==8){ i=0; } case 1: if(m==1){ // P4OUT &=~BIT2; Delay_us(10); m=0; } } } //XT2外部晶振配置 void XT2 () { uchar i ; P7SEL |= BIT0 + BIT1; //P7.0 P7.1 P5SEL |= BIT2+BIT3;//P5.2 P5.43 UCSCTL6 &=~ XT2OFF;//启用 UCSCTL6 |= XCAP_3;//12PF电容调用 do{ UCSCTL7 &=~ (XT2OFFG | XT1LFOFFG | XT1HFOFFG | DCOFFG);//标志位 SFRIFG1 &= ~OFIFG; for (i = 0xFF;i > 0; i--); }while(SFRIFG1 & OFIFG ); UCSCTL4 |= SELS__XT2CLK ;//XT2给smclk UCSCTL5 |= DIVS_3;//8分频 1MHz } P4OUT &=~BIT2;这一句注释了波形正确,不注释错误,这段是为了将波变为低电平持续时间取决于延时函数
最新发布
07-20
<think>首先,用户的问题是关于MSP430微控制器上的UART通信定时器中断代码的优化问题排查。具体是解决波形输出问题。用户提到了参考引用,所以我需要回顾这些引用来提供相关帮助。 回顾引用: - 引用[1]:关于UART通信的时钟误差容忍度。UART允许一定范围内的时钟误差:±2%正常,±3%~5%可能出现错误,±10%以上无法正常解析。 - 引用[2]:MSP430的代码示例,展示了定时器中断服务例程(ISR)来切换P1.0引脚状态,以及主函数中的定时器初始化。 - 引用[3]:MSP430故障排除技巧,包括中断问题(如堆栈溢出、中断嵌套、电源问题)、看门狗定时器导致复位等。 - 引用[4]:关于Cortex-M3的学习,但用户的问题是MSP430,所以这可能不太相关,但提到了一些通用概念如外设驱动、调试技巧。 用户的核心问题:理解优化MSP430上的UART通信定时器中断代码,解决波形输出问题。波形输出可能涉及通过UART发送数据或直接控制引脚输出波形。 结构化我的回答: 1. **理解问题**:解释波形输出可能涉及什么。例如,使用定时器中断生成PWM波形或类似,并通过UART通信。 2. **问题排查**:基于引用,提供常见问题的排查步骤。 3. **优化建议**:给出优化代码的建议。 4. **生成相关问题**:在最后添加相关问题,以引导进一步学习。 关键点从引用中提取: - 对于UART:确保时钟误差在可接受范围内(引用[1])。检查波特率设置是否准确。 - 对于定时器中断:引用[2]展示了基本代码。常见问题包括中断嵌套、堆栈溢出(引用[3])。 - 其他问题:电源稳定性、看门狗定时器(引用[3])。 用户提到“波形输出问题”,可能意味着: - 定时器中断用于生成波形(如PWM),但输出不稳定或错误。 - UART用于通信,但数据传输有问题,影响波形输出。 在回答中,我需要: - 使用中文。 - 行内数学表达式用$...$,但这可能不需要数学,除非涉及计算。 - 独立公式用$$...$$,但同样,可能不适用。 - LaTeX语法正确。 - 结构清晰,逐步解决问题。 - 在引用的段落末尾添加引用标识,如[^1]。 回答结构: 1. **介绍**:简要概述MSP430 UART定时器中断。 2. **问题排查步骤**: - 检查定时器中断代码。 - 检查UART配置。 - 常见硬件问题。 3. **优化建议**。 4. **代码示例**:提供优化后的代码片段。 5. **相关问题**。 从引用[2]的代码: ```c #include <msp430.h> #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A0_ISR(void) { P1OUT ^= BIT0; // 切换P1.0引脚状态 } void main(void) { WDTCTL = WDTPW | WDTHOLD; // 停止看门狗定时器 P1DIR |= BIT0; // 设置P1.0为输出 TA0CTL = TASSEL_2 | MC_1; // 选择SMCLK,定时器模式为增计数 TA0CCR0 = 1000; // 设置定时器周期 TA0CCTL0 = CCIE; // 使能捕获/比较中断 __enable_interrupt(); // 使能全局中断 while (1) {} } ``` 这个代码使用定时器中断来切换P1.0引脚,生成方波。波形输出问题可能包括频率不准确、中断延迟等。 UART部分:用户提到UART通信,但问题中没有具体UART代码。所以,我需假设UART用于相关通信。 优化排查: - **定时器问题**: - 确保中断服务例程(ISR)尽可能短(引用[3]提到中断耗时太长可能导致问题)。 - 检查定时器时钟源分频器设置。 - **UART问题**: - 确保波特率设置正确,时钟误差小(引用[1])。 - 使用正确的UART寄存器配置。 - **通用问题**: - 堆栈大小:增加堆栈以防溢出(引用[3])。 - 中断嵌套:管理中断优先级。 - 电源稳定性:确保Vcc > 1.8V(引用[3])。 - 看门狗:在初始化前关狗(引用[3])。 在回答中引用这些点。 最终回答: - 以清晰段落组织。 - 结束时添加相关问题。</think>### MSP430 UART通信与定时器中断波形输出问题排查与优化 在MSP430微控制器上,UART通信定时器中断常用于实现波形输出(如PWM方波、正弦波等)。波形输出问题可能源于硬件配置错误、中断冲突或软件优化不足。以下基于您的需求参考引用,我将逐步引导您排查问题并提供优化建议。整个过程分为问题排查优化两部分,确保代码可靠且高效。 #### 一、问题排查步骤 波形输出问题通常表现为输出不稳定、频率偏差或通信中断。以下是系统化的排查流程,结合引用中的关键点。 1. **检查定时器中断配置** 定时器中断是生成波形的核心。常见问题包括中断未触发、频率不准确或ISR(中断服务例程)执行时间过长。 - **中断未触发**:确认全局中断已使能(`__enable_interrupt()`),并检查中断向量寄存器设置(如`TA0CCTL0 = CCIE`)。参考引用[2]的代码示例,确保初始化顺序正确:先配置外设,再使能中断。 - **频率偏差**:计算定时器周期是否匹配预期频率。例如,若使用SMCLK(假设8MHz),周期`TA0CCR0 = 1000`对应约8kHz方波(公式:$f = \frac{f_{\text{SMCLK}}}{ \text{TA0CCR0} }$)。使用逻辑分析仪测量实际输出,偏差超过±2%可能导致问题(引用[1])。 - **ISR执行时间过长**:确保ISR代码简洁。避免在ISR内执行复杂操作(如浮点计算),否则可能导致中断嵌套或主程序卡死(引用[3])。示例ISR应仅切换引脚: ```c #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A0_ISR(void) { P1OUT ^= BIT0; // 只做最小操作 } ``` 2. **验证UART通信配置** UART用于数据传输或同步波形输出,时钟误差是常见故障点。 - **波特率误差**:根据引用[1],UART通信要求时钟偏差总≤±2%。计算波特率误差: $$ \text{误差} = \left| \frac{f_{\text{实际}} - f_{\text{理论}}}{f_{\text{理论}}} \right| \times 100\% $$ 例如,目标波特率9600,若使用DCO(内部时钟),需校准DCO频率(通过BCSCTL1寄存器)。误差超过±3%可能导致波形数据解析错误(引用[1])。 - **数据冲突**:如果UART定时器共享资源(如全局变量),未加锁可能导致波形乱序。使用原子操作或禁用中断保护关键代码。 3. **排查硬件系统级问题** - **堆栈溢出**:引用[3]指出,中断嵌套或ISR过深可能耗尽堆栈。在IDE(如CCS)中增大堆栈大小:`Project > Options > Linker > Stack/Heap`,将Stack size设为256+字节(默认可能不足)。 - **电源稳定性**:确保Vcc > 1.8V(引用[3])。电压低于0.8V会导致PC指针乱飞,表现为波形中断或定时器复位。使用示波器检查电源纹波。 - **看门狗复位**:初始化阶段若耗时过长,看门狗(WDT)可能触发复位,导致程序重启。在main函数开头停用WDT:`WDTCTL = WDTPW | WDTHOLD;`(引用[2])。若初始化时间长,参考引用[3]的解决方案:使用`__no_init`定义数组或在启动代码中提前关狗。 - **中断冲突**:多个中断(如UART RX定时器)优先级未管理时,可能引发嵌套。在MSP430中,默认无硬件优先级,需在ISR内禁用其他中断(`__disable_interrupt()`后再使能)。 #### 二、优化建议 优化目标:提高波形输出精度、降低功耗,并确保UART通信可靠。基于引用[2][3],结合最佳实践。 1. **定时器中断优化** - **缩短ISR**:将非关键操作移出ISR。例如,波形生成仅需切换引脚,数据处理放入主循环。 - **使用硬件PWM**:MSP430定时器支持硬件PWM模式(`MC_1 | TASSEL_2`结合OUTMOD设置),直接输出波形无需ISR,减少CPU开销。示例: ```c TA0CCTL0 = OUTMOD_4; // 切换模式输出PWM TA0CCR0 = 1000; // 周期 TA0CCR1 = 500; // 占空比50% ``` - **时钟校准**:使用外部晶振(如32kHz)替代DCO,提高定时精度。配置:`BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ;`。 2. **UART通信优化** - **误差补偿**:针对引用[1]的时钟误差,在软件中实现波特率自动调整(如计算校验重传)。 - **DMA传输**:使用MSP430的DMA模块搬运UART数据,减少中断频率。适用于高波特率(>115200)场景。 - **双缓冲机制**:为UART RX/TX设置双缓冲区,避免数据覆盖。示例伪代码: ```c volatile char uartBuffer[2][64]; volatile int activeBuffer = 0; #pragma vector=USCIAB0RX_VECTOR __interrupt void UART_RX_ISR(void) { uartBuffer[activeBuffer][index++] = UCA0RXBUF; if (index >= 64) activeBuffer ^= 1; // 切换缓冲区 } ``` 3. **系统级优化** - **低功耗设计**:在`while(1)`循环中添加`__low_power_mode_0();`,使CPU休眠,仅由中断唤醒(引用[2])。 - **调试辅助**:使用逻辑分析仪捕获引脚波形UART数据(引用[4])。在代码中添加调试引脚(如P1.1)在ISR入口/出口切换,测量中断延迟。 - **错误处理**:添加看门狗喂狗机制(`WDTCTL = WDTPW | WDTCNTCL;`)硬件复位检测(`if (SYSRSTIV == SYSRSTIV_DOBOR) {...}`)。 #### 三、整合代码示例 以下是优化后的UART通信定时器中断代码,用于生成1kHz方波(P1.0)并通过UART发送状态。基于引用[2]修改,包含错误处理。 ```c #include <msp430g2553.h> // 以MSP430G2系列为例 // UART发送字符串函数 void UART_send(char *str) { while (*str) { while (!(IFG2 & UCA0TXIFG)); // 等待发送缓冲区空 UCA0TXBUF = *str++; } } // 定时器中断服务例程 #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_A0_ISR(void) { P1OUT ^= BIT0; // 生成方波 } // UART接收中断服务例程 #pragma vector=USCIAB0RX_VECTOR __interrupt void UART_RX_ISR(void) { char data = UCA0RXBUF; // 简单回显(可选) UCA0TXBUF = data; } void main(void) { WDTCTL = WDTPW | WDTHOLD; // 停用看门狗 BCSCTL1 = CALBC1_1MHZ; // 校准DCO为1MHz DCOCTL = CALDCO_1MHZ; P1DIR |= BIT0; // P1.0输出波形 P1OUT &= ~BIT0; // 初始低电平 // 定时器初始化 TA0CCR0 = 500; // 1MHz/500 = 2kHz波形(占空比50%) TA0CTL = TASSEL_2 | MC_1; // SMCLK, 增计数模式 TA0CCTL0 = CCIE; // 使能中断 // UART初始化(波特率9600) UCA0CTL1 |= UCSWRST; // 进入复位状态 UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 104; // 1MHz/9600 ≈ 104 UCA0BR1 = 0; UCA0MCTL = UCBRS0; // 调制设置 UCA0CTL1 &= ~UCSWRST; // 退出复位状态 IE2 |= UCA0RXIE; // 使能UART接收中断 __enable_interrupt(); // 全局中断使能 UART_send("System Ready\r\n"); // 发送启动消息 while (1) { __low_power_mode_0(); // CPU休眠,节能 // 主循环处理数据(如波形参数更新) } } ``` #### 四、关键注意事项 - **测试工具**:使用Saleae逻辑分析仪验证波形频率UART数据时序(引用[4])。 - **误差容忍**:UART时钟误差控制在±2%内(引用[1]),定时器误差<1%可通过晶振实现。 - **常见陷阱**:避免在ISR内调用函数或使用浮点运算;初始化阶段关狗后,再执行耗时操作(引用[3])。 通过以上步骤,您可以解决大部分波形输出问题。如果问题持续,请提供具体现象(如频率值、错误代码)以便进一步分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值