c语言 - 难倒 - 代码编译,但在微控制器端没有任何反应。我怀疑 ISR 中的某些内容可能是罪魁祸首



我的任务是把我的老师用汇编语言编写的函数式程序转换为C语言。该程序是为 TI MSP430G2553编写的,并利用附加的 4 位 LED 显示屏和三个并排按钮。显示器应该从空白开始。按下右键时,"ECE-3362"将开始从右向左滚动显示屏。

据我所知,我的转换是"完成"的,并且代码编译没有错误。但是,按钮没有任何可见效果,显示屏保持空白。

我确实收到一些"整数转换导致截断"警告,但我不确定这对程序功能的影响。我最多认为,如果我的部分常量定义被截断,这会导致显示显示错误的值。

我的代码中特别可疑的一部分是我在最底部的port2中断服务例程(主要是PB和P2_IFG比较)。我没有完全理解我的导师对该部分的汇编版本中发生了什么,所以翻译中可能丢失了一些重要的东西。

我一般是组装的新手,就微控制器而言,我是C。我严重依赖我的教师示例代码作为参考。我会把我的代码放在下面,如果有人想看,我手头有我的教师代码。

我知道规则说不要发布整个文件,但据我所知,我可能会在程序中的任何地方出现错误或更多错误。

我的代码:

#include  <msp430g2553.h>
//-----------------------------------------------------------------------------
// Definition of Constants
//-----------------------------------------------------------------------------
#define TIMER_A0_COUNT_1 2000     //2000
#define TIMER_A1_COUNT_1 50000   //50000
#define MAX_TIMER_COUNT 10       //10
#define LONG_DELAY (0xFFFF)          //65535
//definitions of segment positions 
#define SEG_A  (0x01u)   // 00000001  Port pin position P1.0
#define SEG_B  (0x02u)   // 00000010  Port pin position P1.1
#define SEG_C  (0x04u)   // 00000100  Port pin position P1.2
#define SEG_D  (0x08u)   // 00001000  Port pin position P1.3
#define SEG_E  (0x10u)   // 00010000  Port pin position P1.4
#define SEG_F  (0x20u)   // 00100000  Port pin position P1.5
#define SEG_G  (0x40u)   // 01000000  Port pin position P1.6
#define SEG_DP (0x80u)   // 10000000  Port pin position P1.7
//since inverted pattern is needed for the display, this defines inverse pattern
#define SEG_A_N           ~SEG_A  // Port pin position P1.0
#define SEG_B_N           ~SEG_B  // Port pin position P1.1
#define SEG_C_N           ~SEG_C  // Port pin position P1.2
#define SEG_D_N           ~SEG_D  // Port pin position P1.3
#define SEG_E_N           ~SEG_E  // Port pin position P1.4
#define SEG_F_N           ~SEG_F  // Port pin position P1.5
#define SEG_G_N           ~SEG_G  // Port pin position P1.6
#define SEG_DP_N          ~SEG_DP // Port pin position P1.7
//NOTE: display board requires INVERSE of these patterns due to Active LOW
#define DIG_3  (0x01u)    //   00000001  Port pin position P2.0 (MSdigit)
#define DIG_2  (0x02u)    //   00000010  Port pin position P2.1
#define DIG_1  (0x04u)    //   00000100  Port pin position P2.2
#define DIG_0  (0x08u)    //   00001000  Port pin position P2.3(LSdigit)
#define DP_COM (0x10u)    //   00010000  Port pin position P2.4
//since inverted pattern is needed for the display, this defines inverse pattern
#define DIG_3_N      ~DIG_3  // Port pin position P2.0 (MSdigit)
#define DIG_2_N      ~DIG_2  // Port pin position P2.1
#define DIG_1_N      ~DIG_1  // Port pin position P2.2
#define DIG_0_N      ~DIG_0  // Port pin position P2.3(LSdigit)
#define DP_COM_N     ~DP_COM // Port pin position P2.4

//Pushbutton assignments CORRECTED to compensate for board layout swap
#define PB_0  (0x20u)     //  00100000  Port pin position P2.5  RightMost button
#define PB_1  (0x80u)     //  10000000  Port pin position P2.7  Middle button
#define PB_2  (0x40u)     //  01000000  Port pin position P2.6  LeftMost button
#define SEG_PORT  P1OUT
#define DIG_PORT  P2OUT
#define PB_PORT   P2IN
//NOTE: display bd requires the INVERSE of these patterns due to Active LOW
#define ONE                (0x06u) // 00000110
#define TWO                (0x5Bu) // 01011011
#define THREE              (0x4Fu) // 01001111
#define FOUR               (0x66u) // 01100110
#define FIVE               (0x6Du) // 01101101
#define SIX                (0x7Du) // 01111101
#define SEVEN              (0x03u) // 00000111
#define EIGHT              (0x7Fu) // 01111111
#define NINE               (0x67u) // 01100111
#define ZERO               (0x3Fu) // 00111111
//since inverted pattern is needed for the display, this defines inverse pattern
#define ONE_N        (~0x06u)       // ~00000110
#define TWO_N        (~0x5Bu)       // ~01011011
#define THREE_N      (~0x4Fu)       // ~01001111
#define FOUR_N       (~0x66u)       // ~01100110
#define FIVE_N       (~0x6Du)       // ~01101101
#define SIX_N        (~0x7Du)       // ~01111101
#define SEVEN_N      (~0x03u)       // ~00000111
#define EIGHT_N      (~0x7Fu)       // ~01111111
#define NINE_N       (~0x67u)       // ~01100111
#define ZERO_N       (~0x3Fu)       // ~00111111
//other figures for scrolling display
#define E_N          (~0x79u)    //  ~01111001
#define C_N          (~0x39u)    //  ~00111001
#define DASH_N       (~0x40u)    //  ~01000000
#define BLANK_N      (~0x00u)    //  ~00000000

