This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

如何使用PMAP配置P4.4为TA1.2



使用PMAP配置P2.4和P4.4为TA1.1和TA1.2功能配置电机,P2.4配置成功,出现了PWM波形,但是P4.4配置失败,想知道是什么原因:

  • 请问您现在使用的是哪个芯片/开发板?程序是您自己写的还是您修改的TI例程?
  • MSP432P401R   根具ti的例子改的

  • 请问具体是哪个例程呢?能否给出相关路径?我来测试一下
  • 用的是红的launchpad?
  • // RobotArmmain.c
    // Runs on MSP432
    // Basic test functionality for three-servo robot arm.
    // Daniel and Jonathan Valvano
    // November 16, 2018
    
    /* This example accompanies the books
       "Embedded Systems: Introduction to the MSP432 Microcontroller",
           ISBN: 978-1512185676, Jonathan Valvano, copyright (c) 2018
       "Embedded Systems: Real-Time Interfacing to the MSP432 Microcontroller",
           ISBN: 978-1514676585, Jonathan Valvano, copyright (c) 2018
       "Embedded Systems: Real-Time Operating Systems for ARM Cortex-M Microcontrollers",
           ISBN: 978-1466468863, , Jonathan Valvano, copyright (c) 2018
     For more information about my classes, my research, and my books, see
     http://users.ece.utexas.edu/~valvano/
    
    Simplified BSD License (FreeBSD License)
    Copyright (c) 2018, Jonathan Valvano, All rights reserved.
    
    Redistribution and use in source and binary forms, with or without modification,
    are permitted provided that the following conditions are met:
    
    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
    AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of the FreeBSD Project.
    */
    
    // Negative logic bump sensors
    // P4.7 Bump5, left side of robot
    // P4.6 Bump4
    // P4.5 Bump3
    // P4.3 Bump2
    // P4.2 Bump1
    // P4.0 Bump0, right side of robot
    
    // The servos exceed the current limitation of standard USB, so when they
    // are in use, the system must be powered with a bench power supply or
    // the Pololu #3543 Motor Driver and Power Distribution Board.
    
    // Pololu #3543 Vreg (5V regulator output) connected to all three Pololu #136 GP2Y0A21YK0F Vcc's (+5V) and MSP432 +5V (J3.21)
    // Pololu #3543 Vreg (5V regulator output) connected to positive side of three 10 uF capacitors physically near the sensors
    // Pololu ground connected to all three Pololu #136 GP2Y0A21YK0F grounds and MSP432 ground (J3.22)
    // Pololu ground connected to negative side of all three 10 uF capacitors
    // MSP432 P9.0 (J5) (analog input to MSP432) connected to right GP2Y0A21YK0F Vout
    // MSP432 P6.1 (J3.23) (analog input to MSP432) connected to center GP2Y0A21YK0F Vout
    // MSP432 P9.1 (J5) (analog input to MSP432) connected to left GP2Y0A21YK0F Vout
    
    // Sever VCCMD=VREG jumper on Motor Driver and Power Distribution Board and connect VCCMD to 3.3V.
    //   This makes P3.7 and P3.6 low power disables for motor drivers.  0 to sleep/stop.
    // Sever nSLPL=nSLPR jumper.
    //   This separates P3.7 and P3.6 allowing for independent control
    
    // Optional diagnostic LEDs
    // P8.0 connected to yellow front right LED
    // P8.5 connected to yellow front left LED
    // P8.6 connected to red back left LED
    // P8.7 connected to red back right LED
    
    // PWM outputs for servos
    // P2.4/PM_TA0.1 (PMAP from TA1.1) connected to arm height servo
    // P3.5/PM_UCB2CLK (PMAP from TA1.2) connected to arm tilt servo
    // P5.7/TA2.2/VREF-/VeREF-/C1.6 connected to gripper servo
    
    // Analog inputs from servos
    // P8.4/A21 connected to arm height servo
    // P8.3/TA3CLK/A22 connected to arm tilt servo
    // P8.2/TA3.2/A23 connected to gripper servo
    
    #include "msp.h"
    #include <stdint.h>
    #include <stdio.h>
    #include "..\inc\Bump.h"
    #include "..\inc\Clock.h"
    #include "..\inc\CortexM.h"
    #include "..\inc\SysTickInts.h"
    
    // functions in ADC14.c slightly modified below
    // P8.4 = A21
    // P8.3 = A22
    // P8.2 = A23
    // use software trigger, 3.3V reference
    void ADC0_InitSWTriggerCh21_22_23(void){
    // you can use any of the MEM[n], MCTL[n] except n=6 (6 is used by TExaS)
                                       // 1) reference module is not used here
      ADC14->CTL0 &= ~0x00000002;      // 2) ADC14ENC = 0 to allow programming
      while(ADC14->CTL0&0x00010000){}; // 3) wait for BUSY to be zero
      ADC14->CTL0 = 0x04223390;        // 4) single, SMCLK, on, disabled, /1, 32 SHM
      // 31-30 ADC14PDIV  predivider,            00b = Predivide by 1
      // 29-27 ADC14SHSx  SHM source            000b = ADC14SC bit
      // 26    ADC14SHP   SHM pulse-mode          1b = SAMPCON the sampling timer
      // 25    ADC14ISSH  invert sample-and-hold  0b = not inverted
      // 24-22 ADC14DIVx  clock divider         000b = /1
      // 21-19 ADC14SSELx clock source select   100b = SMCLK
      // 18-17 ADC14CONSEQx mode select          01b = Sequence-of-channels
      // 16    ADC14BUSY  ADC14 busy              0b (read only)
      // 15-12 ADC14SHT1x sample-and-hold time 0011b = 32 clocks
      // 11-8  ADC14SHT0x sample-and-hold time 0011b = 32 clocks
      // 7     ADC14MSC   multiple sample         1b = continue conversions automatically after first SHI signal trigger
      // 6-5   reserved                          00b (reserved)
      // 4     ADC14ON    ADC14 on                1b = powered up
      // 3-2   reserved                          00b (reserved)
      // 1     ADC14ENC   enable conversion       0b = ADC14 disabled
      // 0     ADC14SC    ADC14 start             0b = No start (yet)
      ADC14->CTL1 = 0x00020030;        // 5) ADC14MEM2, 14-bit, ref on, regular power
      // 20-16 STARTADDx  start addr          00010b = ADC14MEM2
      // 15-6  reserved                  0000000000b (reserved)
      // 5-4   ADC14RES   ADC14 resolution       11b = 14 bit, 16 clocks
      // 3     ADC14DF    data read-back format   0b = Binary unsigned
      // 2     REFBURST   reference buffer burst  0b = reference on continuously
      // 1-0   ADC14PWRMD ADC power modes        00b = Regular power mode
      ADC14->MCTL[2] = 0x00000015;     // 6a) 0 to 3.3V, channel 21
      // 15   ADC14WINCTH Window comp threshold   0b = not used
      // 14   ADC14WINC   Comparator enable       0b = Comparator disabled
      // 13   ADC14DIF    Differential mode       0b = Single-ended mode enabled
      // 12   reserved                            0b (reserved)
      // 11-8 ADC14VRSEL  V(R+) and V(R-)      0000b = V(R+) = AVCC, V(R-) = AVSS
      // 7    ADC14EOS    End of sequence         0b = Not end of sequence
      // 6-5  reserved                           00b (reserved)
      // 4-0  ADC14INCHx  Input channel       10101b = A21, P8.4
      ADC14->MCTL[3] = 0x00000016;     // 6b) 0 to 3.3V, channel 22
      // 15   ADC14WINCTH Window comp threshold   0b = not used
      // 14   ADC14WINC   Comparator enable       0b = Comparator disabled
      // 13   ADC14DIF    Differential mode       0b = Single-ended mode enabled
      // 12   reserved                            0b (reserved)
      // 11-8 ADC14VRSEL  V(R+) and V(R-)      0000b = V(R+) = VCC, V(R-) = AVSS
      // 7    ADC14EOS    End of sequence         0b = Not end of sequence
      // 6-5  reserved                           00b (reserved)
      // 4-0  ADC14INCHx  Input channel       10110b = A22, P8.3
      ADC14->MCTL[4] = 0x00000097;     // 6c) 0 to 3.3V, channel 23, end of sequence
      // 15   ADC14WINCTH Window comp threshold   0b = not used
      // 14   ADC14WINC   Comparator enable       0b = Comparator disabled
      // 13   ADC14DIF    Differential mode       0b = Single-ended mode enabled
      // 12   reserved                            0b (reserved)
      // 11-8 ADC14VRSEL  V(R+) and V(R-)      0000b = V(R+) = VCC, V(R-) = AVSS
      // 7    ADC14EOS    End of sequence         1b = End of sequence
      // 6-5  reserved                           00b (reserved)
      // 4-0  ADC14INCHx  Input channel       10111b = A23, P8.2
      ADC14->IER0 = 0;                 // 7) no interrupts
      ADC14->IER1 = 0;                 //    no interrupts
      P8->SEL1 |= 0x1C;                // 8) analog mode on P8.4/A21, P8.3/A22, and P8.2/A23
      P8->SEL0 |= 0x1C;
      ADC14->CTL0 |= 0x00000002;       // 9) enable
    }
    
    // ADC14IFGR0 bit 4 is set when conversion done
    //                  cleared on read ADC14MEM4
    // ADC14CLRIFGR0 bit 4, write 1 to clear flag
    // ADC14IVx is 0x14 when ADC14MEM4 interrupt flag; Interrupt Flag: ADC14IFG4
    // ADC14MEM2 14-bit conversion in bits 13-0 (31-16 undefined, 15-14 zero)
    // ADC14MEM3 14-bit conversion in bits 13-0 (31-16 undefined, 15-14 zero)
    // ADC14MEM4 14-bit conversion in bits 13-0 (31-16 undefined, 15-14 zero)
    void ADC_In21_22_23(uint32_t *ch21, uint32_t *ch22, uint32_t *ch23){
    // 1) wait for BUSY to be zero
      while(ADC14->CTL0&0x00010000){};
    // 2) start single conversion
      ADC14->CTL0 |= 0x00000001;
    // 3) wait for ADC14IFG4
      while((ADC14->IFGR0&0x10) == 0){};
    // 4) read three results from MEM
      *ch21 = ADC14->MEM[2];           // P8.4/A21 result 0 to 16383
      *ch22 = ADC14->MEM[3];           // P8.3/A22 result 0 to 16383
      *ch23 = ADC14->MEM[4];           // P8.2/A23 result 0 to 16383
    }
    // end of ADC14.c slight modifications
    
    // functions in PWM.c slightly modified below
    //***************************PWM_Init*******************************
    // PWM outputs on P2.4/PM_TA0.1 (PMAP from TA1.1), P3.5/PM_UCB2CLK (PMAP from TA1.2), and P5.7/TA2.2/VREF-/VeREF-/C1.6
    // Inputs:  period (333.33ns)
    //          duty0 (0<=duty0<period-1)
    //          duty1 (0<=duty1<period-1)
    //          duty2 (0<=duty2<period-1)
    // Outputs: none
    // SMCLK = 48MHz/4 = 12 MHz, 83.33ns
    // Use clock divider of 2 to get timer clock period 166.67ns
    // Counter counts up to TAnCCR0 and back down
    // Let Timerclock period T = 2/12MHz = 166.67nsns
    // P2.4=1 when timer equals TA1CCR1 on way down, P2.4=0 when timer equals TA1CCR1 on way up
    // P3.5=1 when timer equals TA1CCR2 on way down, P3.5=0 when timer equals TA1CCR2 on way up
    // P5.7=1 when timer equals TA2CCR2 on way down, P5.7=0 when timer equals TA2CCR2 on way up
    // Period of P2.4 is period*333.33ns, duty cycle is duty0/period
    // Period of P3.5 is period*333.33ns, duty cycle is duty1/period
    // Period of P5.7 is period*333.33ns, duty cycle is duty2/period
    void PWM_Init(uint16_t period, uint16_t duty0, uint16_t duty1, uint16_t duty2){
      if(duty0 >= period) return;    // bad input
      if(duty1 >= period) return;    // bad input
      if(duty2 >= period) return;    // bad input
      TIMER_A1->CTL &= ~0x0030;      // halt TimerA1 while port mapping is in progress
      PMAP->KEYID = 0x2D52;          // write key to unlock write access to PMAP registers
      PMAP->CTL = 0x0002;            // allow reconfiguration of port mapping (in case needed in another module)
      P2MAP->PMAP_REGISTER4 = PMAP_TA1CCR1A;// configure P2.4 as TA1.1
      P2->DIR |= 0x10;               // P2.4 output
      P2->SEL0 |= 0x10;              // P2.4 PMAP functions
      P2->SEL1 &= ~0x10;             // P2.4 PMAP functions
      P3MAP->PMAP_REGISTER5 = PMAP_TA1CCR2A;// configure P3.5 as TA1.2
      P3->DIR |= 0x20;               // P3.5 output
      P3->SEL0 |= 0x20;              // P3.5 PMAP functions
      P3->SEL1 &= ~0x20;             // P3.5 PMAP functions
      PMAP->KEYID = 0x0000;          // write incorrect key to lock write access to PMAP registers
      TIMER_A1->CCTL[0] = 0x0080;    // CCI0 toggle
      TIMER_A1->CCR[0] = period - 1; // Period is 2*period*8*166.67ns is 2.666*period
      TIMER_A1->EX0 = 0x0000;        //    divide by 1
      TIMER_A1->CCTL[1] = 0x0040;    // CCR1 toggle/reset
      TIMER_A1->CCR[1] = duty0;      // CCR1 duty cycle is duty0/period
      TIMER_A1->CCTL[2] = 0x0040;    // CCR2 toggle/reset
      TIMER_A1->CCR[2] = duty1;      // CCR2 duty cycle is duty1/period
      TIMER_A1->CTL = 0x0270;        // SMCLK=12MHz, divide by 2, up-down mode
    // bit  mode
    // 9-8  10    TASSEL, SMCLK=12MHz
    // 7-6  01    ID, divide by 2
    // 5-4  11    MC, up-down mode
    // 2    0     TACLR, no clear
    // 1    0     TAIE, no interrupt
    // 0          TAIFG
      P5->DIR |= 0x80;               // P5.7 output
      P5->SEL0 |= 0x80;              // P5.7 TimerA2.2 functions
      P5->SEL1 &= ~0x80;             // P5.7 TimerA2.2 functions
      TIMER_A2->CCTL[0] = 0x0080;    // CCI0 toggle
      TIMER_A2->CCR[0] = period - 1; // Period is 2*period*8*166.67ns is 2.666*period
      TIMER_A2->EX0 = 0x0000;        //    divide by 1
      TIMER_A2->CCTL[2] = 0x0040;    // CCR2 toggle/reset
      TIMER_A2->CCR[2] = duty2;      // CCR2 duty cycle is duty2/period
      TIMER_A2->CTL = 0x0270;        // SMCLK=12MHz, divide by 2, up-down mode
    // bit  mode
    // 9-8  10    TASSEL, SMCLK=12MHz
    // 7-6  01    ID, divide by 2
    // 5-4  11    MC, up-down mode
    // 2    0     TACLR, no clear
    // 1    0     TAIE, no interrupt
    // 0          TAIFG
    }
    
    //***************************PWM_Duty0*******************************
    // change duty cycle of PWM output on P2.4
    // Inputs:  duty0
    // Outputs: none
    // Period of P2.4 is period*333.33ns, duty cycle is duty0/period
    void PWM_Duty0(uint16_t duty0){
      if(duty0 >= TIMER_A1->CCR[0]) return; // bad input
      TIMER_A1->CCR[1] = duty0;      // CCR1 duty cycle is duty0/period
    }
    
    //***************************PWM_Duty1*******************************
    // change duty cycle of PWM output on P3.5
    // Inputs:  duty1
    // Outputs: none
    // Period of P3.5 is period*333.33ns, duty cycle is duty1/period
    void PWM_Duty1(uint16_t duty1){
      if(duty1 >= TIMER_A1->CCR[0]) return; // bad input
      TIMER_A1->CCR[2] = duty1;      // CCR2 duty cycle is duty1/period
    }
    
    //***************************PWM_Duty2*******************************
    // change duty cycle of PWM output on P5.7
    // Inputs:  duty2
    // Outputs: none
    // Period of P5.7 is period*333.33ns, duty cycle is duty2/period
    void PWM_Duty2(uint16_t duty2){
      if(duty2 >= TIMER_A2->CCR[0]) return; // bad input
      TIMER_A2->CCR[2] = duty2;      // CCR2 duty cycle is duty2/period
    }
    // end of PWM.c slight modifications
    
    #define HEIGHTARRAYLEN 10
    // The full range of the arm height servo should be from 1000 �s (fully raised) to 1900 �s (fully lowered).
    const uint16_t HEIGHTDUTY[HEIGHTARRAYLEN] = {3000, 3270, 3540, 3810, 4080, 4350, 4620, 4890, 5160, 5700};
    int HeightIndex = 0;
    #define TILTARRAYLEN 10
    // The full range of the arm tilt servo should be from 1200 �s (fully down) to 1900 �s (fully up).
    const uint16_t TILTDUTY[TILTARRAYLEN] = {3600, 3810, 4020, 4230, 4440, 4650, 4860, 5070, 5280, 5700};
    int TiltIndex = 0;
    #define GRIPARRAYLEN 10
    // The full range of the gripper servo should be from about 500 �s (fully open) to 2400 �s (fully closed).
    const uint16_t GRIPDUTY[GRIPARRAYLEN] = {1500, 2070, 2640, 3210, 3780, 4350, 4920, 5490, 6060, 7200};
    int GripIndex = 0;
    
    void SysTick_Handler(void){ // every 100ms
      static uint8_t previous = 0;   // previous button status
      uint8_t current;               // current button status
      uint32_t heightADC, tiltADC, gripADC, expectedADC;
    
      P8->OUT ^= 0x80;               // toggle P8.7
    
      current = Bump_Read();
      if(((current&0x01) == 0x01) && ((previous&0x01) != 0x01)){
        if(HeightIndex > 0){
          HeightIndex = HeightIndex - 1;
          PWM_Duty0(HEIGHTDUTY[HeightIndex]);
        }
      }
      if(((current&0x02) == 0x02) && ((previous&0x02) != 0x02)){
        if(HeightIndex < (HEIGHTARRAYLEN - 1)){
          HeightIndex = HeightIndex + 1;
          PWM_Duty0(HEIGHTDUTY[HeightIndex]);
        }
      }
      if(((current&0x04) == 0x04) && ((previous&0x04) != 0x04)){
        if(TiltIndex > 0){
          TiltIndex = TiltIndex - 1;
          PWM_Duty1(TILTDUTY[TiltIndex]);
        }
      }
      if(((current&0x08) == 0x08) && ((previous&0x08) != 0x08)){
        if(TiltIndex < (TILTARRAYLEN - 1)){
          TiltIndex = TiltIndex + 1;
          PWM_Duty1(TILTDUTY[TiltIndex]);
        }
      }
      if(((current&0x10) == 0x10) && ((previous&0x10) != 0x10)){
        if(GripIndex > 0){
          GripIndex = GripIndex - 1;
          PWM_Duty2(GRIPDUTY[GripIndex]);
        }
      }
      if(((current&0x20) == 0x20) && ((previous&0x20) != 0x20)){
        if(GripIndex < (GRIPARRAYLEN - 1)){
          GripIndex = GripIndex + 1;
          PWM_Duty2(GRIPDUTY[GripIndex]);
        }
      }
      previous = current;
    
      ADC_In21_22_23(&heightADC, &tiltADC, &gripADC);// sample ADC
      // Expect an approximately 1:1 correspondence between the servo position in milliseconds and the feedback voltage in millivolts.
      // So for example, the feedback voltage will be around 1.5 V at the position corresponding to 1.5 ms servo pulses.
      // Convert units of period duration to ADC units:
      // (16,384 ADC counts/3.3 V) * (1 V/1 millisecond) * (1 millisecond/3,000 timer counts) =
      // (16,384 ADC counts/9,900 timer counts) =
      // 1.654949495 ADC counts/timer counts
      expectedADC = (HEIGHTDUTY[HeightIndex]<<14)/9900;
      if((heightADC > ((expectedADC*110)/100)) || (heightADC < ((expectedADC*90)/100))){
        P8->OUT |= 0x01;             // turn on P8.0
      }else{
        P8->OUT &= ~0x01;            // turn off P8.0
      }
      expectedADC = (TILTDUTY[TiltIndex]<<14)/9900;
      if((tiltADC > ((expectedADC*110)/100)) || (tiltADC < ((expectedADC*90)/100))){
        P8->OUT |= 0x20;             // turn on P8.5
      }else{
        P8->OUT &= ~0x20;            // turn off P8.5
      }
      expectedADC = (GRIPDUTY[GripIndex]<<14)/9900;
      if((gripADC > ((expectedADC*110)/100)) || (gripADC < ((expectedADC*90)/100))){
        P8->OUT |= 0x40;             // turn on P8.6
      }else{
        P8->OUT &= ~0x40;            // turn off P8.6
      }
    }
    
    void main(void){
      DisableInterrupts();
      Clock_Init48MHz();             // set system clock to 48 MHz
      ADC0_InitSWTriggerCh21_22_23();// initialize channels 21,22,23
      PWM_Init(60000, HEIGHTDUTY[0], TILTDUTY[0], GRIPDUTY[0]);
      Bump_Init();
      P8->SEL0 &= ~0xE1;
      P8->SEL1 &= ~0xE1;             // configure P8.7-P8.5 and P8.0 as GPIO
      P8->DIR |= 0xE1;               // make P8.7-P8.5 and P8.0 out
      P8->OUT &= ~0xE1;              // P8.7-P8.5 and P8.0 initially off
      SysTick_Init(4800000, 3);      // set up SysTick for 10 Hz interrupts
      EnableInterrupts();            // SysTick is priority 3
      while(1){
        WaitForInterrupt();
      }
    }
    

  • 这个您可以看一下数据手册

    http://www.ti.com/cn/lit/ds/symlink/msp432p401r.pdf 

    P4.4是不具备reconfigurable port mapping secondary function 这个功能的,也就是说是不可以进行重新配置port map的

    如下图所示

    建议您选用其他可以重新配置port map的引脚