STC 89C52RC
#include
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
ulong periodCnt = 0; //PWM周期计数值
uchar highRH = 0; //高电平重载值的高字节
uchar highRL = 0; //高电平重载值的低字节
uchar lowRH = 0; //低电平重载值的高字节
uchar lowRL = 0; //低电平重载值的低字节
uchar T1RH = 0; //T1重载值的高字节
uchar T1RL = 0; //T1重载值的低字节
uchar code dutyCycle[13] = { //占空比调整表
5, 18, 30, 41, 51, 60, 68, 75, 81, 86, 90, 93, 95
};
uchar code image[8] = {
0x81,0x81,0xE7,0xC3,0xC3,0xE7,0x81,0x81
};
uchar hRHi[13], hRLi[13], lRHi[13], lRLi[13];
void configTmr1(uint ms);
void configPWM(uint fr, uchar dc);
void calcRldVal(uchar idx);
void main() {
uchar i;
EA = 1; //开总中断
ADDR3 = 0; //选中LED点阵
configPWM(1000, dutyCycle[0]); //配置并启动PWM
for (i = 0; i < 13; i++)
calcRldVal(i);
configTmr1(50); //用T1定时调整占空比
while (1);
}
/* 配置并启动T1,ms-定时时间 */
void configTmr1(uint ms) {
ulong tmp; //临时变量
tmp = 11059200 / 12; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp + 12; //补偿中断响应延时造成的误差
T1RH = tmp >> 8; //定时器重载值拆分为高低字节
T1RL = tmp;
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x10; //配置T1为模式1
TH1 = T1RH; //加载T1重载值
TL1 = T1RL;
ET1 = 1; //使能T1中断
TR1 = 1; //启动T1
}
/* 配置并启动PWM,fr-频率,dc-占空比 */
void configPWM(uint fr, uchar dc) {
uint high, low;
periodCnt = 11059200 / 12 / fr; //计算一个周期所需的计数值
high = periodCnt * dc / 100; //计算高电平所需的计数值
low = periodCnt - high; //计算低电平所需的计数值
high = 65536 - high + 12; //计算高电平的定时器重载值并补偿中断延时
low = 65536 - low + 12; //计算低电平的定时器重载值并补偿中断延时
highRH = high >> 8; //高电平重载值拆分为高低字节
highRL = high;
lowRH = low >> 8; //低电平重载值拆分为高低字节
lowRL = low;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = highRH; //加载T0重载值
TL0 = highRL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
/* 占空比调整函数,频率不变只调整占空比 */
void calcRldVal(uchar idx) {
uint high, low;
high = periodCnt * dutyCycle[idx] / 100; //计算高电平所需的计数值
low = periodCnt - high; //计算低电平所需的计数值
high = 65536 - high + 12; //计算高电平的定时器重载值并补偿中断延时
low = 65536 - low + 12; //计算低电平的定时器重载值并补偿中断延时
hRHi[idx] = high >> 8; //高电平重载值拆分为高低字节
hRLi[idx] = high;
lRHi[idx] = low >> 8; //低电平重载值拆分为高低字节
lRLi[idx] = low;
}
void LED1_Scan() {
static uchar i = 0;
P0 = 0xFF;
P1 = (P1 & 0xF8) | i;
P0 = image[i];
i = ++i & 0x07;
}
/* T0中断服务函数,产生PWM输出 */
void interruptTimer0() interrupt 1 {
if (ENLED == 1) {
TH0 = lowRH;
TL0 = lowRL;
ENLED = 0;
LED1_Scan();
}
else {
TH0 = highRH;
TL0 = highRL;
ENLED = 1;
}
}
/* T1中断服务函数,定时动态调整占空比 */
void interruptTimer1() interrupt 3 {
static bit dir = 0;
static uchar index = 0;
TH1 = T1RH; //重新加载T1重载值
TL1 = T1RL;
highRH = hRHi[index];
highRL = hRLi[index];
lowRH = lRHi[index];
lowRL = lRLi[index];
if (dir == 0) {
index++;
if (index == 12)
dir = 1;
}
else {
index--;
if (index == 0)
dir = 0;
}
}
上一篇:51单片机之大杂烩
下一篇:51单片机 使用蜂鸣器播放简单音乐
推荐阅读最新更新时间:2024-03-16 15:45
设计资源 培训 开发板 精华推荐
- 2020-2021年安森美和安富利物联网创新设计大赛
- 以科技之力,成就安全 PI与您一起驾驭明天的智慧 答题赢好礼!
- 找小伙伴们一起去闯 STM32 F7英雄联盟设计大赛
- 炎夏来临,足不出户也能尽享2018东芝PCIM在线展会
- 有奖直播:基于DLP® Pico™技术的TI桌面级DLP 3D打印、3D扫描及工业显示应用
- 英特尔 SoC FPGA 开发者论坛 (ISDF) 预约报名享好礼!
- Littelfuse 高效 • 可靠 • 精准的功率控制和电路保护方案在工业、交通、通讯、医疗及新能源中的应用
- 已结束|Maxim IO-Link通信协议设计方案详解,5大优势助你轻松联网!
- 干货下载|ADI 系统方案精选 第6辑