/**
主控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;
}
|