专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

可按照脚本分别控制8路PWM函数波形输出程序+视频

作者:CNTSW   来源:本站原创   点击数:  更新时间:2014年06月03日   【字体:

 

 

 

视频
 
下面是源代码:
#include <AT89X52.H>
//#include <AT892051.H>
 
#define ONE_CYCLE_STEP 255
 
#ifdef AT89C2051_HEADER_FILE
#define PORT P1 //如果使用STC12C2052的话使用P1口作为输出口
#else
#define PORT P0 //否则使用P0口输出
#endif
 
#define LED_CNT 4 //定义输出口的端口数1-8 4代表使用0-3口输出
#define SCRIPT_CNT 6 //定义脚本数
 
//萤火虫结构
struct Firefly{
unsigned int brightness; //最大亮度值0-255
unsigned int timeCell; //时间间隔0-65535
unsigned int count; //运行控制变量:当前计数
unsigned char bn; //运行控制变量:当前亮度
};
 
//定义每个输出端口的执行脚本
//每个端口将执行SCRIPT_CNT次,然后不断循环执行
struct Firefly code fireFlyScript[][SCRIPT_CNT] = {
{{0,300,0,0},{255,400,0,0},{0,500,0,0},{100,600,0,0},{0,900,0,0},{0,500,0,0}},
{{255,300,0,0},{0,400,0,0},{0,500,0,0},{255,800,0,0},{0,700,0,0},{0,500,0,0}},
{{0,300,0,0},{0,400,0,0},{255,500,0,0},{50,1200,0,0},{0,300,0,0},{0,500,0,0}},
{{128,500,0,0},{255,300,0,0},{50,200,0,0},{0,1000,0,0},{255,1500,0,0},{50,100,0,0}},
{{0,900,0,0},{255,300,0,0},{50,200,0,0},{0,1000,0,0},{255,1500,0,0},{50,100,0,0}},
{{255,400,0,0},{255,300,0,0},{50,200,0,0},{0,1000,0,0},{255,1500,0,0},{50,100,0,0}},
{{0,200,0,0},{255,300,0,0},{50,200,0,0},{0,1000,0,0},{255,1500,0,0},{50,100,0,0}},
{{0,750,0,0},{255,300,0,0},{50,200,0,0},{0,1000,0,0},{255,1500,0,0},{50,100,0,0}}
};
 
//定义LED_CNT只萤火虫
struct Firefly fireFlies[LED_CNT];
 
//每只萤火虫的脚本计数器
unsigned char ffScript[LED_CNT];
 
//预先计算好的余弦函数表,PWM输出模拟函数曲线效果更好
unsigned char code cosValue[]={
0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,6,6,7,8,
9,10,11,11,12,13,14,16,17,18,19,20,21,23,24,
25,27,28,29,31,32,34,35,37,39,40,42,44,45,47,
49,50,52,54,56,58,60,62,63,65,67,69,71,73,75,
77,80,82,84,86,88,90,92,94,97,99,101,103,105,
107,110,112,114,116,119,121,123,125,127,130,
132,134,136,139,141,143,145,148,150,152,154,
156,158,161,163,165,167,169,171,173,175,178,
180,182,184,186,188,190,191,193,195,197,199,
201,203,205,206,208,210,211,213,215,216,218,
220,221,223,224,226,227,228,230,231,232,234,
235,236,237,238,239,241,242,243,244,244,245,
246,247,248,249,249,250,251,251,252,252,253,
253,254,254,254,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,254,254,254,
253,253,252,252,251,251,250,249,249,248,247,
246,245,244,244,243,242,241,239,238,237,236,
235,234,232,231,230,228,227,226,224,223,221,
220,218,216,215,213,211,210,208,206,205,203,
201,199,197,195,193,192,190,188,186,184,182,
180,178,175,173,171,169,167,165,163,161,158,
156,154,152,150,148,145,143,141,139,136,134,
132,130,128,125,123,121,119,116,114,112,110,
107,105,103,101,99,97,94,92,90,88,86,84,82,
80,77,75,73,71,69,67,65,64,62,60,58,56,54,52,
50,49,47,45,44,42,40,39,37,35,34,32,31,29,28,
27,25,24,23,21,20,19,18,17,16,14,13,12,11,11,
10,9,8,7,6,6,5,4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,
0
};
 
//计时器中断计数变量
unsigned int time0count_0;
 
//---------------------------------------
//名称 :定时器0中断服务程序
// :Timer0
//参数
//返回
//---------------------------------------
void Timer0(void) interrupt 1 
{                          
unsigned long cell; //计算用临时变量
unsigned char i,p;
TL0=0xE8; //重新给TL0赋初值
TH0=0xFF; //重新给TH0赋初值
 
//一个周期结束,检查脚本以及下一个周期的占空比
if(++time0count_0>ONE_CYCLE_STEP)
{
time0count_0 = 0;
//N路信号分别处理
for(i = 0;i<LED_CNT;i++)
{
//一个脚本执行完毕,装入下一个脚本
if(++fireFlies[i].count>fireFlies[i].timeCell)
{
ffScript[i]++;
ffScript[i] = ffScript[i] % SCRIPT_CNT;
fireFlies[i] = fireFlyScript[i][ffScript[i]];
}
//计算下一个周期的占空比和亮度
cell = fireFlies[i].count;
cell *=360;
cell /= fireFlies[i].timeCell;
fireFlies[i].bn = (cosValue[cell]*fireFlies[i].brightness)/255;
//准备点亮某个LED
p=1<<i;
//如果亮度值不为0则点亮
if(fireFlies[i].bn != 0)
{
PORT |= p;
}
else
{
PORT &= ~p;
}
}
}
//每个输出口占空比达到后输出低电平关闭LED
for(i = 0; i<LED_CNT; i++)
{
p=1<<i;
if(time0count_0==fireFlies[i].bn)PORT &= ~p;
}
}
 
void main()
{
unsigned i;
 
//关闭所有LED
PORT=0;
 
//初始化所有萤火虫和执行脚本
for(i = 0; i<LED_CNT; i++)
{
fireFlies[i] = fireFlyScript[i][0];
ffScript[i] = 0;
}
 
//***定时器Timer0初始化***
TMOD&=0xF0;            //将TMOD的低4位定时器0控制部分清零
TMOD|=0x01;            //设置定时器0为方式1
TL0=0xE8;              //设置定时器0初值低8位
TH0=0xFF;              //设置定时器0初值高8位
TR0=1;                 //启动定时器0
ET0=1;                 //Timer0中断允许
//***开全局中断设置****
//定时器Timer0设置了中断允许,此处要开全局中断
EA=1;                  //开全局中断
while(1);               //死循环,单片机初始化后,将一直运行这个死循环
}
 
关闭窗口

相关文章