使用STC12C5A60S2,用推挽模式直接驱动LED显示,输入用4558缓冲放大,避免对信号的干扰。
制作出来的实物图如下:
效果
PCB-A
PCB-B
电路原理图如下:
单片机源程序如下:
- #include "STC12C5A60S2.H"
- #include <intrins.h>
- #define uchar unsigned char//两个宏定义
- #define uint unsigned int
- //定义左声道15个LED所接的IO口
- sbit LEDL15=P2^2;
- sbit LEDL14=P2^1;
- sbit LEDL13=P2^0;
- sbit LEDL12=P3^7;
- sbit LEDL11=P3^6;
- sbit LEDL10=P3^5;
- sbit LEDL9=P3^4;
- sbit LEDL8=P3^3;
- sbit LEDL7=P3^2;
- sbit LEDL6=P1^7;
- sbit LEDL5=P1^6;
- sbit LEDL4=P1^5;
- sbit LEDL3=P1^4;
- sbit LEDL2=P1^3;
- sbit LEDL1=P1^2;
- //定义右声道15个LED所接的IO口
- sbit LEDR15=P2^3;
- sbit LEDR14=P3^4;
- sbit LEDR13=P2^5;
- sbit LEDR12=P2^6;
- sbit LEDR11=P2^7;
- sbit LEDR10=P4^4;
- sbit LEDR9=P4^5;
- sbit LEDR8=P4^6;
- sbit LEDR7=P0^7;
- sbit LEDR6=P0^6;
- sbit LEDR5=P0^5;
- sbit LEDR4=P0^4;
- sbit LEDR3=P0^3;
- sbit LEDR2=P0^2;
- sbit LEDR1=P0^1;
- uint ADC_resultL,ADC_resultR,voL,voR; //定义几个unsigned int型和unsigned char型变量
- uchar numL,numR,tt0,tt1,ttL,ttR,biaozhiL,biaozhiR,xuantingL,xuantingR,xialuoL,xialuoR,pfL,pfR;
- void delay(uchar z) //延时程序
- {
- uchar x,y;
- for(x=z;x>0;x--)
- for(y=100;y>0;y--);
- }
- void displayL() //左声道显示程序
- { P0M1 = 0x00; P0M0 = 0xFF; //P0(00000000B,11111111B)
- P1M1 = 0x00; P1M0 = 0xFC; //P1(00000000B,11111100B)
- P2M1 = 0x00; P2M0 = 0xFF; //P2(00000000B,11111111B)
- P3M1 = 0x00; P3M0 = 0xFF; //P3(00000000B,11111111B)
- P4M1 = 0x00; P4M0 = 0xFF; //P4(00000000B,11111111B)
- if(pfL==1)
- LEDL1=0;
- else
- {
- if(numL>=1)LEDL1=0;
- else LEDL1=1;
- }
- if(pfL==2)
- LEDL2=0;
- else
- {
- if(numL>=2)LEDL2=0;
- else LEDL2=1;
- }
- if(pfL==3)
- LEDL3=0;
- else
- {
- if(numL>=3)LEDL3=0;
- else LEDL3=1;
- }
- if(pfL==4)
- LEDL4=0;
- else
- {
- if(numL>=4)LEDL4=0;
- else LEDL4=1;
- }
- if(pfL==5)
- LEDL5=0;
- else
- {
- if(numL>=5)LEDL5=0;
- else LEDL5=1;
- }
- if(pfL==6)
- LEDL6=0;
- else
- {
- if(numL>=6)LEDL6=0;
- else LEDL6=1;
- }
- if(pfL==7)
- LEDL7=0;
- else
- {
- if(numL>=7)LEDL7=0;
- else LEDL7=1;
- }
- if(pfL==8)
- LEDL8=0;
- else
- {
- if(numL>=8)LEDL8=0;
- else LEDL8=1;
- }
- if(pfL==9)
- LEDL9=0;
- else
- {
- if(numL>=9)LEDL9=0;
- else LEDL9=1;
- }
- if(pfL==10)
- LEDL10=0;
- else
- {
- if(numL>=10)LEDL10=0;
- else LEDL10=1;
- }
- if(pfL==11)
- LEDL11=0;
- else
- {
- if(numL>=11)LEDL11=0;
- else LEDL11=1;
- }
- if(pfL==12)
- LEDL12=0;
- else
- {
- if(numL>=12)LEDL12=0;
- else LEDL12=1;
- }
- if(pfL==13)
- LEDL13=0;
- else
- {
- if(numL>=13)LEDL13=0;
- else LEDL13=1;
- }
- if(pfL==14)
- LEDL14=0;
- else
- {
- if(numL>=14)LEDL14=0;
- else LEDL14=1;
- }
- if(pfL==15)
- LEDL15=0;
- else
- {
- if(numL>=15)LEDL15=0;
- else LEDL15=1;
- }
- }
- void displayR() //右声道显示程序
- {
-
- if(pfR==1)
- LEDR1=0;
- else
- {
- if(numR>=1)LEDR1=0;
- else LEDR1=1;
- }
- if(pfR==2)
- LEDR2=0;
- else
- {
- if(numR>=2)LEDR2=0; else LEDR2=1;
- }
- if(pfR==3)
- LEDR3=0;
- else
- {
- if(numR>=3)LEDR3=0; else LEDR3=1;
- }
- if(pfR==4)
- LEDR4=0;
- else
- {
- if(numR>=4)LEDR4=0; else LEDR4=1;
- }
- if(pfR==5)
- LEDR5=0;
- else
- {
- if(numR>=5)LEDR5=0; else LEDR5=1;
- }
- if(pfR==6)
- LEDR6=0;
- else
- {
- if(numR>=6)LEDR6=0; else LEDR6=1;
- }
- if(pfR==7)
- LEDR7=0;
- else
- {
- if(numR>=7)LEDR7=0; else LEDR7=1;
- }
- if(pfR==8)
- LEDR8=0;
- else
- {
- if(numR>=8)LEDR8=0; else LEDR8=1;
- }
- if(pfR==9)
- LEDR9=0;
- else
- {
- if(numR>=9)LEDR9=0; else LEDR9=1;
- }
- if(pfR==10)
- LEDR10=0;
- else
- {
- if(numR>=10)LEDR10=0; else LEDR10=1;
- }
- if(pfR==11)
- LEDR11=0;
- else
- {
- if(numR>=11)LEDR11=0; else LEDR11=1;
- }
- if(pfR==12)
- LEDR12=0;
- else
- {
- if(numR>=12)LEDR12=0; else LEDR12=1;
- }
- if(pfR==13)
- LEDR13=0;
- else
- {
- if(numR>=13)LEDR13=0; else LEDR13=1;
- }
- if(pfR==14)
- LEDR14=0;
- else
- {
- if(numR>=14)LEDR14=0; else LEDR14=1;
- }
- if(pfR==15)
- LEDR15=0;
- else
- {
- if(numR>=15)LEDR15=0; else LEDR15=1;
- }
- }
- void init() //初始化程序
- {
- TMOD=0x11; //设定定时器0、1工作方式
- EA=1; //开总中断
- TH0=0xb1; //高8位装初值 TH0=(65536-20000)/256;
- TL0=0xe0; //低8位装初值 TL0=(65536-20000)%256;
- ET0=1; //开定时器0
- TR0=1; //启动定时器0
- TH1=0xd8; //高8位装初值TH1=(65536-10000)/256
- TL1=0xf0; //低8位装初值TL1=(65536-10000)%256
- ET1=1; //开定时器1
- TR1=1; //启动定时器1
- }
- //---------------------------------------------------------------------
- //以下选择 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 个时钟周期转换一次
- //---------------------------------------------------------------------
- uint ad_zhuanhuan(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 高 8 位转换结果
- }
- void main() //主程序
- {
- P4SW=0x70; //0x70=0111 0000 ,将P4.4 P4.5 P4.6设置成IO口
- init();
- // 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 转换电源,启动AD转换
- P1ASF = 0x03; //0000,0011, 将 P1.0 P1.1 置成模拟口
- while(1)
- {
- voL= ADC_resultL*5.0; //左声道电平转换结果。语句中5.0=5*1.0其中*1.0是必不可少
- //的,不然C语言作整数处理,没有想要的结果产生.
- if(voL>2000) numL=14;
- else if(voL>1635) numL=13;
- else if(voL>1432) numL=12;
- else if(voL>1270) numL=11;
- else if(voL>1130) numL=10;
- else if(voL>1006) numL=9;
- else if(voL>895) numL=8;
- else if(voL>797) numL=7;
- else if(voL>709) numL=6;
- else if(voL>650) numL=5;
- else if(voL>400) numL=4;
- else if(voL>262) numL=3;
- else if(voL>159) numL=2;
- else if(voL>70) numL=1;
- else numL=0;
- if(pfL<=numL) //检测如果漂浮物不高于峰值就让漂浮物置于峰值上面,同时 标志位 置0
- {
- pfL=numL+1;
- biaozhiL=0; //标志位 置0
- xuantingL=10; //变量xuantingL 改变此值可以设定左漂浮物悬停时间
- }
- else //if(pfL>numL) 如果漂浮物高于峰值就把标志位置1
- {
- biaozhiL=1; //标志位 置1
- }
- displayL(); //显示左声道具体电平值的段
- voR= ADC_resultR*5.0; //左声道电平转换结果。原理同上边左声道
- if(voR>2000) numR=14;
- else if(voR>1635) numR=13;
- else if(voR>1432) numR=12;
- else if(voR>1270) numR=11;
- else if(voR>1130) numR=10;
- else if(voR>1006) numR=9;
- else if(voR>895) numR=8;
- else if(voR>797) numR=7;
- else if(voR>709) numR=6;
- else if(voR>650) numR=5;
- else if(voR>400) numR=4;
- else if(voR>262) numR=3;
- else if(voR>159) numR=2;
- else if(voR>70) numR=1;
- else numR=0;
-
- if(pfR<=numR)
- {
- pfR=numR+1;
- biaozhiR=0;
- xuantingR=10;
- }
- else
- {
- biaozhiR=1;
- }
- displayR(); //显示右声道具体电平值的段
- }
- }
- void timer0() interrupt 1 //定时器0中断程序
- {
- TH0=0xb1;
- TL0=0xe0;
- tt0++;
- if (tt0>=1) //20ms转换一次.
- {
- tt0=0;
- ADC_resultL = ad_zhuanhuan(0); //P1.0 为 A/D 当前通道, 测量结果存ADC_result0
- ADC_resultR = ad_zhuanhuan(1); //P1.1 为 A/D 当前通道, 测量结果存ADC_result7
-
- }
- }
- void timer1() interrupt 3 //定时器1中断程序
- {
- //再装一次初值
- TH1=0xd8;
- TL1=0xf0;
-
- tt1++;
- if(tt1>=1)
- {
- if(biaozhiL)
- {
- ttL++;
- if(ttL>7) //改变此值可以设定左漂浮物下降速度
- {
- if(xuantingL==0)
- pfL--;
- else if(xuantingL>0)
- xuantingL--;
- ttL=0;
- }
- }
-
- if(biaozhiR)
- {
- ttR++;
- if(ttR>7) //改变此值可以设定右漂浮物下降速度
- {
- if(xuantingR==0)
- pfR--;
- else if(xuantingR>0)
- xuantingR--;
- ttR=0;
- }
- }
- tt1=0;
- }
- }
复制代码
附件只包含上面代码的Keil工程(如上图):
电平指示.rar
(94.75 KB, 下载次数: 62)
|