Compare commits
11 Commits
89113917dc
...
4889a5fdfe
Author | SHA1 | Date |
---|---|---|
|
4889a5fdfe | |
|
7fb97bcab7 | |
|
3b38f6bfc4 | |
|
91e85280d5 | |
|
48fd2e6aed | |
|
609fb0bb76 | |
|
47d08fa8f6 | |
|
71e58c6ea9 | |
|
5a0ceba79a | |
|
1b89bef1dd | |
|
7779553efd |
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
#define BUMP_PINS 0b11101101
|
||||
|
||||
void BumpInit(void) {
|
||||
// Port 4 pins 0, 2, 3, 5, 6, 7
|
||||
// and enables internal resistors
|
||||
|
@ -15,5 +13,5 @@ void BumpInit(void) {
|
|||
|
||||
uint8_t BumpRead(void) {
|
||||
// write this as part of Lab 2
|
||||
return P4->IN & BUMP_PINS;
|
||||
return P4->IN;
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BUMP_PINS 0b11101101
|
||||
// Set port pins Port 4.0, 4.2, 4.3, 4.5, 4.6 and 4.7 and enable internal resistors as needed
|
||||
void BumpInit(void);
|
||||
|
||||
|
|
30
common/cpu.c
30
common/cpu.c
|
@ -20,3 +20,33 @@ uint32_t __attribute__((naked)) CPU_cpsie(void)
|
|||
//
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint32_t __attribute__((naked)) CPU_cpsid(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
//
|
||||
// Read PRIMASK and disable interrupts.
|
||||
//
|
||||
__asm(" mrs r0, PRIMASK\n"
|
||||
" cpsid i\n"
|
||||
" bx lr\n"
|
||||
: "=r" (ret));
|
||||
|
||||
//
|
||||
// The return is handled in the inline assembly, but the compiler will
|
||||
// still complain if there is not an explicit return here (despite the fact
|
||||
// that this does not result in any code being produced because of the
|
||||
// naked attribute).
|
||||
//
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void __attribute__((naked)) CPU_wfi(void)
|
||||
{
|
||||
//
|
||||
// Wait for the next interrupt.
|
||||
//
|
||||
__asm(" wfi\n"
|
||||
" bx lr\n");
|
||||
}
|
||||
|
|
|
@ -4,5 +4,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
uint32_t CPU_cpsie(void);
|
||||
uint32_t CPU_cpsid(void);
|
||||
void CPU_wfi(void);
|
||||
|
||||
#endif /* CPU_H */
|
|
@ -0,0 +1,79 @@
|
|||
#include "input_capture.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
void (*capture_task)(uint16_t time);
|
||||
|
||||
// Initialize Timer A0 in edge time mode to request interrupts on
|
||||
// the rising edge of P7.3 (TA0CCP0). The interrupt service routine
|
||||
// acknowledges the interrupt and calls a user function.
|
||||
void TimerA0CaptureInit(void (*task)(uint16_t time)) {
|
||||
capture_task = task;
|
||||
P7->SEL0 |= 0x08;
|
||||
P7->SEL1 &= ~0x08; // configure P7.3 as TA0CCP0
|
||||
P7->DIR &= ~0x08;
|
||||
|
||||
TIMER_A0->CTL &= ~0x30; // halt Timer A0
|
||||
TIMER_A0->CTL = 0x200; // SMCLK
|
||||
TIMER_A0->CCTL[0] = 0x4910; // capture on rising edge, synchronous capture, capture mode, interrupt enabled
|
||||
TIMER_A0->EX0 &= ~0x7; // input clock divider /1
|
||||
|
||||
NVIC->IP[2] = (NVIC->IP[2] & 0xFFFFFF00) | 0x00000002; // priority 2
|
||||
|
||||
// interrupts enabled in the main program after all devices initialized
|
||||
NVIC->ISER[0] = 0x100; // enable interrupt 8 in NVIC
|
||||
|
||||
TIMER_A0->CTL |= 0x24; // reset and start Timer A0 in continuous up mode
|
||||
}
|
||||
|
||||
void TA0_0_IRQHandler(void) {
|
||||
TIMER_A0->CCTL[0] &= ~0x1; // acknowledge capture/compare interrupt
|
||||
capture_task(TIMER_A0->CCR[0]); // execute user task
|
||||
}
|
||||
|
||||
|
||||
// Left Encoder A connected to P10.5 (J5)
|
||||
// Right Encoder A connected to P10.4 (J5)
|
||||
|
||||
// user function, time is up-counting timer value when edge occurred in units of 0.083 usec
|
||||
// called when P10.4/.5 (TA3CCP0/1) edge occurs
|
||||
void (*capture_task0)(uint16_t time);
|
||||
void (*capture_task1)(uint16_t time);
|
||||
|
||||
// Initialize Timer A3 in edge time mode to request interrupts on
|
||||
// the rising edges of P10.4 (TA3CCP0) and P10.5 (TA3CCP1).
|
||||
// Interrupt service routines acknowledge the interrupt and call a user function.
|
||||
// Assumes: low-speed subsystem master clock is 12 MHz
|
||||
void TimerA3CaptureInit(void (*task0)(uint16_t time),
|
||||
void (*task1)(uint16_t time)) {
|
||||
capture_task0 = task0;
|
||||
capture_task1 = task1;
|
||||
P10->SEL0 |= 0x30; // Set SEL0 for bits 4 and 5
|
||||
P10->SEL1 &= ~0x30; // Clear SEL1 for bits 4 and 5
|
||||
P10->DIR &= ~0x30; // Set as inputs
|
||||
|
||||
TIMER_A3->CTL &= ~0x30; // halt Timer A3
|
||||
TIMER_A3->CTL = 0x200; // SMCLK
|
||||
TIMER_A3->CCTL[0] = 0x4910; // rising, sync, capture, interrupt
|
||||
TIMER_A3->CCTL[1] = 0x4910;
|
||||
TIMER_A3->EX0 &= ~0x7; // input clock divider /1
|
||||
|
||||
NVIC->IP[3] = (NVIC->IP[3] & 0xFF0000FF) | 0x00020300; // priority 2 and 3
|
||||
|
||||
NVIC->ISER[0] = (1 << 14) | (1 << 15); // enable 14 and 15
|
||||
|
||||
// Start Timer A3 in continuous mode with clear
|
||||
TIMER_A3->CTL |= 0x0024; // TACLR | MC__CONTINUOUS
|
||||
}
|
||||
|
||||
// The rising edge of P10.4 will cause an interrupt
|
||||
void TA3_0_IRQHandler(void) {
|
||||
TIMER_A3->CCTL[0] &= ~0x0001; // ack
|
||||
capture_task0(TIMER_A3->CCR[0]);
|
||||
}
|
||||
|
||||
// The rising edge of P10.5 will cause an interrupt
|
||||
void TA3_N_IRQHandler(void) {
|
||||
TIMER_A3->CCTL[1] &= ~0x0001; // ack
|
||||
capture_task1(TIMER_A3->CCR[1]);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef INPUT_CAPTURE_H
|
||||
#define INPUT_CAPTURE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void TimerA3CaptureInit(void (*task0)(uint16_t time),
|
||||
void (*task1)(uint16_t time));
|
||||
|
||||
#endif /* INPUT_CAPTURE */
|
|
@ -0,0 +1,113 @@
|
|||
#include "motor.h"
|
||||
#include "pwm.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
#undef BIT0
|
||||
#undef BIT1
|
||||
#undef BIT2
|
||||
#undef BIT3
|
||||
#undef BIT4
|
||||
#undef BIT5
|
||||
#undef BIT6
|
||||
#undef BIT7
|
||||
|
||||
#define BIT0 (uint8_t)(0x01)
|
||||
#define BIT1 (uint8_t)(0x02)
|
||||
#define BIT2 (uint8_t)(0x04)
|
||||
#define BIT3 (uint8_t)(0x08)
|
||||
#define BIT4 (uint8_t)(0x10)
|
||||
#define BIT5 (uint8_t)(0x20)
|
||||
#define BIT6 (uint8_t)(0x40)
|
||||
#define BIT7 (uint8_t)(0x80)
|
||||
|
||||
// duty := H/(H+L) = H/10000
|
||||
// H+L is always 10 000 microsecond
|
||||
|
||||
// Left motor (PH) direction connected to P5.4 (J3.29)
|
||||
#define LEFT_DIR_PIN BIT4 // P5.4
|
||||
// Right motor (PH) direction connected to P5.5 (J3.30)
|
||||
#define RIGHT_DIR_PIN BIT5 // P5.5
|
||||
|
||||
// Left motor (EN) PWM connected to P2.7/TA0CCP4 (J4.40)
|
||||
#define LEFT_PWM_PIN BIT7 // P2.7
|
||||
// Right motor (EN) PWM connected to P2.6/TA0CCP3 (J4.39)
|
||||
#define RIGHT_PWM_PIN BIT6 // P2.6
|
||||
|
||||
// Left motor (nSLEEP) enable connected to P3.7 (J4.31)
|
||||
#define LEFT_SLEEP_PIN BIT7 // P3.7
|
||||
// Right motor (nSLEEP) enable connected to P3.6 (J2.11)
|
||||
#define RIGHT_SLEEP_PIN BIT6 // P3.6
|
||||
|
||||
|
||||
// Initializes the 6 GPIO output lines and puts driver to sleep
|
||||
void MotorInit(void) {
|
||||
// 1. Configure all motor control pins as outputs
|
||||
// P5.4 (Left DIR), P5.5 (Right DIR)
|
||||
P5->SEL0 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN); // GPIO function
|
||||
P5->SEL1 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
P5->DIR |= (LEFT_DIR_PIN | RIGHT_DIR_PIN); // Output direction
|
||||
|
||||
// P3.6 (Right SLEEP), P3.7 (Left SLEEP)
|
||||
P3->SEL0 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // GPIO function
|
||||
P3->SEL1 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
P3->DIR |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // Output direction
|
||||
|
||||
// 2. Initial state: disable motors
|
||||
P3->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // SLEEP pins low - DRV8838 disabled
|
||||
}
|
||||
|
||||
// Stop the motors, power down the drivers, and
|
||||
// set the PWM speed control to 0% duty cycle.
|
||||
void MotorStop(void) {
|
||||
P3->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // SLEEP pins low
|
||||
P2->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // EN pins low
|
||||
|
||||
SetPWMDutyLeftMotor(0);
|
||||
SetPWMDutyRightMotor(0);
|
||||
}
|
||||
|
||||
// Left and right wheels forward with the given duty cycles.
|
||||
// Duty cycle is 0 to 14,998.
|
||||
void MotorForward(uint16_t left_duty, uint16_t right_duty) {
|
||||
P5->OUT &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN); // set direction - PH low
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // wake up motors
|
||||
// P2->OUT |= (LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
|
||||
SetPWMDutyRightMotor(right_duty);
|
||||
SetPWMDutyLeftMotor(left_duty);
|
||||
}
|
||||
|
||||
// Left and right wheels backward with the given duty cycles.
|
||||
// Duty cycle is 0 to 14,998.
|
||||
void MotorBackward(uint16_t left_duty, uint16_t right_duty) {
|
||||
P5->OUT |= (LEFT_DIR_PIN | RIGHT_DIR_PIN); // set direction - PH high
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // wake up motors
|
||||
// P2->OUT |= (LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
|
||||
SetPWMDutyRightMotor(right_duty);
|
||||
SetPWMDutyLeftMotor(left_duty);
|
||||
|
||||
}
|
||||
|
||||
// Left wheel backward, right wheel forward with the given duty cycles.
|
||||
// Duty cycle is 0 to 14,998.
|
||||
void MotorLeft(uint16_t left_duty, uint16_t right_duty) {
|
||||
P5->OUT &= ~(RIGHT_DIR_PIN); // set direction forward
|
||||
P5->OUT |= LEFT_DIR_PIN; // set direction backward
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // wake up motors
|
||||
|
||||
SetPWMDutyRightMotor(right_duty);
|
||||
SetPWMDutyLeftMotor(left_duty);
|
||||
}
|
||||
|
||||
// Left wheel forward, right wheel backward with the given duty cycles.
|
||||
// Duty cycle is 0 to 14,998.
|
||||
void MotorRight(uint16_t left_duty, uint16_t right_duty) {
|
||||
P5->OUT &= ~(LEFT_DIR_PIN); // set direction forward
|
||||
P5->OUT |= RIGHT_DIR_PIN; // set direction backward
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // wake up motors
|
||||
|
||||
SetPWMDutyRightMotor(right_duty);
|
||||
SetPWMDutyLeftMotor(left_duty);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef MOTOR_H
|
||||
#define MOTOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void MotorInit(void);
|
||||
void MotorStop(void);
|
||||
void MotorForward(uint16_t left_duty, uint16_t right_duty);
|
||||
void MotorBackward(uint16_t left_duty, uint16_t right_duty);
|
||||
void MotorLeft(uint16_t left_duty, uint16_t right_duty);
|
||||
void MotorRight(uint16_t left_duty, uint16_t right_duty);
|
||||
|
||||
#endif /* MOTOR_H */
|
|
@ -0,0 +1,145 @@
|
|||
#include <stdbool.h>
|
||||
#include "motor_simple.h"
|
||||
|
||||
#include "bump.h"
|
||||
#include "systick.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
|
||||
#define BIT0 (uint8_t)(0x01)
|
||||
#define BIT1 (uint8_t)(0x02)
|
||||
#define BIT2 (uint8_t)(0x04)
|
||||
#define BIT3 (uint8_t)(0x08)
|
||||
#define BIT4 (uint8_t)(0x10)
|
||||
#define BIT5 (uint8_t)(0x20)
|
||||
#define BIT6 (uint8_t)(0x40)
|
||||
#define BIT7 (uint8_t)(0x80)
|
||||
|
||||
|
||||
// Left motor (PH) direction connected to P5.4 (J3.29)
|
||||
#define LEFT_DIR_PIN BIT4 // P5.4
|
||||
// Right motor (PH) direction connected to P5.5 (J3.30)
|
||||
#define RIGHT_DIR_PIN BIT5 // P5.5
|
||||
|
||||
// Left motor (EN) PWM connected to P2.7/TA0CCP4 (J4.40)
|
||||
#define LEFT_PWM_PIN BIT7 // P2.7
|
||||
// Right motor (EN) PWM connected to P2.6/TA0CCP3 (J4.39)
|
||||
#define RIGHT_PWM_PIN BIT6 // P2.6
|
||||
|
||||
// Left motor (nSLEEP) enable connected to P3.7 (J4.31)
|
||||
#define LEFT_SLEEP_PIN BIT7 // P3.7
|
||||
// Right motor (nSLEEP) enable connected to P3.6 (J2.11)
|
||||
#define RIGHT_SLEEP_PIN BIT6 // P3.6
|
||||
|
||||
|
||||
// Initializes the 6 GPIO output lines and puts driver to sleep
|
||||
void MotorInit(void) {
|
||||
P5->SEL0 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN); // GPIO enable
|
||||
P5->SEL1 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
P5->DIR |= (LEFT_DIR_PIN | RIGHT_DIR_PIN); // Output direction
|
||||
P5->OUT &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN); // Initialize low
|
||||
|
||||
// motor enable pins - P2.6 P2.7
|
||||
P2->SEL0 |= (LEFT_PWM_PIN | RIGHT_PWM_PIN); // TimerA function
|
||||
P2->SEL1 &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
P2->DIR |= (LEFT_PWM_PIN | RIGHT_PWM_PIN); // Output direction
|
||||
|
||||
// motor sleep pins - P3.6 P3.7
|
||||
P3->SEL0 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // GPIO enable
|
||||
P3->SEL1 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
P3->DIR |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // Output direction
|
||||
P3->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // Initialize low (sleep mode)
|
||||
}
|
||||
|
||||
// Stops both motors, puts driver to sleep
|
||||
void MotorStop(void) {
|
||||
P2->OUT &= ~0xC0; // off
|
||||
P3->OUT &= ~0xC0; // low current sleep mode
|
||||
}
|
||||
|
||||
// Drives both motors forward at duty (100 to 9900)
|
||||
// Runs for time duration, and then stops
|
||||
// Stop the motors and return if any bumper switch is active
|
||||
void MotorForward(uint16_t duty, uint32_t times_10ms) {
|
||||
// set direction - PH low
|
||||
P5->OUT &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
|
||||
// wake up motors
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
|
||||
// Set PWM duty cycle
|
||||
TIMER_A0->CCR[3] = duty; // Right motor (P2.6/TA0.3)
|
||||
TIMER_A0->CCR[4] = duty; // Left motor (P2.7/TA0.4)
|
||||
|
||||
while(times_10ms--) {
|
||||
Delay10ms(1);
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
||||
|
||||
// Drives both motors backward at duty (100 to 9900)
|
||||
// Runs for time duration, and then stops
|
||||
// Runs even if any bumper switch is active
|
||||
void MotorBackward(uint16_t duty, uint32_t times_10ms) {
|
||||
// set direction - PH high
|
||||
P5->OUT |= (LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
|
||||
// wake up motors
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
|
||||
// Set PWM duty cycle
|
||||
TIMER_A0->CCR[3] = duty; // Right motor (P2.6/TA0.3)
|
||||
TIMER_A0->CCR[4] = duty; // Left motor (P2.7/TA0.4)
|
||||
|
||||
while(times_10ms--) {
|
||||
Delay10ms(1);
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
||||
|
||||
// Drives just the left motor forward at duty (100 to 9900)
|
||||
// Right motor is stopped (sleeping)
|
||||
// Runs for time duration, and then stops
|
||||
// Stop the motor and return if any bumper switch is active
|
||||
void MotorLeft(uint16_t duty, uint32_t times_10ms) {
|
||||
// set direction - PH low
|
||||
P5->OUT &= ~LEFT_DIR_PIN;
|
||||
|
||||
// wake up motors
|
||||
P3->OUT = (P3->OUT & ~RIGHT_SLEEP_PIN) | LEFT_SLEEP_PIN;
|
||||
|
||||
// Set PWM duty cycle
|
||||
TIMER_A0->CCR[3] = 0; // Right motor off
|
||||
TIMER_A0->CCR[4] = duty; // Left motor on
|
||||
|
||||
while(times_10ms--) {
|
||||
Delay10ms(1);
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
||||
|
||||
// Drives just the right motor forward at duty (100 to 9900)
|
||||
// Left motor is stopped (sleeping)
|
||||
// Runs for time duration, and then stops
|
||||
// Stop the motor and return if any bumper switch is active
|
||||
void MotorRight(uint16_t duty, uint32_t times_10ms) {
|
||||
// set direction - PH low
|
||||
P5->OUT &= ~RIGHT_DIR_PIN;
|
||||
|
||||
// wake up motors
|
||||
P3->OUT = (P3->OUT & ~LEFT_SLEEP_PIN) | RIGHT_SLEEP_PIN;
|
||||
|
||||
// Set PWM duty cycle
|
||||
TIMER_A0->CCR[3] = duty; // Right motor off
|
||||
TIMER_A0->CCR[4] = 0; // Left motor on
|
||||
|
||||
while(times_10ms--) {
|
||||
Delay10ms(1);
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
|
@ -6,38 +6,116 @@
|
|||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
// Left motor (PH) direction connected to P5.4 (J3.29)
|
||||
// Left motor (EN) PWM connected to P2.7/TA0CCP4 (J4.40)
|
||||
// Left motor (nSLEEP) enable connected to P3.7 (J4.31)
|
||||
#undef BIT0
|
||||
#undef BIT1
|
||||
#undef BIT2
|
||||
#undef BIT3
|
||||
#undef BIT4
|
||||
#undef BIT5
|
||||
#undef BIT6
|
||||
#undef BIT7
|
||||
|
||||
#define BIT0 (uint8_t)(0x01)
|
||||
#define BIT1 (uint8_t)(0x02)
|
||||
#define BIT2 (uint8_t)(0x04)
|
||||
#define BIT3 (uint8_t)(0x08)
|
||||
#define BIT4 (uint8_t)(0x10)
|
||||
#define BIT5 (uint8_t)(0x20)
|
||||
#define BIT6 (uint8_t)(0x40)
|
||||
#define BIT7 (uint8_t)(0x80)
|
||||
|
||||
// duty := H/(H+L) = H/10000
|
||||
// H+L is always 10 000 microsecond
|
||||
|
||||
// Left motor (PH) direction connected to P5.4 (J3.29)
|
||||
#define LEFT_DIR_PIN BIT4 // P5.4
|
||||
// Right motor (PH) direction connected to P5.5 (J3.30)
|
||||
#define RIGHT_DIR_PIN BIT5 // P5.5
|
||||
|
||||
// Left motor (EN) PWM connected to P2.7/TA0CCP4 (J4.40)
|
||||
#define LEFT_PWM_PIN BIT7 // P2.7
|
||||
// Right motor (EN) PWM connected to P2.6/TA0CCP3 (J4.39)
|
||||
#define RIGHT_PWM_PIN BIT6 // P2.6
|
||||
|
||||
// Left motor (nSLEEP) enable connected to P3.7 (J4.31)
|
||||
#define LEFT_SLEEP_PIN BIT7 // P3.7
|
||||
// Right motor (nSLEEP) enable connected to P3.6 (J2.11)
|
||||
#define RIGHT_SLEEP_PIN BIT6 // P3.6
|
||||
|
||||
|
||||
// Initializes the 6 GPIO output lines and puts driver to sleep
|
||||
void MotorInit(void) {
|
||||
// write this code
|
||||
// 1. Configure all motor control pins as outputs
|
||||
// P5.4 (Left DIR), P5.5 (Right DIR)
|
||||
P5->SEL0 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN); // GPIO function
|
||||
P5->SEL1 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
P5->DIR |= (LEFT_DIR_PIN | RIGHT_DIR_PIN); // Output direction
|
||||
|
||||
// P3.6 (Right SLEEP), P3.7 (Left SLEEP)
|
||||
P3->SEL0 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // GPIO function
|
||||
P3->SEL1 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
P3->DIR |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // Output direction
|
||||
|
||||
// P2.6 (Right EN), P2.7 (Left EN)
|
||||
P2->SEL0 &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN); // GPIO function
|
||||
P2->SEL1 &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
P2->DIR |= (LEFT_PWM_PIN | RIGHT_PWM_PIN); // Output direction
|
||||
|
||||
// 2. Initial state: disable motors
|
||||
P3->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // SLEEP pins low - DRV8838 disabled
|
||||
P2->OUT &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN); // EN pins low
|
||||
|
||||
SysTickWait1us(1000);
|
||||
}
|
||||
|
||||
// Stops both motors, puts driver to sleep
|
||||
void MotorStop(void) {
|
||||
P2->OUT &= ~0xC0; // off
|
||||
P3->OUT &= ~0xC0; // low current sleep mode
|
||||
P3->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // SLEEP pins low
|
||||
P2->OUT &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // EN pins low
|
||||
}
|
||||
|
||||
// Drives both motors forward at duty (100 to 9900)
|
||||
// Runs for time duration, and then stops
|
||||
// Stop the motors and return if any bumper switch is active
|
||||
void MotorForward(uint16_t duty, uint32_t times_10ms) {
|
||||
// write this code
|
||||
P5->OUT &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN); // set direction - PH low
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // wake up motors
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < times_10ms; ++i) {
|
||||
P2->OUT |= (LEFT_PWM_PIN | RIGHT_PWM_PIN); // Enable both motors (EN high)
|
||||
SysTickWait1us(duty);
|
||||
|
||||
P2->OUT &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN); // Disable motors
|
||||
SysTickWait1us(10000 - duty);
|
||||
|
||||
uint8_t bump = BumpRead();
|
||||
if ((~bump & BUMP_PINS)) break;
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
||||
|
||||
// Drives both motors backward at duty (100 to 9900)
|
||||
// Runs for time duration, and then stops
|
||||
// Runs even if any bumper switch is active
|
||||
void MotorBackward(uint16_t duty, uint32_t times_10ms) {
|
||||
// write this code
|
||||
P5->OUT |= (LEFT_DIR_PIN | RIGHT_DIR_PIN); // set direction - PH high
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN); // wake up motors
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < times_10ms; ++i) {
|
||||
P2->OUT |= (LEFT_PWM_PIN | RIGHT_PWM_PIN); // Enable both motors (EN high)
|
||||
SysTickWait1us(duty);
|
||||
|
||||
P2->OUT &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN); // Disable motors
|
||||
SysTickWait1us(10000 - duty);
|
||||
|
||||
uint8_t bump = BumpRead();
|
||||
if ((~bump & BUMP_PINS)) break;
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
||||
|
||||
// Drives just the left motor forward at duty (100 to 9900)
|
||||
|
@ -45,7 +123,22 @@ void MotorBackward(uint16_t duty, uint32_t times_10ms) {
|
|||
// Runs for time duration, and then stops
|
||||
// Stop the motor and return if any bumper switch is active
|
||||
void MotorLeft(uint16_t duty, uint32_t times_10ms) {
|
||||
// write this code
|
||||
P5->OUT &= ~(LEFT_DIR_PIN); // set direction
|
||||
P3->OUT |= (LEFT_SLEEP_PIN); // wake up motors
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < times_10ms; ++i) {
|
||||
P2->OUT |= (LEFT_PWM_PIN); // Enable both motors (EN high)
|
||||
SysTickWait1us(duty);
|
||||
|
||||
P2->OUT &= ~(LEFT_PWM_PIN); // Disable motors
|
||||
SysTickWait1us(10000 - duty);
|
||||
|
||||
uint8_t bump = BumpRead();
|
||||
if ((~bump & BUMP_PINS)) break;
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
||||
|
||||
// Drives just the right motor forward at duty (100 to 9900)
|
||||
|
@ -53,5 +146,20 @@ void MotorLeft(uint16_t duty, uint32_t times_10ms) {
|
|||
// Runs for time duration, and then stops
|
||||
// Stop the motor and return if any bumper switch is active
|
||||
void MotorRight(uint16_t duty, uint32_t times_10ms) {
|
||||
// write this code
|
||||
P5->OUT &= ~(RIGHT_DIR_PIN); // set direction - PH high
|
||||
P3->OUT |= (RIGHT_SLEEP_PIN); // wake up motors
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < times_10ms; ++i) {
|
||||
P2->OUT |= (RIGHT_PWM_PIN); // Enable both motors (EN high)
|
||||
SysTickWait1us(duty);
|
||||
|
||||
P2->OUT &= ~(RIGHT_PWM_PIN); // Disable motors
|
||||
SysTickWait1us(10000 - duty);
|
||||
|
||||
uint8_t bump = BumpRead();
|
||||
if ((~bump & BUMP_PINS)) break;
|
||||
}
|
||||
|
||||
MotorStop();
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#include "pwm.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
// PWM on P2.4/.5 using TimerA0 TA0.CCR1/2
|
||||
// period is 1.333us (1.333us = 2 * 666.7ns because of up/down)
|
||||
// SMCLK = 48MHz/4 = 12 MHz, 83.33ns
|
||||
// Let Timerclock period T = 8/12MHz = 666.7ns
|
||||
// P2.4/.5 = 1 when timer equals TA0CCR1/2 on way down,
|
||||
// P2.4/.5 = 0 when timer equals TA0CCR1/2 on way up
|
||||
void PWMInitP2_4_P2_5(uint16_t period) {
|
||||
P2->DIR |= 0x30;
|
||||
P2->SEL0 |= 0x30; // Timer0A functions
|
||||
P2->SEL1 &= ~0x30;
|
||||
|
||||
TIMER_A0->CCR[0] = period;
|
||||
TIMER_A0->EX0 = 0; // Divide by 1
|
||||
|
||||
TIMER_A0->CCTL[1] = 0x40; // Toggle/reset
|
||||
TIMER_A0->CCTL[2] = 0x40;
|
||||
|
||||
TIMER_A0->CCR[1] = 0; // Initial duty cycle to 0
|
||||
TIMER_A0->CCR[2] = 0;
|
||||
|
||||
TIMER_A0->CTL = 0x2F0; // SMCLK = 12MHz, divide by 8, up-down mode
|
||||
}
|
||||
|
||||
void SetPWMDutyP2_4(uint16_t duty) {
|
||||
if (duty >= TIMER_A0->CCR[0]) return;
|
||||
TIMER_A0->CCR[1] = duty;
|
||||
}
|
||||
|
||||
void SetPWMDutyP2_5(uint16_t duty) {
|
||||
if (duty >= TIMER_A0->CCR[0]) return;
|
||||
TIMER_A0->CCR[2] = duty;
|
||||
}
|
||||
|
||||
// PWM on P2.6/.7 using TimerA0 TA0.CCR3/4
|
||||
// SMCLK = 48MHz/4 = 12 MHz, 83.33ns
|
||||
// period is 1.333us
|
||||
// Let Timerclock period T = 8/12MHz = 666.7ns
|
||||
// P2.6/.7 = 1 when timer equals TA0CCR3/4 on way down,
|
||||
// P2.6/.7 = 0 when timer equals TA0CCR3/4 on way up
|
||||
void PWMInitMotor(uint16_t period) {
|
||||
P2->DIR |= BIT6 | BIT7;
|
||||
P2->SEL0 |= BIT6 | BIT7;
|
||||
P2->SEL1 &= ~(BIT6 | BIT7);
|
||||
|
||||
TIMER_A0->CCR[0] = period;
|
||||
TIMER_A0->EX0 = 0x00;
|
||||
|
||||
TIMER_A0->CCTL[3] = 0x40;
|
||||
TIMER_A0->CCTL[4] = 0x40;
|
||||
|
||||
TIMER_A0->CCR[3] = 0;
|
||||
TIMER_A0->CCR[4] = 0;
|
||||
|
||||
TIMER_A0->CTL = 0x02F0;
|
||||
|
||||
// ZKURVENA MRDKA
|
||||
}
|
||||
|
||||
// right motor on P2.6 -> CCR3
|
||||
void SetPWMDutyRightMotor(uint16_t duty) {
|
||||
if (duty >= TIMER_A0->CCR[0]) return;
|
||||
TIMER_A0->CCR[3] = duty;
|
||||
}
|
||||
|
||||
// left motor on P2.7 -> CCR4
|
||||
void SetPWMDutyLeftMotor(uint16_t duty) {
|
||||
if (duty >= TIMER_A0->CCR[0]) return;
|
||||
TIMER_A0->CCR[4] = duty;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef PWM_H
|
||||
#define PWM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void PWMInitMotor(uint16_t period);
|
||||
void SetPWMDutyRightMotor(uint16_t duty);
|
||||
void SetPWMDutyLeftMotor(uint16_t duty);
|
||||
|
||||
#endif /* PWM_H */
|
|
@ -9,10 +9,24 @@ void SysTickInit(void) {
|
|||
|
||||
// Assumes 48 MHz bus clock
|
||||
void SysTickWait(uint32_t delay_ticks) {
|
||||
// write this code
|
||||
// 1. Write a desired delay_ticks value into the SysTick->LOAD register and subtract 1 from it,
|
||||
SysTick->LOAD = delay_ticks - 1;
|
||||
|
||||
// 2. Clear the SysTick->VAL counter value, which also clears the COUNT bit,
|
||||
SysTick->VAL = 0;
|
||||
|
||||
// 3. Wait for the COUNT bit in the SysTick->CTRL register to be set.
|
||||
while((SysTick->CTRL & 0x00010000) == 0); // wait for COUNTFLAG
|
||||
|
||||
// any write to CVR clears it and COUNTFLAG in CSR
|
||||
}
|
||||
|
||||
void SysTickWait1us(uint32_t times) {
|
||||
// write this code
|
||||
uint32_t count = (48 * times) / 0x00FFFFFF;
|
||||
uint32_t rem = (48 * times) % 0x00FFFFFF;
|
||||
uint32_t i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
SysTickWait(0x00FFFFFF); // wait max
|
||||
}
|
||||
SysTickWait(rem);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#include "tachometer.h"
|
||||
|
||||
#include "input_capture.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
#define P5_0_IN (*((volatile uint8_t *)(0x42098800)))
|
||||
#define P5_2_IN (*((volatile uint8_t *)(0x42098808)))
|
||||
|
||||
uint16_t tach_r_time1, tach_r_time2, tach_l_time1, tach_l_time2;
|
||||
|
||||
// incremented with every step forward, decremented with every step backward
|
||||
int tach_r_steps, tach_l_steps;
|
||||
|
||||
TachDirection_t tach_r_dir, tach_l_dir;
|
||||
|
||||
// Right Encoder B connected to P5.0 (J2.13)
|
||||
// When high, increase r_steps and set dir forward
|
||||
// When low, decrease r_steps and set dir reverse
|
||||
void TachometerRightInt(uint16_t current_time) {
|
||||
tach_r_time1 = tach_r_time2;
|
||||
tach_r_time2 = current_time;
|
||||
|
||||
tach_r_dir = (P5->IN & 0x01) ? Forward : Reverse;
|
||||
|
||||
// int delta = tach_r_time2 - tach_r_time1;
|
||||
// int speed = 2000000 / delta;
|
||||
|
||||
if (tach_r_dir == Forward)
|
||||
++tach_r_steps;
|
||||
else
|
||||
--tach_r_steps;
|
||||
return;
|
||||
}
|
||||
|
||||
// Left Encoder B connected to P5.2 (J2.12)
|
||||
// When high, increase l_steps and set dir forward
|
||||
// When low, decrease l_steps and set dir reverse
|
||||
void TachometerLeftInt(uint16_t current_time) {
|
||||
tach_l_time1 = tach_l_time2;
|
||||
tach_l_time2 = current_time;
|
||||
|
||||
tach_l_dir = (P5->IN & 0x04) ? Forward : Reverse;
|
||||
|
||||
// int delta = tach_l_time2 - tach_l_time1;
|
||||
// int speed = 2000000 / delta;
|
||||
|
||||
if (tach_l_dir == Forward)
|
||||
++tach_l_steps;
|
||||
else
|
||||
--tach_l_steps;
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize P5.0 and P5.2 and make them GPIO inputs,
|
||||
// which will be used to determine the direction of rotation.
|
||||
// Initialize the input capture interface, which
|
||||
// will be used to measure the speed of rotation.
|
||||
void TachometerInit(void) {
|
||||
P5->SEL0 |= 0x05; // Set SEL0 for bits 0 and 2
|
||||
P5->SEL1 &= ~0x05; // Clear SEL1 for bits 0 and 2
|
||||
P5->DIR &= ~0x05; // Set as inputs
|
||||
|
||||
tach_r_dir = tach_l_dir = Stopped;
|
||||
|
||||
TimerA3CaptureInit(&TachometerRightInt, &TachometerLeftInt);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef TACHOMETER_H
|
||||
#define TACHOMETER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Specifies the direction of the motor rotation, relative to the front of the robot
|
||||
typedef enum TachDirection {
|
||||
Reverse = -1,
|
||||
Stopped,
|
||||
Forward,
|
||||
} TachDirection_t;
|
||||
|
||||
void TachometerInit(void);
|
||||
|
||||
#endif /* TACHOMETER_H */
|
|
@ -0,0 +1,35 @@
|
|||
#include "timer_a1.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
void (*timer_a1_task)(void); // user function
|
||||
|
||||
// Activate Timer A1 interrupts to run user task periodically
|
||||
// 16 bits period in units (24/SMCLK, with SMCLK 12 MHz -> 2us)
|
||||
void TimerA1Init(void (*task)(void), uint16_t period) {
|
||||
timer_a1_task = task;
|
||||
|
||||
// Stop timer, SMCLK, /4 divider
|
||||
TIMER_A1->CTL = 0x0280;
|
||||
|
||||
// Configure CCR0
|
||||
TIMER_A1->CCTL[0] = 0x0010; // Compare mode, enable interrupt
|
||||
TIMER_A1->CCR[0] = (period - 1);
|
||||
|
||||
// Clock divider (EX0 register)
|
||||
TIMER_A1->EX0 = 0x0005; // /6 divider (additional to the /4 above)
|
||||
|
||||
// NVIC configuration
|
||||
NVIC->IP[3] = (NVIC->IP[3]&0xFFFFFF00)|0x00000040; // priority 2
|
||||
NVIC->ISER[0] = 0x00001000; // enable interrupt 12 in NVIC
|
||||
|
||||
// Enable timer interrupts and start in up mode
|
||||
TIMER_A1->CTL |= 0x0014 | 0x0020; // reset, up mode, enable interrupts
|
||||
|
||||
NVIC_EnableIRQ(TA1_0_IRQn);
|
||||
}
|
||||
|
||||
void TA1_0_IRQHandler(void) {
|
||||
TIMER_A1->CCTL[0] &= ~0x0001;
|
||||
timer_a1_task();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef TIMER_A1_H
|
||||
#define TIMER_A1_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void TimerA1Init(void (*task)(void), uint16_t period);
|
||||
void TimerA1Stop(void);
|
||||
|
||||
#endif /* TIMER_A1_H */
|
|
@ -46,11 +46,11 @@ void SysTick_Handler(void) { // every 1ms
|
|||
++tick_count;
|
||||
|
||||
if (1 == (tick_count % 10)) {
|
||||
//ReflectanceStart(); // every 10ms
|
||||
ReflectanceStart(); // every 10ms
|
||||
}
|
||||
|
||||
if (2 == (tick_count % 10)) {
|
||||
uint8_t r = ReflectanceRead(1000);
|
||||
uint8_t r = ReflectanceEnd();
|
||||
DebugDump( BumpRead(), ReflectancePosition(r) );
|
||||
return;
|
||||
}
|
||||
|
|
34
lab4/main.c
34
lab4/main.c
|
@ -44,16 +44,17 @@ void SwitchInit(void) {
|
|||
}
|
||||
|
||||
void WaitTouchRelease(void) {
|
||||
while(!(SW1IN || SW2IN)) {} // wait for touch
|
||||
while(SW1IN || SW2IN) {} // wait for release
|
||||
while(!(SW1IN || SW2IN)); // wait for touch
|
||||
while( SW1IN || SW2IN ); // wait for release
|
||||
}
|
||||
|
||||
int main_test_systick(void) {
|
||||
int main_f(void) {
|
||||
ClockInit48MHz();
|
||||
SysTickInit();
|
||||
RedLEDInit();
|
||||
uint32_t H = 7500;
|
||||
uint32_t H = 5000;
|
||||
uint32_t L = 10000 - H;
|
||||
|
||||
while (true) {
|
||||
P1->OUT |= 0x01;
|
||||
SysTickWait1us(H);
|
||||
|
@ -66,20 +67,37 @@ int main_test_systick(void) {
|
|||
// The heartbeat stops when the operator pushes Button 2
|
||||
// When beating, the P1.0 LED oscillates at 100 Hz (too fast to see with the eye)
|
||||
// and the duty cycle is varied sinuosoidally once a second
|
||||
int main_heartbeat(void) {
|
||||
int main_s(void) {
|
||||
uint32_t H;
|
||||
uint32_t L;
|
||||
uint32_t i = 0;
|
||||
ClockInit48MHz();
|
||||
// write this code
|
||||
SysTickInit();
|
||||
RedLEDInit();
|
||||
|
||||
while (true) {
|
||||
// write this code
|
||||
H = pulse_us[i];
|
||||
L = 10000 - H; // 2. calculate L
|
||||
P1->OUT |= 0x01; // 3. set P1.0 high
|
||||
SysTickWait1us(H); // 4. wait H us
|
||||
P1->OUT &= ~0x01; // 5. clear P1.0 low
|
||||
SysTickWait1us(L); // 6. Wait L us
|
||||
i = (i + 1) % 100;
|
||||
}
|
||||
}
|
||||
|
||||
int main_test_wheels(void) {
|
||||
|
||||
void MotorTestPulse(void);
|
||||
int main(void) {
|
||||
ClockInit48MHz();
|
||||
SysTickInit();
|
||||
SwitchInit();
|
||||
BumpInit();
|
||||
MotorInit(); // your function
|
||||
|
||||
// MotorForward(1500, 100);
|
||||
// return 0;
|
||||
|
||||
while (true) {
|
||||
WaitTouchRelease();
|
||||
MotorForward(1500, 100); // your function
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
CC = arm-none-eabi-gcc
|
||||
|
||||
# The location of the C compiler
|
||||
# ARMGCC_ROOT is used by some makefiles that need to know where the compiler
|
||||
# is installed.
|
||||
ARMGCC_BIN := ${shell which ${CC}}
|
||||
ifeq (${shell test -h ${ARMGCC_BIN} && echo "true" || echo "false"}, true)
|
||||
ARMGCC_ROOT := ${shell dirname ${shell readlink ${ARMGCC_BIN}}}/..
|
||||
else
|
||||
ARMGCC_ROOT := ${shell dirname ${ARMGCC_BIN}}/..
|
||||
endif
|
||||
|
||||
# Search for source files that are not in this directory
|
||||
VPATH = ../common/
|
||||
|
||||
OBJECTS = main.o timer_a1.o delay.o motor.o pwm.o bump.o cpu.o clock.o system.o startup.o syscalls.o
|
||||
|
||||
NAME = lab
|
||||
|
||||
CFLAGS = -I.. -I../inc -I../common \
|
||||
-D__MSP432P401R__ \
|
||||
-DDeviceFamily_MSP432P401x \
|
||||
-mcpu=cortex-m4 \
|
||||
-march=armv7e-m \
|
||||
-mthumb \
|
||||
-std=c99 \
|
||||
-mfloat-abi=hard \
|
||||
-mfpu=fpv4-sp-d16 \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-gstrict-dwarf \
|
||||
-Wall \
|
||||
-I$(ARMGCC_ROOT)/arm-none-eabi/include/newlib-nano \
|
||||
-I$(ARMGCC_ROOT)/arm-none-eabi/include
|
||||
|
||||
LFLAGS = -Wl,-T,../config.lds \
|
||||
-Wl,-Map,$(NAME).map \
|
||||
-march=armv7e-m \
|
||||
-mthumb \
|
||||
-mfloat-abi=hard \
|
||||
-mfpu=fpv4-sp-d16 \
|
||||
-static \
|
||||
-Wl,--gc-sections \
|
||||
-lgcc \
|
||||
-lc \
|
||||
-lm \
|
||||
-lnosys \
|
||||
--specs=nano.specs
|
||||
|
||||
all: $(NAME).out
|
||||
@echo "SUCCESS: Compilation completed successfully."
|
||||
|
||||
%.o: %.c
|
||||
@$(CC) $(CFLAGS) -g $< -c -o $@
|
||||
|
||||
cpu.o: ../common/cpu.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
clock.o: ../common/clock.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
system.o: ../system.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
startup.o: ../startup.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
syscalls.o: ../syscalls.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
$(NAME).out: $(OBJECTS)
|
||||
@$(CC) $(OBJECTS) $(LFLAGS) -o $(NAME).out
|
||||
|
||||
clean: # Redirecting both the stderr and stdout to /dev/null
|
||||
@rm -f $(OBJECTS) > /dev/null 2>&1
|
||||
@rm -f $(NAME).out > /dev/null 2>&1
|
||||
@rm -f $(NAME).map > /dev/null 2>&1
|
|
@ -0,0 +1,147 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../common/cpu.h"
|
||||
#include "../common/motor.h"
|
||||
#include "../common/pwm.h"
|
||||
#include "../common/clock.h"
|
||||
#include "../common/input_capture.h"
|
||||
#include "../common/timer_a1.h"
|
||||
#include "../common/tachometer.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
void RedLEDInit(void) {
|
||||
P1->SEL0 &= ~0x01;
|
||||
P1->SEL1 &= ~0x01; // 1) configure P1.0 as GPIO
|
||||
P1->DIR |= 0x01; // 2) make P1.0 out
|
||||
}
|
||||
|
||||
// bit-banded address
|
||||
#define REDLED (*((volatile uint8_t *)(0x42098040)))
|
||||
|
||||
void ColorLEDInit(void) {
|
||||
P2->SEL0 &= ~0x07;
|
||||
P2->SEL1 &= ~0x07; // 1) configure P2.2-P2.0 as GPIO
|
||||
P2->DIR |= 0x07; // 2) make P2.2-P2.0 out
|
||||
P2->DS |= 0x07; // 3) activate increased drive strength
|
||||
P2->OUT &= ~0x07; // all LEDs off
|
||||
}
|
||||
|
||||
// bit-banded addresses
|
||||
#define BLUEOUT (*((volatile uint8_t *)(0x42098068)))
|
||||
#define GREENOUT (*((volatile uint8_t *)(0x42098064)))
|
||||
#define REDOUT (*((volatile uint8_t *)(0x42098060)))
|
||||
|
||||
uint16_t period0, period1; // (1/SMCLK) units = 83.3 ns units
|
||||
uint16_t first0, first1; // Timer A3 first edge, P10.4/.5
|
||||
bool done0, done1; // set each rising
|
||||
|
||||
// max period is (2^16-1)*83.3 ns = 5.4612 ms
|
||||
// min period determined by time to run ISR, which is about 1 us
|
||||
void PeriodMeasure0(uint16_t time) {
|
||||
REDOUT ^= 1;
|
||||
period0 = time - first0; // 83.3 ns resolution
|
||||
first0 = time; // setup for next
|
||||
done0 = true;
|
||||
}
|
||||
|
||||
// max period is (2^16-1)*83.3 ns = 5.4612 ms
|
||||
// min period determined by time to run ISR, which is about 1 us
|
||||
void PeriodMeasure1(uint16_t time) {
|
||||
REDLED ^= 1;
|
||||
period1 = time - first1; // 83.3 ns resolution
|
||||
first1 = time; // setup for next
|
||||
done1 = true;
|
||||
}
|
||||
|
||||
void dummy() {
|
||||
volatile int i = 1;
|
||||
i = i + 2;
|
||||
return;
|
||||
}
|
||||
int main(void) {
|
||||
CPU_cpsid(); // Disable interrupts
|
||||
ClockInit48MHz(); // 48 MHz clock; 12 MHz Timer A clock
|
||||
RedLEDInit();
|
||||
ColorLEDInit();
|
||||
PWMInitMotor(7502);
|
||||
MotorInit();
|
||||
TimerA1Init(&dummy, 1000);
|
||||
TimerA3CaptureInit(&PeriodMeasure0, &PeriodMeasure1);
|
||||
// MotorForward(3751, 3751); // 50%
|
||||
// MotorForward(1000, 1000);
|
||||
CPU_cpsie(); // Enable interrupts
|
||||
CPU_wfi(); // Wait for interrupt
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t speed_buf[500]; // RPM, radius 0.035m wheels
|
||||
uint32_t period_buf[500]; // 1/12MHz = 0.083 usec
|
||||
uint32_t duty; // 0 to 15000
|
||||
uint32_t time; // in 0.01 sec
|
||||
|
||||
void Collect(void) {
|
||||
GREENOUT ^= 1;
|
||||
if (!done0) period0 = 0xFFFF - 1; // stopped
|
||||
if (!done1) period1 = 0xFFFF - 1;
|
||||
done0 = done1 = false; // set on subsequent
|
||||
switch (time) {
|
||||
case 0:
|
||||
duty = 1875; // 25%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 100:
|
||||
duty = 3751; // 50%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 200:
|
||||
duty = 5626; // 75%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 300:
|
||||
duty = 3751; // 50%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 400:
|
||||
duty = 1875; // 25%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 500:
|
||||
MotorStop();
|
||||
TIMER_A1->CTL &= ~0x30; // Halt timer A1
|
||||
break;
|
||||
default:
|
||||
speed_buf[time] = 2000000 / period0;
|
||||
period_buf[time] = period0;
|
||||
break;
|
||||
}
|
||||
++time;
|
||||
}
|
||||
|
||||
int main_collect(void) {
|
||||
CPU_cpsid(); // Disable interrupts
|
||||
ClockInit48MHz(); // 48 MHz clock; 12 MHz Timer A clock
|
||||
RedLEDInit();
|
||||
ColorLEDInit();
|
||||
PWMInitMotor(7502);
|
||||
MotorInit();
|
||||
TimerA3CaptureInit(&PeriodMeasure0, &PeriodMeasure1);
|
||||
TimerA1Init(&Collect, 5000); // 100 Hz
|
||||
CPU_cpsie(); // Enable interrupts
|
||||
CPU_wfi(); // Wait for interrupt
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main_tach(void) {
|
||||
CPU_cpsid(); // Disable interrupts
|
||||
ClockInit48MHz();
|
||||
PWMInitMotor(7502);
|
||||
MotorInit();
|
||||
TachometerInit();
|
||||
MotorForward(2000, 2000); // confirm if rotating forward
|
||||
//MotorBackward(2000, 2000); // confirm if rotating backward
|
||||
CPU_cpsie(); // Enable interrupts
|
||||
CPU_wfi(); // Wait for interrupt
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
CC = arm-none-eabi-gcc
|
||||
|
||||
# The location of the C compiler
|
||||
# ARMGCC_ROOT is used by some makefiles that need to know where the compiler
|
||||
# is installed.
|
||||
ARMGCC_BIN := ${shell which ${CC}}
|
||||
ifeq (${shell test -h ${ARMGCC_BIN} && echo "true" || echo "false"}, true)
|
||||
ARMGCC_ROOT := ${shell dirname ${shell readlink ${ARMGCC_BIN}}}/..
|
||||
else
|
||||
ARMGCC_ROOT := ${shell dirname ${ARMGCC_BIN}}/..
|
||||
endif
|
||||
|
||||
# Search for source files that are not in this directory
|
||||
VPATH = ../common/
|
||||
|
||||
OBJECTS = main.o timer_a1.o motor.o pwm.o input_capture.o tachometer.o cpu.o clock.o system.o startup.o syscalls.o
|
||||
|
||||
NAME = lab
|
||||
|
||||
CFLAGS = -I.. -I../inc -I../common \
|
||||
-D__MSP432P401R__ \
|
||||
-DDeviceFamily_MSP432P401x \
|
||||
-mcpu=cortex-m4 \
|
||||
-march=armv7e-m \
|
||||
-mthumb \
|
||||
-std=c99 \
|
||||
-mfloat-abi=hard \
|
||||
-mfpu=fpv4-sp-d16 \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-gstrict-dwarf \
|
||||
-Wall \
|
||||
-I$(ARMGCC_ROOT)/arm-none-eabi/include/newlib-nano \
|
||||
-I$(ARMGCC_ROOT)/arm-none-eabi/include
|
||||
|
||||
LFLAGS = -Wl,-T,../config.lds \
|
||||
-Wl,-Map,$(NAME).map \
|
||||
-march=armv7e-m \
|
||||
-mthumb \
|
||||
-mfloat-abi=hard \
|
||||
-mfpu=fpv4-sp-d16 \
|
||||
-static \
|
||||
-Wl,--gc-sections \
|
||||
-lgcc \
|
||||
-lc \
|
||||
-lm \
|
||||
-lnosys \
|
||||
--specs=nano.specs
|
||||
|
||||
all: $(NAME).out
|
||||
@echo "SUCCESS: Compilation completed successfully."
|
||||
|
||||
%.o: %.c
|
||||
@$(CC) $(CFLAGS) -g $< -c -o $@
|
||||
|
||||
cpu.o: ../common/cpu.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
clock.o: ../common/clock.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
system.o: ../system.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
startup.o: ../startup.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
syscalls.o: ../syscalls.c
|
||||
@$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
$(NAME).out: $(OBJECTS)
|
||||
@$(CC) $(OBJECTS) $(LFLAGS) -o $(NAME).out
|
||||
|
||||
clean: # Redirecting both the stderr and stdout to /dev/null
|
||||
@rm -f $(OBJECTS) > /dev/null 2>&1
|
||||
@rm -f $(NAME).out > /dev/null 2>&1
|
||||
@rm -f $(NAME).map > /dev/null 2>&1
|
|
@ -0,0 +1,149 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../common/cpu.h"
|
||||
#include "../common/motor.h"
|
||||
#include "../common/pwm.h"
|
||||
#include "../common/clock.h"
|
||||
#include "../common/input_capture.h"
|
||||
#include "../common/timer_a1.h"
|
||||
#include "../common/tachometer.h"
|
||||
|
||||
#include "inc/msp432p401r.h"
|
||||
|
||||
void RedLEDInit(void) {
|
||||
P1->SEL0 &= ~0x01;
|
||||
P1->SEL1 &= ~0x01; // 1) configure P1.0 as GPIO
|
||||
P1->DIR |= 0x01; // 2) make P1.0 out
|
||||
}
|
||||
|
||||
// bit-banded address
|
||||
#define REDLED (*((volatile uint8_t *)(0x42098040)))
|
||||
|
||||
void ColorLEDInit(void) {
|
||||
P2->SEL0 &= ~0x07;
|
||||
P2->SEL1 &= ~0x07; // 1) configure P2.2-P2.0 as GPIO
|
||||
P2->DIR |= 0x07; // 2) make P2.2-P2.0 out
|
||||
P2->DS |= 0x07; // 3) activate increased drive strength
|
||||
P2->OUT &= ~0x07; // all LEDs off
|
||||
}
|
||||
|
||||
// bit-banded addresses
|
||||
#define BLUEOUT (*((volatile uint8_t *)(0x42098068)))
|
||||
#define GREENOUT (*((volatile uint8_t *)(0x42098064)))
|
||||
#define REDOUT (*((volatile uint8_t *)(0x42098060)))
|
||||
|
||||
uint16_t period0, period1; // (1/SMCLK) units = 83.3 ns units
|
||||
uint16_t first0, first1; // Timer A3 first edge, P10.4/.5
|
||||
bool done0, done1; // set each rising
|
||||
|
||||
// max period is (2^16-1)*83.3 ns = 5.4612 ms
|
||||
// min period determined by time to run ISR, which is about 1 us
|
||||
void PeriodMeasure0(uint16_t time) {
|
||||
REDOUT ^= 1;
|
||||
period0 = time - first0; // 83.3 ns resolution
|
||||
first0 = time; // setup for next
|
||||
done0 = true;
|
||||
}
|
||||
|
||||
// max period is (2^16-1)*83.3 ns = 5.4612 ms
|
||||
// min period determined by time to run ISR, which is about 1 us
|
||||
void PeriodMeasure1(uint16_t time) {
|
||||
REDLED ^= 1;
|
||||
period1 = time - first1; // 83.3 ns resolution
|
||||
first1 = time; // setup for next
|
||||
done1 = true;
|
||||
}
|
||||
|
||||
void dummy() {
|
||||
volatile int i = 1;
|
||||
i = i + 2;
|
||||
return;
|
||||
}
|
||||
|
||||
int main_f(void) {
|
||||
CPU_cpsid(); // Disable interrupts
|
||||
ClockInit48MHz(); // 48 MHz clock; 12 MHz Timer A clock
|
||||
RedLEDInit();
|
||||
ColorLEDInit();
|
||||
PWMInitMotor(3751);
|
||||
MotorInit();
|
||||
// TimerA1Init(&dummy, 1000);
|
||||
TimerA3CaptureInit(&PeriodMeasure0, &PeriodMeasure1);
|
||||
// MotorForward(3751, 3751); // 50%
|
||||
// MotorForward(1000, 1000);
|
||||
CPU_cpsie(); // Enable interrupts
|
||||
CPU_wfi(); // Wait for interrupt
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t speed_buf[500]; // RPM, radius 0.035m wheels
|
||||
uint32_t period_buf[500]; // 1/12MHz = 0.083 usec
|
||||
uint32_t duty; // 0 to 15000
|
||||
uint32_t time; // in 0.01 sec
|
||||
|
||||
void Collect(void) {
|
||||
GREENOUT ^= 1;
|
||||
if (!done0) period0 = 0xFFFF - 1; // stopped
|
||||
if (!done1) period1 = 0xFFFF - 1;
|
||||
done0 = done1 = false; // set on subsequent
|
||||
switch (time) {
|
||||
case 0:
|
||||
duty = 1875; // 25%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 100:
|
||||
duty = 3751; // 50%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 200:
|
||||
duty = 5626; // 75%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 300:
|
||||
duty = 3751; // 50%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 400:
|
||||
duty = 1875; // 25%
|
||||
MotorForward(duty, duty);
|
||||
break;
|
||||
case 500:
|
||||
MotorStop();
|
||||
TIMER_A1->CTL &= ~0x30; // Halt timer A1
|
||||
break;
|
||||
default:
|
||||
speed_buf[time] = 2000000 / period0;
|
||||
period_buf[time] = period0;
|
||||
break;
|
||||
}
|
||||
++time;
|
||||
}
|
||||
|
||||
int main_s(void) {
|
||||
CPU_cpsid(); // Disable interrupts
|
||||
ClockInit48MHz(); // 48 MHz clock; 12 MHz Timer A clock
|
||||
RedLEDInit();
|
||||
ColorLEDInit();
|
||||
PWMInitMotor(3751);
|
||||
MotorInit();
|
||||
TimerA3CaptureInit(&PeriodMeasure0, &PeriodMeasure1);
|
||||
TimerA1Init(&Collect, 5000); // 100 Hz
|
||||
CPU_cpsie(); // Enable interrupts
|
||||
CPU_wfi(); // Wait for interrupt
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CPU_cpsid(); // Disable interrupts
|
||||
ClockInit48MHz();
|
||||
PWMInitMotor(3751);
|
||||
MotorInit();
|
||||
TachometerInit();
|
||||
// MotorForward(2000, 2000); // confirm if rotating forward
|
||||
//MotorBackward(2000, 2000); // confirm if rotating backward
|
||||
CPU_cpsie(); // Enable interrupts
|
||||
// CPU_wfi(); // Wait for interrupt
|
||||
while (1);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue