Ejemplo n.º 1
0
/***********************************************************************************************
 功能:PDB DAC触发初始化配置
 形参:PDB_ADC_InitStruct: PDB_ADC 初始化结构
 返回:0
 详解:专为PDB模块触发DAC模块设计的初始化函数  不许在PDB_Init后调用
************************************************************************************************/
void PDB_ADC_TriggerInit(PDB_ADC_PreTriggerInitTypeDef * PDB_ADC_InitStruct)
{
	uint16_t pt_value = 0;
	//参数检查
	assert_param(IS_PDB_TRIGGER_CH(PDB_ADC_InitStruct->PDB_ADC_TriggerSelect));
	assert_param(IS_PDB_ADC_PRE_TRIGGER_CHL(PDB_ADC_InitStruct->PDB_ADC_PreTriggerChl));
	assert_param(IS_FUNCTIONAL_STATE(PDB_ADC_InitStruct->PDB_ADC_Enable));
	assert_param(IS_FUNCTIONAL_STATE(PDB_ADC_InitStruct->PDB_ADC_BBEnable));
	
	pt_value = (1<<PDB_ADC_InitStruct->PDB_ADC_PreTriggerChl);
	//开启或者关闭模块
	if(ENABLE == PDB_ADC_InitStruct->PDB_ADC_Enable)
	{
		PDB0->CH[PDB_ADC_InitStruct->PDB_ADC_TriggerSelect].C1 |= PDB_C1_TOS(pt_value)|PDB_C1_EN(pt_value);
	}
	else
	{
		PDB0->CH[PDB_ADC_InitStruct->PDB_ADC_TriggerSelect].C1 &= ~(PDB_C1_TOS(pt_value)|PDB_C1_EN(pt_value));
	}
	//是否使能BB
	if(ENABLE == PDB_ADC_InitStruct->PDB_ADC_BBEnable)
	{
		PDB0->CH[PDB_ADC_InitStruct->PDB_ADC_TriggerSelect].C1 |= PDB_C1_BB(pt_value);
	}
	else
	{
		PDB0->CH[PDB_ADC_InitStruct->PDB_ADC_TriggerSelect].C1 &= ~PDB_C1_BB(pt_value);
	}
	//DLY
	PDB0->CH[PDB_ADC_InitStruct->PDB_ADC_TriggerSelect].DLY[PDB_ADC_InitStruct->PDB_ADC_PreTriggerChl] = 0;
}
Ejemplo n.º 2
0
//==========================================================================
//函数名称:hw_pdb_init                                                  
//功能概要:PDB初始化
//         1.设置成软件触发器输入
//         2.使能PDB模块
//         3.预分频设置成0
//         4. LDMOD = 0: 在设置完LDOK后立即加载
//         5. 使能PDB中断
//         注意:只有在使能PDB模块后,才可以写入通道延时值                                                 
//参数说明:无                                                    
//函数返回:无                                                               
//==========================================================================
void hw_pdb_init(void)
{
	//1.开PDB时钟
	SIM_SCGC6 |= (SIM_SCGC6_PDB_MASK);
	
	//2.初始化PDB状态与控制寄存器
	PDB0_SC = 0x00000000; //LDMOD = 0: 在设置完LDOK后立即加载
	// 必须在写缓冲区寄存器之前使能PDB,否则只是之前的值
	PDB0_SC |= PDB_SC_PDBEN_MASK;  //使能 PDB	
	PDB0_SC |= PDB_SC_TRGSEL(0xF); //软件触发器
	PDB0_SC |= PDB_SC_CONT_MASK;   //使能连续模式 

	//3.初始化PDB通道1控制寄存器1
	PDB0_CH1C1 = PDB_C1_TOS(3)|PDB_C1_EN(3);   //使能预触发器输出到  ADC1
	
	
	//4.初始化PDB通道1延时寄存器
	PDB0_CH1DLY0 = 0;
	PDB0_CH1DLY1 = 3648;    // 延时 = 76us
	
	//5.初始化PDB模寄存器
	PDB0_MOD = 48000;     //设置PDB_MOD时间=1ms,相应的采样频率Fs=1KHz

	//6.初始化PDB中断延时寄存器
	PDB0_IDLY = 48000;    //设置中断延时值
	
	
	PDB0_SC |= PDB_SC_LDOK_MASK;//加载延时值
	
	PDB0_SC |= PDB_SC_PDBIE_MASK; //使能PDB中断
	PDB0_SC &= ~PDB_SC_DMAEN_MASK;
	//PDB0_SC |= PDB_SC_PDBEIE_MASK; //使能PDB 序列错误中断
	
	PDB0_SC |= PDB_SC_SWTRIG_MASK;//设置成软件触发器
}
Ejemplo n.º 3
0
void PDB_INIT(void) {
	//Enable PDB Clock
	SIM_SCGC6 |= SIM_SCGC6_PDB_MASK;
	//PDB0_CNT = 0x0000;
	PDB0_MOD = 50000; // 50,000,000 / 50,000 = 1000

	PDB0_SC = PDB_SC_PDBEN_MASK | PDB_SC_CONT_MASK | PDB_SC_TRGSEL(0xf) | PDB_SC_LDOK_MASK;
	PDB0_CH1C1 = PDB_C1_EN(0x01) | PDB_C1_TOS(0x01);
}
Ejemplo n.º 4
0
/**
 * @brief  设置PDB触发ADC
 * @param  adcInstance: 需要触发的ADC模块号 如HW_ADC0
 * @param  adcMux:     ADC转换通道
 * @param  dlyValue:   延时计数值
 * @param  status:     开关
 * @retval None
 */
void PDB_SetADCPreTrigger(uint32_t adcInstance, uint32_t adcMux, uint32_t dlyValue, bool status)
{
    /* disable PDB */
    (status)?
    (PDB0->CH[adcInstance].C1 |= PDB_C1_EN(1<<adcMux)):
    (PDB0->CH[adcInstance].C1 &= ~PDB_C1_EN(1<<adcMux));
    
    (status)?
    (PDB0->CH[adcInstance].C1 |= PDB_C1_TOS(1<<adcMux)):
    (PDB0->CH[adcInstance].C1 &= ~PDB_C1_TOS(1<<adcMux));
}
/*FUNCTION*********************************************************************
 *
 * Function Name : PDB_HAL_SetAdcPreTriggerEnable
 * Description   : Switch to enable pre-trigger's.
 *
 *END*************************************************************************/
void PDB_HAL_SetAdcPreTriggerEnable(PDB_Type * base, uint32_t chn, uint32_t preChnMask, bool enable)
{
    assert(chn < PDB_C1_COUNT);
    
    uint32_t c1 = PDB_RD_C1(base, chn);
    if (enable)
    {
        c1 |= PDB_C1_EN(preChnMask);
    }
    else
    {
        c1 &= ~PDB_C1_EN(preChnMask);
    }
    PDB_WR_C1(base, chn, c1);
}
Ejemplo n.º 6
0
uint8_t Hw_Trig_Test(void)
{
  // Notes:

  //      PDB settings : continous mode, started by sotware trigger.
  //      This means that once the software "pulls the trigger" by setting a certain bit, the PDB starts counting
  //      and handing out four triggers per cycle of its counter.

  //      PDB settings: CH0_DLY0, CH0_DLY1 , CH1_DLY0, CH1_DLY1
  //      set to different values to distinguish effect on ADCx_Ry register
  //      need to provide 4 different voltages to convert at two ADC0 and two ADC1 input channels
  //      PDB counter clock prescaled to allow time for printf's and slow down things to they are visible, each trigger.

  //      Using adiclk= BUS ,  and adidiv/4 to get  12,5MHz on Tower demonstration.
  //      visibility of PDB start trigger is obtained by generating a toggling edge on
  //      GPIOxx with PDBisr set to trigger immediatly at zero value of PDB counter.

  //      Conversion end of each ADC and channel within the ADC ( A,B ) will be done by
  //      toggling second GPIO pin inside ADCisr  ( this pin is also reset by PDB isr )



// GPIO PIN to low voltage .. this macro sets the PIN low.
 PIN_LOW

// Initialize PIN1 and PIN2 GPIO outputs
 Init_Gpio2();

// Disable ADC and PDB interrupts
 disable_irq(ADC0_irq_no) ;   // not ready for this interrupt yet. Plug vector first.
 disable_irq(ADC1_irq_no) ;   // not ready for this interrupt yet. Plug vector first.
 disable_irq(PDB_irq_no) ;    // not ready for this interrupt yet. Plug vector first.

// Dynamic interrupt vector modification whilst those interruts are disabled
 __VECTOR_RAM[73] = (uint32)adc0_isr;  // plug isr into vector table in case not there already
 __VECTOR_RAM[74] = (uint32)adc1_isr;  // plug isr into vector table in case not there already
 __VECTOR_RAM[88] = (uint32)pdb_isr;   // plug isr into vector table in case not there already

// The System Integration Module largely determines the role of the different ball map locations on Kinetis.
// When an external pin is used, the System Integration Module should be consulted and invoked as needed.
// System integration module registers start with SIM_

// Turn on the ADC0 and ADC1 clocks as well as the PDB clocks to test ADC triggered by PDB
 SIM_SCGC6 |= (SIM_SCGC6_ADC0_MASK );
 SIM_SCGC3 |= (SIM_SCGC3_ADC1_MASK );
 SIM_SCGC6 |= SIM_SCGC6_PDB_MASK ;

// Configure System Integration Module for defaults as far as ADC
 SIM_SOPT7 &= ~(SIM_SOPT7_ADC1ALTTRGEN_MASK  | // selects PDB not ALT trigger
                SIM_SOPT7_ADC1PRETRGSEL_MASK |
                SIM_SOPT7_ADC0ALTTRGEN_MASK  | // selects PDB not ALT trigger
                SIM_SOPT7_ADC0ALTTRGEN_MASK) ;
 SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0);       // applies only in case of ALT trigger, in which case
                                             // PDB external pin input trigger for ADC
 SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0);       // same for both ADCs




/////////////////////////////////////////////////////////////////////////////////////////
//PDB configured below  以下是PDB配置



// Configure the Peripheral Delay Block (PDB):
// enable PDB, pdb counter clock = busclock / 20 , continous triggers, sw trigger , and use prescaler too
 PDB0_SC =  PDB_SC_CONT_MASK       // Contintuous, rather than one-shot, mode
         | PDB_SC_PDBEN_MASK      // PDB enabled
         | PDB_SC_PDBIE_MASK      // PDB Interrupt Enable
         | PDB_SC_PRESCALER(0x5)  // Slow down the period of the PDB for testing
         | PDB_SC_TRGSEL(0xf)     // Trigger source is Software Trigger to be invoked in this file
         | PDB_SC_MULT(2);        // Multiplication factor 20 for the prescale divider for the counter clock
                                  // the software trigger, PDB_SC_SWTRIG_MASK is not triggered at this time.

 PDB0_IDLY = 0x0000;   // need to trigger interrupt every counter reset which happens when modulus reached

 PDB0_MOD = 0xffff;    // largest period possible with the slections above, so slow you can see each conversion.

// channel 0 pretrigger 0 and 1 enabled and delayed
 PDB0_CH0C1 = PDB_C1_EN(0x01)
           | PDB_C1_TOS(0x01)
           | PDB_C1_EN(0x02)
           | PDB_C1_TOS(0x02) ;

 PDB0_CH0DLY0 = ADC0_DLYA ;
 PDB0_CH0DLY1 = ADC0_DLYB ;

// channel 1 pretrigger 0 and 1 enabled and delayed
 PDB0_CH1C1 = PDB_C1_EN(0x01)
           | PDB_C1_TOS(0x01)
           | PDB_C1_EN(0x02)
           | PDB_C1_TOS(0x02) ;

 PDB0_CH1DLY0 = ADC1_DLYA ;
 PDB0_CH1DLY1 = ADC1_DLYB ;

 PDB0_SC =  PDB_SC_CONT_MASK        // Contintuous, rather than one-shot, mode
         | PDB_SC_PDBEN_MASK       // PDB enabled
         | PDB_SC_PDBIE_MASK       // PDB Interrupt Enable
         | PDB_SC_PRESCALER(0x5)   // Slow down the period of the PDB for testing
         | PDB_SC_TRGSEL(0xf)      // Trigger source is Software Trigger to be invoked in this file
         | PDB_SC_MULT(2)          // Multiplication factor 20 for the prescale divider for the counter clock
         | PDB_SC_LDOK_MASK;       // Need to ok the loading or it will not load certain regsiters!
                                   // the software trigger, PDB_SC_SWTRIG_MASK is not triggered at this time.



//PDB configured above  以上是PDB配置
/////////////////////////////////////////////////////////////////////////////////////////
//ADC configured below  以下是ADC配置

// setup the initial ADC default configuration
 Master_Adc_Config.CONFIG1  = ADLPC_NORMAL
                            | ADC_CFG1_ADIV(ADIV_4)
                            | ADLSMP_LONG
                            | ADC_CFG1_MODE(MODE_16)
                            | ADC_CFG1_ADICLK(ADICLK_BUS);
 Master_Adc_Config.CONFIG2  = MUXSEL_ADCA
                            | ADACKEN_DISABLED
                            | ADHSC_HISPEED
                            | ADC_CFG2_ADLSTS(ADLSTS_20) ;
 Master_Adc_Config.COMPARE1 = 0x1234u ;                 // can be anything
 Master_Adc_Config.COMPARE2 = 0x5678u ;                 // can be anything
                                                        // since not using
                                                        // compare feature
 Master_Adc_Config.STATUS2  = ADTRG_HW
                            | ACFE_DISABLED
                            | ACFGT_GREATER
                            | ACREN_ENABLED
                            | DMAEN_DISABLED
                            | ADC_SC2_REFSEL(REFSEL_EXT);

 Master_Adc_Config.STATUS3  = CAL_OFF
                            | ADCO_SINGLE
                            | AVGE_ENABLED
                            | ADC_SC3_AVGS(AVGS_32);

 Master_Adc_Config.PGA      = PGAEN_DISABLED
                            | PGACHP_NOCHOP
                            | PGALP_NORMAL
                            | ADC_PGA_PGAG(PGAG_64);
 Master_Adc_Config.STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31);
 Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31);


