我在用stc12c5a60s2做呼吸灯设计时遇到的问题,我想设计出几路频率变化不一样的pwm波形,我第一个是利用了C51里面的两个计数器实现了呼吸灯设计,可以使三个灯做相同频率的呼吸,代码如下://实现三个灯的呼吸
- #include <reg52.h>
- sbit PWMOUT0 = P0^0;
- sbit PWMOUT1 = P0^1;
- sbit PWMOUT2 = P0^2;
- unsigned char HighRH = 0; //高电平重载值的高字节
- unsigned char HighRL = 0; //高电平重载值的低字节
- unsigned char LowRH = 0; //低电平重载值的高字节
- unsigned char LowRL = 0; //低电平重载值的低字节
- unsigned char T1RH = 0;
- unsigned char T1RL = 0;
- unsigned long PeriodCnt = 0;
- void ConfigTimer1(unsigned int ms);
- void ConfigPWM(unsigned int fr, unsigned char dc);
- void main()
- {
- EA = 1; //开定时器总中断
- ConfigPWM(100, 10); //配置并启动PWM
- ConfigTimer1(50); //用T1定时调整占空比
- while (1);
- }
- void ConfigTimer1(unsigned int ms)
- {
- unsigned long tmp; //临时变量
- tmp = 11059200 / 12; //定时器计数频率
- tmp = (tmp * ms) / 1000; //计算所需的计数值
- tmp = 65536 - tmp; //计算定时器重载值
- tmp = tmp + 12; //补偿中断响应延时造成的误差
- T1RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
- T1RL = (unsigned char)tmp;
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x10; //配置T1为模式1
- TH1 = T1RH; //加载T1重载值
- TL1 = T1RL;
- ET1 = 1; //使能T1中断
- TR1 = 1; //启动T1
- }
- void ConfigPWM(unsigned int fr, unsigned char dc)
- {
- unsigned int high, low;
- PeriodCnt = (11059200/12) / fr; //计算一个周期所需的计数值
- high = (PeriodCnt*dc) / 100; //计算高电平所需的计数值
- low = PeriodCnt - high; //计算低电平所需的计数值
- high = 65536 - high + 12; //计算高电平的定时器重载值并补偿中断延时
- low = 65536 - low + 12; //计算低电平的定时器重载值并补偿中断延时
- HighRH = (unsigned char)(high>>8); //高电平重载值拆分为高低字节
- HighRL = (unsigned char)high;
- LowRH = (unsigned char)(low>>8); //低电平重载值拆分为高低字节
- LowRL = (unsigned char)low;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0为模式1
- TH0 = HighRH; //加载T0重载值
- TL0 = HighRL;
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- PWMOUT0 = 1; //输出高电平
- PWMOUT1 = 1; //输出高电平
- PWMOUT2 = 1; //输出高电平
- }
- void AdjustDutyCycle(unsigned char dc) //调整占空比
- {
- unsigned int high, low;
- high = (PeriodCnt*dc)/100;
- low = PeriodCnt - high;
- high = 65536 - high + 12;
- low = 65536 - low + 12;
- HighRH = (unsigned char)(high >> 8);
- HighRL = (unsigned char)high;
- LowRH = (unsigned char)(low >> 8);
- LowRL = (unsigned char)low;
- }
- void InterruptTimer0() interrupt 1 //用定时器0,实现了灯的亮灭连续变化,实现电平的反转
- {
- if (PWMOUT0 == 1) //当前输出为高电平时,装载低电平值并输出低电平
- {
- TH0 = LowRH;
- TL0 = LowRL;
- PWMOUT0 = 0;
- PWMOUT1 = 0;
- PWMOUT2 = 0;
- }
- else //当前输出为低电平时,装载高电平值并输出高电平
- {
- TH0 = HighRH;
- TL0 = HighRL;
- PWMOUT0 = 1;
- PWMOUT1 = 1;
- PWMOUT2 = 1;
- }
- }
- void InterruptTimer1() interrupt 3
- {
- unsigned char code table[13] = {
- 5, 18, 30, 41, 51, 60, 68, 75, 81, 86, 90, 93, 95
- };
- static bit dir = 0;
- static unsigned char index = 0;
- TH1 = T1RH;
- TL1 = T1RL;
- AdjustDutyCycle(table[index]);
- if(dir == 0)
- {
- index++;
- if(index >= 12)
- {
- dir = 1;
- }
- }
- else
- {
- index--;
- if(index == 0)
- {
- dir = 0;
- }
- }
- }
- 可是,我并不想看到一样的频率变化,我希望三个灯变化的频率不一样,可是上述代码实现呼吸灯的效果是基于计数器的个数的,C51的计数器已经用完了,我只好把目光投向了stc12c5a60s,这里面不仅有四个计数器,而且有两路PWM输出,
- 我通过设置PCA,实现了通过按键可以实时改变输出波形,
- 代码如下:
- //利用按键s1对led灯的亮度调节
- #include"STC12C5A60S2.h"
- void delay(unsigned int cnt)
- {
- unsigned char i;
- for(;cnt>0;cnt--)
- for(i=0;i<250;i++);
- }
- void main()
- {
- EA = 1; //开定时器总中断
- CCON=0; //禁止寄存器CCON中CF位的中断
- CL=0; //PCA的16位计数器低8位
- CH=0; //PCA的16位计数器高8位
- CMOD=0x00; //选择系统时钟/12为计数脉冲,则PWM的频率f=sysclk/256/12
- //PCA模块0
- CCAP0H=0x80; //占空比控制,此时的占空比为50%,一路输出
- CCAP0L=0x80;
- PCA_PWM0=0x00; //控制占空比的第九位为0
- CCAPM0=0x42; //允许P13作为PWM输出
- //PCA模块1
- CCAP1H=0xcc; //占空比控制,此时的占空比为20%,一路输出
- CCAP1L=0xcc;
- PCA_PWM1=0x00;
- CCAPM1=0x42; //允许P13作为PWM输出
- CR=1; //启动PCA计数器
- while(1)
- {
- if(P10==0)
- {
- delay(200);
- while(P10==0);
- CCAP0H+=10; //占空比调节
- CCAP0L+=10;
- CCAP1H+=25; //占空比调节
- CCAP1L+=25;
- }
- }
- }
- 可是就在我想结合两者的特点一起实现三个灯做呼吸灯,另外两个灯通过按键做使其的波形不断变化,因为这在设计上我觉得是行得通的,因为我做呼吸灯时,只涉及到51的定时器,而stc12c5a60s2很好的兼容了51的两个定时器,这样的话,应该是可以同时出现三个灯是呼吸灯,最后两个灯通过按键调节亮度,所以我就把两个函数粘贴在一起了,可是却没有出现应有的现象。
- 问题如下:只能通过按键对最后两个灯实现亮度调节,而呼吸灯的现象出不来。
- 有问题的程序如下,不知道怎样修改,还请大神解惑。
- //利用按键s1对led灯的亮度调节
- #include"STC12C5A60S2.h"
- sbit PWMOUT0 = P0^0;
- sbit PWMOUT1 = P0^1;
- sbit PWMOUT2 = P0^2;
- unsigned char HighRH = 0; //高电平重载值的高字节
- unsigned char HighRL = 0; //高电平重载值的低字节
- unsigned char LowRH = 0; //低电平重载值的高字节
- unsigned char LowRL = 0; //低电平重载值的低字节
- unsigned char T1RH = 0;
- unsigned char T1RL = 0;
- unsigned long PeriodCnt = 0;
- void ConfigTimer1(unsigned int ms);
- void ConfigPWM(unsigned int fr, unsigned char dc);
- void delay(unsigned int cnt)
- {
- unsigned char i;
- for(;cnt>0;cnt--)
- for(i=0;i<250;i++);
- }
- void main()
- {
- EA = 1; //开定时器总中断
- CCON=0; //禁止寄存器CCON中CF位的中断
- CL=0; //PCA的16位计数器低8位
- CH=0; //PCA的16位计数器高8位
- CMOD=0x00; //选择系统时钟/12为计数脉冲,则PWM的频率f=sysclk/256/12
- //PCA模块0
- CCAP0H=0x80; //占空比控制,此时的占空比为50%,一路输出
- CCAP0L=0x80;
- PCA_PWM0=0x00; //控制占空比的第九位为0
- CCAPM0=0x42; //允许P13作为PWM输出
- //PCA模块1
- CCAP1H=0xcc; //占空比控制,此时的占空比为80%,一路输出
- CCAP1L=0xcc;
- PCA_PWM1=0x00;
- CCAPM1=0x42; //允许P13作为PWM输出
- CR=1; //启动PCA计数器
- while(1)
- {
- ConfigPWM(100, 10); //配置并启动PWM
- ConfigTimer1(50); //用T1定时调整占空比
- if(P10==0)
- {
- delay(200);
- while(P10==0);
- CCAP0H+=10; //占空比调节
- CCAP0L+=10;
- CCAP1H+=25; //占空比调节
- CCAP1L+=25;
- }
- }
- }
- void ConfigTimer1(unsigned int ms)
- {
- unsigned long tmp; //临时变量
- tmp = 11059200 / 12; //定时器计数频率
- tmp = (tmp * ms) / 1000; //计算所需的计数值
- tmp = 65536 - tmp; //计算定时器重载值
- tmp = tmp + 12; //补偿中断响应延时造成的误差
- T1RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
- T1RL = (unsigned char)tmp;
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x10; //配置T1为模式1
- TH1 = T1RH; //加载T1重载值
- TL1 = T1RL;
- ET1 = 1; //使能T1中断
- TR1 = 1; //启动T1
- }
- void ConfigPWM(unsigned int fr, unsigned char dc)
- {
- unsigned int high, low;
- PeriodCnt = (11059200/12) / fr; //计算一个周期所需的计数值
- high = (PeriodCnt*dc) / 100; //计算高电平所需的计数值
- low = PeriodCnt - high; //计算低电平所需的计数值
- high = 65536 - high + 12; //计算高电平的定时器重载值并补偿中断延时
- low = 65536 - low + 12; //计算低电平的定时器重载值并补偿中断延时
- HighRH = (unsigned char)(high>>8); //高电平重载值拆分为高低字节
- HighRL = (unsigned char)high;
- LowRH = (unsigned char)(low>>8); //低电平重载值拆分为高低字节
- LowRL = (unsigned char)low;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0为模式1
- TH0 = HighRH; //加载T0重载值
- TL0 = HighRL;
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- PWMOUT0 = 1; //输出高电平
- PWMOUT1 = 1; //输出高电平
- PWMOUT2 = 1; //输出高电平
- }
- void AdjustDutyCycle(unsigned char dc) //调整占空比
- {
- unsigned int high, low;
- high = (PeriodCnt*dc)/100;
- low = PeriodCnt - high;
- high = 65536 - high + 12;
- low = 65536 - low + 12;
- HighRH = (unsigned char)(high >> 8);
- HighRL = (unsigned char)high;
- LowRH = (unsigned char)(low >> 8);
- LowRL = (unsigned char)low;
- }
- void InterruptTimer0() interrupt 1 //用定时器0,实现了灯的亮灭连续变化,实现电平的反转
- {
- if (PWMOUT0 == 1) //当前输出为高电平时,装载低电平值并输出低电平
- {
- TH0 = LowRH;
- TL0 = LowRL;
- PWMOUT0 = 0;
- PWMOUT1 = 0;
- PWMOUT2 = 0;
- }
- else //当前输出为低电平时,装载高电平值并输出高电平
- {
- TH0 = HighRH;
- TL0 = HighRL;
- PWMOUT0 = 1;
- PWMOUT1 = 1;
- PWMOUT2 = 1;
- }
- }
- void InterruptTimer1() interrupt 3
- {
- unsigned char code table[13] = {
- 5, 18, 30, 41, 51, 60, 68, 75, 81, 86, 90, 93, 95
- };
- static bit dir = 0;
- static unsigned char index = 0;
- TH1 = T1RH;
- TL1 = T1RL;
- AdjustDutyCycle(table[index]);
- if(dir == 0)
- {
- index++;
- if(index >= 12)
- {
- dir = 1;
- }
- }
- else
- {
- index--;
- if(index == 0)
- {
- dir = 0;
- }
- }
- }
复制代码
|