//------------------------------------------------------------------------------
// Definition of Variables
//------------------------------------------------------------------------------
int DisplayValue  =  0;         // contains 4 digit value to display in BCD format
// BCDdig3 | BCDdig2  | BCDdig1  | BCDdig0
// xxxx      xxxx       xxxx       xxxx
char CurrentDigitPos  =  0;     // global variable used by WriteDigitToDisplay ISR
// holds digit position of current digit to write
char CurrentDigitValue = 0;     // global variable used by WriteDigitToDisplay ISR
// holds digit value of next digit to write    
char StartFlag     =   0;       // Boolean state flags
char PauseFlag     =   0;
char ContinueFlag  =   0;
char ScrollingStateFlag  =  0;
char PB_0_Mode       =   0;
char PB_1_Mode       =   0;
char PB_2_Mode       =   0;
char Hundred_mS      =   0;
char TotalINTCount1  =   0;
int PatternsToScroll[12] = {0x0000, 0x0006, 0x0065, 0x0656, 0x6561, 0x5613, 
0x6133, 0x1334, 0x3342, 0x3420, 0x4200, 0x2000};
char PatternsIndex = 0;
int CurrentPattern = 0;
char PatternsLeft = 12;
char SegPatterns[7] = {BLANK_N, DASH_N, TWO_N, THREE_N, SIX_N, C_N, E_N};
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
void WriteNextDigitToDisplay(int DisplayValue, char CurrentDigitPos, char CurrentDigitValue)
{
int DisplayValueCopy = 0; // initialize function variable
DIG_PORT |= DIG_0+DIG_1+DIG_2+DIG_3+DP_COM; // eliminate ghosting
if ((CurrentDigitPos - 0) == 0)
{
DisplayValueCopy = DisplayValue;
DisplayValueCopy &= 0x000F;
SEG_PORT = SegPatterns[DisplayValueCopy];
DIG_PORT = DIG_0_N;
CurrentDigitPos++;
}
if ((CurrentDigitPos - 1) == 0)
{
DisplayValueCopy = DisplayValue;
DisplayValueCopy &= 0x00F0;
DisplayValueCopy >>=4;               //rra 4 times to get val into LSnibble
SEG_PORT = SegPatterns[DisplayValueCopy];
DIG_PORT = DIG_1_N;
CurrentDigitPos++;
}
if ((CurrentDigitPos - 2) == 0)
{
DisplayValueCopy = DisplayValue;
DisplayValueCopy &= 0x0F00;
DisplayValueCopy = __swap_bytes(DisplayValueCopy);
SEG_PORT = SegPatterns[DisplayValueCopy];
DIG_PORT = DIG_2_N;
CurrentDigitPos++;
}
if ((CurrentDigitPos - 3) == 0)
{
DisplayValueCopy = DisplayValue;
DisplayValueCopy &= 0xF000;
DisplayValueCopy = __swap_bytes(DisplayValueCopy);
DisplayValueCopy >>=4;
SEG_PORT = SegPatterns[DisplayValueCopy];
DIG_PORT = DIG_3_N;
CurrentDigitPos++;
}
if ((CurrentDigitPos - 4) == 0)
{
CurrentDigitPos = 0;
}
}
void delay()
{
for (int i = 0; i < LONG_DELAY; i++);
}
int main( void )
{
//---------------------------------------------------------------------------
// Setup
//---------------------------------------------------------------------------
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
// Setup Port 1 (all outputs for segment display)
P1DIR = SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G + SEG_DP;
// Setup Port 2 
P2DIR = 0x1F; // (00011111 : 3MSbits as inputs (pushbuttons) 5LSbits as outputs)
P2OUT = PB_0 + PB_1 + PB_2;  // 11100000 or 0xE0 defines pushbutton positions
P2REN |= PB_0 + PB_1 + PB_2; // turn on internal pull-up for the pushbuttons
// Activate the General Purpose Digital I/O mode for P2.6 and P2.7
P2SEL &= ~PB_1 + ~PB_2;     
// Setup Port 2 interrupts for the pushbuttons
P2IE |= PB_0 + PB_1 + PB_2;
P2IES |= PB_0 + PB_1 + PB_2;
// Turn off all the segments and digits
SEG_PORT = 0xFF;
DIG_PORT = 0xFF;
// SetupCalibratedClock       
// Set up the clock (calibrated mode at 1 MHz)
// Get the calibrated data for the DCO clock
// Set DCO to 1 MHz:  (this directly from TI Family Guide page283 and 284
DCOCTL = 0;                // Select lowest DCOx  and MODx settings
BCSCTL1 = CALBC1_1MHZ;     // Set range
DCOCTL = CALDCO_1MHZ;      // Set DCO step + modulation     
// Set up Timers
// TimerA0
TA0CCR0 = TIMER_A0_COUNT_1;              // load a count "up to"value into timer
TA0CTL = TASSEL_2+ID_3 + MC_1;        // SMCLK, input div = 8, upmode
TA0CCTL0 = CCIE;                        //  interrupt enabled for Timer0
// TimerA1
TA1CCR0 = TIMER_A1_COUNT_1;              // load a count "up to"value into timer
TA1CTL = TASSEL_2+ID_3 + MC_1;        // SMCLK, input div = 8, upmode
TA1CCTL0 = CCIE;                        //  interrupt enabled for Timer1 
// Start of main program   
// Initialize Boolean state flags and some other variables
StartFlag = 0;
PauseFlag = 0;
ContinueFlag = 0;
ScrollingStateFlag  = 0;
PB_0_Mode = 0;      
PB_1_Mode = 0; 
PB_2_Mode = 0;   
DisplayValue = 0;  

// Clear Interrupt Flags
P1IFG = 0;    // clear the Int flag register for Port 1 
P2IFG = 0;    // clear the Int flag register for Port 2 
// Enable General Interrupts
_BIS_SR(GIE);         // enable the general interrupts bit   
//----------------------------------------------------------------------------
// Top of main program loop structure
//----------------------------------------------------------------------------  
while(1)  // forever loop
{
// test the Pushbutton mode Boolean variables to see what to do 
if ((PB_0_Mode - 1) == 0) // (START CONDITION)
{
// Rightmost button (START)
PB_0_Mode = 0;
ScrollingStateFlag = 1; // make it TRUE
PatternsIndex = 0; // beginning of pattern array
PatternsLeft = 12;
CurrentPattern = PatternsToScroll[PatternsIndex]; // might be redundant
}
if ((PB_1_Mode - 1) == 0) // (CONTINUE CONDITION)
{
// Middle button (CONTINUE)
PB_1_Mode = 0;
ScrollingStateFlag = 1; // make it TRUE
}
if ((PB_2_Mode - 1) == 0) // (PAUSE CONDITION)
{
// Leftmost button (PAUSE)
PB_2_Mode = 0;
ScrollingStateFlag = 0; // make it FALSE
}
else
{
if ((ScrollingStateFlag - 1) == 0)
{
CurrentPattern = PatternsToScroll[PatternsIndex];
DisplayValue = CurrentPattern; // save pattern array element
PatternsIndex++;               // move to next element
PatternsLeft--;                // one less pattern to display
if ((PatternsLeft - 0) == 0)   // done all the patterns --> reset variables
{
PatternsIndex = 0;
CurrentPattern = PatternsToScroll[PatternsIndex]; // might be redundant
PatternsLeft = 12;
}
delay();   // update the scrolling slowly
delay();        
}
}
}


return 0;
} // end of MAIN
//------------------------------------------------------------------------------
//           Subroutines
//------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// WriteNextDigitToDisplay
//  passed in - DisplayValue, CurrentDigitPos 
//  returned - nothing
//  accomplishes - Writes next digit to the expansion bd display
//  uses: R15, global variable CurrentDigitPos, CurrentDigitValue
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
//          Interrupt Service Routines
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// Interrupt Service Routine for Timer_A 1
//  Passed in: nothing
//  Activated every time TimerA_1 times out
//  Updates global variable TotalINTCount1 to keep track of number of TimerA_1 
//   interrupt events
//  Uses: nothing except modifies global variable TotalINTCount
//  For this example, set up to trigger every 100 mS
//-------------------------------------------------------------------------------
//Timer0_A0 ISR
#pragma vector=TIMER0_A0_VECTOR   // this line tells the C compiler to put
// the start address of the following ISR
// into the Interupt Vector table
__interrupt void Timer_A0_ISR (void)   // required syntax for first line of ISR
{
WriteNextDigitToDisplay(DisplayValue, CurrentDigitPos, CurrentDigitValue);
}
//Timer0_A1 ISR
#pragma vector=TIMER1_A1_VECTOR   // this line tells the C compiler to put
// the start address of the following ISR
// into the Interupt Vector table
__interrupt void Timer_A1_ISR (void)   // required syntax for first line of ISR
{
Hundred_mS++;
TotalINTCount1++;
}
// Port2_ISR
//  passed in - nothing
//  returned - nothing
//  accomplishes - updates global Boolean variables for Pushbutton status
//  uses: nothing
//-------------------------------------------------------------------------------
//Port2_ISR
// if we get to here, an interrupt occurred on the Port 2
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
if ((PB_0 & P2IFG) == 1)
{
PB_0_Mode |= 1;
PB_1_Mode &= ~1;
PB_2_Mode &= ~1;
}
if ((PB_1 & P2IFG) == 1)
{
PB_0_Mode &= ~1;
PB_1_Mode |= 1;
PB_2_Mode &= ~1;
}
if ((PB_2 & P2IFG) == 1)
{
PB_0_Mode &= ~1;
PB_1_Mode &= ~1;
PB_2_Mode |= 1;
}
P2IFG = 0;
}

