问题一:ADC模块的中断需要写两次清除中断标志寄存器才能清除中断,测试代码如下: 
 
#define TESTPIN_ON()                GPIOA->BOR = (1UL << 2)                        //PA2拉高 
#define TESTPIN_OFF()        GPIOA->BOR = (1UL << 18)                        //PA2拉低 
#define WAITE_NOP()                __nop();__nop();__nop();        \ 
                                        __nop();__nop();__nop();        \ 
                                        __nop();__nop();__nop();        \ 
                                        __nop();__nop();__nop() 
/**************************************************************************** 
** 函数名称 :void ADC_Init (VMEAS *v) 
** 函数功能 :ADC初始化 
****************************************************************************/ 
void ADC_Init (void) 
{         
        RCC->APB2RCR |= RCC_APB2RCR_ADC1RST;        //复位ADC1 
        RCC->APB2RCR &= ~RCC_APB2RCR_ADC1RST;        //复位关闭 
 
        RCC->APB2CCR |= RCC_APB2CCR_ADC1EN;                //开启ADC时钟 
        RCC->AHBCCR  |= RCC_AHBCCR_PAEN;                //使能引脚时钟PA 
         
        RCC->GCFGR   |= RCC_GCFGR_ADCPS_DIV4;        //ADC时钟4分频,12MHz 
        RCC->GCFGR3  |= (1UL << 8);                                //ADC时钟源选择  0:HSI14  1:APB2 
        WAITE_RCC();                                                        //等待时钟稳定 
         
        GPIOA->CTLR |= (GPIO_CTLR_CTLR0 |                 //PA0配置为ADCIN0 
                                    GPIO_CTLR_CTLR1 |                 //PA1配置为ADCIN1 
                                        GPIO_CTLR_CTLR3 );                //PA3配置为ADCIN3                         
         
        ADC1->ISQ = (2UL << 20) |                                //注入转换3个通道  2+1 
                                (0UL << 5 ) |                                //ADCIN0 
                                (1UL << 10) |                                //ADCIN1 
                                (3UL << 15) ;                                //ADCIN3 
         
        /*设置通道的采样时间为7.5个周期*/ 
        ADC1->SPT2 &= ~(ADC_SPT2_SPT0 | ADC_SPT2_SPT1 | ADC_SPT2_SPT3); 
        ADC1->SPT2 |= ADC_SPT2_SPT0_0 | ADC_SPT2_SPT1_0 | ADC_SPT2_SPT3_0;         
 
        ADC1->CTLR1 = (1UL << 8) |                                //开启扫描模式 
                                  (1UL << 7) ;                                //允许注入通道转换结束中断 
 
        ADC1->CTLR2 = (1UL << 15) |                                //注入组外部触发使能 
                                  (0UL << 12) |                                //TIM1_TRGO事件触发 
                                  (0UL << 11) |                                //数据右对齐 
                                  (0UL << 8 ) ;                                //不使用DMA 
                                   
        ADC1->CTLR2 |= ADC_CTLR2_ADCON;                        //开启ADC 
         
        ADC1->CTLR2 |= ADC_CTLR2_RSTCLB;                //复位校准寄存器 
        while(ADC1->CTLR2 & ADC_CTLR2_RSTCLB); 
         
        ADC1->CTLR2 |= ADC_CTLR2_CLB;                        //校准ADC 
        while(ADC1->CTLR2 & ADC_CTLR2_CLB); 
         
        ADC1->STR &= ~(1UL << 2);                                //清除标志位 
         
        NVIC_EnableIRQ(ADC1_CMP_IRQn);                        //允许中断 
} 
 
/**************************************************************************** 
** 函数名称 :void ADC1_CMP_IRQHandler (void) 
** 函数功能 :ADC1中断处理 
****************************************************************************/ 
void ADC1_CMP_IRQHandler (void) 
{ 
        adc1.ADCRes[ADC_HB]   = ADC1->IDTR1;                 
        adc1.ADCRes[ADC_MPV]  = ADC1->IDTR2;                 
        adc1.ADCRes[ADC_HALL] = ADC1->IDTR3;                 
 
        TESTPIN_ON();  
        WAITE_NOP();         
               TESTPIN_OFF(); 
         
        ADC1->STR &= ~(ADC_STR_STIC | ADC_STR_EOIC);    //用示波器查看TESTPIN电平,发现中断处理函数连续进来了两次。 
                                                                                    //如果这条语句让他执行两次或者先清EOIC再清STIC标志,中断处理函数恢复正常(不再连续进来) 
} 
 
问题二:将TIM3配置成霍尔传感器输入接口后,在TIM3_CH1 (PA6)、TIM3_CH2 (PA7)、TIM3_CH3 (PB0)上通过4.7K电阻上拉到5V。发现上述配置的ADC_IN0上存在向外的灌电流200uA左右。而且在ADC被外部触发信号触发转换时,ADC_IN0上的电压会不断波动。 
 
问题三:SPI模块抗干扰能力偏弱。在SPI模块在发送数据时,如果用示波器表笔点SCK这个信号线(点在与这个信号相连的外部10K上拉电阻上)。通过多次点击测试后,SPI的内部移位寄存器会发生移位现象。我猜测内部移位寄存器的移位CLK与SPI接口的SCK信号共用,但是外部和内部没有输出缓冲器,所以在对这个SCK信号进行干扰时,直接影响了内部移位寄存器移位。以下是初始化代码: 
/***************************************************************************** 
** 函数名称 :void SPI1_Reset (void) 
** 函数功能 :重置SPI 
*****************************************************************************/ 
static void SPI1_Reset (void) 
{ 
        RCC->APB2RCR |= RCC_APB2RCR_SPI1RST;                //复位SPI1 
        RCC->APB2RCR &= ~RCC_APB2RCR_SPI1RST;                //复位关闭 
        RCC->APB2CCR |= RCC_APB2CCR_SPI1EN;              //使能SPI1时钟 
        WAITE_RCC();                                                                //等待时钟稳定 
         
        SPI1->CTLR1 &= ~SPI_CTLR1_SPIEN;                        //关闭SPI设备 
         
        SPI1->CTLR1  =         (1UL << 15)|                                //选择单向单线模式 
                                        (1UL << 14)|                                //发送模式 
                                        (0UL << 11)|                                //数据长度为8位 
                                        (1UL << 9) |                                //启用软件从设备管理 
                                        (1UL << 8) |                                //主模式 
                                        (0UL << 7) |                                //先发LSB 
                                        (4UL << 3) |                                 //Fsck=Fcpu/32 
                                        (1UL << 2) |                                //配置设备模式                  0:从设备           1:主设备 
                                        (1UL << 1) |                                //空闲状态SCK电平          0:低电平          1:高电平 
                                        (1UL << 0);                                        //数据采样                        0:第一个时钟边沿         1:第二个时钟边沿 
         
        SPI1->CTLR2 = 0;                                         
 
        SPI1->CTLR1 |= SPI_CTLR1_SPIEN;                                //开启SPI设备 
} 
 
/***************************************************************************** 
** 函数名称 :void SPI1_Init (void) 
** 函数功能 :SPI初始化 
*****************************************************************************/ 
void SPI1_Init (void) 
{ 
        RCC->AHBCCR |= RCC_AHBCCR_PAEN;                                                        //使能引脚时钟PA 
        RCC->AHBCCR |= RCC_AHBCCR_PBEN;                                                        //使能引脚时钟PB 
        WAITE_RCC();                                                                                        //等待时钟稳定 
         
        /*初始化SPI1管脚*/ 
        GPIOA->CTLR  &= ~GPIO_CTLR_CTLR15; 
        GPIOA->CTLR  |= GPIO_CTLR_CTLR15_0;                                                //PA15配置为CS 
         
        GPIOA->OMODE &= ~GPIO_OMODE_OM15;                                                //推挽输出 
        GPIOA->OSPD  &= ~GPIO_OSPD_OSPD15; 
         
        CLR_NSS; 
         
        GPIOB->CTLR  &= ~(GPIO_CTLR_CTLR3 | GPIO_CTLR_CTLR5); 
        GPIOB->CTLR  |= GPIO_CTLR_CTLR3_1 | GPIO_CTLR_CTLR5_1; 
         
        GPIOB->OMODE &= ~(GPIO_OMODE_OM3 | GPIO_OMODE_OM5);                //推挽输出 
        GPIOB->OSPD  &= ~(GPIO_OSPD_OSPD3 | GPIO_OSPD_OSPD5); 
        GPIOB->OSPD  |= GPIO_OSPD_OSPD3_0 | GPIO_OSPD_OSPD5_0; 
         
        GPIOB->AFS[0] &= ~(GPIO_AFSL_AFSL3 | GPIO_AFSL_AFSL5); 
        GPIOB->AFS[0] |= (0UL << 12) |                                                        //PB3配置为SPI1_SCK 
                                         (0UL << 20) ;                                                        //PB5配置为SPI1_MOSI 
         
        SPI1_Reset(); 
} 
 
 |   
     
  
 |