您好!
很抱歉、这个主题的标题太可怕了、但很难描述这个问题。 我看到了一些奇怪的行为。 有时、当我运行代码时、调试器似乎总是在其中一个 ADC 读取调用中的"_bis_SR_register (LPM0_bits + GIE);"中停止。 如果点击"Play"、它将再次循环浏览代码并再次停止。 我没有设置断点。 奇怪的是、如果我删除其中一个 ADC 读取调用、它将消失(例如 ADC0_SAMPLE())。 我进一步探讨了这一点、并在 CPU 处于唤醒状态时开始切换 P2.3、并注意到当它执行这种奇怪的行为时、GPIO P2.3将始终处于高电平、这在某种程度上意味着 CPU 永远不会回到睡眠状态。 我甚至断开调试器并看到相同的行为。 就像我之前说过的、如果我移除其中一个 ADC 读取调用、它就会消失。 然后我在每个 ADC_SAMPLE()调用中添加了更多代码,这些代码会在 P2.3进入睡眠状态之前将其设置为低电平,等待 ADC 转换完成。 转换完成后、我再次将 P2.3设置为高电平。 我这么做后、问题又消失了。 我看到了我的预期。 P2.3在短时间内保持高电平、然后进入睡眠模式。 它执行此操作三次、然后在更长的时间间隔内保持高电平以处理其他所有内容、然后最终恢复睡眠更长的时间间隔、直到下一个 RTC 中断在 while (1)中开始下一个周期。
因此、如果我有某种竞争状态、或者如果我有实施错误、我会感到非常困惑。 下面我附上了我的代码的一般概念。 值得注意的是、我正在对编译器中的大小进行最高级别的优化。
#include "driverlib.h"
#include
/*
main.c
*/
int main (void){
//停止 WDT
WDT_A_HOLD (WDT_A_base);
initClockTo16MHz();
inituart();
/*初始化外设*/
initGPIO();
initrtc();
_delay_cycles (10000);
EUSCI_A_UART_ENABLE (EUSCI_A0_BASE);
while (1){
//由 RTC 中断唤醒
P2OUT |= BIT3;//检查 CPU 使用情况
adc1Sample();
ADC1_READING = ADC_Conversion_Result;
adc0Sample();
ADC0_READING = ADC_Conversion_Result;
tempSample ();
temp_reading = ADC_Conversion_Result;
do _Other_processing ();
P2OUT &=~BIT3;//检查 CPU 使用情况
_bis_SR_register (LPM0_bits + GIE); //更改为 LPM0
}
void enable_ADC10 (uint8_t ADC_channel){
//初始化 ADC 模块
//
* ADC 模块的基地址
*使用内部 ADC 位作为采样/保持信号来启动转换
*使用 MODOSC 5MHZ 数字振荡器作为时钟源
*使用默认的1个时钟分频
器*/
ADC_init (ADC_base、 ADC_SAMPLEHOLDSOURCE_SC、ADC_CLOCKSOURCE_ADCOSC、ADC_CLOCKDIVIDER_1);
ADC_ENABLE (ADC_BASE);
ADC_setupSamplingTimer (ADC_base、ADC_CYCLEHOLD_1024_cycles、ADC_MULTIPLESAMPLESDISABLE);
IF (ADC_CHANNEL = ADCINCH_12)
{
ADC_configureMemory (ADC_base、ADC_channel、ADC_VREFPS_INT、ADC_VREFNEG_AVSS);
}
否则
{
ADC_configureMemory (ADC_base、ADC_channel、ADC_VREFPOS_AVCC、ADC_VREFNEG_AVSS);
}
ADC_clearInterrupt (ADC_base、 ADC_completed_interrupt);
//启用存储器缓冲器中断
ADC_enableInterrupt (ADC_base、ADC_completed_interrupt);
}
void disable_ADC10 (void){
ADC_disableConversions (ADC_base、0);
ADC_disable (ADC_base);
}
void adc1Sample (void)
{
ENABLE_ADC10 (ADCINCH_1);
_DELAY_CYCLES (15);
//启用并开始转换
//在单通道、单次转换模式中
ADC_startConversion (ADC_base、ADC_SINGLECHANNEL);
//LPM0、ADC 转换完成将强制退出
_bis_SR_register (LPM0_bits + GIE);
disable_ADC10 ();
}
void adc0Sample (void)
{
ENABLE_ADC10 (ADCINCH_0);//应为0
_DELAY_CYCLES (15);
//启用并开始转换
//在单通道、单次转换模式中
ADC_startConversion (ADC_base、ADC_SINGLECHANNEL);
//LPM0、ADC 转换完成将强制退出
_bis_SR_register (LPM0_bits + GIE);
disable_ADC10 ();
}
void tempSample (void)
{
ENABLE_ADC10 (ADCINCH_12);
_DELAY_CYCLES (15);
//启用并开始转换
//在单通道、单次转换模式中
ADC_startConversion (ADC_base、ADC_SINGLECHANNEL);
//LPM0、ADC 转换完成将强制退出
_bis_SR_register (LPM0_bits + GIE);
disable_ADC10 ();
}
void initGPIO (void){
P1DIR |= 0b01000000;
P2DIR |= 0b00001111;// P0-P3所有输出
P2OUT = 0x00;
PMM_enableTempSensor ();//启用温度传感器
PMM_enableInternalReference();
P1SEL1 |= GPIO_PIN6;// PWM 模式
P1SEL1 &=~(BIT7); // USCI_A0 UART 操作仅发送
P1SEL0 |= BIT7;
// I2C 引脚
P1SEL0 |= BIT2 | BIT3;
P1SEL1 &=~(BIT2 | BIT3);
//ADC 引脚
P1SEL0 |= BIT0 | BIT1;
P1SEL1 |= BIT0 | BIT1;
/*
*禁用 GPIO 上电默认高阻抗模式以激活
*先前配置的端口设置
*
PMM_unlockLPM5 ();
}
// ADC 中断服务例程
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_ICC__)
#pragma vector=ADC_vector
__interrupt void ADC_ISR (void)
#Elif defined (__GIC_)
void ___attribute_isr (
nc
)(void)(nc) interrupt!
#endif
{
ADC_Conversion_Result = ADCMEM0;// AP
__ BIC_SR_register_ON_EXIT (LPM0_BITS); //退出 LPM0
}
void initClockTo16MHz()
{
//根据 MCLK 的器件数据表的要求配置一个 FRAM 等待状态
//在配置时钟系统之前在8MHz 以上运行。
FRCTL0 = FRCTLPW | NWAITS_1;
_bis_SR_register (SCG0);//禁用 FLL
CSCTL8 |= MODOSCREQEN;
CSCTL3 |= SELREF_REFOCLK;//将 REFO 设置为 FLL 基准源
CSCTL0 = 0; //清除 DCO 和 MOD 寄存器
CSCTL1 &=~(DCORSEL_7); //首先清除 DCO 频率选择位
CSCTL1 |= DCORSEL_5; //设置 DCO = 16MHz
CSCTL2 = FLLD_0 + 487; //设置为 fDCOCLKDIV =(FLLN + 1)*(fFLLREFCLK/n)
// =(487 + 1)*(32.768 kHz/1)
// = 16MHz
_DELAY_CYCLES (3);
_BIC_SR_register (SCG0); //启用 FLL
while (CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1)); // FLL 锁定
CSCTL4 = SELMS_DCOCLKDIV | SELA_REFOCLK;
}
// RTC 中断服务例程
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_ICC__)
#pragma vector=RTC_vector
__interrupt RTC_ISR (void)
#Elif defined (__IAR_systems_ICC_)(void
)(void)(void)(n_rtc)(void)(void)(void)
#endif
{
_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS); //睡眠定时器退出 LPM0
开关(__evo_in_range (RTCIV、RTCIV_RTCIF)
{
案例 RTCIV_NONE:中断; //无中断
案例 RTCIV_RTCIF: // RTC 溢出
中断;
默认值:break;
}
void initrtc()
{
RTCMOD = 16-1;//设置为256Hz
SYSCFG2 |= RTCCKSEL; //选择 ACLK 作为 RTC 时钟
RTCCTL = RTCSS_1 | RTCSR | RTCPS__16 | RTCIE;
}