问题一: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();
}
|