本帖最后由 小恩GG 于 2023-6-1 14:48 编辑
LPC55xx:ARM tx event触发ADC你了解吗? 一、简介 本文讨论了基于LPC55S69-EVK板、mcxpresso IDE和SDK下的ARMtx event触发ADC的方法。ARM tx event是ADC的触发源之一,虽然是硬件触发,但是其机制与软件触发相同,经过ADC配置后,执行指令asm(“SEV”),将生成ARM tx event并触发ADC进行采样。 LPC55xx的ADC支持硬件触发模式,每个硬件触发源对应一个触发寄存器,如表1所示,ARM tx event ADC触发源索引为11,因此必须初始化ADC触发控制寄存器TCTRL11。在TCTRL11寄存器中,可以分配命令ID,选择FIFO0或FIFO1去保存ADC结果,使能硬件触发。 表1 二、"SEV "指令 在执行指令asm(" SEV ")之后,ADC触发源11将产生事件触发ADC。"SEV "是一种提示指令,内核执行这条指令asm(“SEV”)后,会产生一个event给外设或其他内核(多内核处理器)以便触发外设或唤醒其他内核。手册user guide of ARM_Cortex_M33.pdf中" SEV "说明如图1所示: 图 1 三、ARM tx event触发ADC设置 在基于LPC55S69-EVK板SDK包中的lpadc_interrupt项目,修改了项目程序中的两个位置,实现ARM tx event触发ADC。 1)原始代码初始化了TCTRL0寄存器,因为它采用了软件触发方式,所以任何TCTRLx寄存器都可以使用。但是对于ARM tx event,必须使用TCTRL11寄存器并启用硬件触发模式。 mLpadcTriggerConfigStruct.enableHardwareTrigger =true; LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE,11U,&mLpadcTriggerConfigStruct);/*配置触发器* / 2)每次采样执行asm(“SEV”)指令,指令完成后ADC进行转换,转换完成后执行ADC ISR(中断服务程序),g_lpadcconveroncompletedflag将会被设置。 在例程中执行asm(“SEV”)指令代码如下: while (1) { GETCHAR(); //LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U);/* 1U is trigger0 mask. */ asm("SEV"); while (!g_LpadcConversionCompletedFlag) { } PRINTF("ADCvalue: %d\r\nADC interrupt count: %d\r\n", ((g_LpadcResultConfigStruct.convValue) >> g_LpadcResultShift), g_LpadcInterruptCounter); g_LpadcConversionCompletedFlag = false; } 四、修改后的ADC代码 int main(void) { lpadc_config_t mLpadcConfigStruct; lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct; lpadc_conv_command_config_tmLpadcCommandConfigStruct; /* set BODVBAT level to 1.65V */ POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false); /* attach main clock divide toFLEXCOMM0 (debug console) */ CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH); BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); /* Set clock source for ADC0 */ CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk, 8U, true); CLOCK_AttachClk(kMAIN_CLK_to_ADC_CLK); /* Disable LDOGPADC power down */ POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC); ANACTRL_Init(ANACTRL); ANACTRL_EnableVref1V(ANACTRL, true); PRINTF("LPADCInterrupt Example\r\n"); LPADC_GetDefaultConfig(&mLpadcConfigStruct); mLpadcConfigStruct.enableAnalogPreliminary = true; #if defined(DEMO_LPADC_VREF_SOURCE) mLpadcConfigStruct.referenceVoltageSource = DEMO_LPADC_VREF_SOURCE; #endif /* DEMO_LPADC_VREF_SOURCE */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS)&& FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS mLpadcConfigStruct.conversionAverageMode = kLPADC_ConversionAverage128; #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */ LPADC_Init(DEMO_LPADC_BASE, &mLpadcConfigStruct); #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS)&& FSL_FEATURE_LPADC_HAS_CTRL_CALOFS #if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM)&& FSL_FEATURE_LPADC_HAS_OFSTRIM /* Request offset calibration. */ #ifdefined(DEMO_LPADC_DO_OFFSET_CALIBRATION) && DEMO_LPADC_DO_OFFSET_CALIBRATION LPADC_DoOffsetCalibration(DEMO_LPADC_BASE); #else LPADC_SetOffsetValue(DEMO_LPADC_BASE, DEMO_LPADC_OFFSET_VALUE_A,DEMO_LPADC_OFFSET_VALUE_B); #endif /* DEMO_LPADC_DO_OFFSET_CALIBRATION */ #endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */ /* Request gain calibration. */ LPADC_DoAutoCalibration(DEMO_LPADC_BASE); #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */ #if(defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) &&FSL_FEATURE_LPADC_HAS_CFG_CALOFS) /* Do auto calibration. */ LPADC_DoAutoCalibration(DEMO_LPADC_BASE); #endif /*FSL_FEATURE_LPADC_HAS_CFG_CALOFS */ /* Set conversion CMDconfiguration. */ LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct); mLpadcCommandConfigStruct.channelNumber =DEMO_LPADC_USER_CHANNEL; #ifdefined(DEMO_LPADC_USE_HIGH_RESOLUTION) &&DEMO_LPADC_USE_HIGH_RESOLUTION mLpadcCommandConfigStruct.conversionResolutionMode =kLPADC_ConversionResolutionHigh; #endif /*DEMO_LPADC_USE_HIGH_RESOLUTION */ LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID,&mLpadcCommandConfigStruct); /* Set trigger configuration. */ LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct); mLpadcTriggerConfigStruct.targetCommandId = DEMO_LPADC_USER_CMDID; /* CMD15 is executed. */ mLpadcTriggerConfigStruct.enableHardwareTrigger= true; LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 11U,&mLpadcTriggerConfigStruct); /* Configurate the trigger0. */ /* Enable the watermark interrupt.*/ #if (defined(FSL_FEATURE_LPADC_FIFO_COUNT)&& (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) LPADC_EnableInterrupts(DEMO_LPADC_BASE, kLPADC_FIFO0WatermarkInterruptEnable); #else LPADC_EnableInterrupts(DEMO_LPADC_BASE,kLPADC_FIFOWatermarkInterruptEnable); #endif /*FSL_FEATURE_LPADC_FIFO_COUNT */ EnableIRQ(DEMO_LPADC_IRQn); PRINTF("ADCFull Range: %d\r\n", g_LpadcFullRange); #ifdefined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) &&FSL_FEATURE_LPADC_HAS_CMDL_CSCALE if(kLPADC_SampleFullScale == mLpadcCommandConfigStruct.sampleScaleMode) { PRINTF("Full channel scale(Factor of 1).\r\n"); } else if(kLPADC_SamplePartScale == mLpadcCommandConfigStruct.sampleScaleMode) { PRINTF("Divided inputvoltage signal. (Factor of 30/64).\r\n"); } #endif /* When the number of datawordsstored in the ADC Result FIFO is greater * than watermark value(0U), LPADC watermark interruptwould be triggered. */ PRINTF("Pleasepress any key to get user channel's ADC value.\r\n"); while (1) { GETCHAR(); //LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE,1U); /* 1U is trigger0 mask. */ asm("SEV"); while (!g_LpadcConversionCompletedFlag) { } PRINTF("ADCvalue: %d\r\nADC interrupt count: %d\r\n", ((g_LpadcResultConfigStruct.convValue) >> g_LpadcResultShift),g_LpadcInterruptCounter); g_LpadcConversionCompletedFlag = false; }
} 五、ARM txevent 触发ADC程序测试结果 5.1 找到开发板ADC通道引脚 lpadc_interrupt例程中选择了ADC0_0通道,PORT0 PIN23引脚设置为了ADC0_0通道引脚。 5.2 通过串口输出ADC采样结果 每次单击PC上的任何按钮,ADC将经行一转换。
当PORT0 PIN23引脚接地时,单击PC上的任何按钮,串口输出ADC值ADC value=1。 当PORT0PIN23引脚接3.3V时,单击PC上的任何按钮,串口输出ADC值ADC value=4095。
|