前言
本教程是基于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年电赛会将数字频率计作为出题点
前言
本教程是基于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年电赛会将数字频率计作为出题点
举报