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.
// 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的引脚