- 积分
- 10608
- 在线时间
- 15508 小时
- 最后登录
- 2022-3-31
- 阅读权限
- 150
- 精华
- 6
 
- UID
- 13663
- 帖子
- 13726
- 精华
- 6
- 经验
- 10608 点
- 金钱
- 8449 ¥
- 注册时间
- 2006-10-21
|

楼主 |
发表于 2011-8-16 10:58
|
显示全部楼层
再来一个带有峰值保持的音频电平LED显示电路
本帖最后由 ahao 于 2011-9-28 11:27 编辑
电路图如下
C程序只弄了一边,目前显示还不稳定。先发上来,等有时间了再优化。
如下(仅供参考,还不能用于实际电路)
#include <intrins.h>
#include "STC12C5A60S2.H"
typedef unsigned char uchar;
typedef unsigned int uint;
uchar count; //中断次数计数
uint ADC_result0,ADC_result1,ADC_result7,VOL_resultA,VOL_resultB;
uchar abc,pp,tt,tt0,tt1,tt2;
sbit A0=P2^2;
sbit A1=P2^1;
sbit A2=P2^0;
uchar code led[]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00}; //定义led显示的编码
uchar code pf[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义漂浮物的编码
void delay(uint z) //延时程序
{
uint x,y;
for(x=z;x>0;x--)
for(y=100;y>0;y--);
}
void piaofu() //漂浮物显示程序
{
switch(pp)
{
case 20:
A0=1;A1=1;A2=0; P0=pf[3];
break;
case 19:
A0=1;A1=1;A2=0; P0=pf[2];
break;
case 18:
A0=1;A1=1;A2=0; P0=pf[1];
break;
case 17:
A0=1;A1=1;A2=0; P0=pf[0];
break;
case 16:
A0=1;A1=0;A2=1; P0=pf[7];
break;
case 15:
A0=1;A1=0;A2=1; P0=pf[6];
break;
case 14:
A0=1;A1=0;A2=1; P0=pf[5];
break;
case 13:
A0=1;A1=0;A2=1; P0=pf[4];
break;
case 12:
A0=1;A1=0;A2=1; P0=pf[3];
break;
case 11:
A0=1;A1=0;A2=1; P0=pf[2];
break;
case 10:
A0=1;A1=0;A2=1; P0=pf[1];
break;
case 9:
A0=1;A1=0;A2=1; P0=pf[0];
break;
case 8:
A0=0;A1=1;A2=1; P0=pf[7];
break;
case 7:
A0=0;A1=1;A2=1; P0=pf[6];
break;
case 6:
A0=0;A1=1;A2=1; P0=pf[5];
break;
case 5:
A0=0;A1=1;A2=1; P0=pf[4];
break;
case 4:
A0=0;A1=1;A2=1; P0=pf[3];
break;
case 3:
A0=0;A1=1;A2=1; P0=pf[2];
break;
case 2:
A0=0;A1=1;A2=1; P0=pf[1];
break;
case 1:
A0=0;A1=1;A2=1; P0=pf[0];
break;
}
delay(1);
}
void displayA(uchar dd) //led显示程序
{
if(dd>0)
{
A0=0; A1=1; A2=1;
if(dd>=8) P0=led[7];
else P0=led[dd];
}
delay(2);
P0=0xff;
if(dd>=8)
{
A0=1; A1=0; A2=1;
if(dd>=16) P0=led[7];
else P0=led[dd%8];
}
delay(2);
P0=0xff;
if(dd>=16)
{
A0=1; A1=1; A2=0;
P0=led[dd%16];
}
delay(2);
P0=0xff;
}
void init() //初始化程序
{
TMOD=0x11;
TH0=(65536-100)/256;
TL0=(65536-100)%256;
EA=1; //开总中断
ET0=1;//开定时器0中断
TR0=1;//启动定时器0
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
ET1=1;//开定时器1中断
TR1=0;//启动定时器1
P1ASF = 0x83; //1000,0011, 将 P1.0 P1.1 P1.7置成模拟口
}
//以下选择 ADC 转换速率,只能选择其中一种
//SPEED1 SPEED0 A/D转换所需时间
#define AD_SPEED 0x60 // 0110,0000 1 1 70 个时钟周期转换一次,
//CPU工作频率21MHz时 A/D转换速度约 300KHz
//#define AD_SPEED 0x40 //0100,0000 1 0 140 个时钟周期转换一次
//#define AD_SPEED 0x20 //0010,0000 0 1 280 个时钟周期转换一次
//#define AD_SPEED 0x00 //0000,0000 0 0 420 个时钟周期转换一次
//---------------------------------------------------------------------
/*---------------------------------------------------------------------
STC12C5A60S2单片机AD转换函数,直接引用于宏晶科技网站
----------------------------------------------------------------------*/
uint get_AD_result(uchar channel)
{
uchar AD_finished=0; //存储 A/D 转换标志
ADC_RES = 0;
ADC_RESL = 0;
channel &= 0x07; //0000,0111 清0高5位
ADC_CONTR = AD_SPEED;
_nop_();
ADC_CONTR |= channel; //选择 A/D 当前通道
_nop_();
ADC_CONTR |= 0x80; //启动 A/D 电源
delay(1); //使输入电压达到稳定
ADC_CONTR |= 0x08; //0000,1000 令 ADCS = 1, 启动A/D转换,
AD_finished = 0;
while (AD_finished ==0 ) //等待A/D转换结束
{
AD_finished = (ADC_CONTR & 0x10); //0001,0000 测试A/D转换结束否
}
ADC_CONTR &= 0xE7; //1111,0111 清 ADC_FLAG 位, 关闭A/D转换,
return (ADC_RES*256+ADC_RESL); //返回 A/D 高2位 + 低8位转换结果
}
void main()
{
//ADRJ = AUXR1^2:
// 0: 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器
// 1: 10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器
// AUXR1 &= ~0x04; //0000,0100, 令 ADRJ=0
AUXR1 |= 0x04; //0000,0100, 令 ADRJ=1
ADC_CONTR |= 0x80; //1000,0000 打开 A/D 转换电源
pp=20; //上电后让漂浮物置顶,然后从顶部落下
init();
while(1)
{
VOL_resultA= ADC_result0*1.0/ADC_result7*2500; //语句中"*1.0"是必不可少的,不然C语言作整数处理,没有想要的结果产生.
if(VOL_resultA>2200) tt1=19;
else if(VOL_resultA>1800) tt1=18;
else if(VOL_resultA>1400) tt1=17;
else if(VOL_resultA>1200) tt1=16;
else if(VOL_resultA>1000) tt1=15;
else if(VOL_resultA>850) tt1=14;
else if(VOL_resultA>700) tt1=13;
else if(VOL_resultA>600) tt1=12;
else if(VOL_resultA>500) tt1=11;
else if(VOL_resultA>420) tt1=10;
else if(VOL_resultA>350) tt1=9;
else if(VOL_resultA>300) tt1=8;
else if(VOL_resultA>250) tt1=7;
else if(VOL_resultA>200) tt1=6;
else if(VOL_resultA>177) tt1=5;
else if(VOL_resultA>150) tt1=4;
else if(VOL_resultA>125) tt1=3;
else if(VOL_resultA>100) tt1=2;
else if(VOL_resultA>88) tt1=1;
else if(VOL_resultA>60) tt1=0;
displayA(tt1); //显示具体电压值
if(pp<=tt1)
{
pp=tt1+1; //令pp始终大于tt1一格
TR1=0; //关闭定时器1
abc=7; //这里可以设定悬停时间
}
else if(pp>tt1)
{
TR1=1; //打开定时器1
}
piaofu(); //运行漂浮程序
}
}
void timer0() interrupt 1 //定时器0中断程序
{
//再装一次初值
TH0=(65536-100)/256;
TL0=(65536-100)%256;
count++;
if (count==100) //10ms转换一次.
{
count=0;
ADC_result7 = get_AD_result(7); //P1.1 为 A/D 当前通道, 测量结果存ADC_result7
ADC_result0 = get_AD_result(0); //P1.0 为 A/D 当前通道, 测量结果存ADC_result0
ADC_result1 = get_AD_result(1); //P1.0 为 A/D 当前通道, 测量结果存ADC_result0
}
}
void timer1() interrupt 3 //定时器1中断程序
{
//再装一次初值
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
tt0++;
if(tt0>=7) //设定下降速度
{
if(abc==0) //检测是否悬停时间到了,是的话pp自减下降
pp--;
else if(abc>0)
abc--;
tt0=0;
}
}
先看看显示效果,目前基本完成一个声道,还有一些小问题正在调试中。
http://player.youku.com/player.php/sid/XMjk1MTQ3MzMy/v.swf |
|