Stumped - код компилируется, но ничего не происходит на конце микроконтроллера. Я подозреваю, что что-то в ISR может быть виновником - PullRequest
0 голосов
/ 18 апреля 2019

Моя задача - взять функциональную программу, написанную моим инструктором на языке ассемблера, и преобразовать ее в язык Си.Программа написана для TI MSP430G2553 и использует прилагаемый 4-значный светодиодный дисплей с тремя соседними кнопками.Дисплей должен начинаться пустым.Когда нажата правая кнопка, «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
;-------------------------------------------------------------------------------


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

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019
#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)) для нуля.

0 голосов
/ 18 апреля 2019

Вы установили все свои PB_N_MODE на 0 и проверяете, равняется ли вычитание 1 этим 0, не можете ли вы установить их на 1 или, возможно, проверить, равняются ли они -1?

PB_1_MODE = 1
PB_2_MODE = 1
...
...