/**
****************************************************************
* @file : main.c
* @xu ran
* @date : 2014年5月23日20:55:19 - 2014年5月23日22:32:12
* @version : V2.0
* @brief : PWM脉冲宽度调制技术 实现呼吸灯
****************************************************************
* @attention
* 实验平台 : 51hei开发板
* 单片机 : STC89C52RC MCU 晶振 : 11.0592 MHZ
****************************************************************
*/
#include //使用STC89C52库
/* 三八译码器74HC138 */
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit PWMOUT = P0^0; //LED0
/* PWM占空比 */
unsigned char code pwmTable[] = {
3, 5, 8, 11, 13, 16, 21, 24, 27, 30, 33, 36, 40, 45, 49,
53, 55, 57, 61, 65, 67, 69, 72, 75, 79, 82, 86, 89, 91,
93, 96, 99
}; // dc%
/* PWM的高电平和低电平的定时器的重载值 */
unsigned char Highthr0, Hightlr0;
unsigned char Lowthr0, Lowtlr0;
/* 定时器T1计数装载值 */
unsigned char thr1, tlr1;
/* PWM 频率计数值 */
unsigned long tmp = 0;
/******************local function defines**************************/
void ConfigPWM(unsigned int fr, unsigned char dc);
void ConfigTimer1(unsigned int xms);
/******************************************************************/
/**
* @brief : 主函数
* @param : 无
* @retval : 无
*/
void main(void)
{
P0 = 0xFF; //初始化P0数据口
ADDR3 = 1;
ENLED = 0; //选择LED
P1 = (P1 & 0xF8) | 0x06; //LEDS6
PWMOUT = 1; //初始化为熄灭
ConfigPWM(100, 2); //PWM频率为100HZ, 占空比为2%
ConfigTimer1(50); //50ms调整一次占空比
EA = 1; //开启总中断!
while (1); //wait interrupt happen!
}
/**
* @brief : 配置PWM 调制PWM脉冲宽度
* @param : PWM的脉冲宽度 PWM的占空比
* @retval : 无
*/
void ConfigPWM(unsigned int fr, unsigned char dc)
{
unsigned int high = 0, low = 0;
tmp = (11059200/12/fr); //fr频率的计数值
high = (tmp * dc) / 100; //高电平计数值
low = tmp - high; //低电平计数值
high = 65536 - high; //高电平的计数定时器装载初值
low = 65536 - low; //低电平的计数定时器装载初值
Highthr0 = (unsigned char)(high >> 8);
Hightlr0 = (unsigned char)high; //高电平
Lowthr0 = (unsigned char)(low >> 8);
Lowtlr0 = (unsigned char)low; //低电平
/* 配置Timer0 方式1 */
TMOD &= 0xF0; //清零T0控制位
TMOD |= 0x01; //方式1
TH0 = Highthr0;
TL0 = Hightlr0; //先装高电平
TR0 = 1;
ET0 = 1; //开启定时器T0中断
}
/**
* @brief : 配置Timer1,用来调整PWM占空比
* @param : 待定时的时间
* @retval : 无
*/
void ConfigTimer1(unsigned int xms)
{
unsigned long tmp;
tmp = 11059200/12;
tmp = (tmp * xms) / 1000; //定时xms时间需要的计数值
tmp = 65536 - tmp; //需要装载的计数初值
thr1 = (unsigned char)(tmp >> 8);
tlr1 = (unsigned char)tmp;
TMOD &= 0x0F; //清零T1控制位
TMOD |= 0x10; //T1方式1
TH1 = thr1;
TL1 = tlr1; //装载初值
TR1 = 1;
ET1 = 1;
}
/**
* @brief : 调整PWM的占空比 (高电平的脉冲宽度)
* @param : 占空比 dc
* @retval : 无
*/
void tiaoZhengPWM(unsigned char dc)
{
unsigned int high = 0, low = 0;
high = (tmp * dc) / 100; //高电平计数值
low = tmp - high; //低电平计数值
high = 65536 - high;
low = 65536 - low; //计数装载初值
Highthr0 = (unsigned char)(high >> 8);
Hightlr0 = (unsigned char)high; //取高电平计数装载初值
Lowthr0 = (unsigned char)(low >> 8);
Lowtlr0 = (unsigned char)low; //取低电平计数装载初值
}
/**
* @brief : 定时器T0中断服务 改变PWM的状态
* @param : 无
* @retval : 无
*/
void Timer0_ISP() interrupt 1
{
if (PWMOUT) //由高电平切换到低电平
{
TH0 = Lowthr0;
TL0 = Lowtlr0; //装载低电平计数初值
PWMOUT = 0; //点亮LED
}
else
{
TH0 = Highthr0;
TL0 = Hightlr0; //装载高电平计数值
PWMOUT = 1; //熄灭LED
}
}
/**
* @brief : 定时器T1中断服务 调整PWM的占空比
* @param : 无
* @retval : 无
*/
void Timer1_ISP() interrupt 3
{
static unsigned char index = 0;
static bit bir = 0; //方向标志 (0 小->大 1 大->小)
TH1 = thr1;
TL1 = tlr1;
tiaoZhengPWM(pwmTable[index]); //调整PWM占空比
if (bir == 0)
{
index++;//递增
if (index >= 31) //到31立刻改变PWM的控制方向,即占空比由大到小变化(LED 暗->亮)
{
bir = 1; //改变方向
}
}
else
{
index--;
if (index == 0) //到0时立刻改变PWM的方向,即占空比由小到大变化(LED 亮->暗)
{
bir = 0; //改变方向
}
}
}
/**********************************END OF FILE*************new line****************/