PY32F003F18之比较器问题

PY32F003F18的模拟模块,其内部参考电压容易受到电源电压影响。当我连接"USB转串口的RXD"时,PC接收到模拟数据均正常;当我连接“USB转串口的TXD”时,发现内部参考电压的AD值为0xFFF。断开连接的“USB转串口的TXD”,模拟功能模块又恢复正常。于是用万用表测量“USB转串口的TXD”的电压,开路电压为5V,CPU电压为3.3V。难道是因为接入这个TXD导线的原因吗?经过反复测试,AD转换和模拟比较器都会受到这个电压影响。

 

 测试代码:

COMP比较器功能:
比较器正端输入:PA1
比较器负端输入:VREFINT
比较器的输出端口:PA6作为
通过调整PA1上的输入电压,观测PA6引脚上的电平变化

使用步骤:
1. 配置PA1输入电压小于1.1V,检测PA06应该输出低电平,
2. 配置PA1输入电压大于1.3V,检测PA06应该输出高电平。
3. 每进一次比较器中断,翻转PB5

#include "Comparator.h"
#include "LED.h"

/*
COMP比较器功能:
比较器正端输入:PA1
比较器负端输入:VREFINT
比较器的输出端口:PA6作为
通过调整PA1上的输入电压,观测PA6引脚上的电平变化

使用步骤:
1. 配置PA1输入电压小于1.1V,检测PA06应该输出低电平,
2. 配置PA1输入电压大于1.3V,检测PA06应该输出高电平。
3. 每进一次比较器中断,翻转PB5
*/

COMP_HandleTypeDef  hcomp1;

void Comparator_Init(void);
void TIM1_COUNTERMODE_UP_Init(uint16_t arr,uint16_t psc);

//函数功能:TIM1中基本计数功能,并使能了更新中断,每次重装ARR值时会产生一次更新中断
//arr:自动重装值。
//psc:时钟预分频数
//TIM1_COUNTERMODE_UP_Init(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
//TIM1_COUNTERMODE_UP_Init(20000,80);//若使用HSI,当arr=20000,psc=80时,则为200ms,误差为10us;
void TIM1_COUNTERMODE_UP_Init(uint16_t arr,uint16_t psc)
{
	TIM_HandleTypeDef  TIM1_HandleStructure;

//HAL_TIM_Base_MspInit开始/
  __HAL_RCC_TIM1_CLK_ENABLE();                          //使能TIM1时钟
  HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0, 0); //设置中断优先级
  HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);         //使能TIM1中断
//HAL_TIM_Base_MspInit结束/

  TIM1_HandleStructure.Instance = TIM1;   //选择TIM1
  TIM1_HandleStructure.Init.Period            = arr-1;
	//设置在下一个更新事件产生时,装入"自动重载入寄存器TIMx_ARR"的值
	//将(arr-1)写入"自动重载入寄存器TIMx_ARR",设置自动重装载值
  TIM1_HandleStructure.Init.Prescaler         = psc-1;
	//设置用来作为TIMx时钟频率除数的预分频值
	//将(psc-1)写入"预装载寄存器TIMx_PSC",的PSC[15:0],设置预分频值
	//计数器的时钟频率CK_CNT=fCK_PSC/(PSC[15:0]+1)
  TIM1_HandleStructure.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;//时钟不分频,则tDTS=tCK_INT
	//若使用HSE,计算公式:arr*psc/24000000/1,当arr=20000,psc=240时,则为200ms,误差为10us;
	//若使用HSI,计算公式:arr*psc/8000000/1,当arr=20000,psc=80时,则为200ms,误差为100us;
  TIM1_HandleStructure.Init.CounterMode       = TIM_COUNTERMODE_UP;//向上计数
  TIM1_HandleStructure.Init.RepetitionCounter = 1 - 1;
	//不重复计数
	//将(1-1)写入"重复计数寄存器TIMx_RCR"中的REP[7:0],设置"重复计数器值"
  TIM1_HandleStructure.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	//"自动重装载寄存器"没有缓冲
	//不允许将"TIMx自动重新加载寄存器TIMx_ARR"的值被装入缓冲区;
	HAL_TIM_Base_Init(&TIM1_HandleStructure);    //TIM1初始化
	//选择计数器模式:向上计数
	//设置时钟分频因子:时钟不分频,则tDTS=tCK_INT
	//设置自动重装载:"自动重装载寄存器"没有缓冲
	//设置自动重装载值:TIM_Base_InitStructure.Period
	//设置预分频值:TIM_Base_InitStructure.Prescaler
	//设置"重复计数器值":TIM_Base_InitStructure.RepetitionCounter
  //启动更新事件:将TIMx_EGR中的UG位置1,由软件产生更新事件

	HAL_TIM_Base_Start_IT(&TIM1_HandleStructure);
  //允许计数器产生"更新中断";
  //如果计数器不是工作在触发模式中,则开始计数
}

