Skip to content

Instantly share code, notes, and snippets.

@totoroAKI
Last active November 28, 2020 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save totoroAKI/14b6ff129a4f9caafbeb1ccdf0861cce to your computer and use it in GitHub Desktop.
Save totoroAKI/14b6ff129a4f9caafbeb1ccdf0861cce to your computer and use it in GitHub Desktop.
#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