由于字符限制,无法发布教师的完整代码。这是他的端口 2 ISR:

; Port2_ISR
;  passed in - nothing
;  returned - nothing
;  accomplishes - updates global Boolean variables for Pushbutton status
;  uses: nothing
;-------------------------------------------------------------------------------
Port2_ISR
; if we get to here, an interrupt occurred on the Port 2
bit.b  #PB_0, &P2IFG   ; PB_0 Pushbutton?  (if 1 it is pressed)
jnz  PB_0_Case        ; it is PB_0
;no so try the next case
bit.b  #PB_1, &P2IFG   ; PB_1 Pushbutton?  (if 1 it is pressed)
jnz  PB_1_Case        ; it is PB_1
;no so try the next case
bit.b  #PB_2, &P2IFG   ; PB_2 Pushbutton?  (if 1 it is pressed)
jnz  PB_2_Case        ; it is PB_2
jmp  DoneWithPort_2_ISR       ; no, so don't do anything
PB_0_Case
bis.b  #1,  &PB_0_Mode 
bic.b  #1,  &PB_1_Mode   ;clear other modes
bic.b  #1,  &PB_2_Mode        
jmp DoneWithPort_2_ISR
PB_1_Case
bis.b  #1,  &PB_1_Mode
bic.b  #1,  &PB_0_Mode   ;clear other modes
bic.b  #1,  &PB_2_Mode        
jmp DoneWithPort_2_ISR    
PB_2_Case
bis.b  #1,  &PB_2_Mode
bic.b  #1,  &PB_1_Mode   ;clear other modes
bic.b  #1,  &PB_0_Mode        
jmp DoneWithPort_2_ISR    
DoneWithPort_2_ISR   
clr.b &P2IFG    ; clear the flag so system is ready for another interrupt
reti         ; return from interrupt
;-------------------------------------------------------------------------------
;  end of Port2_ISR
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------

您已将所有PB_N_MODE设置为 0 并检查减去 1 是否等于0,您不能将它们设置为 1 或检查它们是否等于 -1?

PB_1_MODE = 1
PB_2_MODE = 1
...
#define PB_0  (0x20u)
if ((PB_0 & P2IFG) == 1)

表达式PB_0 & P2IFG的值为 0x20 或 0;它永远不能为 1。

所有if都具有相同的结构(if ((x) == 0)if ((x) == 1)),这令人困惑并可能导致错误。应将x正确视为布尔表达式,并使用if (x)检查非零值或if (!(x))零值。

最新更新