void HAL_COMP_MspInit(COMP_HandleTypeDef *hcomp)
{
	GPIO_InitTypeDef GPIO_InitStructureure;

	if(hcomp->Instance == COMP1)
	{
    __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
    __HAL_RCC_COMP1_CLK_ENABLE();//使能COMP1时钟
    __HAL_RCC_COMP2_CLK_ENABLE();//使能COMP2时钟

    //PA1配置为模拟输入COMP1_INP2
    GPIO_InitStructureure.Pin = GPIO_PIN_1;             //选择第1脚
	  GPIO_InitStructureure.Pull = GPIO_PULLDOWN;         //引脚下拉被激活
	  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_HIGH; //配置GPIO速度为高
    GPIO_InitStructureure.Mode = GPIO_MODE_ANALOG;      //设置引脚工作模式为模拟输入模式
    HAL_GPIO_Init(GPIOA,&GPIO_InitStructureure);
	  //根据GPIO_InitStructure结构变量指定的参数初始化GPIOA的外设寄存器

    //PA6映射到COMP1_OUT,配置为输出
    GPIO_InitStructureure.Pin = GPIO_PIN_6;             //选择第6脚
    GPIO_InitStructureure.Pull = GPIO_PULLDOWN;         //引脚下拉被激活
	  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_HIGH; //配置GPIO速度为高
	  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;       //复用功能推挽输出模式
    GPIO_InitStructureure.Alternate = GPIO_AF7_COMP1;   //选择AF7,将PA6复用为COM1_OUT
    HAL_GPIO_Init(GPIOA,  &GPIO_InitStructureure);            //初始化GPIO

    HAL_NVIC_EnableIRQ(ADC_COMP_IRQn);            //使能COMP中断
    HAL_NVIC_SetPriority(ADC_COMP_IRQn,0x01, 0);
	  //设置COMP1中断优先级为0x01,0无意义
  }
	if(hcomp->Instance == COMP2)
	{
	}
}

//函数功能:比较器1初始化
void Comparator_Init(void)
{
  hcomp1.Instance = COMP1;                                              //选择COM1
  hcomp1.Init.InputMinus      = COMP_INPUT_MINUS_VREFINT;               //比较器负输入端为VREF(1.2V)
  hcomp1.Init.InputPlus       = COMP_INPUT_PLUS_IO3;                    //比较器正输入端选择为PA1,pin PA1 for COMP1
  hcomp1.Init.OutputPol       = COMP_OUTPUTPOL_NONINVERTED;             //COMP1极性选择为不反向
  hcomp1.Init.Mode            = COMP_POWERMODE_HIGHSPEED;               //COMP1功耗模式选择为High speed模式
  hcomp1.Init.Hysteresis      = COMP_HYSTERESIS_DISABLE;                //迟滞功能关闭
  hcomp1.Init.WindowMode      = COMP_WINDOWMODE_DISABLE;                //WIODOW关闭
  hcomp1.Init.TriggerMode     = COMP_TRIGGERMODE_IT_RISING_FALLING;     //COMP1上升/下降沿触发
	HAL_COMP_Init(&hcomp1);//COMP1初始化

  HAL_COMP_Start(&hcomp1);  
}

void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
{
	if(hcomp1.Instance == COMP1)
	{
		MCU_LED_Toggle();
	}
}

//函数功能:比较器1中断服务程序
void ADC_COMP_IRQHandler(void)
{
  HAL_COMP_IRQHandler(&hcomp1);
}

//函数功能:TIM1中断服务程序
//200ms中断一次
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
HAL_TIM_PeriodElapsedCallback开始/
  if (_HAL_TIM_GET_FLAG(TIM1,TIM_FLAG_UPDATE) != RESET)
  {//根据TIM_FLAG_UPDATE,读"TIMx状态寄存器(TIMx_SR)"中更新中断标志位
    _HAL_TIM_CLEAR_IT(TIM1, TIM_IT_UPDATE);
		//TIM_IT_UPDATE,令UIF=0,清除定时器更新中断标志位
    TIM1_LED_Toggle();
  }
HAL_TIM_PeriodElapsedCallback结束/
}
#include "py32f0xx_hal.h"
#include "SystemClock.h"
#include "delay.h"
#include "LED.h"
#include "SystemClock.h"
#include "Comparator.h"
//#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
//#include "string.h" //使能strcpy(),strlen(),memset()

const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";

int main(void)
{
	HSE_Config();
//	HAL_Init();//systick初始化
  delay_init();
	HAL_Delay(1000);

//	USART2_Init(115200);
//PA0是为USART2_TX,PA1是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
//	printf("%s",CPU_Reset_REG);

	MCU_LED_Init();
	TIM1_LED_Init();
	TIM1_COUNTERMODE_UP_Init(20000,240);//若使用HSE,当arr=20000,psc=240时,则为200ms,误差为10us;
	Comparator_Init();

  while (1)
  {
		delay_ms(100);
//		MCU_LED_Toggle();

  }
}

注意:普冉单片机PY32F003F18,国产ARM芯片,在使用模拟量时,一定要注意CPU的“IO输入电压”要小于等于“CPU电源电压”,否则,会导致AD转换错误。切记踩坑啊!!!

注意:两个比较器初始化之间要添加延时,否则,比较器1初始化结束后,比较器2不工作。 

    Comparator1_Init();//比较器1初始化
    delay_ms(100);//两个比较器初始化之间要添加延时,否则,比较器1初始化结束后,比较器2不工作
    Comparator2_Init();//比较器2初始化 

或者修改比较器初始化程序,见程序注释。

  COMP_HandleStructureure.Instance = COMP2;                                              //选择COM2
  COMP_HandleStructureure.Init.InputMinus      = COMP_INPUT_MINUS_VREFINT;               //比较器负输入端为VREF(1.2V)
  COMP_HandleStructureure.Init.InputPlus       = COMP_INPUT_PLUS_IO3;                    //比较器正输入端选择为PA3,pin PA3 for COMP2
  COMP_HandleStructureure.Init.OutputPol       = COMP_OUTPUTPOL_NONINVERTED;             //COMP2极性选择为不反向
  COMP_HandleStructureure.Init.Mode            = COMP_POWERMODE_HIGHSPEED;               //COMP2功耗模式选择为High speed模式
  COMP_HandleStructureure.Init.Hysteresis      = COMP_HYSTERESIS_DISABLE;                //迟滞功能关闭
  COMP_HandleStructureure.Init.WindowMode      = COMP_WINDOWMODE_DISABLE;                //WINDOW关闭
  COMP_HandleStructureure.Init.TriggerMode     = COMP_TRIGGERMODE_IT_RISING_FALLING;     //COMP2上升/下降沿触发
	HAL_COMP_DeInit(&COMP_HandleStructureure);
	//没有这一句,比较器初始化后,可能会不工作
	//也可以在两个比较器初始化程序之间要添加延时,否则会出现后初始化的比较器不工作
	HAL_COMP_Init(&COMP_HandleStructureure);//COMP2初始化

竟然有这么奇葩的事情会发生!!!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值