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初始化
竟然有这么奇葩的事情会发生!!!