Last active
November 28, 2020 14:03
-
-
Save totoroAKI/14b6ff129a4f9caafbeb1ccdf0861cce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <msp430.h> //MSP430F2619TPM | |
/* main.c */ | |
//* GPIO pin definitions *///////////////////////////////////////// | |
// LED | |
#define test_LED 0b00000001 // P1.0 test_LED | |
#define YELLOW_LED 0b00000001 // P4.0 YELLOW_LED [TB0] | |
#define RED_LED 0b00000010 // P4.1 RED_LED | |
#define BLUE_LED 0b00000100 // P4.2 BLUE_LED | |
#define GREEN_LED 0b00001000 // P4.3 GREEN_LED | |
//CLK monitor | |
#define MCLK 0b00010000 // P5.4 MCLK監視 [MCLK] | |
#define SMCLK 0b00100000 // P5.5 SMCLK監視 [SMCLK] | |
#define ACLK 0b01000000 // P5.6 ACLK監視 [ACLK] | |
// CONTROL | |
#define P2LPM 0b00010000 // P2.4 [JP10] LPMに入る/戻る指示を、ここの割り込みでやる | |
// ADC | |
#define ADC0 0b00000001 // P6.0 [A0] | |
#define ADC1 0b00000010 // P6.1 [A1] | |
#define ADC2 0b00000100 // P6.2 [A2] | |
// DAC | |
#define DAC0 0b01000000 // P6.6 [DAC0] | |
#define DAC1 0b10000000 // P6.7 [DAC1] | |
#define DA_max 4095 // 上限値 | |
#define DA_min 2000 // 下限値: LEDの順方向電圧 | |
// Timer B // TBCCR: 16bitレジスタだから、最大値は2^16-1 = 65,536-1 = 65,535 | |
#define Tpwm0 16000000/*入力CLK*/ /8/*DIVS*/ /8/*ID*/ /8000/*目標周波数*/ - 1 // TimerBの分周用カウンタ // コンペアマッチする周期を50kHzに設定 DIVS: /8, ID: /8 | |
#define Tpwm3 32768/*入力CLK*/ /1/*DIVA*/ /2/*ID*/ /2000/*目標周波数*/ - 1 // TimerBの分周用カウンタ // コンペアマッチする周期を 4kHzに設定 DIVA: /1, ID: /2 | |
#define DIV_Tpwm0 8000/*入力CLK*/ /2/*三角波だから*/ /2/*目標周波数*/ // LPM0 | |
#define DIV_Tpwm3 2000/*入力CLK*/ /2/*三角波だから*/ *2/*目標周波数*/ // LPM3 | |
//* GPIO pin definitions *///////////////////////////////////////// | |
//* Global variables definitions *///////////////////////////////// | |
short TIMER_INTR_FLAG = 0; // タイマー割り込みが掛かった | |
short P2_INTR_FLAG = 0; // 外部ボタン割り込みが掛かった | |
short LPMode_FLAG = 0; // ローパワーモードのどこに入っているか 0:LPM0.TimerB.DCO , 1:LPM3.TimerB.LFXT | |
//* Global variables definitions *///////////////////////////////// | |
//* Local function definitions *////////////////////////////////// | |
static inline void SETUP( void ); | |
static inline void GPIO_Init( void ); | |
static inline void TIMERB_Init( void ); | |
static inline void ADC12_Init( void ); | |
static inline void DAC12_Init( void ); | |
//* Local function definitions *////////////////////////////////// | |
//* Initial definitions *////////////////////////////////////////// | |
static inline void DAC12_Init( void ){ | |
// ※Must be connected VeRef+(10pin) to AVcc+ // 25.3.1 DAC12_xCTL, DAC12 Control Register | |
DAC12_1CTL |= DAC12SREF_2 + DAC12IR + DAC12AMP_2; // VeRef = AVcc (3.3V) , full scale = VerRef = AVcc に設定する | |
DAC12_0CTL |= DAC12SREF_2 + DAC12IR + DAC12AMP_2; // VeRef = AVcc (3.3V) , full scale = VerRef = AVcc に設定する | |
// DAC12SREFx:Bits 14-13 DAC12 select reference voltage; initial Ref:VREF+, external Ref:VeREF+ | |
// DAC12IR Bit 8 DAC12 input range. This bit sets the reference input and voltage output range. | |
// 0 DAC12 full-scale output = 3x reference voltage | |
// 1 DAC12 full-scale output = 1x reference voltage | |
// DAC12AMPx:Bits 7-5 DAC12 amplifier setting. These bits select settling time vs current consumption | |
// DAC12AMPx Input Buffer Output Buffer | |
// 010 Low speed/current Low speed/current | |
// DAC12ENC Bit 1 DAC12 enable conversion. This bit enables the DAC12 module when DAC12LSELx > 0. when DAC12LSELx = 0, DAC12ENC is ignored. | |
// 0 DAC12 disabled | |
// 1 DAC12 enabled | |
DAC12_1DAT = 0x000; // ここでマイコン起動後のDACの初期値を決定する | |
DAC12_0DAT = 0x000; // DAC12 Data Register -Bits 11-0 | |
// Output voltage = (Full scale)/0xFFF * DAT =~ 0.8mV/1bit(?) | |
} | |
static inline void ADC12_Init( void ){ | |
// 主参照電圧: AVcc 3.3V デフォルト // The ADC12OSC is generated internally and is in the 5-MHz range | |
ADC12CTL0 = SHT1_3 + SHT0_3 + REFON + ADC12ON + MSC; | |
ADC12CTL1 = SHS_0 + SHP + ADC12SSEL_0 + CONSEQ_1; // Use sampling timer, Multi-channel, single-conversion | |
//// 各チャンネルの設定 //// | |
ADC12MCTL0 = SREF_2 + INCH_0; // VRef = Ve_ref+, channel = A0 | |
ADC12MCTL1 = SREF_2 + INCH_1; // VRef = Ve_ref+, channel = A1 | |
ADC12MCTL2 = SREF_2 + INCH_2; // VRef = Ve_ref+, channel = A2 | |
ADC12MCTL3 = SREF_1 + INCH_10 + EOS; // VRef = Vref+ (internal 1.5V), channel = A10, end of seq. CPU内部温度センサの電圧を取得 | |
} | |
static inline void TIMERB_Init( void ){ | |
TBCTL |= TBSSEL_2 + ID_3 + MC_1; // Timer_B Control resister (13.3.1 TBCTL, Timer_A Control Register P.391) | |
TBCCR0 = Tpwm0; // TBCCRx:Bits 15-0 TBCCRx:Timer_B Capture/Compare Resister (13.3.3 TBCCRx, Timer_B Capture/Compare Register x, P.390) | |
TBCCR4 = Tpwm0 * 0.2; | |
TBCCTL0 |= CCIE + OUTMOD_7; // 13.3.4 TBCCTLx, Capture/Compare Control Register, P. | |
TBCCTL4 |= OUTMOD_7; | |
} | |
static inline void GPIO_Init( void ){ | |
P1DIR |= test_LED; // P1.0:OUT | |
P2DIR |= 0xFF; // P2 All Output | |
P2DIR &= ~P2LPM; // P2.4 Input | |
P2OUT &= 0x00; // P2.4以外 Output low | |
P4DIR |= 0xFF; | |
P4OUT &= 0x00; // Output low | |
P4SEL |= YELLOW_LED; // P4.4: TimerB4 | |
P5DIR |= MCLK | SMCLK | ACLK; // P5.4 ~ 5.6:OUT | |
P5SEL |= MCLK | SMCLK | ACLK; // P5.4にはMCLKが出力される | |
P6DIR &= 0x00; // P6 :IN | |
P6SEL |= ADC0 | ADC1 | ADC2; // P6.0, P6.1; Primary peripheral module function = A0, A1, A2 | |
// DACについては特にピン設定は必要ない | |
// Port2 interrupt // 8.2.7 P1 and P2 Interrupts | |
P2IE |= P2LPM; // P2.4 interrupt enabled [JP10] | |
P2IES |= P2LPM; // 0: low-to-high edge 1: high-to-low edge | |
P2IFG &= ~P2LPM; // P2 IFG cleared | |
// Setup GPIO ////////////////////////////////////////////////////////////////// | |
} | |
static inline void SETUP(void){ | |
// Stop WathcDog Timer // | |
WDTCTL = WDTPW + WDTHOLD; // Stop WathcDog Timer, | |
// Supply Voltage Supervisor // | |
SVSCTL &= ~SVSFG; // 低電圧フラグを消去 Supply Voltage Supervisor | |
SVSCTL = 0x60 + PORON; // SVS POR enabled @ 2.5V 電圧低下検出.この電圧以下ではマイコンリセット. | |
while(!(SVSCTL & SVSON)); // 電圧監視機能がONになるまで待機 | |
// Setup Clock system ///////////////////////////////////////////// | |
BCSCTL1 = CALBC1_16MHZ; // Set RSELx | |
DCOCTL = CALDCO_16MHZ; // Set DCOx and MODx = MCLK :16MHZ | |
BCSCTL1 |= XT2OFF + DIVA_0; // XT2OFF; 1 XT2OSC stop | |
BCSCTL2 |= SELM_0 + DIVM_0 /* +SELSx */ + DIVS_3; | |
// SELMx MCLK source; 00: DCOCLK | |
// SELSx SMCLK source; 0: DCOCLK 1: LFXT1CLK | |
BCSCTL3 |= LFXT1S_0 + XCAP_3; // Source of Low frequency : VLOCLK | |
// LFXT1 source; These bits select between LFXT1 and VLO when XTS = 0, and select the frequency range for LFXT1 when XTS = 1. | |
// When XTS = 0: 00: 32768-Hz crystal on LFXT1 | |
// XCAPx Bits 3-2 Oscillator capacitor selection. 11 ~12.5 pF | |
// 種類 ソース 周波数 | |
// MCLK : DCO : 16MHz | |
// SMCLK : DCO : 250kHz | |
// ACLK : LFXT1S : 16kHz | |
// Setup Clock system ///////////////////////////////////////////// | |
} | |
//////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////// | |
/*!!! ************************************************ | |
* タイマー割り込みの処理 | |
******************************************************/ | |
#pragma vector = TIMERB0_VECTOR // Datasheet, Interrupt Vector Addresses P.16 | |
__interrupt void TIMER_B0(void){ // Timer interrupt 発生時に割り込む関数の定義 | |
//<<割り込み要件>> タイマーがCMしたとき。 | |
//<<割り込み処理>> LPM抜ける | |
//LPMode_FLAG : 0:LPM0.TimerB.DCO , 1:LPM3.TimerB.LFXT | |
if( LPMode_FLAG == 0 ){ | |
__bic_SR_register_on_exit(LPM0_bits); // exit LPM3 | |
}else{ // LPMode_FLAG == 1 | |
__bic_SR_register_on_exit(LPM3_bits); // exit LPM3 | |
} | |
if(ADC12BUSY == 1){ | |
ADC12CTL0 |= ADC12SC; // ADC12 enable, start conversion | |
} | |
TIMER_INTR_FLAG = 1; | |
//<<割り込み処理後すること>> | |
TBCTL &= ~TBIFG; // タイマーの割り込みフラグのクリア | |
} | |
//////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////// | |
/*!!! ************************************************ | |
* P2割り込みの処理 | |
******************************************************/ | |
#pragma vector = PORT2_VECTOR | |
__interrupt void Port_2(void){ | |
//<<割り込み要件>> P2IES = 1: high-to-low edge --> ボタン押して、電位下げたらエッジ検出で割り込み | |
//<<割り込み処理>> LPMから復帰 & フラグ立て | |
P2_INTR_FLAG = ~P2_INTR_FLAG; | |
//<<割り込み処理後すること>> | |
P2IFG &= 0x00; // P2 IFG cleared | |
} | |
//////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////// | |
int main(void){ | |
// Initialization | |
SETUP(); // クロックシステム の初期設定.これ以前には何も処理をしないこと | |
GPIO_Init(); // GPIOピン の初期設定 | |
TIMERB_Init(); // TIMER B の初期設定 | |
ADC12_Init(); // ADC12 の初期設定 | |
DAC12_Init(); // DAC12 の初期設定 | |
// setubp Interrupt // | |
__bis_SR_register(GIE); // 汎用割り込み許可 | |
// Start command | |
ADC12CTL0 |= ADC12SC | ENC; // ADC12 enable, start conversion | |
DAC12_0CTL |= DAC12ENC; // DAC go working | |
//* 変数定義 */ //////////////////////////////////////////////////// | |
unsigned int Timer_Counter = 0; // TimerBがコンペアマッチするごとにインクリメント | |
int Up_down_mode = 0; | |
unsigned int AData_0 = 0; // analog data buffer | |
unsigned int AData_1 = 0; // analog data buffer | |
unsigned int AData_2 = 0; // analog data buffer | |
// <<<< Mainループ <<<<<<<<<<<<<<<< | |
while(1){ | |
// LPMから抜けて、ここから始まる | |
AData_0 = ADC12MEM0; | |
AData_1 = ADC12MEM1; | |
AData_2 = ADC12MEM2; | |
// <<<<< P2のボタンを押された割り込み後の処理 <<<<<<<<<<<<<<<< | |
// P2が押されると、P2_INTR_FLAGが反転( 0 <-> 1 )される。 | |
if( LPMode_FLAG != P2_INTR_FLAG ){ | |
if( LPMode_FLAG == 0 ){ | |
//LPMode_FLAG = 0; // ローパワーモードのどこに入っているか 0:LPM0.TimerB.DCO , 1:LPM3.TimerA.LFXT | |
// 0(LPM0) -> 1(LPM3) | |
LPMode_FLAG = 1; | |
P2_INTR_FLAG = 1; | |
// 変数の初期化 | |
Timer_Counter = 0;; | |
Up_down_mode = 0; // DOWN mode -> UP mode | |
TIMER_INTR_FLAG = 0; | |
// Timerの設定変更 | |
TBCTL &= 0x00; | |
TBCTL |= TBSSEL_1 + ID_1 + MC_1; // 01 ACLK :(外部32768HZ発振子) /(div) | |
TBCCR4 = (Tpwm3 >> 2 ); | |
TBR = Tpwm3; | |
TBCTL |= TBCLR; | |
}else if( LPMode_FLAG == 1 ){ | |
//LPMode_FLAG = 1; // ローパワーモードのどこに入っているか 0:LPM0.TimerB.DCO , 1:LPM3.TimerA.LFXT | |
// 1(LPM3) -> 0(LPM0) | |
LPMode_FLAG = 0; | |
P2_INTR_FLAG = 0; | |
// 変数の初期化 | |
Timer_Counter = 0; | |
Up_down_mode = 0; // DOWN mode -> UP mode | |
TIMER_INTR_FLAG = 0; | |
// Timerの設定変更 | |
TBCTL &= 0x00; | |
TBCTL |= TBSSEL_2 + ID_3 + MC_1; // 10 SMCLK :サブシステムクロック(DCOから) /(div) | |
TBCCR0 = Tpwm0; | |
TBCCR4 = (Tpwm0 >> 3 ); | |
TBR = Tpwm0; | |
TBCTL |= TBCLR; | |
} | |
} | |
// <<<<< P2のボタンを押されたときの割り込み処理 <<<<<<<<<<<<<<<< | |
//// TimerB //// //TimerBが割り込みを掛けた。 カウンタのインクリメント と クリア | |
if( TIMER_INTR_FLAG == 1 ){ | |
Timer_Counter = Timer_Counter + 1 - Up_down_mode; // UpならTimer_Counter + 1, DownならTimer_Counter - 1 | |
if( LPMode_FLAG == 0 ){ // LPM0 mode | |
if(Timer_Counter > DIV_Tpwm0 ){ // UP mode -> DOWN mode | |
Up_down_mode = 2; | |
P4OUT |= BLUE_LED; | |
}else if( Timer_Counter <= 0 ){ // DOWN mode -> UP mode | |
Up_down_mode = 0; | |
P4OUT &= ~BLUE_LED; | |
}else{} | |
}else{ // ( LPMode_FLAG == 1 ) // LPM3 | |
if(Timer_Counter > DIV_Tpwm3 ){ // UP mode -> DOWN mode | |
Up_down_mode = 2; | |
P4OUT |= BLUE_LED; | |
}else if( Timer_Counter <= 0 ){ // DOWN mode -> UP mode | |
Up_down_mode = 0; | |
P4OUT &= ~BLUE_LED; | |
}else{} | |
} | |
TIMER_INTR_FLAG = 0; | |
} | |
//// TimerB //// //TimerBが割り込みを掛けた。 カウンタのインクリメント と カウンタのクリア | |
//// DAC //// | |
DAC12_0DAT = DA_min + Timer_Counter * 0.8; // YELLOW_LED Vth:1.69V => 2097 | |
DAC12_1DAT = ( AData_0 + AData_0 + AData_1 + AData_2 ) >> 2; | |
//// DAC //// | |
// <<<<< Enter LPM <<<<<<<<<<<<<<<< | |
if( LPMode_FLAG == 0 ){ | |
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts | |
P4OUT |= GREEN_LED; // LPM0 | |
P4OUT &= ~RED_LED; // LPM3 | |
}else{ // LPMode_FLAG == 1 | |
__bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/ interrupts | |
P4OUT &= ~GREEN_LED; // LPM0 | |
P4OUT |= RED_LED; // LPM3 | |
} | |
// <<<<< Enter LPM <<<<<<<<<<<<<<<< | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment