你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

输入捕获测频率返回异常?

[复制链接]
车到山前 提问时间:2025-11-17 20:28 / 已解决

include "sys.h"

include "delay.h"

include "usart.h"

include "modbus.h"

include "usart2.h"

include "timer3.h"

DataStruct Data; DataStruct * AppDataPointer; // 指向数据库的指针,通过指针方式访问数据库

// 如果想在别的.c文件访问数据库成员,先包含#include "data.h"文件 // 然后通过AppDataPointer指针访问,如:AppDataPointer->Frequency、AppDataPointer->DO.Y0 // 如想要改变数据库中的某个变量值:AppDataPointer->Voltage = 220;

// Modbus数据初始化

void IC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量 TIM_ICInitTypeDef TIM_ICInitStructure; //定义结构体变量 /开启时钟/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //开启TIM3的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟

/GPIO初始化/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA6引脚初始化为上拉输入

/配置时钟源/ //TIM_InternalClockConfig(TIM5); //选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟

/时基单元初始化/

TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数 TIM_TimeBaseInitStructure.TIM_Period = 65535; //计数周期,即ARR的值 TIM_TimeBaseInitStructure.TIM_Prescaler = 0; //预分频器,即PSC的值 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到 TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM3的时基单元

/输入捕获初始化/

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1 TIM_ICInitStructure.TIM_ICFilter = 0xF; //输入滤波器参数,可以过滤信号抖动 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性,选择为上升沿触发捕获 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //捕获预分频,选择不分频,每次信号都触发捕获 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入信号交叉,选择直通,不交叉 TIM_ICInit(TIM5, &TIM_ICInitStructure); //将结构体变量交给TIM_ICInit,配置TIM3的输入捕获通道

/选择触发源及从模式/ TIM_SelectInputTrigger(TIM5, TIM_TS_TI1FP1); //触发源选择TI1FP1 TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset); //从模式选择复位 //即TI1产生上升沿时,会触发CNT归零 /TIM使能/ TIM_Cmd(TIM5, ENABLE); //使能TIM3,定时器开始运行 }

uint32_t IC_GetFreq(void) { return 1000000 / (TIM_GetCapture1(TIM5)); }

static void InitData(void) { AppDataPointer = &Data; // 获取数据库首地址

Data.DI.X0 = Data.DO.Y0; Data.DI.X1 = Data.DO.Y1; Data.DI.X2 = Data.DO.Y2; Data.DI.X3 = Data.DO.Y3;

Data.DO.Y0 = 1; Data.DO.Y1 = 0; Data.DO.Y2 = 0; Data.DO.Y3 = 1;

Data.Adc.A0 = 1; Data.Adc.A1 = 2; Data.Adc.A2 = 3; Data.Adc.A3 = 4; Data.Adc.A4 = 5; Data.Adc.A5 = 6; Data.Adc.A6 = 7; Data.Adc.A7 = 8; Data.F1 = 100; Data.F2 = 100; Data.F3 = 100; Data.F4 = 100; }

int main(void) {

GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 IC_Init(); //输入捕获初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟 PWR_BackupAccessCmd(DISABLE);//允许修改RTC和后背寄存器 RCC_LSEConfig(RCC_LSE_OFF);//关闭外部低频时钟 BKP_TamperPinCmd(DISABLE); /GPIO初始化/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; //GPIO引脚,赋值为第0号引脚 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数

InitData(); // 初始化数据库 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 InitDelay(); InitUart(115200);

InitUsart2(); // 初始化串口2 用于Modbus收发数据 InitSlaveModbus(); // 初始化Modbus RTU InitTimer3(99,71); // 10K 0.1ms中断1次,用于查询收发、解析Mosbus RTU数据

while(1) { Data.Adc.A0 = Data.F1; Data.Adc.A1 = Data.F2; Data.Adc.A2 = Data.F3; Data.Adc.A3 = Data.F4; Data.Adc.A4 = Data.F5; Data.Adc.A5 = Data.F6; Data.Adc.A6 = Data.F7; Data.Adc.A7 = IC_GetFreq(); GPIO_SetBits(GPIOA, GPIO_Pin_4);
DelayMs(Data.F1);

    GPIO_ResetBits(GPIOA, GPIO_Pin_4);                                
    DelayMs(Data.F1);                                                                        

} }

各位老师,初学单片机遇到问题请教,代码如上。利用输入捕获测频率,Data.F1设置为100ms时IC_GetFreq()返回20,Data.F1设置为50ms时IC_GetFreq()返回17,请问这是哪里出问题了?

收藏 评论3 发布时间:2025-11-17 20:28

举报

3个回答
butterflyspring 回答时间:2025-11-18 10:02:52
通常遇到外设工作的结果不符合期望时,最好先单独调试通外设,这样的好处时:

1. 化繁为简,避免过多的其他因素增加判断难度。
2. 熟悉外设,对外设运行原理更熟悉才能用好它。
3. 真正解决问题,避免下次使用或变动时又发生。

所以最好先调试好PWM的检测代码,然后添加应用上去。
另外捕获值的获取,最好在捕获中断标志位置起后去获取。
HyunYong 回答时间:2025-11-18 12:24:19

东西太多了

把程序分成N个模块去做

一一验证 然后再放到项目中结合一个验证一次

xmshao 回答时间:2025-11-19 11:15:44

你现在说基于捕获测试的频率不对。首先要 保证计算本身没有问题,即相应的时钟别弄错了。

再就是注意捕获过程中是否发生多次溢出,这点是新手最容易忽视的地方。

总之,要先把测试原理搞清晰。

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版