add lab w8 (week 9)
This commit is contained in:
296
labs/lab_w8/main.c
Normal file
296
labs/lab_w8/main.c
Normal file
@@ -0,0 +1,296 @@
|
||||
#include "Clock.h"
|
||||
#include "msp.h"
|
||||
#include <stdint.h>
|
||||
|
||||
//=============================================================================
|
||||
// 1. 상수 정의 (Constants)
|
||||
//=============================================================================
|
||||
// (!!주의!!) SMCLK = 12MHz 기준입니다.
|
||||
#define RPM_MAGIC_NUMBER 2000000
|
||||
#define TIMER_A0_PWM_PERIOD_TICKS 15000
|
||||
#define STALL_TIMER_PERIOD 50000
|
||||
|
||||
#define LEFT_PWM_PIN BIT7
|
||||
#define LEFT_DIR_PIN BIT5
|
||||
#define LEFT_SLEEP_PIN BIT7
|
||||
|
||||
#define RIGHT_PWM_PIN BIT6
|
||||
#define RIGHT_DIR_PIN BIT4
|
||||
#define RIGHT_SLEEP_PIN BIT6
|
||||
|
||||
#define TURN_30_DEG_PULSES 60
|
||||
#define TURN_SPEED 2000
|
||||
|
||||
static volatile uint32_t g_left_pulse_period = 0;
|
||||
static volatile uint32_t g_right_pulse_period = 0;
|
||||
static volatile uint16_t g_last_left_capture = 0;
|
||||
static volatile uint16_t g_last_right_capture = 0;
|
||||
static volatile uint32_t g_left_pulse_count = 0;
|
||||
static volatile uint32_t g_right_pulse_count = 0;
|
||||
|
||||
static volatile uint8_t g_left_new_data = 0;
|
||||
static volatile uint8_t g_right_new_data = 0;
|
||||
|
||||
/*
|
||||
FUNCTION DECLARATIONS
|
||||
*/
|
||||
void Motor_Init(void);
|
||||
void Motor_Left_Forward(uint16_t speed);
|
||||
void Motor_Left_Backward(uint16_t speed);
|
||||
void Motor_Right_Forward(uint16_t speed);
|
||||
void Motor_Right_Backward(uint16_t speed);
|
||||
void Motor_Left_Stop(void);
|
||||
void Motor_Right_Stop(void);
|
||||
void Motor_Stop_All(void);
|
||||
|
||||
void rpm_tachometer_init(void);
|
||||
uint32_t get_left_rpm(void);
|
||||
uint32_t get_right_rpm(void);
|
||||
void reset_pulse_counts(void);
|
||||
uint32_t get_left_pulse_count(void);
|
||||
uint32_t get_right_pulse_count(void);
|
||||
|
||||
static void capture_init_timer_A3(void);
|
||||
static void Timer_A2_Stall_Init(void);
|
||||
void Rotate_30_Degrees(void);
|
||||
|
||||
/*
|
||||
MAIN FUNCTION
|
||||
*/
|
||||
int main(void) {
|
||||
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;
|
||||
|
||||
Clock_Init48MHz();
|
||||
|
||||
Motor_Init();
|
||||
rpm_tachometer_init();
|
||||
|
||||
__enable_irq();
|
||||
|
||||
__delay_cycles(12000000);
|
||||
|
||||
Rotate_30_Degrees();
|
||||
|
||||
while (1) {
|
||||
Clock_Delay1ms(1000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
IMPLEMENTATIONS 30DEG ROT. FUNCTION
|
||||
*/
|
||||
void Rotate_30_Degrees(void) {
|
||||
reset_pulse_counts();
|
||||
Motor_Left_Forward(TURN_SPEED);
|
||||
Motor_Right_Backward(TURN_SPEED);
|
||||
|
||||
uint8_t left_reached = 0;
|
||||
uint8_t right_reached = 0;
|
||||
|
||||
while (left_reached == 0 || right_reached == 0) {
|
||||
if (left_reached == 0) {
|
||||
if (get_left_pulse_count() >= TURN_30_DEG_PULSES) {
|
||||
Motor_Left_Stop();
|
||||
left_reached = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (right_reached == 0) {
|
||||
if (get_right_pulse_count() >= TURN_30_DEG_PULSES) {
|
||||
Motor_Right_Stop();
|
||||
right_reached = 1;
|
||||
}
|
||||
}
|
||||
__delay_cycles(1000);
|
||||
}
|
||||
|
||||
Motor_Stop_All();
|
||||
}
|
||||
|
||||
/*
|
||||
IMPLEMENTATION MOTOR RELATIVE FUNCTIONS
|
||||
*/
|
||||
void Motor_Init(void) {
|
||||
P3->OUT |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
P3->DIR |= (LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
P3->SEL0 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
P3->SEL1 &= ~(LEFT_SLEEP_PIN | RIGHT_SLEEP_PIN);
|
||||
|
||||
P5->OUT &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
P5->DIR |= (LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
P5->SEL0 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
P5->SEL1 &= ~(LEFT_DIR_PIN | RIGHT_DIR_PIN);
|
||||
|
||||
P2->OUT &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
P2->DIR |= (LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
P2->SEL0 |= (LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
P2->SEL1 &= ~(LEFT_PWM_PIN | RIGHT_PWM_PIN);
|
||||
|
||||
TIMER_A0->CTL = TIMER_A_CTL_SSEL__SMCLK |
|
||||
TIMER_A_CTL_ID__1 |
|
||||
TIMER_A_CTL_CLR;
|
||||
TIMER_A0->CCR[0] = TIMER_A0_PWM_PERIOD_TICKS;
|
||||
|
||||
TIMER_A0->CCTL[3] = TIMER_A_CCTLN_OUTMOD_7;
|
||||
TIMER_A0->CCR[3] = 0;
|
||||
|
||||
TIMER_A0->CCTL[4] = TIMER_A_CCTLN_OUTMOD_7;
|
||||
TIMER_A0->CCR[4] = 0;
|
||||
|
||||
TIMER_A0->CTL |= TIMER_A_CTL_MC__UP;
|
||||
}
|
||||
|
||||
void Motor_Left_Forward(uint16_t speed) {
|
||||
if (speed > TIMER_A0_PWM_PERIOD_TICKS) speed = TIMER_A0_PWM_PERIOD_TICKS;
|
||||
P5->OUT &= ~LEFT_DIR_PIN;
|
||||
TIMER_A0->CCR[4] = speed;
|
||||
}
|
||||
|
||||
void Motor_Left_Backward(uint16_t speed) {
|
||||
if (speed > TIMER_A0_PWM_PERIOD_TICKS) speed = TIMER_A0_PWM_PERIOD_TICKS;
|
||||
P5->OUT |= LEFT_DIR_PIN;
|
||||
TIMER_A0->CCR[4] = speed;
|
||||
}
|
||||
|
||||
void Motor_Right_Forward(uint16_t speed) {
|
||||
if (speed > TIMER_A0_PWM_PERIOD_TICKS) speed = TIMER_A0_PWM_PERIOD_TICKS;
|
||||
P5->OUT &= ~RIGHT_DIR_PIN;
|
||||
TIMER_A0->CCR[3] = speed;
|
||||
}
|
||||
|
||||
void Motor_Right_Backward(uint16_t speed) {
|
||||
if (speed > TIMER_A0_PWM_PERIOD_TICKS) speed = TIMER_A0_PWM_PERIOD_TICKS;
|
||||
P5->OUT |= RIGHT_DIR_PIN;
|
||||
TIMER_A0->CCR[3] = speed;
|
||||
}
|
||||
|
||||
void Motor_Left_Stop(void) {
|
||||
TIMER_A0->CCR[4] = 0;
|
||||
}
|
||||
|
||||
void Motor_Right_Stop(void) {
|
||||
TIMER_A0->CCR[3] = 0;
|
||||
}
|
||||
|
||||
void Motor_Stop_All(void) {
|
||||
Motor_Left_Stop();
|
||||
Motor_Right_Stop();
|
||||
}
|
||||
|
||||
/*
|
||||
IMPLEMENTATION RPM FUNC.
|
||||
*/
|
||||
void rpm_tachometer_init(void) {
|
||||
capture_init_timer_A3();
|
||||
Timer_A2_Stall_Init();
|
||||
}
|
||||
|
||||
uint32_t get_left_rpm(void) {
|
||||
uint32_t period;
|
||||
__disable_irq();
|
||||
period = g_left_pulse_period;
|
||||
__enable_irq();
|
||||
|
||||
if (period == 0) return 0;
|
||||
return RPM_MAGIC_NUMBER / period;
|
||||
}
|
||||
|
||||
uint32_t get_right_rpm(void) {
|
||||
uint32_t period;
|
||||
__disable_irq();
|
||||
period = g_right_pulse_period;
|
||||
__enable_irq();
|
||||
|
||||
if (period == 0) return 0;
|
||||
return RPM_MAGIC_NUMBER / period;
|
||||
}
|
||||
|
||||
void reset_pulse_counts(void) {
|
||||
__disable_irq();
|
||||
g_left_pulse_count = 0;
|
||||
g_right_pulse_count = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
uint32_t get_left_pulse_count(void) {
|
||||
uint32_t count;
|
||||
__disable_irq();
|
||||
count = g_left_pulse_count;
|
||||
__enable_irq();
|
||||
return count;
|
||||
}
|
||||
uint32_t get_right_pulse_count(void) {
|
||||
uint32_t count;
|
||||
__disable_irq();
|
||||
count = g_right_pulse_count;
|
||||
__enable_irq();
|
||||
return count;
|
||||
}
|
||||
|
||||
static void Timer_A2_Stall_Init(void) {
|
||||
TIMER_A2->CTL = TIMER_A_CTL_SSEL__SMCLK |
|
||||
TIMER_A_CTL_ID__2 |
|
||||
TIMER_A_CTL_MC__STOP;
|
||||
TIMER_A2->CCTL[0] = TIMER_A_CCTLN_CCIE;
|
||||
TIMER_A2->CCR[0] = (STALL_TIMER_PERIOD - 1);
|
||||
TIMER_A2->EX0 = TIMER_A_EX0_TAIDEX_5;
|
||||
|
||||
NVIC->IP[3] = (NVIC->IP[3] & 0xFFFFFF00) | 0x40;
|
||||
NVIC->ISER[0] = 1 << TA2_0_IRQn;
|
||||
|
||||
TIMER_A2->CTL |= TIMER_A_CTL_MC__UP | TIMER_A_CTL_CLR;
|
||||
}
|
||||
|
||||
void TA2_0_IRQHandler(void) {
|
||||
TIMER_A2->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG;
|
||||
|
||||
if (g_left_new_data == 0) g_left_pulse_period = 0;
|
||||
else
|
||||
g_left_new_data = 0;
|
||||
|
||||
if (g_right_new_data == 0) g_right_pulse_period = 0;
|
||||
else
|
||||
g_right_new_data = 0;
|
||||
}
|
||||
|
||||
static void capture_init_timer_A3(void) {
|
||||
TIMER_A3->CTL = TIMER_A_CTL_SSEL__SMCLK |
|
||||
TIMER_A_CTL_MC__CONTINUOUS |
|
||||
TIMER_A_CTL_ID__1 |
|
||||
TIMER_A_CTL_CLR;
|
||||
P10->SEL0 |= BIT4;
|
||||
P10->SEL1 &= ~BIT4;
|
||||
P10->DIR &= ~BIT4;
|
||||
TIMER_A3->CCTL[0] = TIMER_A_CCTLN_CM_1 | TIMER_A_CCTLN_CCIS_0 |
|
||||
TIMER_A_CCTLN_SCS | TIMER_A_CCTLN_CAP | TIMER_A_CCTLN_CCIE;
|
||||
P10->SEL0 |= BIT5;
|
||||
P10->SEL1 &= ~BIT5;
|
||||
P10->DIR &= ~BIT5;
|
||||
TIMER_A3->CCTL[1] = TIMER_A_CCTLN_CM_1 | TIMER_A_CCTLN_CCIS_0 |
|
||||
TIMER_A_CCTLN_SCS | TIMER_A_CCTLN_CAP | TIMER_A_CCTLN_CCIE;
|
||||
NVIC->IP[3] = (NVIC->IP[3] & 0x00FFFFFF) | 0x40000000;
|
||||
NVIC->ISER[0] = 1 << TA3_0_IRQn;
|
||||
NVIC->IP[4] = (NVIC->IP[4] & 0xFFFFFF00) | 0x40;
|
||||
NVIC->ISER[0] = 1 << TA3_N_IRQn;
|
||||
}
|
||||
|
||||
void TA3_0_IRQHandler(void) {
|
||||
TIMER_A3->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG;
|
||||
uint16_t current_capture = TIMER_A3->CCR[0];
|
||||
uint32_t period = (current_capture > g_last_right_capture) ? (current_capture - g_last_right_capture) : ((0xFFFF - g_last_right_capture) + current_capture + 1);
|
||||
g_right_pulse_period = period;
|
||||
g_right_new_data = 1;
|
||||
g_last_right_capture = current_capture;
|
||||
g_right_pulse_count++;
|
||||
}
|
||||
|
||||
void TA3_N_IRQHandler(void) {
|
||||
if (TIMER_A3->CCTL[1] & TIMER_A_CCTLN_CCIFG) {
|
||||
TIMER_A3->CCTL[1] &= ~TIMER_A_CCTLN_CCIFG;
|
||||
uint16_t current_capture = TIMER_A3->CCR[1];
|
||||
uint32_t period = (current_capture > g_last_left_capture) ? (current_capture - g_last_left_capture) : ((0xFFFF - g_last_left_capture) + current_capture + 1);
|
||||
g_left_pulse_period = period;
|
||||
g_left_new_data = 1;
|
||||
g_last_left_capture = current_capture;
|
||||
g_left_pulse_count++;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user