初中生
最后登录1970-1-1
在线时间 小时
注册时间2020-6-18
|
发表于 2023-3-28 23:26:05
|
显示全部楼层
本帖最后由 江瀚林 于 2023-3-28 23:38 编辑
野火哥好,大家好,我是来自2023年3月28日的硬件小菜鸡一枚,留爪爪
1、首先根据参数手册的建议将BKIN脚PB12配置为GPIO_Mode_IN_FLOATING(浮空输入),将BKIN脚PB12的检测极性改为高电平触发
实际调试发现定时器TIM1的CH1、CH1N输出波形不稳定,会有杂波,表现为隐约的0电平(此时示波器开启窄带宽20MHz,排除高频干扰,探头已提前校准)
static void ADVANCE_TIM_GPIO_Config(void) // 加上static表示只能在Advanced_Tim.c中调用
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
// 输出比较通道互补通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);
// 输出比较通道刹车通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
}
static void ADVANCE_TIM_Mode_Config(void) // 加上static表示只能在Advanced_Tim.c中调用
{
// 开启定时器时钟,即内部时钟CK_INT=72M
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK, ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period = ADVANCE_TIM_PERIOD; // 周期
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler = ADVANCE_TIM_PSC; // 分频
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 对CK_INT的分频得到死区时钟的频率,该成员配置高级定时器不能省略
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 不使用重复计数器
// 初始化定时器
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;
// 配置为PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM1模式,默认递增模式下先输出1,计数到CCRx输出0
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补输出使能
TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE; // 设置占空比大小
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出通道电平极性配置,通常配置有效电平=1
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // 互补输出通道电平极性配置,通常配置有效电平=1
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; // 刹车BKIN起作用时输出通道的电平(刹车功能使用时会用到,idle_state学名是空闲状态)
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // 刹车BKIN起作用时互补输出通道的电平
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure); // 初始化通道1(注意CCRx不同,函数不一样)
TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable); // 使能重装载功能(注意CCRx不同,函数不一样)
/*-------------------刹车和死区结构体初始化-------------------*/
// 有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; // 运行模式下“关闭状态”选择,通常使能
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; // 空闲模式下“关闭状态”选择,通常使能
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; // 锁定级别1
// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述
// 这里配置的死区时间为152ns
TIM_BDTRInitStructure.TIM_DeadTime = 11; // 死区时间配置为152nS
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; // 刹车功能使能
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; // 当BKIN引脚检测极性配置,高电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; // 通常配置为自动输出使能
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure); // 初始化BDTR
TIM_Cmd(ADVANCE_TIM, ENABLE); // 使能计数器
TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE); // 主输出使能,当使用的是通用定时器时,这句不需要
}
个人分析是因为PB12配置为浮空输入以后,且没有外置下拉/上拉电路,使得引入噪声(来源环境电磁干扰)
将PB12接3V3后,PWM波确实全部不输出(因为由于实际项目需要全部输出低电平,所以将CH1,CH1N的idle_state空闲状态都配置为0)
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; // 刹车BKIN起作用时输出通道的电平(刹车功能使用时会用到,idle_state学名是空闲状态)
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // 刹车BKIN起作用时互补输出通道的电平
断开3V3后,PWM波输出自动恢复
总结:由于输出波形不稳定,所以不采用这个方法
2、野火哥的建议,配置BKIN脚PB12为GPIO_Mode_AF_PP(复用推挽输出),将BKIN脚PB12的检测极性改为高电平触发
static void ADVANCE_TIM_GPIO_Config(void) // 加上static表示只能在Advanced_Tim.c中调用
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
// 输出比较通道互补通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);
// 输出比较通道刹车通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT, ADVANCE_TIM_BKIN_PIN);//// BKIN引脚默认先输出低电平
}
static void ADVANCE_TIM_Mode_Config(void) // 加上static表示只能在Advanced_Tim.c中调用
{
// 开启定时器时钟,即内部时钟CK_INT=72M
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK, ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period = ADVANCE_TIM_PERIOD; // 周期
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler = ADVANCE_TIM_PSC; // 分频
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 对CK_INT的分频得到死区时钟的频率,该成员配置高级定时器不能省略
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 不使用重复计数器
// 初始化定时器
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;
// 配置为PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM1模式,默认递增模式下先输出1,计数到CCRx输出0
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补输出使能
TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE; // 设置占空比大小
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出通道电平极性配置,通常配置有效电平=1
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // 互补输出通道电平极性配置,通常配置有效电平=1
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; // 刹车BKIN起作用时输出通道的电平(刹车功能使用时会用到,idle_state学名是空闲状态)
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // 刹车BKIN起作用时互补输出通道的电平
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure); // 初始化通道1(注意CCRx不同,函数不一样)
TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable); // 使能重装载功能(注意CCRx不同,函数不一样)
/*-------------------刹车和死区结构体初始化-------------------*/
// 有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; // 运行模式下“关闭状态”选择,通常使能
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; // 空闲模式下“关闭状态”选择,通常使能
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; // 锁定级别1
// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述
// 这里配置的死区时间为152ns
TIM_BDTRInitStructure.TIM_DeadTime = 11; // 死区时间配置为152nS
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; // 刹车功能使能
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; // 当BKIN引脚检测极性配置,高电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; // 通常配置为自动输出使能
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure); // 初始化BDTR
TIM_Cmd(ADVANCE_TIM, ENABLE); // 使能计数器
TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE); // 主输出使能,当使用的是通用定时器时,这句不需要
}
烧录完成之后,此时的波形稳定干净,且接上3V3后,波形自动不输出
但是这个方法是有风险的!!!
由于推挽输出的驱动力很强,且默认输出低电平,实际测试短接3V3会有44.5mA的电流灌进PB12引脚!!!
虽然没有烧毁指南者芯片STM32F103VET6
3、自己尝试,配置BKIN脚PB12为 GPIO_Mode_IPU(上拉输入),将BKIN脚PB12的检测极性改为低电平触发
达到同样效果,向外输出的电流也是最小的73.85uA!!!!效果最优,所以采用!!
static void ADVANCE_TIM_GPIO_Config(void) // 加上static表示只能在Advanced_Tim.c中调用
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
// 输出比较通道互补通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);
// 输出比较通道刹车通道 GPIO 初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
}
static void ADVANCE_TIM_Mode_Config(void) // 加上static表示只能在Advanced_Tim.c中调用
{
// 开启定时器时钟,即内部时钟CK_INT=72M
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK, ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period = ADVANCE_TIM_PERIOD; // 周期
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler = ADVANCE_TIM_PSC; // 分频
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 对CK_INT的分频得到死区时钟的频率,该成员配置高级定时器不能省略
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 不使用重复计数器
// 初始化定时器
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;
// 配置为PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM1模式,默认递增模式下先输出1,计数到CCRx输出0
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补输出使能
TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE; // 设置占空比大小
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出通道电平极性配置,通常配置有效电平=1
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // 互补输出通道电平极性配置,通常配置有效电平=1
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; // 刹车BKIN起作用时输出通道的电平(刹车功能使用时会用到,idle_state学名是空闲状态)
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // 刹车BKIN起作用时互补输出通道的电平
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure); // 初始化通道1(注意CCRx不同,函数不一样)
TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable); // 使能重装载功能(注意CCRx不同,函数不一样)
/*-------------------刹车和死区结构体初始化-------------------*/
// 有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; // 运行模式下“关闭状态”选择,通常使能
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; // 空闲模式下“关闭状态”选择,通常使能
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; // 锁定级别1
// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述
// 这里配置的死区时间为152ns
TIM_BDTRInitStructure.TIM_DeadTime = 11; // 死区时间配置为152nS
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; // 刹车功能使能
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low; // 当BKIN引脚检测极性配置,高电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; // 通常配置为自动输出使能
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure); // 初始化BDTR
TIM_Cmd(ADVANCE_TIM, ENABLE); // 使能计数器
TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE); // 主输出使能,当使用的是通用定时器时,这句不需要
}
经过实际测试,波形如下
|
|