找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1205|回复: 1
打印 上一主题 下一主题
收起左侧

不使用定时器T的频率测量程序(基于stc32g12k128单片机)

[复制链接]
跳转到指定楼层
楼主
    学习时发现,stc32g12k128单片机的功能蛮强大的,这里给出了一个不使用定时器T的频率测量方法,所谓不使用定时器T,一方面可以理解为省出了定时器T。方便给其它任务使用,另一方面可以理解为,这个程序里没有定时。它采用的是频率比较法测定脉冲信号的频率,就是把一个被测信号与一个已知频率的信号做比较,从而测出其频率。就是对已知频率信号和被测信号同时进行计数,在适当的时侯(非定时)同时停止计数,比较两个计数的结果,计算出被测信号的频率。这个已知频率的信号由pwmb时钟给出,并且可以通过调整其频率,改变系统的测量范围,其中向下扩展范围还是挺有用的。为方便使用,程序中加入了两个测量范围扩展常数,通过设定常数可以分别获得测量范围向上或向下的扩展。其中向上扩展要受芯片IO口速度和系统运行速度的影响。扩展空间不是太大。另外注意不要同时使用两个扩展常数,否则不仅作用会抵消一些,而且影响精度。做为一般测量,这个程序还是比较方便的,但对精度要求很高时,建议对程序中的数学计算公式进行优化,否则,会由于mcu在计算时对小数部分的切割,产生不少误差。频率扩展常数在头文件mcu_initial.h中设置。
    笔者是个新人,不当之处,欢迎各位大神批评指正。
本程序是基于stc32g12k128的频率测量程序。在降龙棍核心板和屠龙刀核心板验证通过。

    下面给出主程序,完整程序在附件中。本程序使用的是jlxlcd12864单色液晶屏,使用其它屏的朋友需要自己更换驱动函数。

mcu_initial.h
#ifndef _mcu_initial_h_
#define _mcu_initial_h_
#define sysclk0 33177600//系统时钟
//未扩展前基础测量范围是2000HZ——2.7MHZ,不要同时向两个方向扩展,效果会抵消不说,还要影响测量精度,另外,对精度要求高时应对相应的计算公式做优化,可减少由MCU计算产生的误差(计算误差主要在最终计算公式中由于小数被切除而产生)
#define up_freq 1//向上扩展测量范围倍数
#define down_freq 200//向下扩展测量范围比例,基础是1
void mcu_initial(void);
        #endif


main.c
#include "STC32G.H"
#include "stc32_12864driver.h"
#include "mcu_initial.h"
#include "initial_lcd.h"
#include "chinese_zhouqi.h"
unsigned long int cnt1=10,cnt2,cnt3;//cnt1的初值是为指示程序是否进入测量状态。cnt2,cnt3是调试时用到的参数
bit first=1;//程序走向控制参数,初值不影响测量结果
void main(void)
{
        unsigned int N,M;
        mcu_initial();
        initial_lcd();
        clear_screen();
transfer_chine_word(1,0,pin);
transfer_chine_word(1,16,lu);
N=up_freq-1;
M=down_freq-1;
PWMA_PSCRH=0;
PWMB_PSCRH=0;
        PWMB_PSCRL=M;//向下扩展分频器
        PWMA_PSCRL=N;//向上扩展分频器
//        cnt3=PWMA_PSCRL+1;
        PWMB_CR1=0x00;//关PWMB计数
        PWMB_SR1=0;//中断标志位清零
        PWMA_SR1=0;//中断标志位清零
        
        PWMA_CR1|=0x01; //使能计数器
        PWMA_IER=0x02;//开捕获中断,用于捕获第一次中断
        while (1)
{        
        digit6_display(1,32,(cnt1*up_freq*((sysclk0*10)/(cnt2*down_freq+1)))/10);//输出频率单位HZ
        digit6_display(3,32,cnt1);//显示捕获计数,正常测量下限,该值不能小于2,就是说,真正的测量下限捕获计数是2
        digit6_display(5,32,cnt2);//显示基准信号计数值,要大于65535才是正常的

}
}
void PWMB_ISR() interrupt 27//开捕获中断
{
                        PWMB_SR1=0;//中断标志位清零
        PWMA_SR1=0;//中断标志位清零
        PWMA_IER=0x02;//开捕获中断,用于捕获第二次中断

}

void PWMA_isr() interrupt 26//用来启动和停止计数器,输出测量数值
{

        first=!first;
        if(first)
{
        PWMA_CR1=0x00;//停止计数
        PWMB_CR1=0x00;//停止计数
        cnt2=(PWMB_CNTRH<<8)+PWMB_CNTRL;//读计时器
        cnt2=cnt2+65535;
        cnt1=(PWMA_CCR1H<<8)+PWMA_CCR1L; //CCp1 捕获值输出
        //下一次测量的初始化
        PWMB_EGR|=0x01;//产生一次更新事件,可用来使计数器初始化,硬件自动清零
        PWMA_EGR|=0x01;//产生一次更新事件,可用来使计数器初始化,硬件自动清零
        PWMB_SR1=0;//中断标志位清零
        PWMA_SR1=0;//中断标志位清零
        PWMA_CR1|=0x01; //使能计数器
        PWMA_IER=0x02;//开捕获中断,用于捕获第一次中断

}
else
{
        
        PWMB_CR1|=0x01; //使能计数器
        //PWMA_SR1=0;//中断标志位清零
        PWMA_IER=0;//关捕获中断
}
}


10HZ测量结果.png (3.82 MB, 下载次数: 46)

10Hz测量结果,向下扩展200时

10Hz测量结果,向下扩展200时

Keil代码.7z

26.56 KB, 下载次数: 15, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:1039438 发表于 2022-10-15 08:14 | 只看该作者
对三个语句的注释部分做了修改,之前误用了旧程序的注释,抱歉。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表