Tacking

  • 2024-12-18
  • 回复了主题帖: 检测风扇是否停转或者被卡主了应该用什么方法检测?

    兄弟,你最后用什么方案实现的啊?我现在有12个风扇需要测速,而且还需要监测好坏,头大!测速倒还好,直接用定时器输入捕获抓12个风扇的FG信号线,但是这好坏,难道我也用12个外部中断来实时监测么?

  • 2024-12-17
  • 回复了主题帖: 多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!

    zhoupxa 发表于 2024-12-16 22:55 各个输入捕获通道应该是可以互不干扰、独立运作的,仔细梳理下你的软件前后台处理过程是否存在错误操作或共 ... 好的,感谢回复!我感觉应该是四个捕获通道不停的来中断,进入中断,OLED我采用的软件模拟的形式,是不是OLED刷新不过来导致显示错误,实际上捕捉回来的是没有错误的

  • 2024-12-16
  • 回复了主题帖: 多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!

    有没哪位大佬知道这是什么原因导致的不?我还是想找出原因,不甚感激!

  • 回复了主题帖: 多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!

    tagetage 发表于 2024-12-16 16:25 你的要监测12个风扇的PWM转速值,要我做的话我会用硬件的多通道选择器,比如用2个8通道选择器做一个16通道 ... 您说的有道理,我之前也考虑过这种方案,但是我看有这么多个输入捕获通道,我就想着用起来,但是现在遇到这个问题,不知道是不是通道间有干扰还是咋回事?

  • 回复了主题帖: 多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!

    tagetage 发表于 2024-12-16 16:11  STM32输入捕获--“PWM输入模式”(可拓展多路同时捕获) https://www.eeworld.com.cn/m ... 我认真学习下,非常谢谢您!

  • 回复了主题帖: 多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!

    多个通道捕获时现象如下视频:[localvideo]865639522c91c9c2a61b2c2b4e515a60[/localvideo] 单个通道捕获时现象如下视频:[localvideo]c2a04992109ffb7c053b6ca83dec1a50[/localvideo]  

  • 发表了主题帖: 多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!

    写了一个多通道输入捕获的代码,代码见附件。 目的是想通过TIM3的四个通道同时捕获风扇转速反馈回来的方波波形,再计算相应的转速,风扇方波波形如下图:   在调试过程中发现,如果我单独捕获某一个通道的频率时数值是很稳定的,但是两个或者多个一起捕获时,通道数值跳变的很厉害!一直找不到原因。在百度上搜索也没有相关资料,但是看到一篇关于多通道PWM波形输出时有类似情况,说是通道之间干扰。不知道是不是这个原因,也不知道如何去解决。还请大佬们帮忙提供下思路、难道非得一个定时器捕获一个风扇么?我总共12个风扇呐! 四通道输入捕获代码如下: #include "stm32f10x.h" // Device header /** * 函 数:风扇转速捕获初始化 * 参 数:无 * 返 回 值:无 */ void FG_Capture_Init(uint16_t ARR,uint16_t PSC) { /*开启时钟*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启TIM3的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启GPIOA的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOB的时钟 /*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //将PA6、PA7引脚初始化为上拉输入 GPIO_ResetBits(GPIOA,GPIO_Pin_6); GPIO_ResetBits(GPIOA,GPIO_Pin_7); //将引脚电平全部拉低 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); //将PB0、PB1引脚初始化为上拉输入 GPIO_ResetBits(GPIOB,GPIO_Pin_0); GPIO_ResetBits(GPIOB,GPIO_Pin_1); //将引脚电平全部拉低 /*配置时钟源*/ TIM_InternalClockConfig(TIM3); //选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟 /*时基单元初始化*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数 TIM_TimeBaseInitStructure.TIM_Period = ARR; //计数周期,即ARR的值 TIM_TimeBaseInitStructure.TIM_Prescaler = PSC; //预分频器,即PSC的值 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimBaseInit,配置TIM3的时基单元 /*输入捕获初始化*/ TIM_ICInitTypeDef TIM_ICInitStructure; //定义结构体变量 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1 TIM_ICInitStructure.TIM_ICFilter = 0x0; //输入滤波器参数,可以过滤信号抖动 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性,选择为上升沿触发捕获 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //捕获预分频,选择不分频,每次信号都触发捕获 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入信号交叉,选择直通,不交叉 TIM_ICInit(TIM3,&TIM_ICInitStructure); //将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //选择配置定时器通道2 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInit(TIM3,&TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; //选择配置定时器通道3 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInit(TIM3,&TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; //选择配置定时器通道4 TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInit(TIM3,&TIM_ICInitStructure); /*中断分组优先级初始化*/ NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //配置寄存器 /* NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure);*/ //配置寄存器 //允许更新中断,允许CCxIE捕获中断 // TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABLE); TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC3,ENABLE); /*选择触发源及从模式*/ // TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //触发源选择TI1FP1 // TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //从模式选择复位 //即TI1产生上升沿时,会触发CNT归零 /*TIM使能*/ TIM_Cmd(TIM3,ENABLE); //使能TIM3,定时器开始运行 } uint8_t TIM3CH_CAPTURE_STA[4] = {0}; //输入捕获状态数组 uint16_t TIM3CH_CAPTURE_VAL[4] = {0}; //输入捕获值数组 /*输入捕获状态数组位说明: -------------------------------------------------------------- bit7 | bit6 | bit5~0 ------------|----------------|-------------------------------- 捕获完成标志|捕获到高电平标志|捕获到高电平后定时器溢出的次数 -------------------------------------------------------------- */ /** * 函 数:定时器3中断服务程序 * 参 数:无 * 返 回 值:无 */ void TIM3_IRQHandler(void) { //CH1 if((TIM3CH_CAPTURE_STA[0] & 0X80) == 0) //若bit7为0,还未捕获到一个完整的周期 { //溢出中断处理部分 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检测定时器3是否发生中断 { //若发生中断 if(TIM3CH_CAPTURE_STA[0] & 0X40) //若bit6为1,即已经第一次捕获到高电平 { if((TIM3CH_CAPTURE_STA[0] & 0X3F) == 0X3F) //若高电平太长,且溢出次数超过bit5~0可实现的计数 { TIM3CH_CAPTURE_STA[0] |= 0X80; //将bit7赋值为1,标记成功捕获了一次 TIM3CH_CAPTURE_VAL[0] = 0XFFFF; } else TIM3CH_CAPTURE_STA[0]++; //溢出次数+1 } } //捕获中断处理 if(TIM_GetITStatus(TIM3,TIM_IT_CC1) != RESET) //捕获1发生捕获事件 { if(TIM3CH_CAPTURE_STA[0]&0X40) //捕获到第二个上升沿 { TIM3CH_CAPTURE_STA[0] |= 0X80; //标记捕获到一个完整的周期,给主程序处理 TIM3CH_CAPTURE_VAL[0] = TIM_GetCapture1(TIM3); //获取事件 } else //捕获到第一个上升沿 { TIM3CH_CAPTURE_STA[0] = 0; //清空标志位 TIM3CH_CAPTURE_VAL[0] = 0; //清空计时器 TIM_SetCounter(TIM3,0); //清空定时器 TIM3CH_CAPTURE_STA[0] |= 0X40; //标记捕获到第一个上升沿 } } } //清除中断标志位 TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 | TIM_IT_Update); //CH2 if((TIM3CH_CAPTURE_STA[1] & 0X80) == 0) { //溢出中断处理部分 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { if(TIM3CH_CAPTURE_STA[1] & 0X40) { if((TIM3CH_CAPTURE_STA[1] & 0X3F) == 0X3F) { TIM3CH_CAPTURE_STA[1] |= 0X80; TIM3CH_CAPTURE_VAL[1] = 0XFFFF; } else TIM3CH_CAPTURE_STA[1]++; } } //捕获中断处理 if(TIM_GetITStatus(TIM3,TIM_IT_CC2) != RESET) //捕获2发生捕获事件 { if(TIM3CH_CAPTURE_STA[1]&0X40) { TIM3CH_CAPTURE_STA[1] |= 0X80; TIM3CH_CAPTURE_VAL[1] = TIM_GetCapture2(TIM3); } else { TIM3CH_CAPTURE_STA[1] = 0; TIM3CH_CAPTURE_VAL[1] = 0; TIM_SetCounter(TIM3,0); TIM3CH_CAPTURE_STA[1] |= 0X40; } } } //清除中断标志位 TIM_ClearITPendingBit(TIM3, TIM_IT_CC2 | TIM_IT_Update); //CH3 if((TIM3CH_CAPTURE_STA[2] & 0X80) == 0) { //溢出中断处理部分 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { if(TIM3CH_CAPTURE_STA[2] & 0X40) { if((TIM3CH_CAPTURE_STA[2] & 0X3F) == 0X3F) { TIM3CH_CAPTURE_STA[2] |= 0X80; TIM3CH_CAPTURE_VAL[2] = 0XFFFF; } else TIM3CH_CAPTURE_STA[2]++; } } //捕获中断处理 if(TIM_GetITStatus(TIM3,TIM_IT_CC3) != RESET) //捕获3发生捕获事件 { if(TIM3CH_CAPTURE_STA[2]&0X40) { TIM3CH_CAPTURE_STA[2] |= 0X80; TIM3CH_CAPTURE_VAL[2] = TIM_GetCapture3(TIM3); } else { TIM3CH_CAPTURE_STA[2] = 0; TIM3CH_CAPTURE_VAL[2] = 0; TIM_SetCounter(TIM3,0); TIM3CH_CAPTURE_STA[2] |= 0X40; } } } //清除中断标志位 TIM_ClearITPendingBit(TIM3, TIM_IT_CC3 | TIM_IT_Update); //CH4 if((TIM3CH_CAPTURE_STA[3] & 0X80) == 0) { //溢出中断处理部分 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { if(TIM3CH_CAPTURE_STA[3] & 0X40) { if((TIM3CH_CAPTURE_STA[3] & 0X3F) == 0X3F) { TIM3CH_CAPTURE_STA[3] |= 0X80; TIM3CH_CAPTURE_VAL[3] = 0XFFFF; } else TIM3CH_CAPTURE_STA[3]++; } } //捕获中断处理 if(TIM_GetITStatus(TIM3,TIM_IT_CC4) != RESET) //捕获4发生捕获事件 { if(TIM3CH_CAPTURE_STA[3]&0X40) { TIM3CH_CAPTURE_STA[3] |= 0X80; TIM3CH_CAPTURE_VAL[3] = TIM_GetCapture4(TIM3); } else { TIM3CH_CAPTURE_STA[3] = 0; TIM3CH_CAPTURE_VAL[3] = 0; TIM_SetCounter(TIM3,0); TIM3CH_CAPTURE_STA[3] |= 0X40; } } } //清除中断标志位 TIM_ClearITPendingBit(TIM3, TIM_IT_CC4 | TIM_IT_Update); } 主程序代码如下:  

  • 2024-12-11
  • 回复了主题帖: 关于延时函数很奇怪的问题

    tagetage 发表于 2024-12-10 19:13 你程序整体逻辑有问题,你30s延时的时候查询按键是没有办法响应的, 也就是说你的while里面不能有占用时 ... 谢谢您的指导,我也怀疑是这个问题,这地方我还是有些疑惑,我30s用的延时也是定时器弄的,是不是我必须要将这个延时修改为定时器中断延时才可以?

  • 2024-12-10
  • 发表了主题帖: 关于延时函数很奇怪的问题

        我今天在测试一个程序的时候,利用stm32普通IO口去控制风扇12V供电的开启和关闭,然后利用PWM通过按键去控制风扇的转速。 在测试时,主程序我写了一个代码,12V风扇供电开启30s,再关闭30s,一直循环,中间放置了一个30s的延时函数,按键控制PWM的占空比 测试程序时发现,风扇供电开启和关闭可以实现,但是按键按下去没反应,通过排查,发现按键消抖部分同样调用了延时函数,想着应该是使用的同一延时函数造成的影响,于是屏蔽掉了主函数风扇供电的延时函数,屏蔽后,按键可以正常控制PWM占空比。     于是我便自己写了一个最普通的延时函数,用在了按键消抖部分,但是验证后结果依然是解决不了问题,觉得很奇怪,还请有知道的指导下,不甚感激。 代码如下:     延时程序如下:    

  • 回复了主题帖: 寻找一款可替代8253可编程计数器的芯片

    chunyang 发表于 2024-11-17 22:50 现在已不可能有新产的类似芯片,用MCU实现是性价比最高的方案。 明白啦,感谢

  • 2024-11-15
  • 回复了主题帖: 寻找一款可替代8253可编程计数器的芯片

    maychang 发表于 2024-11-15 15:57 【需要带门控信号的,类似8253那种的可编程控制的,还可以读回计数值,可否帮忙推荐一款】 最简单的方法 ... 非常感谢,找了一圈实在找不到,看来只有这个办法了!

  • 回复了主题帖: 寻找一款可替代8253可编程计数器的芯片

    8253芯片,现在也找不到,也买不着,有没类似功能的?难道只能用单片机么?

  • 发表了主题帖: 寻找一款可替代8253可编程计数器的芯片

    需要带门控信号的,类似8253那种的可编程控制的,还可以读回计数值,可否帮忙推荐一款,性价比高的,谢谢!

  • 2024-10-19
  • 回复了主题帖: STM32控制风扇转速以及测速方案咨询。

    maychang 发表于 2024-10-10 21:06 【但是转速监控需要每个去监控的话,哪有那么多输入捕获通道去捕获PWM频率?】 这个倒是比较容易。单片 ... 太牛了!一下子解惑了,感谢感谢!输出我准备采用光耦加达林顿来控制风扇,输入捕获用12片计数器芯片!

  • 2024-10-10
  • 回复了主题帖: STM32控制风扇转速以及测速方案咨询。

    请教下大家,我用三个四选一多路复用器,通过单片机普通IO口去控制12个DCDC直流风扇分别切换到TIM2的输入捕获通道上进行转速测量是否可以?

  • 发表了主题帖: STM32控制风扇转速以及测速方案咨询。

    因公司要求,需要对设备里所有的风扇进行转速控制以及转速监控。 整个系统里拥有12个DCDC四线风扇,风扇本身具有传感器输出PWM信号,每转一圈输出2个PWM信号。有专用的端子脚可通过外部输入PWM波形进行转速控制! 现需要对每个风扇进行转速控制以及监控每个风扇的转速,我这边实在想不出合适的方式! 转速控制倒还好,大不了所有风扇全部接到一个PWM控制脚上,但是转速监控需要每个去监控的话,哪有那么多输入捕获通道去捕获PWM频率? 不知是否有更好的方案,节省资源的方式实现12个风扇转速监控? STM32采用的是最基础的STM32F103C8T6

  • 2024-07-14
  • 回复了主题帖: 江科大STM32课程学习时,旋转编码器章节遇到的问题点,还请大佬指点迷津

    Gen_X 发表于 2024-7-14 13:55 正确。 这个叫增量的速度:你用的是手转的编码器,当转慢的时候就减小,当不转了就回零。 所以你得到 ... 理解了,非常感谢,原来编码器还分增量式和绝对值式。太感谢了

  • 2024-07-13
  • 回复了主题帖: 江科大STM32课程学习时,旋转编码器章节遇到的问题点,还请大佬指点迷津

    int16_t Encoder_Get(void) {     /*使用Temp变量作为中继,目的是返回Encoder_Count后将其清零*/     /*在这里,也可以直接返回Encoder_Count       但这样就不是获取增量值的操作方法了       也可以实现功能,只是思路不一样*/     int16_t Temp;     Temp = Encoder_Count;     Encoder_Count = 0;     return Temp; }   经过我多方排查,终于找到问题点了,出问题的地方就是这个获取增量值函数里面:Encoder_Count = 0;这句代码,加上这句,Return回去的值一直是0,不是需要的增量值,Temp一开始是增量值,等到执行该句代码后,Temp也变为常量0了,所以导致值一直是0,将该句代码注释掉后,一切显示正常。 也终于理解UP主为啥采用Num += Encoder_Get(); 的方式。 但是为啥执行那句代码后,Temp也变常量0了呢?不是应该Encoder_Count清零之前的值么?

  • 回复了主题帖: 江科大STM32课程学习时,旋转编码器章节遇到的问题点,还请大佬指点迷津

    常见泽1 发表于 2024-7-13 13:45 temp改成全局变量再去watch吧 非常感谢您的回复,我试了转全局,看到一直是 0,所以出不来结果,编码器不起作用

  • 回复了主题帖: 江科大STM32课程学习时,旋转编码器章节遇到的问题点,还请大佬指点迷津

    大佬们,谁知道啊?别沉啊:surrender:

最近访客

< 1/1 >

统计信息

已有1人来访过

  • 芯积分:86
  • 好友:--
  • 主题:9
  • 回复:29

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言