我的任务是使用汇编语言的教师编写的函数程序并将其转换为C语言。该程序是为TI MSP430G2553编写的,采用附带的4位LED显示屏和三个并排按钮。显示应该从空白开始。按下右键时,“ECE-3362”将开始从右向左滚动显示。
据我所知,我的转换是“完整的”,代码编译时没有错误。但是,按钮没有任何可见效果,显示屏仍为空白。
我确实得到了一些“整数转换导致截断”警告,但我不确定这对程序功能的影响。最多我会假设如果部分常量定义被截断,这将导致显示显示错误的值。
我的代码的一部分对我来说特别可疑是我最底层的port2中断服务程序(主要是PB和P2_IFG比较)。我并没有完全理解我教师的那个部分的汇编版本中发生了什么,所以在翻译中可能会丢失一些重要内容。
对于微控制器来说,我是一般的新装配工具。我非常依赖我的教师示例代码作为参考。我会把我的代码放在下面,如果有人想看的话,我手头有我的教师代码。
我知道规则说不发布整个文件,但据我所知,我可能会在程序的任何地方出错或更多。
我的代码:
#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
s都有相同的结构(if ((x) == 0)
或if ((x) == 1)
),这会令人困惑,并可能导致错误。您应该将x
正确地视为布尔表达式,并使用if (x)
检查非零值,或使用if (!(x))
检查零。