/*! \brief Detect Board Revision * * @retval Version Number of Board */ uint8_t BOARD_Detect_Revision(void) { ADC_Result result; uint16_t revision_value; uint8_t i; PGA_SetChannel(SPI_DEVICE_AMP_V_I_DCBUS, CHANNEL1); ADC_Enable(TSB_ADB); ADC_SetClk(TSB_ADB, ADC_HOLD_FIX, ADC_FC_DIVIDE_LEVEL_2); ADC_SetSWTrg(TSB_ADB, ADC_REG2, TRG_ENABLE(ADC_REG2)); ADC_Start(TSB_ADB, ADC_TRG_SW); while (ADC_GetConvertState(TSB_ADB, ADC_TRG_SW) == BUSY); result=ADC_GetConvertResult(TSB_ADB, ADC_REG2); ADC_Disable(TSB_ADB); PGA_SetChannel(SPI_DEVICE_AMP_V_I_DCBUS, CHANNEL0); for (i=0;i<sizeof(revisions)/sizeof(revisions[0]);i++) { revision_value = result.Bit.ADResult*10/gaintable[ChannelValues[1].gain_current_measure]; if (abs((revisions[i][0]-revision_value)<100)) break; } return revisions[i][1]; }
uint16_t analogin_read_u16(analogin_t *obj) { ADC_TypeDef *adc = obj->adc; uint16_t sample = 0; //Make sure a single conversion is not in progress adc->CMD = ADC_CMD_SINGLESTOP; // Make sure we are checking the correct channel #if defined _ADC_SINGLECTRL_INPUTSEL_MASK adc->SINGLECTRL = (adc->SINGLECTRL & ~_ADC_SINGLECTRL_INPUTSEL_MASK) | obj->channel; #elif _ADC_SINGLECTRL_POSSEL_MASK adc->SINGLECTRL = (adc->SINGLECTRL & ~_ADC_SINGLECTRL_POSSEL_MASK) | obj->channel << _ADC_SINGLECTRL_POSSEL_SHIFT; #endif ADC_Start(adc, adcStartSingle); /* Wait while conversion is active */ while (adc->STATUS & ADC_STATUS_SINGLEACT); /* Get ADC result */ sample = ADC_DataSingleGet(adc); /* The ADC has 12 bit resolution. We shift in 4 0s */ /* from the right to make it a 16 bit number as expected */ return sample << 4; }
void center() { for(m = 0; m < 8; m++) { ADC_Start(m); ADC_Get( &ad[m] ); ad_data[m] = ad[m]; } X_l = abs(abs(ad_data[0]-ad_data[1]) - abs(ad_data[2]-ad_data[3])); Y_l = abs(abs(ad_data[0]-ad_data[2]) - abs(ad_data[1]-ad_data[3])); X_r = abs(abs(ad_data[4]-ad_data[5]) - abs(ad_data[6]-ad_data[7])); Y_r = abs(abs(ad_data[4]-ad_data[6]) - abs(ad_data[5]-ad_data[7])); if(X_l>X_r) { center_x = ((float)(X_l-X_r))/2; center_y = ((float)(Y_l-Y_r))/2; } if(X_l<X_r) { center_x = ((float)(X_r-X_l))/2; center_y = ((float)(Y_r-Y_l))/2; } usart1_transmit(100); usart1_transmit(center_x); }
void Mode_Error_Handler(void) { Base_Peripheral_Init(); LED1_ON; LED2_ON; Delay(LED_BLINK_DELAY); if(logic.send_error_packet_sec >= LOGIC_SEND_EROR_PACKET_SEC) { ADC_Peripheral_Init(); Delay(1); ADC_Start(ADC_TYPE_TERMISTOR); LPM3_GOTO; RTC_Remove_Alarm(); RF_GPIO_Init(); RF_Init(); RF_Send_Packet(); logic.send_error_packet_sec = 0; }else logic.send_error_packet_sec ++; LED1_OFF; LED2_OFF; Peripheral_Power_Down(); }
/******************************************************************************* Function Name : Clear_All Description : clear all data *******************************************************************************/ void Clear_All_Data(void) { Display_Info("Clear_All_Data", 0); stop = FALSE; // stop / start sampling Acq_Clear_All(); Disp_Clear_All(); ADC_Start(); }
/***********************************Main***********************************/ int main() { int16 mav_data; ADC_ISR_StartEx(ADC_interrupt); CyGlobalIntEnable; UART_Start(); /* Initialize ADC */ ADC_Start(); /* Initialize ADC */ ADC_StartConvert(); /* Start ADC conversions */ ADC_IRQ_Enable(); /* Enable ADC interrupts */ for (;;) { if(data_ready) { mav_data = mavg_filter(accgroen); gradergroen = grader(mav_data); //UART_UartPutChar(mav_data); //UART_UartPutChar(mav_data>>8); UART_UartPutChar(gradergroen); UART_UartPutChar(gradergroen>>8); data_ready = FALSE; } } }
/******************************************************************************* Signal_Process: 计算处理数据缓冲区 *******************************************************************************/ void Signal_Process(void) { int i, p, q; int Vs, Vr; if(Sync==3) t0=150; //若同步不成功,设定默认起始位置 p=(Frame*(1024*X_SIZE)/Ks[Item_Index[X_SENSITIVITY]])+t0+Item_Index[X_POSITION]-(4096+150); for(i=X_Counter; i<(X_SIZE); ++i){ Sync=5; //部分转换完成后转去显示扫描波形 q=p+(i*1024)/Ks[Item_Index[X_SENSITIVITY]]; if(q<0) { q=0; Item_Index[X_POSITION]++; } if(q>=(0x1000-DMA_CNDTR1)) break; //跳空一个周期,等待A/D转换结束 X_Counter=i+1; Vr=Km[Item_Index[Y_SENSITIVITY]]*(Scan_Buffer[q+1]-Scan_Buffer[q])/4096; Vs=(Km[Item_Index[Y_SENSITIVITY]]*(2048-Scan_Buffer[q]))/4096+120 //当前波形点的主值 -(((i*1024)%Ks[Item_Index[X_SENSITIVITY]])*Vr)/Ks[Item_Index[X_SENSITIVITY]]; //当前波形点的插值 if(Vs>MAX_Y) Vs=MAX_Y; else if(Vs<MIN_Y) Vs=MIN_Y; Signal_Buffer[i]=Vs; Sync=4; //全部转换完成后转去显示扫描波形 } if(DMA_CNDTR1==0) { Measure_Wave();//若采样完成,计算波形的各个测量值 if(Item_Index[RUNNING_STATUS]==RUN) ADC_Start(); //若在"RUN"模式下,重新采样 } }
// 12-bit ADC resolution uint16_t read_ADC(ADC_CH ch) { ADC_ChannelSelect(ch); ///< Select ADC channel to CH0 ADC_Start(); ///< Start ADC while(ADC_IsEOC()); ///< Wait until End of Conversion return ((uint16_t)ADC_ReadData()); ///< read ADC Data }
void Example_ADC_ReadData(void) { /* 1. set ADC clock */ ADC_SetClk(TSB_ADB, ADC_HOLD_FIX, ADC_FC_DIVIDE_LEVEL_2); /* 2. select trigger and AD channel, this time we use sofeware trigger, */ /* the VR1 is connected to ADC unit B channel 2, remember to input with macro TRG_ENABLE() */ ADC_SetSWTrg(TSB_ADB, ADC_REG0, TRG_ENABLE(ADC_AIN2)); /* 3. enable ADC module */ ADC_Enable(TSB_ADB); /* 4. now start ADC */ ADC_Start(TSB_ADB, ADC_TRG_SW); /* initialize LEDs on M374-SK board before display something */ LED_Init(); while (1U) { /* check ADC module state */ adcState = ADC_GetConvertState(TSB_ADB, ADC_TRG_SW); if (adcState == DONE) { /* read ADC result when it is finished */ result = ADC_GetConvertResult(TSB_ADB, ADC_REG0); /* get the real ADC result without other information */ /* "/16" is to limit the range of AD value */ myResult = result.Bit.ADResult / 16U; /* software trigger, need to trigger it again */ ADC_Start(TSB_ADB, ADC_TRG_SW); } myDelay(myResult); if(idx) { LED_Off(LEDs[idx-1]); } idx &= 0x03U; myDelay(myResult); LED_On(LEDs[idx]); idx++; } }
int main() { //Initializations clearPacketSBD(); clearPacketwind(); UART_Wind_Start(); UART_SBD_Start(); psoc_Start(); isr_Wind_StartEx(IntWind); SBD_reply_StartEx(SBD_int); clock_Start(); master_Start(); ADC_Start(); CyGlobalIntEnable; //Writes to magnetometer to be read from (not calibration mode) writeregister((uint8) 0x00, (uint8) 0x70); writeregister((uint8) 0x01, (uint8) 0xA0); writeregister((uint8) 0x02, (uint8) 0x00); CyDelay(15000u); clearPacketwind(); //Query Sensor for wind, pressure, temperature and humidity data UART_Wind_PutString("0R\r\n"); timeout_isr_StartEx(windtimer); timer_clock_Start(); Timer_Start(); windtime = 0; for(;;) { //When the packet is received takes other sensor data, sends packet and turns off power if(windpacketReceived){ Timer_Stop(); timer_clock_Stop(); timeout_isr_Stop(); windprocessPacket(); } //Here to clear any unexpected outputs from SBD Warrior if(SBDpacketReceived) { clearPacketSBD(); } //changes if(windtimeout == 1) { windbroke = 1; windprocessPacket(); } //end changes } }
void init() { // LCD Init LCD_Start(); LCD_DisplayOn(); //LCD_PrintNumber(1); ADC_Start(); }
void main() { ISR_UpBuff_Start(); //Start the Interrupt Component. ISR_UpBuff_SetVector(BufferUpdate);//Set Vector to the above ISR. CyGlobalIntEnable;//Enable Global Interrupts,EzI2C ad ADC require them. EZI2C_Start();//Start the EzI2C component. EZI2C_SetBuffer1(BUFFER_SIZE,BUFFER_RW_AREA_SIZE,(void *) (&EZI2C_Buffer));//Configure the Buffer for the EzI2C Component. ADC_Start();//Start the ADC ADC_IRQ_Enable();//Enable the EOC Interrupt ADC_StartConvert();//Start the Conversion for(;;);//Everything is done in the ISR. }
/* * Function Name: ADC_setup * Description: Configures ADC0 */ void LEUART_Setup(void) { /* Enabling the required clocks */ CMU_ClockEnable(cmuClock_LFB, true); //Enable the clock input to LETIMER CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO); //Selecting the ULFRCO as the source clock CMU_ClockEnable(cmuClock_LEUART0, true); //Enable the clock input to LETIMER /* Defining the LEUART1 initialization data */ LEUART_Init_TypeDef leuart0Init = { .enable = leuartEnable, // Activate data reception on LEUn_TX pin. .refFreq = 0, // Inherit the clock frequency from the LEUART clock source .baudrate = LEUART0_BAUD, // Baudrate = 9600 bps .databits = LEUART0_Databits, // Each LEUART frame contains 8 databits .parity = LEUART0_Parity, // No parity bits in use .stopbits = LEUART0_Stopbits, // Setting the number of stop bits in a frame to 2 bitperiods }; LEUART_Init(LEUART0, &leuart0Init); // Route LEUART1 TX,RX pin to DMA location 0 LEUART0->ROUTE = LEUART_ROUTE_TXPEN | LEUART_ROUTE_RXPEN | LEUART_ROUTE_LOCATION_LOC0; // Enable GPIO for LEUART1. TX is on D4 GPIO_PinModeSet(gpioPortD, 4, gpioModePushPull, 0); // Enable GPIO for LEUART1. RX is on D5 GPIO_PinModeSet(gpioPortD, 5, gpioModeInputPull, 0); // Pull PD15(CTS pin of BLE module) to GRND GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 0); } /* *Function name: LETIMER0_IRQHandler *Description : Interrupt Service Routine for LETIMER. */ void LETIMER0_IRQHandler(void) { LETIMER_IntClear(LETIMER0, LETIMER_IF_UF); //Clear LETIMER0 underflow (UF) and COMP1 flag. DMA_ActivateBasic(DMA_CHANNEL_ADC, true, false, (void *)ADC_Buffer, (void *)&(ADC0->SINGLEDATA), ADC_SAMPLES - 1); ADC_Setup(); // ADC start ADC_Start(ADC0, adcStartSingle); unblockSleepMode(EM2); blockSleepMode(EM1); trfComplete=false; }
void main() { /* Place your initialization/startup code here (e.g. MyInst_Start()) */ uint16 adc, compare; LCD_Start(); ADC_Start(); PWM_Start(); /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */ for(;;) { /* Place your application code here. */ // LCD_ClearDisplay(); LCD_Start(); adc = 0; ADC_StartConvert(); ADC_IsEndConversion(ADC_WAIT_FOR_RESULT); ADC_StopConvert(); adc = ADC_GetResult16(); if(adc > 255) { if(adc == 0xFFFF) /* underflow correction */ { adc = 0x00; } else adc = 0xFF; /* Overflow correction */ } LCD_Position(0,0); LCD_PrintHexUint8(adc); compare = (uint16)(1000 + ((float)((float)((float)adc / (float)255) * (float)1000))); LCD_Position(1,0); LCD_PrintDecUint16(compare); PWM_WriteCompare(compare); PWM_WritePeriod(compare + 39999); } }
void Do_Keys_Rate (keycodes key){ s16 tmp, step; s16 cursor; Display_Info("Do_Keys_Rate", 0); cursor = confp->rate_cursor; switch (key){ case KEYCODE_PLAY: stop = !stop; if(stop) ADC_Stop(); else ADC_Start(); break; case KEYCODE_M: confp->rtn_mode = confp->mode; confp->mode = MENU; Display_Menu(confp->menu_index); break; case KEYCODE_UP: // no zoom in rate mode break; case KEYCODE_DOWN: // no zoom in rate mode break; case KEYCODE_RIGHT: step = 2; cursor += step; if(cursor >= confp->graph_width){ // stop on far right side cursor = confp->graph_width - 1; } Display_Rate(); break; case KEYCODE_LEFT: step = 2; cursor -= step; if(cursor < 0){ // stop on far right side cursor = 0; } Display_Rate(); break; } confp->rate_cursor = cursor; }
/***************************************************************************//** * @brief RTC Interrupt Handler. ******************************************************************************/ void RTC_IRQHandler(void) { /* Start ADC conversion as soon as we wake up. */ ADC_Start(ADC0, adcStartSingle); /* Clear the interrupt flag */ RTC_IntClear(RTC_IF_COMP0); /* Wait while conversion is active */ while (ADC0->STATUS & ADC_STATUS_SINGLEACT); /* Get ADC result */ sampleBuffer[sampleCount++] = ADC_DataSingleGet(ADC0); if(sampleCount >= N_SAMPLES){ adcFinished = 1; RTC_Enable(false); RTC_IntDisable(_RTC_IF_MASK); } }
/******************************************************************************* Erase_Draw: 先擦除后显示扫描波形 *******************************************************************************/ void Erase_Draw(void) { unsigned short i; unsigned char y1, y2, y3, y4,y5, y6; y1=View_Buffer[0]; y3=Signal_Buffer[0]; y5=Ref_Buffer[0]; for(i=0; i<X_Counter; ++i){ y2=View_Buffer[i]; y4=Signal_Buffer[i]; View_Buffer[i]=y4; y6=Ref_Buffer[i]; Erase_SEG(i,y1,y2,CH1_COLOR); Erase_SEG(i,y5,y6,CH3_COLOR); Draw_CH1_SEG(i,y3,y4); if(Hide_Index[REF]==0) Draw_CH3_SEG(i,y5,y6); y1 = y2; y3 = y4; y5 = y6; } if(X_Counter>=X_SIZE-1) {//一帧显示完成 Stop=1; X_Counter=0; //窗口指针复零 Battery_Detect();//检测电池电压 if((((Frame+2)*X_SIZE)+t0+Item_Index[X_POSITION]-4096)<0x1000) Frame++;//指向下一帧 else { Frame=0; ADC_Start(); Item_Index[X_POSITION]=4096; } Delay_Counter=100; //维持波形显示100mS if(Item_Index[0]!=4) Sync=0;//非"SCAN"模式下,重新开始处理显示波形 else Erase_Wave();//在"SCAN"模式下,擦除已经显示的波形,准备下一帧的显示 } else { Sync=2; Stop=0;//扫描数据显示未完成,则继续对应帧的数据转换处理和显示 } }
void zmp() { for(m = 0; m < 8; m++) { ADC_Start(m); ADC_Get( &ad[m] ); ad_data[m] = ad[m]; } for(gg=0;gg<8;gg++) { numerator=ad_data[gg]*lenx[gg]; count_numerator = count_numerator+numerator; } for(gg=0;gg<8;gg++) { denominator=ad_data[gg]; count_denominator = count_denominator+denominator; } zmpx = count_numerator/count_denominator; for(gg=0;gg<8;gg++) { numerator_1=ad_data[gg]*leny[gg]; count_numerator_1 = count_numerator_1+numerator_1; } for(gg=0;gg<8;gg++) { denominator_1=ad_data[gg]; count_denominator_1 = count_denominator_1+denominator_1; } zmpy = count_numerator_1/count_denominator_1; unsigned_dec(zmpx); unsigned_dec(zmpy); usart1_transmit(0x0d); usart1_transmit(0x0a); }
int main() { BootIRQ_Start(); CyGlobalIntEnable; /* Enable global interrupts. */ for(uint8 i=0; i<5;i++){ LED_Write(1u); CyDelay(10u); LED_Write(0u); CyDelay(100u); } usb_init(); xprintf("Start"); ADC_Start(); EEPROM_Start(); status_register.matrix_output = 0; status_register.emergency_stop = 0; for(;;) { /* Host can send double SET_INTERFACE request. */ // if (0u != USB_IsConfigurationChanged()) // { /* Initialize IN endpoints when device is configured. */ // if (0u != USB_GetConfiguration()) // { /* Enumeration is done, enable OUT endpoint to receive data * from host. */ // USB_EnableOutEP(8); // xprintf("Reconfigured"); // } // } if (message_for_you_in_the_lobby) { process_msg(); } scan(); } }
/***************************************************************************//** * @brief * Initialize touch panel driver * * @param config * Driver configuration data. ******************************************************************************/ void TOUCH_Init(TOUCH_Config_TypeDef *config) { ADC_Init_TypeDef init = ADC_INIT_DEFAULT; #ifndef TOUCH_WITHOUT_STORE touch_LoadCalibration(); #endif CMU_ClockEnable(cmuClock_ADC0, true); ADC_IntDisable(ADC0, _ADC_IF_MASK); init.prescale = ADC_PrescaleCalc(config->frequency, 0); touch_ignore_move = config->ignore; init.ovsRateSel = config->oversampling; ADC_Init(ADC0, &init); BSP_PeripheralAccess(BSP_TOUCH, true); sInit.input = ADC_Y; sInit.reference = adcRefVDD; sInit.resolution = adcResOVS; ADC_InitSingle(ADC0, &sInit); ADC_IntClear(ADC0, _ADC_IF_MASK); touch_state = TOUCH_INIT; NVIC_ClearPendingIRQ(ADC0_IRQn); NVIC_EnableIRQ(ADC0_IRQn); ADC_IntEnable(ADC0, ADC_IF_SINGLE); ADC_Start(ADC0, adcStartSingle); }
uint16_t adc_get_value(uint8_t u8_adc_channel, ADC_Ref_TypeDef adcref) { ADC_InitSingle_TypeDef sInit = ADC_INITSINGLE_DEFAULT; uint32_t rawvalue = 0; /* Set reference */ sInit.reference = adcref; sInit.input = u8_adc_channel; ADC_InitSingle(ADC0, &sInit); _u8_conv_complete = 0; ADC_Start(ADC0, adcStartSingle); /* Wait in EM1 for ADC to complete */ EMU_EnterEM1(); // Make sure it's ADC interrupt // TODO : timeout while(_u8_conv_complete == 0); rawvalue = ADC_DataSingleGet(ADC0); return (uint16_t) rawvalue; }
/*---------------------------------------------------------------------------*/ void Potentiometer_Init(void) { ADC_Start(); ADC_EnableChannel(POTENTIOMETER_CHANNEL); }
void Scan_Samples(void){ fixed ybox[7]; // array box car derivative s16 bin; // index into peak height array fixed dt, tau, *yp0, *yp1, y, y_i; fixed threshold; // trigger level for leading edge fixed deriv; fixed alpha, beta, gamma, peak; s16 i; configurations *cp = &configuration; ADC_Stop(); tail = head = Get_Scan_Pos(); // get current absolute position in adc buffer /* if(cp->sig_filter){ // Set up Butterworth low pass filter dt = FIXED_HALF; // sample time 0.5 uS tau = fixed_from_int(cp->sig_filter); // filter time in uS alpha = fixed_div(dt, tau + dt); } */ ADC_Start(); while(TRUE){ if(tail == head){ head = Get_Scan_Pos(); // recalculate filter elements in case changed /* if(cp->sig_filter){ // Set up Butterworth low pass filter in case of changes dt = FIXED_HALF; // sample time 0.5 uS tau = fixed_from_int(cp->sig_filter); // filter time in uS alpha = fixed_div(dt, tau + dt); } */ } if(tail == head) continue; // track live time if(samp_cntr++ >= SAMP_PER_MS){ live_time++; samp_cntr = 0; } // get new value, adjust for zero and inversion at same time y = fixed_from_int(zero - scan_buffer[tail++]); if(tail >= SCAN_BUFFER_SZ){ tail = 0; } // filter signal if needed /* if(cp->sig_filter){ // Butterworth low pass filter y = *yp0 + fixed_mul(alpha, (y - *yp0)); } */ // shift the boxcar window and find derivative yp0 =&ybox[0]; yp1 = &ybox[1]; for(i = 6; i > 0; i--){ // last box slot gets new y value *yp0++ = *yp1++; } *yp0 = y; // place latest sample in end of boxcar // compute the derivative deriv = 0; yp0 =&ybox[0]; deriv -= *yp0++; deriv -= *yp0++; alpha = *yp0; deriv -= *yp0++; beta = *yp0++; gamma = *yp0; deriv += *yp0++; deriv += *yp0++; deriv += *yp0++; // process depending on state switch(scan_state){ case RESTART: scan_state = LEADING; //cp->scope_valid = FALSE; break; case LEADING: if(cp->sig_type == PULSE_POS && deriv > cp->sig_dvdt_lim){ scan_state = PEAK; break; } if(cp->sig_type == PULSE_NEG && deriv < cp->sig_dvdt_lim){ scan_state = PEAK; break; } // if no pulse then check the zero avg_zero = (avg_zero * 20 + y)/21; break; case PEAK: // reverse derivative indicates peak if(cp->sig_type == PULSE_POS && deriv < 0){ scan_state = TAIL; } if(cp->sig_type == PULSE_NEG && deriv > 0){ scan_state = TAIL; } if(scan_state == TAIL){ // handle gaussian approximation if enabled if(cp->sig_gaussian){ // p = ((a - g)/(a -2b + g))/2 = position of peak peak = (fixed_div((alpha - gamma),(alpha - (2 * beta) + gamma))) / 2; // y(p) = b - ((a - g) * p)/4 = peak value peak = beta - (fixed_mul((alpha - gamma), peak) / 4); } else { peak = (alpha + beta + gamma) / 3; } if(cp->sig_type == PULSE_NEG){ peak = -peak; } // peak now always positive if( peak > cp->sig_lo_lim && peak < cp->sig_hi_lim){ bin = fixed_to_int(peak); pulse_height[bin]++; // increment count in spectrum array cur_cnt++; // handle rate meter beeping if(cp->rate_beep && !alarm_on){ Beep(BEEP_500Hz, 10); } } } break; case TAIL: // find where curve turns back to baseline if(cp->sig_type == PULSE_POS && deriv >= 0){ scan_state = LEADING; } if(cp->sig_type == PULSE_NEG && deriv <= 0){ scan_state = LEADING; } break; } // switch(scan_state) } // while ring buffer not empty }
uint32_t adc_read_single( void ) { ADC_Start(ADC0, adcStartSingle); while ( ( ADC0->STATUS & ADC_STATUS_SINGLEDV ) == 0 ){} return ADC_DataSingleGet(ADC0); }
/***************************************************************************//** * @brief * Calibrate offset and gain for the specified reference. * Supports currently only single ended gain calibration. * Could easily be expanded to support differential gain calibration. * * @details * The offset calibration routine measures 0 V with the ADC, and adjust * the calibration register until the converted value equals 0. * The gain calibration routine needs an external reference voltage equal * to the top value for the selected reference. For example if the 2.5 V * reference is to be calibrated, the external supply must also equal 2.5V. * * @param[in] adc * Pointer to ADC peripheral register block. * * @param[in] ref * Reference used during calibration. Can be both external and internal * references. * * @return * The final value of the calibration register, note that the calibration * register gets updated with this value during the calibration. * No need to load the calibration values after the function returns. ******************************************************************************/ uint32_t ADC_Calibration(ADC_TypeDef *adc, ADC_Ref_TypeDef ref) { int32_t sample; uint32_t cal; /* Binary search variables */ uint8_t high; uint8_t mid; uint8_t low; /* Reset ADC to be sure we have default settings and wait for ongoing */ /* conversions to be complete. */ ADC_Reset(adc); ADC_Init_TypeDef init = ADC_INIT_DEFAULT; ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT; /* Init common settings for both single conversion and scan mode */ init.timebase = ADC_TimebaseCalc(0); /* Might as well finish conversion as quickly as possibly since polling */ /* for completion. */ /* Set ADC clock to 7 MHz, use default HFPERCLK */ init.prescale = ADC_PrescaleCalc(7000000, 0); /* Set an oversampling rate for more accuracy */ init.ovsRateSel = adcOvsRateSel4096; /* Leave other settings at default values */ ADC_Init(adc, &init); /* Init for single conversion use, measure diff 0 with selected reference. */ singleInit.reference = ref; singleInit.input = adcSingleInpDiff0; singleInit.acqTime = adcAcqTime16; singleInit.diff = true; /* Enable oversampling rate */ singleInit.resolution = adcResOVS; ADC_InitSingle(adc, &singleInit); /* ADC is now set up for offset calibration */ /* Offset calibration register is a 7 bit signed 2's complement value. */ /* Use unsigned indexes for binary search, and convert when calibration */ /* register is written to. */ high = 128; low = 0; /* Do binary search for offset calibration*/ while (low < high) { /* Calculate midpoint */ mid = low + (high - low) / 2; /* Midpoint is converted to 2's complement and written to both scan and */ /* single calibration registers */ cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SCANOFFSET_MASK); cal |= (mid - 63) << _ADC_CAL_SINGLEOFFSET_SHIFT; cal |= (mid - 63) << _ADC_CAL_SCANOFFSET_SHIFT; adc->CAL = cal; /* Do a conversion */ ADC_Start(adc, adcStartSingle); /* Wait while conversion is active */ while (adc->STATUS & ADC_STATUS_SINGLEACT) ; /* Get ADC result */ sample = ADC_DataSingleGet(adc); /* Check result and decide in which part of to repeat search */ /* Calibration register has negative effect on result */ if (sample < 0) { /* Repeat search in bottom half. */ high = mid; } else if (sample > 0) { /* Repeat search in top half. */ low = mid + 1; } else { /* Found it, exit while loop */ break; } } /* Now do gain calibration, only input and diff settings needs to be changed */ adc->SINGLECTRL &= ~(_ADC_SINGLECTRL_INPUTSEL_MASK | _ADC_SINGLECTRL_DIFF_MASK); adc->SINGLECTRL |= (adcSingleInpCh4 << _ADC_SINGLECTRL_INPUTSEL_SHIFT); adc->SINGLECTRL |= (false << _ADC_SINGLECTRL_DIFF_SHIFT); /* ADC is now set up for gain calibration */ /* Gain calibration register is a 7 bit unsigned value. */ high = 128; low = 0; /* Do binary search for gain calibration */ while (low < high) { /* Calculate midpoint and write to calibration register */ mid = low + (high - low) / 2; /* Midpoint is converted to 2's complement */ cal = adc->CAL & ~(_ADC_CAL_SINGLEGAIN_MASK | _ADC_CAL_SCANGAIN_MASK); cal |= mid << _ADC_CAL_SINGLEGAIN_SHIFT; cal |= mid << _ADC_CAL_SCANGAIN_SHIFT; adc->CAL = cal; /* Do a conversion */ ADC_Start(adc, adcStartSingle); /* Wait while conversion is active */ while (adc->STATUS & ADC_STATUS_SINGLEACT) ; /* Get ADC result */ sample = ADC_DataSingleGet(adc); /* Check result and decide in which part to repeat search */ /* Compare with a value atleast one LSB's less than top to avoid overshooting */ /* Since oversampling is used, the result is 16 bits, but a couple of lsb's */ /* applies to the 12 bit result value, if 0xffe is the top value in 12 bit, this */ /* is in turn 0xffe0 in the 16 bit result. */ /* Calibration register has positive effect on result */ if (sample > 0xffd0) { /* Repeat search in bottom half. */ high = mid; } else if (sample < 0xffd0) { /* Repeat search in top half. */ low = mid + 1; } else { /* Found it, exit while loop */ break; } } return adc->CAL; }
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { SYSTEM_ChipRevision_TypeDef revision; char string[8]; int i; uint32_t temp; /* Chip revision alignment and errata fixes */ CHIP_Init(); /* Initialize DVK board register access */ BSP_Init(BSP_INIT_DEFAULT); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); CMU_ClockEnable(cmuClock_HFPER, true); CMU_ClockEnable(cmuClock_ADC0, true); CMU_ClockEnable(cmuClock_GPIO, true); /* Initialize LCD controller without boost */ SegmentLCD_Init(false); SegmentLCD_AllOff(); /* Check for revision after revision B. Chips with revision earlier than */ /* Revision C has known problems with the internal temperature sensor. */ /* Display a warning in this case */ SYSTEM_ChipRevisionGet(&revision); if (revision.minor < 2) { SegmentLCD_Write("WARNING"); RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(true); SegmentLCD_Write("REV C+"); RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(true); SegmentLCD_Write("REQUIRD"); RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(true); } /* Enable board control interrupts */ BSP_InterruptDisable(0xffff); BSP_InterruptFlagsClear(0xffff); BSP_InterruptEnable(BC_INTEN_JOYSTICK); temperatureIRQInit(); /* Setup ADC for sampling internal temperature sensor. */ setupSensor(); /* Main loop - just read temperature and update LCD */ while (1) { /* Start one ADC sample */ ADC_Start(ADC0, adcStartSingle); /* Wait in EM1 for ADC to complete */ EMU_EnterEM1(); /* Read sensor value */ temp = ADC_DataSingleGet(ADC0); /* Convert ADC sample to Fahrenheit / Celsius and print string to display */ if (showFahrenheit) { /* Show Fahrenheit on alphanumeric part of display */ i = (int)(convertToFahrenheit(temp) * 10); snprintf(string, 8, "%2d,%1d%%F", (i/10), i%10); /* Show Celsius on numeric part of display */ i = (int)(convertToCelsius(temp) * 10); SegmentLCD_Number(i*10); SegmentLCD_Symbol(LCD_SYMBOL_DP10, 1); } else { /* Show Celsius on alphanumeric part of display */ i = (int)(convertToCelsius(temp) * 10); snprintf(string, 8, "%2d,%1d%%C", (i/10), i%10); /* Show Fahrenheit on numeric part of display */ i = (int)(convertToFahrenheit(temp) * 10); SegmentLCD_Number(i*10); SegmentLCD_Symbol(LCD_SYMBOL_DP10, 1); } SegmentLCD_Write(string); /* Sleep for 2 seconds in EM 2 */ RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(true); } }
/***************************************************************************//** * @brief * Interrupt handler is executed with frequency ~28Hz when panel is not pressed * and with frequency ~140Hz when panel is pressed - this will give ~50 readings per second ******************************************************************************/ void ADC0_IRQHandler(void) { switch (touch_state) { case TOUCH_INIT: /* enter this state if touch panel is not pressed */ GPIO_PinModeSet(TOUCH_Y1, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_Y2, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_X1, gpioModeInputPullFilter , 0); GPIO_PinModeSet(TOUCH_X2, gpioModeInput, 0); sInit.input = ADC_Y; sInit.reference = adcRefVDD; sInit.resolution = adcResOVS; sInit.acqTime = adcAcqTime128; /* used to slow down */ if(GPIO_PinInGet(TOUCH_X2)) { touch_state = TOUCH_MEASURE_Y; GPIO_PinModeSet(TOUCH_X1, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_X2, gpioModePushPull, 0); GPIO_PinModeSet(TOUCH_Y1, gpioModeInput, 0); GPIO_PinModeSet(TOUCH_Y2, gpioModeInput, 0); sInit.input = ADC_X; sInit.acqTime = adcAcqTime16; /* pressed, so speed-up */ } ADC_InitSingle(ADC0, &sInit); break; case TOUCH_CHECK_PRESS: /* checks if touch panel is still pressed */ if( GPIO_PinInGet(TOUCH_X2) ) { touch_state = TOUCH_MEASURE_Y; GPIO_PinModeSet(TOUCH_X1, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_X2, gpioModePushPull, 0); GPIO_PinModeSet(TOUCH_Y1, gpioModeInput, 0); GPIO_PinModeSet(TOUCH_Y2, gpioModeInput, 0); sInit.input = ADC_X; sInit.acqTime = adcAcqTime16; /* pressed, so speed-up */ ADC_InitSingle(ADC0, &sInit); current_pos.pen = newpos.pen; TOUCH_RecalculatePosition(&newpos); if (newpos.pen) { int call_upcall = TOUCH_StateChanged(); if (call_upcall) { current_pos.x = newpos.x; current_pos.y = newpos.y; } current_pos.adcx = newpos.adcx; current_pos.adcy = newpos.adcy; current_pos.pen = 1; if (call_upcall) TOUCH_CallUpcall(); } newpos.pen = 1; } else { touch_state = TOUCH_INIT; newpos.pen = 0; current_pos.pen = 0; TOUCH_CallUpcall(); } break; case TOUCH_MEASURE_Y: /* touch panel pressed, measure Y position */ newpos.adcy = (ADC_DataSingleGet(ADC0) + 31) >> 6; /* reduce ADC resolution to 10-bits */ GPIO_PinModeSet(TOUCH_Y1, gpioModePushPull, 0); /* to avoid overflow in calibration routines */ GPIO_PinModeSet(TOUCH_Y2, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_X1, gpioModeInput, 0); GPIO_PinModeSet(TOUCH_X2, gpioModeInput, 0); sInit.input = ADC_Y; ADC_InitSingle(ADC0, &sInit); touch_state = TOUCH_MEASURE_X; break; case TOUCH_MEASURE_X: /* touch panel pressed, measure X position */ newpos.adcx = (ADC_DataSingleGet(ADC0) + 31) >> 6; GPIO_PinModeSet(TOUCH_Y1, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_Y2, gpioModePushPull, 1); GPIO_PinModeSet(TOUCH_X1, gpioModeInputPullFilter , 0); GPIO_PinModeSet(TOUCH_X2, gpioModeInput, 0); sInit.input = ADC_Y; ADC_InitSingle(ADC0, &sInit); touch_state = TOUCH_CHECK_PRESS; break; default: touch_state = TOUCH_INIT; } ADC_IntClear(ADC0, ADC_IF_SINGLE); ADC_Start(ADC0, adcStartSingle); }
*******************************************************************************/int main() { CyGlobalIntEnable; #if (DEBUG_UART_ENABLED == ENABLED) UART_DEB_Start(); #endif /* (DEBUG_UART_ENABLED == ENABLED) */ DBG_PRINTF("BLE HID Keyboard Example Project \r\n"); LED_RED_Write(LED_OFF); LED_BLU_Write(LED_OFF); LED_GRN_Write(LED_OFF); /* Start CYBLE component and register generic event handler */ CyBle_Start(AppCallBack); #if (BAS_MEASURE_ENABLE != 0) ADC_Start(); #endif /* BAS_MEASURE_ENABLE != 0 */ while(1) { /* CyBle_ProcessEvents() allows BLE stack to process pending events */ CyBle_ProcessEvents(); /* To achieve low power in the device */ LowPowerImplementation(); if((CyBle_GetState() == CYBLE_STATE_CONNECTED) && (suspend != CYBLE_HIDS_CP_SUSPEND)) { if(mainTimer != 0u) { mainTimer = 0u; #if (BAS_SIMULATE_ENABLE != 0) SimulateBattery(); CyBle_ProcessEvents(); #endif /* BAS_SIMULATE_ENABLE != 0 */ #if (BAS_MEASURE_ENABLE != 0) MeasureBattery(); CyBle_ProcessEvents(); #endif /* BAS_MEASURE_ENABLE != 0 */ if(keyboardSimulation == ENABLED) { SimulateKeyboard(); } } /* Store bonding data to flash only when all debug information has been sent */ #if(CYBLE_BONDING_REQUIREMENT == CYBLE_BONDING_YES) #if (DEBUG_UART_ENABLED == ENABLED) if((cyBle_pendingFlashWrite != 0u) && ((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) == 0u)) #else if(cyBle_pendingFlashWrite != 0u) #endif /* (DEBUG_UART_ENABLED == ENABLED) */ { CYBLE_API_RESULT_T apiResult; apiResult = CyBle_StoreBondingData(0u); (void)apiResult; DBG_PRINTF("Store bonding data, status: %x \r\n", apiResult); } #endif /* CYBLE_BONDING_REQUIREMENT == CYBLE_BONDING_YES */ } } }
int main(void) { /** Number of samples/channels taken from accelerometer. */ #define ACCEL_SAMPLES 3 /** X axis sample index. */ #define ACCEL_X 0 /** Y axis sample index. */ #define ACCEL_Y 1 /** Z axis sample index. */ #define ACCEL_Z 2 /* * Tilt levels: Midpoint is theoretically half value of max sampling value * (ie 0x800 for 12 bit sampling). In real world, some sort of calibration * is required if more accurate sensing is required. We just use set some * fixed limit, that should be sufficient for this basic example. */ /** Tilt left limit */ #define TILT_LEFT 0x750 /** Tilt right limit */ #define TILT_RIGHT 0x8b0 SYSTEM_ChipRevision_TypeDef chipRev; uint32_t leds; uint32_t samples[ACCEL_SAMPLES]; int errataShift = 0; int i; /* Chip revision alignment and errata fixes */ CHIP_Init(); /* ADC errata for rev B when using VDD as reference, need to multiply */ /* result by 2 */ SYSTEM_ChipRevisionGet(&chipRev); if ((chipRev.major == 1) && (chipRev.minor == 1)) { errataShift = 1; } /* Initialize DK board register access */ BSP_Init(BSP_INIT_DEFAULT); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); /* Connect accelerometer to EFM32. */ BSP_PeripheralAccess(BSP_ACCEL, true); /* Enable clocks required */ CMU_ClockEnable(cmuClock_HFPER, true); CMU_ClockEnable(cmuClock_ADC0, true); CMU_ClockEnable(cmuClock_DMA, true); /* Configure ADC and DMA used for scanning accelerometer */ accelADCConfig(); accelDMAConfig(); /* Main loop, keep polling accelerometer */ leds = 0x0180; while (1) { DMA_ActivateBasic(ACCEL_DMA_CHANNEL, true, false, samples, (void *)((uint32_t)&(ADC0->SCANDATA)), ACCEL_SAMPLES - 1); /* Scan all axis', even though this app only use the X axis */ ADC_IntClear(ADC0, ADC_IF_SCAN); ADC_Start(ADC0, adcStartScan); /* Poll for completion, entering EM2 when waiting for next poll */ while (!(ADC_IntGet(ADC0) & ADC_IF_SCAN)) { RTCDRV_Trigger(5, NULL); EMU_EnterEM2(true); } if (errataShift) { for (i = 0; i < ACCEL_SAMPLES; i++) { samples[i] <<= errataShift; } } if (samples[ACCEL_X] < TILT_LEFT) { if (leds < 0xc000) { leds <<= 1; } } else if (samples[ACCEL_X] > TILT_RIGHT) { if (leds > 0x0003) { leds >>= 1; } } else { if (leds > 0x0180)
/**************************************************************************//** * @brief Main function *****************************************************************************/ int main(void) { uint8_t prod_rev; uint32_t temp; uint32_t temp_offset; float temperature; /* Initialize DK board register access */ BSP_Init(BSP_INIT_DEFAULT); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceProfilerSetup(); /* Initialize the TFT stdio retarget module. */ RETARGET_TftInit(); printf("\nEFM32 onchip temperature sensor example\n\n"); CMU_ClockEnable(cmuClock_HFPER, true); CMU_ClockEnable(cmuClock_ADC0, true); CMU_ClockEnable(cmuClock_GPIO, true); /* Enable board control interrupts */ BSP_InterruptDisable(0xffff); BSP_InterruptFlagsClear(0xffff); BSP_InterruptEnable(BC_INTEN_JOYSTICK); temperatureIRQInit(); /* This is a work around for Chip Rev.D Errata, Revision 0.6. */ /* Check for product revision 16 and 17 and set the offset */ /* for ADC0_TEMP_0_READ_1V25. */ prod_rev = (DEVINFO->PART & _DEVINFO_PART_PROD_REV_MASK) >> _DEVINFO_PART_PROD_REV_SHIFT; if( (prod_rev == 16) || (prod_rev == 17) ) { temp_offset = 112; } else { temp_offset = 0; } /* Setup ADC for sampling internal temperature sensor. */ setupSensor(); /* Main loop - just read temperature and update LCD */ while (1) { /* Start one ADC sample */ ADC_Start(ADC0, adcStartSingle); /* Wait in EM1 for ADC to complete */ EMU_EnterEM1(); /* Read sensor value */ /* According to rev. D errata ADC0_TEMP_0_READ_1V25 should be decreased */ /* by the offset but it is the same if ADC reading is increased - */ /* reference manual 28.3.4.2. */ temp = ADC_DataSingleGet(ADC0) + temp_offset; /* Convert ADC sample to Fahrenheit / Celsius and print string to display */ if (showFahrenheit) { temperature = convertToFahrenheit(temp); } else { temperature = convertToCelsius(temp); } printf("%d.%d %c\n", (int) temperature, (int)(10*(temperature-(int)temperature)), showFahrenheit? 'F' : 'C'); /* Sleep for 2 seconds in EM 2 */ RTCDRV_Trigger(2000, NULL); EMU_EnterEM2(true); } }