找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 299|回复: 3
收起左侧

单片机程序(FOSC/1000000)这里的1000000这个数值是哪里来的

[复制链接]
ID:849894 发表于 2024-2-27 11:31 | 显示全部楼层 |阅读模式
/**
        主控MCU:STC15F104W
        开关:INT0(P3.2)                        下降沿触发
        亮度增加:INT2(P3.4)                下降沿触发
        亮度减少:INT3(P3.5)                下降沿触发
        PWM输出:P3.3
**/

#include <reg51.h>
#include <intrins.h>

//#define FOSC                 24000000L                //晶振频率
#define FOSC                 6000000L                //晶振频率

#define MACHINE_CYCLE        (FOSC / 1000000)        //时钟震荡6次1μs

#define _1US                1                                //1us
#define _50US                50                                //50us
#define _100US                100                                //100us
#define _150US                150                                //150us
#define _200US                200                                //200us
#define _250US                250                                //250us

sfr INT_CLKO = 0x8f;                //外部中断与时钟输出控制寄存器
sfr AUXR = 0x8e;                    //辅助寄存器
sfr P3M1 = 0xB1;                                        //P3口寄存器
sfr P3M0 = 0xB2;

signed int duty_cycle;                        //占空比,0-10,带符号

unsigned int init_value;        //定时器初值

unsigned int count;                                //定时器中断次数

sbit pwm = P3 ^ 3;                                        //PWM输出口

bit flag;                                                //灯开关状态


//INT0初始化程序
void init_int0(void)
{
        INT0 = 1;
        IT0 = 1;                    //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
        EX0 = 1;                    //使能INT0中断
}

//INT2初始化程序
void init_int2(void)
{
        INT_CLKO |= 0x10;               //(EX2 = 1)使能INT2中断
}
//INT3初始化程序
void init_int3(void)
{
        INT_CLKO |= 0x20;               //(EX3 = 1)使能INT3中断
}
//初始化计时值
void set_tm0_init_value(unsigned int value) reentrant
{
        switch(value) {
                case 50:
                        TL0 = (65536 - (_50US * MACHINE_CYCLE)) % 256;
                        TH0 = (65536 - _50US * MACHINE_CYCLE) / 256;
                        break;

                case 100:
                        TL0 = (65536 - _100US * MACHINE_CYCLE) % 256;
                        TH0 = (65536 - _100US * MACHINE_CYCLE) / 256;
                        break;

                case 150:
                        TL0 = (65536 - _150US * MACHINE_CYCLE) % 256;
                        TH0 = (65536 - _150US * MACHINE_CYCLE) / 256;
                        break;

                case 200:
                        TL0 = (65536 - _200US * MACHINE_CYCLE) % 256;
                        TH0 = (65536 - _200US * MACHINE_CYCLE) / 256;
                        break;

                case 250:
                        TL0 = (65536 - _250US * MACHINE_CYCLE) % 256;
                        TH0 = (65536 - _250US * MACHINE_CYCLE) / 256;
                        break;

                default:
                        TL0 = (65536 - value * MACHINE_CYCLE) % 256;
                        TH0 = (65536 - value * MACHINE_CYCLE) / 256;
                        break;
        }
}


//定时器0初始化程序
/**
        时钟周期 = 1 / FOSC = 1 / 6 MHz = 1/6us
        机器周期 = 1 * 时钟周期 = 1/6us        (1T模式)
        定时100us:
        100us = 100 / (1/6) = 600机器周期
**/
void init_timer0(void)
{
        TMOD = 0x00;                   //设置定时器0为模式0(16位自动重装载)
        set_tm0_init_value(init_value);
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

/**
        频率 = 1 / 周期
**/
void main(void)
{
        P3M1 = 0x00;
        P3M0 = 0xFF;
        AUXR |= 0x80;                   //定时器0为1T模式

        duty_cycle = 5;        //初始占空比为50%

        count = 0;

        init_value = 100;        //初始频率1kHz

        init_int0();
        init_int2();
        init_int3();

        init_timer0();                                        //定时器初始值为0.1ms,初始频率为 1 / 0.001 = 1000Hz

        flag = 0;

        EA = 1;


        while(1);

}

//INT0中断服务程序
void ex_int0() interrupt 0       //INT0中断入口
{
        EA = 0;

        flag = !flag;

        if(flag) {                //关灯
                TR0 = 0;
                ET0 = 0;
        } else {
                TR0 = 1;
                ET0 = 1;
        }

        pwm = flag;

        EA = 1;
}
//INT2中断服务程序
void ex_int2() interrupt 10       //INT2中断入口
{
        EA = 0;

        if(++duty_cycle > 10) {
                duty_cycle = 10;
        }

        INT_CLKO &= 0xEF;           //若需要手动清除中断标志,可先关闭中断,此时系统会自动清除内部的中断标志
        INT_CLKO |= 0x10;           //然后再开中断即可
        EA = 1;
}
//INT3中断服务程序
void ex_int3() interrupt 11       //INT3中断入口
{
        EA = 0;

        if(--duty_cycle < 0) {
                duty_cycle = 0;
        }

        INT_CLKO &= 0xDF;               //若需要手动清除中断标志,可先关闭中断,此时系统会自动清除内部的中断标志
        INT_CLKO |= 0x20;               //然后再开中断即可
        EA = 1;
}
//定时器0中断服务程序
void tm0_isr() interrupt 1 using 1
{
        EA = 0;

        //初始化计时值
        
        set_tm0_init_value(init_value);

        //pwm = !pwm;
        if(++count > 9) {
                count = 0;
        }

        if(count < duty_cycle) {
                pwm = 1;
        } else {
                pwm = 0;
        }

        EA = 1;
}
回复

使用道具 举报

ID:1064915 发表于 2024-2-27 16:19 | 显示全部楼层
1s=1000ms
1ms=1000us
则1s=1000,000us
回复

使用道具 举报

ID:1110945 发表于 2024-2-27 18:54 | 显示全部楼层
#define FOSC                 6000000L                //晶振频率
#define MACHINE_CYCLE        (FOSC / 1000000)        //时钟震荡6次1μs

这两行定义了时钟频率(其数字和实际安装的晶振频率对应)和
每微秒的时钟数,当改换了其它频率的晶振时,只要改“FOSC”
对应的数字就可以了,而“每微秒的时钟数”可以自动同时改变,
1秒=1000000微秒,所以要除以这个数。

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:849894 发表于 2024-3-4 20:06 | 显示全部楼层
谢谢各位的解答。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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