STM32
直播中

张鑫

7年用户 816经验值
私信 关注
[问答]

如何对基于STM32单片机的频率计进行Proteus仿真呢

如何对基于STM32单片机的频率计进行proteus仿真呢?有哪些操作流程?

回帖(1)

孙翼飞

2021-11-15 15:01:57
  前言
  本教程是基于STM32的嵌入式仿真大作业。
  使用 Proteus 仿真32单片机,实现了可以测量正弦波、方波、正弦波和锯齿波等波形频率的 频率计,测量误差在1%以内
  一、电路图设计
  前端处理电路由LM324运算放大器组成迟滞比较器和电压跟随器,迟滞特性一定程度上解决了噪声扰动的问题,且可将任意固定频率的信号转化为脉冲,便于单片机的后续处理,而电压跟随器可增强其带载能力。
  
  单片机最小系统如下图所示,也可删除右侧电路,在Proteus中不受影响
  
  二、代码设计
  新建一个f103R6Tx的工程,先开启外部高速晶振
  
  在Clock Configuration中将SYSCLK时钟配置最低,为16MHz,APB2总线频率配置最低,为1MHz,后面解释为何这样配置。
  
  将PA6引脚配置为外部中断引脚,使能串口1,并更改波特率为9600。打开左边的TIM2定时器,选择Clock Source的时钟源为Internal Clock,并且配置分频系数为0,即1分频,自动装载值为999,此时定时器每1ms进入一次外部中断。
  
  打开左边的NVIC,使能定时器中断和外部中断,并配置抢占优先级分别为1和2
  
  选择添加工程路径,并将工具链设置为MDK-ARM
  
  勾上.c/.h文件
  
  打开生成的MDK工程,在主函数中添加如下代码
  HAL_TIM_Base_Start_IT(&htim2);//开启定时器2中断
  while(1)
  {
  HAL_Delay(500);
  printf(“频率:%dHzrn”,freq);
  }
  
  在tim.c文件里面添加如下代码:
  /* USER CODE BEGIN 1 */
  uint16_t exitTimes = 0;
  //每1ms进入一次定时器中断
  void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  {
  if (htim == (&htim2))
  {
  exitTimes++;
  if(exitTimes 》 500)
  {
  freq = pluseCount * 2;
  pluseCount = 0;
  exitTimes = 0;
  }
  }
  }
  /* USER CODE END 1 */
  在gpio.c中添加如下代码
  /* USER CODE BEGIN 2 */
  void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  {
  if(GPIO_PIN_6)
  {
  pluseCount++;//每检测到一个脉冲的下降沿就进入一次外部中断,即pluseCount变量加1
  }
  }
  /* USER CODE END 2 */
  编译通过,打开Proteus工程,双击单片机,弹出下载对话框,两个最重要的参数如图所示。
  第一个参数是编译通过的hex文件的路径,若无法找到hex文件,可自行百度 Keil如何生成hex文件
  第二个参数关乎整个系统功能的实现,极其重要!!!
  该参数是stm32的SYSCLK的系统时钟,并非晶振频率!!!若与keil配置的系统时钟不符,则无法实现代码功能。在此设置为16MHz。
  下载运行即可
  
  三、测试结果
  正弦波测试结果如下,此时你会发现,仿真速度很慢,甚至到最后无法实现后续功能,串口没有输出频率。
  
  proteus仿真有如下规律:
  函数信号发生器设置的输出频率越大,仿真速度越慢
  单片机定时器时钟频率越大,仿真速度越慢,故而我在配置时钟时将systick时钟和定时器时钟都设置为最小值。否则奇慢无比,具体仿真时长可以查看仿真界面下方的ANIMATING提示
  单片机的Crystal Frequency参数需要与keil配置的SYSCLK时钟一致,否则串口打印出乱码,甚至无法仿真
  串口无法连续打印数据,代码如下:
  while(1)
  {
  HAL_Delay(500);
  printf(“频率:%dHzrn”,freq);
  printf(“周期:%fHzrn”,1.0/freq);
  }
  此代码打印一次频率后便不再打印输出,此代码仿真存在问题。
  可能遇到的问题:
  串口持续打印0Hz的情况:可能是信号源设置信号的Vpp或者运放输出的电压较小,无法达到数字电路高电平的标准
  没有任何输出的情况:可能是原始信号频率过高(远超过1kHz),导致Proteus仿真极慢,最终计算量过大,无法输出
  四、总结
  由于大作业必须使用仿真的缘故,故而第一次使用Proteus仿真STM32功能。特别是在使用定时器功能时,Proteus仿真显得极其鸡肋。
  我曾使用输入捕获功能计算脉冲个数,在检测脉冲时需要不断更新捕获极性,记录捕获比较寄存器的CCR值,并加上中断溢出的计数值可得到定时器总的计数值。
  经过一天的debug测试发现,在引脚检测脉冲上升沿或者下降沿的时候,程序始终无法进入中断回调函数。实物测试可行但proteus仿真无法实现功能,若有大佬实现了输入捕获的仿真功能,欢迎私信交流。基于输入捕获功能的频率计仿真下载链接如下:基于输入捕获的stm32频率计的Proteus仿真
  本例程采取了外部中断计算脉冲数目的方法,最终可实现频率计的所有功能,迫于Proteus仿真速度和计算力,测试频率最大可达1kHz左右。
  测频有多种方法,包括外部中断、PWM输入模式、输入捕获、使用外部时钟计数器、ADC采样测量等方法,每种方法各有优缺点,具体可参考这篇文章:使用 STM32 测量频率和占空比的几种方法。这也是为何15年电赛会将数字频率计作为出题点
举报

更多回帖

发帖
×
20
完善资料,
赚取积分