// Configure ADC as it will be used, but becuase ADC_SC1_ADCH is 31,
// the ADC will be inactive.  Channel 31 is just disable function.
// There really is no channel 31.

 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config);  // config ADC

// Calibrate the ADC in the configuration in which it will be used:
 ADC_Cal(ADC0_BASE_PTR);                    // do the calibration

// The structure still has the desired configuration.  So restore it.
// Why restore it?  The calibration makes some adjustments to the
// configuration of the ADC.  The are now undone:

// config the ADC again to desired conditions
 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config);

// REPEAT for BOTH ADC's.  However we will only 'use' the results from
// the ADC wired to the Potentiometer on the Kinetis Tower Card.

// Repeating for ADC1:
  ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config);  // config ADC
  ADC_Cal(ADC1_BASE_PTR);                    // do the calibration
//  ADC_Read_Cal(ADC1_BASE_PTR,&CalibrationStore[0]);   // store the cal


// config the ADC again to default conditions
 ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config);

// *****************************************************************************
//      ADC0 and ADC1 using the PDB trigger in ping pong
// *****************************************************************************

// use interrupts, single ended mode, and real channel numbers now:

 Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC0_CHANA);
 Master_Adc_Config.STATUS1B = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC0_CHANB);
 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config);  // config ADC0

 Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC1_CHANA);
 Master_Adc_Config.STATUS1B = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC1_CHANB);
 ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config);  // config ADC1

 // Note that three different balls are being sampled:
 // ADC0_CHANA not used in this demo, but readings are shown
 // ADC0_CHANB not used in this demo, but readings are shown
 // ADC1_CHANA POT channel set the same as the following for demo: 20
 // ADC1_CHANB POT channel set the same as the above for demo: 20

 // The potentiometer is only on ADC1.  That is the one used
 // to calculate the change of the potentiometer below.


 while(char_present()) in_char();                     // flush terminal buffer

 printf ("\n\n\n");
 printf("********************************************************\n");
 printf("* Running ADC0 & ADC1 HARDWARE TRIGGER by PDB          *\n");
 printf("* The one PDB is triggering both ADC0 and ADC1         *\n");
 printf("* ADC1 A,B is the POT.   Vary the POT setting.         *\n");
 printf("* Hit any key to exit   (ADC0 readings not used)       *\n");
 printf("********************************************************\n");
 printf ("\n\n");

// Enable the ADC and PDB interrupts in NVIC
 enable_irq(ADC0_irq_no) ;   // ready for this interrupt.
 enable_irq(ADC1_irq_no) ;   // ready for this interrupt.
 enable_irq(PDB_irq_no) ;    // ready for this interrupt.

// In case previous test did not end with interrupts enabled, enable used ones.
 EnableInterrupts ;

 cycle_flags=0;
 PDB0_SC |= PDB_SC_SWTRIG_MASK ;    // kick off the PDB  - just once

 //The system is now working!!!!  The PDB is *continuously* triggering ADC
 // conversions.  Now, to display the results!  The line above
 // was the SOFTWARE TRIGGER...

 // The demo will continue as long as no character is pressed on the terminal.

 while(!char_present()) // as long as no operater intervention, keep running this:
 {
  while( cycle_flags != ( ADC0A_DONE | ADC0B_DONE | ADC1A_DONE | ADC1B_DONE ));  // wait for one complete cycle
  printf("R0A=%6d  R0B=%6d  R1A=%6d  R1B=%6d   POT=%6d\r",
          result0A,result0B,result1A,result1B, exponentially_filtered_result1);
 }

// disable the PDB

  PDB0_SC = 0 ;

// Disable the ADC and PDB interrupts in NVIC
  disable_irq(ADC0_irq_no) ;   // through with this interrupt.
  disable_irq(ADC1_irq_no) ;   // through with this interrupt.
  disable_irq(PDB_irq_no) ;    // through with this interrupt.


 printf ("\n\n\n");
 printf("********************************************************\n");
 printf("* Demonstration ended at operator request              *\n");
 printf("* ADC0 & ADC1 PDB      TRIGGER DEMO COMPLETE           *\n");
 printf("********************************************************\n");
 printf ("\n\n");


return 0;
}