找回密码
 立即注册

QQ登录

只需一步,快速开始

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

用stc89C52做的方波发生器

[复制链接]
跳转到指定楼层
楼主
本帖最后由 jmkl128 于 2018-3-20 19:01 编辑


很简单的东西,输出方波的频率还比较准。程序中按键部分采用了新的方法。
//晶振:12M (6T使能)
/*T0-计时25 微秒溢出中断一次;P1.3 P1.4为增加、减少键P3.3 输出方波
变量的定义:  pwm 设定的频率数
connter_1 根据设定频率计算后的,定时器溢的出次数值
connter : 定时器0计数溢出数
led_seg_code: 数码管7 段码
*/
/*用单片机产生频率可调的方波信号。输出方波的频率范围为1Hz-200Hz,频率误差比小于0.5%。
要求用"增加"、"减小"2 个按钮改变方波给定频率,按钮每按下一次,给定频率改变的步进步长为1Hz,
当按钮持续按下的时间超过2 秒后,给定频率以10 次/秒的速度连续增加(减少),输出方波的频率要求在数码管上显示。
P1.3,P1.4分别为增加和减小按键*/
#include<reg52.h>
#include<intrins.h>
#include <math.h>
sbit    led_1=P2^4;
sbit    led_2=P2^3;
sbit    led_3=P2^2;
sbit    led_4=P2^1;
sbit    out=P2^0;
sbit    pwm_out=P3^3;
unsigned char pwm;
unsigned int  counter,counter_1;
unsigned char Trg;                          //点按
unsigned char Cont;                         //长按
unsigned char cnt_plus;                     //长按延时
unsigned char cnt_plus_time;                //长按速度
unsigned char code seg_table[10]= {0xfa,0x22,0xb9,0xab,0x63,0x0cb,0x0db,0xa2,0xfb,0xeb}; //1~~~~9段选码
/**************************************
****************定时器初始化函数****************
**************************************/
void InitTimer(void)
{
    TMOD &= 0xFF;      //设置定时器模式 T0,8位自动加载,25us定时中断。T1,16位,20ms,用于按键检测
    TMOD |= 0x12;       //设置定时器模式
    TL0 = 0xCE;     //设置定时初值
    TH0 = 0xCE;     //设置定时重载值 25us
    TF0=0;    //清除中断标记
    ET0 = 1;  //TO使能
    TR0 = 1;   //T0开始计时
    TL1 = 0xC0;     //设置定时初值
    TH1 = 0x63;     //设置定时初值 20ms
    TF1=0;      //清除中断标记
    ET1=1;    //T1使能
    TR1=1; //T1开始计时
    EA = 1; //开总中断
}
/**************************************
****************延时1ms****************
**************************************/
void delay1ms(void) //@12.000MHz
{
    unsigned char i, j;
    i = 2;
    j = 239;
    do
    {
        while (--j)
        {
            ;
        }
    }
    while (--i);
}
/**************************************
****************按键检测****************
**************************************/
void Key(void)
{
    unsigned char ReadData=P1^0xff;
    Trg=ReadData&(ReadData^Cont);
    Cont=ReadData;
    if (Cont==0)
    {
        cnt_plus=0;     //长按标志清0
    }
    if (Trg&0x10)       //按下P1.3
    {
        pwm++;
        if(pwm==201)
        {
            pwm=1;
        }
    }
    if (Trg&0x08)       //按下P1.4
    {
        pwm--;
        if(pwm==0)
        {
            pwm=200;
        }
    }
    if (cnt_plus<50)
    {
        cnt_plus++;        //开始长按延时
    }
    if (cnt_plus>=50)     //长按1秒后开始动作
    {
        cnt_plus_time++;        //长按时速度变化
        if (cnt_plus_time>10)
        {
            cnt_plus_time=0;
            if (Cont&0X10)  //长按P1.3
            {
                if(pwm<=190)
                {
                    pwm=pwm+10;
                }
                else
                {
                    pwm++;
                }
                if(pwm==201)
                {
                    pwm=1;
                }
            }
            if (Cont&0X08)      //长按P1.4
            {
                if(pwm>=10)
                {
                    pwm=pwm-10;
                }
                else
                {
                    pwm--;
                }
                if(pwm==0)
                {
                    pwm=200;
                }
            }
        }
    }
}
/**************************************
****************显示函数****************
**************************************/
void display()
{
    P0=seg_table[pwm/100];
    led_1=0;
    led_2=1;
    led_3=1;
    led_4=1;
    delay1ms();
    led_1=1;
    P0=seg_table[(pwm%100-(pwm%10))/10];
    led_1=1;
    led_2=0;
    led_3=1;
    led_4=1;
    delay1ms();
    led_2=1;
    P0=seg_table[pwm%10];
    led_1=1;
    led_2=1;
    led_3=0;
    led_4=1;
    delay1ms();
    led_3=1;
    P0=0x73;
    led_1=1;
    led_2=1;
    led_3=1;
    led_4=0;
    delay1ms();
    led_4=1;
}
/**************************************
****************T0中断溢出数计算****************
**************************************/
unsigned int get_T0_over_num(unsigned char p) //p 为频率数
{
    unsigned int h;
    double f,*k;
    f=(double)p; //转化为浮点数
    f=0.5/f; //半个周期的时间
    f=f/0.0000272; //中断溢出数=f/0.000025;
    h=f; //取整
    if (modf(f,k)>=0.5)//四舍五入
    {
        h=h+1;
    }
    return h;
}
/* C51 有专门的库文件MATH.H,里面有个函数
它是这样定义的extern float modf(float x, float *ip);
调用它之后,整数部分被放入*ip, 小数部分作为返回值。
*/
/**************************************
****************主函数***************
**************************************/
void main ()
{
    InitTimer();
    pwm = 15;
    while(1)
    {
        counter_1=get_T0_over_num(pwm);
        display();
    }
}
/**************************************
****************T0中断,用于改变方波频率****************
**************************************/
void Timer0Interrupt(void) interrupt 1
{

    counter++;
    if(counter==counter_1)
    {
        counter = 0 ;
        pwm_out = ~pwm_out;
        out=    pwm_out;
    }
}
/**************************************
****************T1中断,用于检测按键****************
**************************************/
void tm1_isr() interrupt 3 using 1
{
    TR1=0;                 //关闭定时器T1
    Key();              //执行键盘扫描
    TL1 = 0xC0;     //设置定时初值
    TH1 = 0x63;     //设置定时初值
    TR1=1;                  //启动定时器T1
}

方波.rar (1.96 KB, 下载次数: 73)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:370303 发表于 2018-8-3 09:21 | 只看该作者
你是编程大神,51有你而精彩
回复

使用道具 举报

板凳
ID:272158 发表于 2018-8-7 12:31 | 只看该作者
不错,下载学习一下,可以做一个小玩具
回复

使用道具 举报

地板
ID:757761 发表于 2020-5-21 21:28 | 只看该作者
仿真的晶振在哪里呀
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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