我的代码应该读取ADC 3次,然后取平均值,如果小于满量程值的一半,则板载LED应关闭,如果高于满量程值的一半,则应打开。 据我通过调试得知,adc 部分工作正常,它按应有的方式进行测量,但是当我进入比较值的部分时,代码会跳过打开或关闭 LED 的部分,然后返回到主循环的开始,然后返回到 while(1) 循环(所有这些都使用 atmel studio 上的逐步按钮)
这是代码:
/*
* Include header files for all drivers that have been imported from
* Atmel Software Framework (ASF).
*/
/*
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
*/
#include <asf.h>
int main (void)
{
system_init();
uint32_t result = 0;
uint8_t samp = 0;
PORT->Group[0].DIRSET.reg |= 1<<19;
ADC->DBGCTRL.reg = 1;
SYSCTRL->OSC8M.reg |= 1<<30 | 1<<6 | 0b10;
//ADC Pin6 Config
PORT->Group[0].DIRCLR.reg |= 1<<6;
PORT->Group[0].PMUX[3].reg = 0x1;
PORT->Group[0].PINCFG[6].reg &= ~(0b11);
PORT->Group[0].PINCFG[6].reg |= 1;
//ADC CLK Config
PM->APBCMASK.reg |= PM_APBCMASK_ADC; //Enable clk bus
/* Enable GCLK1 for the ADC */
GCLK->GENDIV.reg = 0;
while (GCLK->STATUS.bit.SYNCBUSY) {};
GCLK->GENCTRL.reg = 1<<21 | 1<<19 | 1<<17 | 1<<16 | 1<<10 | 1<<9;
while (GCLK->STATUS.bit.SYNCBUSY) {};
GCLK->CLKCTRL.reg = 1<<14 | 0x1E;
/* Wait for bus synchronization. */
while (GCLK->STATUS.bit.SYNCBUSY) {};
uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
/* Wait for bus synchronization. */
while (ADC->STATUS.bit.SYNCBUSY) {};
/* Write the calibration data. */
ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
/* Wait for bus synchronization. */
while (ADC->STATUS.bit.SYNCBUSY) {};
/* Use the internal VCC reference. This is 1/2 of what's on VCCA.
since VCCA is typically 3.3v, this is 1.65v.
*/
ADC->REFCTRL.reg = 2;
/* Only capture one sample. The ADC can actually capture and average multiple
samples for better accuracy, but there's no need to do that for this
example.
*/
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1;
/* Set the clock prescaler to 512, which will run the ADC at
8 Mhz / 512 = 31.25 kHz.
Set the resolution to 12bit.
*/
while (ADC->STATUS.bit.SYNCBUSY) {};
ADC->CTRLB.reg = 0;
/* Configure the input parameters.
- GAIN_DIV2 means that the input voltage is halved. This is important
because the voltage reference is 1/2 of VCCA. So if you want to
measure 0-3.3v, you need to halve the input as well.
- MUXNEG_GND means that the ADC should compare the input value to GND.
- MUXPOST_PIN3 means that the ADC should read from AIN3, or PB09.
This is A2 on the Feather M0 board.
*/
while (ADC->STATUS.reg == STATUS_BUSY) {}
ADC->INPUTCTRL.reg = 0b1111<<24 | 0b11 << 11 | 6;
/* Wait for bus synchronization. */
while (ADC->STATUS.bit.SYNCBUSY) {};
/* Enable the ADC. */
ADC->CTRLA.reg = 0b10;
/* Wait for bus synchronization. */
while (ADC->STATUS.bit.SYNCBUSY) {};
while (1) {
while (ADC->STATUS.bit.SYNCBUSY) {};
/* Wait for the result ready flag to be set. */
ADC->SWTRIG.bit.START = 1;
while(ADC->INTFLAG.bit.RESRDY == 0){};
/* Clear the flag. */
ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;
/* Read the value. */
result += ADC->RESULT.reg;
samp++;
if(samp >= 3){
if((result/3) < 2045){
PORT->Group[0].OUTSET.reg |= 1<<19;
}
else{
PORT->Group[0].OUTCLR.reg |= 1<<19;
}
result = 0;
samp = 0;
}
}
}
尝试逐行调试,期望执行
PORT->Group[0].OUT
行,但行不执行,代码跳转到main()
的开头,然后跳转到while(1)
的开头
TL;DR 继续单步执行并享受使用调试器的乐趣。
很长的故事(不是真的)。变量
uint32_t result
和 uint8_t samp = 0
在循环之前未使用。编译器已将其初始化移至循环体。只需继续单步执行代码,指令指针将分两步返回到循环体。