找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3619|回复: 9
打印 上一主题 下一主题
收起左侧

STC单片机电平指示制作 附程序

  [复制链接]
跳转到指定楼层
楼主
使用STC12C5A60S2,用推挽模式直接驱动LED显示,输入用4558缓冲放大,避免对信号的干扰。
制作出来的实物图如下:
效果


PCB-A


PCB-B


电路原理图如下:


单片机源程序如下:
  1. #include "STC12C5A60S2.H"  
  2. #include <intrins.h>                                                               
  3. #define uchar unsigned char//两个宏定义
  4. #define uint unsigned int

  5. //定义左声道15个LED所接的IO口
  6. sbit LEDL15=P2^2;
  7. sbit LEDL14=P2^1;
  8. sbit LEDL13=P2^0;            
  9. sbit LEDL12=P3^7;
  10. sbit LEDL11=P3^6;
  11. sbit LEDL10=P3^5;
  12. sbit LEDL9=P3^4;

  13. sbit LEDL8=P3^3;
  14. sbit LEDL7=P3^2;
  15. sbit LEDL6=P1^7;
  16. sbit LEDL5=P1^6;
  17. sbit LEDL4=P1^5;
  18. sbit LEDL3=P1^4;
  19. sbit LEDL2=P1^3;
  20. sbit LEDL1=P1^2;                  



  21. //定义右声道15个LED所接的IO口
  22. sbit LEDR15=P2^3;
  23. sbit LEDR14=P3^4;
  24. sbit LEDR13=P2^5;           
  25. sbit LEDR12=P2^6;
  26. sbit LEDR11=P2^7;
  27. sbit LEDR10=P4^4;
  28. sbit LEDR9=P4^5;

  29. sbit LEDR8=P4^6;
  30. sbit LEDR7=P0^7;
  31. sbit LEDR6=P0^6;
  32. sbit LEDR5=P0^5;
  33. sbit LEDR4=P0^4;
  34. sbit LEDR3=P0^3;
  35. sbit LEDR2=P0^2;
  36. sbit LEDR1=P0^1;


  37. uint ADC_resultL,ADC_resultR,voL,voR; //定义几个unsigned int型和unsigned char型变量
  38. uchar numL,numR,tt0,tt1,ttL,ttR,biaozhiL,biaozhiR,xuantingL,xuantingR,xialuoL,xialuoR,pfL,pfR;

  39. void delay(uchar z)       //延时程序
  40. {
  41.   uchar x,y;
  42.   for(x=z;x>0;x--)  
  43.   for(y=100;y>0;y--);
  44. }

  45. void displayL()   //左声道显示程序
  46. {                P0M1 = 0x00; P0M0 = 0xFF; //P0(00000000B,11111111B)
  47.             P1M1 = 0x00; P1M0 = 0xFC; //P1(00000000B,11111100B)
  48.         P2M1 = 0x00; P2M0 = 0xFF; //P2(00000000B,11111111B)
  49.                 P3M1 = 0x00; P3M0 = 0xFF; //P3(00000000B,11111111B)
  50.                 P4M1 = 0x00; P4M0 = 0xFF; //P4(00000000B,11111111B)
  51.         if(pfL==1)
  52.         LEDL1=0;
  53.         else
  54.         {
  55.           if(numL>=1)LEDL1=0;
  56.               else LEDL1=1;
  57.         }

  58.           if(pfL==2)
  59.           LEDL2=0;
  60.         else
  61.         {
  62.           if(numL>=2)LEDL2=0;        
  63.                   else LEDL2=1;
  64.         }

  65.         if(pfL==3)
  66.                 LEDL3=0;
  67.         else
  68.         {
  69.                 if(numL>=3)LEDL3=0;        
  70.                                 else LEDL3=1;
  71.         }

  72.         if(pfL==4)
  73.                 LEDL4=0;
  74.         else
  75.         {
  76.                 if(numL>=4)LEDL4=0;        
  77.                                 else LEDL4=1;
  78.         }

  79.         if(pfL==5)
  80.                 LEDL5=0;
  81.         else
  82.         {
  83.                 if(numL>=5)LEDL5=0;        
  84.                                 else LEDL5=1;
  85.         }

  86.         if(pfL==6)
  87.                 LEDL6=0;
  88.         else
  89.         {
  90.                 if(numL>=6)LEDL6=0;        
  91.                                 else LEDL6=1;
  92.         }

  93.         if(pfL==7)
  94.                 LEDL7=0;
  95.         else
  96.         {
  97.                 if(numL>=7)LEDL7=0;        
  98.                                 else LEDL7=1;
  99.         }

  100.         if(pfL==8)
  101.                 LEDL8=0;
  102.         else
  103.         {
  104.                 if(numL>=8)LEDL8=0;        
  105.                                 else LEDL8=1;
  106.         }

  107.         if(pfL==9)
  108.                 LEDL9=0;
  109.         else
  110.         {
  111.                 if(numL>=9)LEDL9=0;        
  112.                                 else LEDL9=1;
  113.         }

  114.         if(pfL==10)
  115.                 LEDL10=0;
  116.         else
  117.         {
  118.                 if(numL>=10)LEDL10=0;        
  119.                                 else LEDL10=1;
  120.         }

  121.         if(pfL==11)
  122.                 LEDL11=0;
  123.         else
  124.         {
  125.                 if(numL>=11)LEDL11=0;        
  126.                                 else LEDL11=1;
  127.         }

  128.         if(pfL==12)
  129.                 LEDL12=0;
  130.         else
  131.         {
  132.                 if(numL>=12)LEDL12=0;        
  133.                                 else LEDL12=1;
  134.         }

  135.         if(pfL==13)
  136.                 LEDL13=0;
  137.         else
  138.         {
  139.                 if(numL>=13)LEDL13=0;        
  140.                                 else LEDL13=1;
  141.         }

  142.         if(pfL==14)
  143.                 LEDL14=0;
  144.         else
  145.         {
  146.                 if(numL>=14)LEDL14=0;        
  147.                                 else LEDL14=1;
  148.         }

  149.         if(pfL==15)
  150.                 LEDL15=0;
  151.         else
  152.         {
  153.                 if(numL>=15)LEDL15=0;        
  154.                                 else LEDL15=1;
  155.         }
  156. }

  157. void displayR()      //右声道显示程序
  158. {
  159.         
  160.         if(pfR==1)
  161.         LEDR1=0;
  162.         else
  163.         {
  164.                 if(numR>=1)LEDR1=0;        
  165.                                 else LEDR1=1;
  166.         }

  167.         if(pfR==2)
  168.                 LEDR2=0;
  169.         else
  170.         {
  171.                 if(numR>=2)LEDR2=0;        else LEDR2=1;
  172.         }

  173.         if(pfR==3)
  174.                 LEDR3=0;
  175.         else
  176.         {
  177.                 if(numR>=3)LEDR3=0;        else LEDR3=1;
  178.         }

  179.         if(pfR==4)
  180.                 LEDR4=0;
  181.         else
  182.         {
  183.                 if(numR>=4)LEDR4=0;        else LEDR4=1;
  184.         }

  185.         if(pfR==5)
  186.                 LEDR5=0;
  187.         else
  188.         {
  189.                 if(numR>=5)LEDR5=0;        else LEDR5=1;
  190.         }

  191.         if(pfR==6)
  192.                 LEDR6=0;
  193.         else
  194.         {
  195.                 if(numR>=6)LEDR6=0;        else LEDR6=1;
  196.         }

  197.         if(pfR==7)
  198.                 LEDR7=0;
  199.         else
  200.         {
  201.                 if(numR>=7)LEDR7=0;        else LEDR7=1;
  202.         }

  203.         if(pfR==8)
  204.                 LEDR8=0;
  205.         else
  206.         {
  207.                 if(numR>=8)LEDR8=0;        else LEDR8=1;
  208.         }

  209.         if(pfR==9)
  210.                 LEDR9=0;
  211.         else
  212.         {
  213.                 if(numR>=9)LEDR9=0;        else LEDR9=1;
  214.         }

  215.         if(pfR==10)
  216.                 LEDR10=0;
  217.         else
  218.         {
  219.                 if(numR>=10)LEDR10=0;        else LEDR10=1;
  220.         }

  221.         if(pfR==11)
  222.                 LEDR11=0;
  223.         else
  224.         {
  225.                 if(numR>=11)LEDR11=0;        else LEDR11=1;
  226.         }

  227.         if(pfR==12)
  228.                 LEDR12=0;
  229.         else
  230.         {
  231.                 if(numR>=12)LEDR12=0;        else LEDR12=1;
  232.         }

  233.         if(pfR==13)
  234.                 LEDR13=0;
  235.         else
  236.         {
  237.                 if(numR>=13)LEDR13=0;        else LEDR13=1;
  238.         }

  239.         if(pfR==14)
  240.                 LEDR14=0;
  241.         else
  242.         {
  243.                 if(numR>=14)LEDR14=0;        else LEDR14=1;
  244.         }

  245.         if(pfR==15)
  246.                 LEDR15=0;
  247.         else
  248.         {
  249.                 if(numR>=15)LEDR15=0;        else LEDR15=1;
  250.         }

  251. }

  252. void init()         //初始化程序
  253. {
  254.         TMOD=0x11;  //设定定时器0、1工作方式
  255.         EA=1;       //开总中断        
  256.         TH0=0xb1;   //高8位装初值 TH0=(65536-20000)/256;
  257.         TL0=0xe0;   //低8位装初值 TL0=(65536-20000)%256;
  258.         ET0=1;      //开定时器0
  259.         TR0=1;      //启动定时器0

  260.         TH1=0xd8;   //高8位装初值TH1=(65536-10000)/256
  261.         TL1=0xf0;   //低8位装初值TL1=(65536-10000)%256
  262.         ET1=1;      //开定时器1
  263.         TR1=1;      //启动定时器1
  264. }

  265. //---------------------------------------------------------------------
  266. //以下选择 ADC 转换速率,只能选择其中一种
  267.                         //            SPEED1 SPEED0  A/D转换所需时间
  268. #define AD_SPEED   0x60 //  0110,0000   1      1   70 个时钟周期转换一次,
  269.                         //  CPU工作频率21MHz时 A/D转换速度约 300KHz
  270. //#define AD_SPEED   0x40 //0100,0000   1      0     140 个时钟周期转换一次
  271. //#define AD_SPEED   0x20 //0010,0000   0      1     280 个时钟周期转换一次
  272. //#define AD_SPEED   0x00 //0000,0000   0      0     420 个时钟周期转换一次
  273. //---------------------------------------------------------------------

  274. uint ad_zhuanhuan(uchar channel)
  275. {
  276.     uchar AD_finished=0;            //存储 A/D 转换标志

  277.     ADC_RES = 0;                    //高八位清零
  278.     ADC_RESL = 0;                   //低两位清零

  279.     channel &= 0x07;                //0000,0111 清0高5位
  280.     ADC_CONTR = AD_SPEED;
  281.     _nop_();
  282.     ADC_CONTR |= channel;           //选择 A/D 当前通道
  283.     _nop_();
  284.     ADC_CONTR |= 0x80;              //启动 A/D 电源
  285.     delay(1);                       //使输入电压达到稳定
  286.     ADC_CONTR |= 0x08;              //0000,1000 令 ADCS = 1, 启动A/D转换,
  287.     AD_finished = 0;
  288.     while (AD_finished ==0 )        //等待A/D转换结束
  289.     {
  290.         AD_finished = (ADC_CONTR & 0x10); //0001,0000 测试A/D转换结束否
  291.     }
  292.     ADC_CONTR &= 0xE7;              //1111,0111 清 ADC_FLAG 位, 关闭A/D转换,

  293.     return (ADC_RES*256+ADC_RESL);  //返回 A/D 高 8 位转换结果
  294. }



  295. void main()                         //主程序
  296. {
  297.         P4SW=0x70;                  //0x70=0111 0000 ,将P4.4 P4.5 P4.6设置成IO口

  298.         init();

  299. //        ADRJ = AUXR1^2:
  300. //        0: 10 位A/D 转换结果的高8 位放在ADC_RES 寄存器, 低2 位放在ADC_RESL 寄存器
  301. //        1: 10 位A/D 转换结果的最高2 位放在ADC_RES 寄存器的低2 位, 低8 位放在ADC_RESL 寄存器
  302. //        AUXR1 &= ~0x04;               
  303. //0000,0100, 令 ADRJ=0

  304.     AUXR1 |= 0x04;                  //0000,0100, 令 ADRJ=1

  305.     ADC_CONTR |= 0x80;              //1000,0000 打开 A/D 转换电源,启动AD转换        
  306.         P1ASF = 0x03;               //0000,0011, 将 P1.0 P1.1 置成模拟口        

  307.         while(1)
  308.         {

  309.                 voL= ADC_resultL*5.0;   //左声道电平转换结果。语句中5.0=5*1.0其中*1.0是必不可少
  310.                                         //的,不然C语言作整数处理,没有想要的结果产生.        
  311.                 if(voL>2000) numL=14;               
  312.                 else if(voL>1635) numL=13;               
  313.                 else if(voL>1432) numL=12;        
  314.                 else if(voL>1270) numL=11;               
  315.                 else if(voL>1130) numL=10;        
  316.                 else if(voL>1006) numL=9;               
  317.                 else if(voL>895) numL=8;        
  318.                 else if(voL>797) numL=7;                                
  319.                 else if(voL>709) numL=6;        
  320.                 else if(voL>650) numL=5;               
  321.                 else if(voL>400) numL=4;               
  322.                 else if(voL>262) numL=3;               
  323.                 else if(voL>159) numL=2;
  324.                 else if(voL>70) numL=1;                                                                                       
  325.                 else numL=0;

  326.                 if(pfL<=numL)         //检测如果漂浮物不高于峰值就让漂浮物置于峰值上面,同时 标志位 置0
  327.                 {
  328.                         pfL=numL+1;
  329.                         biaozhiL=0;   //标志位 置0   
  330.                         xuantingL=10; //变量xuantingL   改变此值可以设定左漂浮物悬停时间
  331.                 }
  332.                 else                  //if(pfL>numL) 如果漂浮物高于峰值就把标志位置1
  333.                 {
  334.                         biaozhiL=1;   //标志位 置1
  335.                 }
  336.                 displayL();           //显示左声道具体电平值的段


  337.                 voR= ADC_resultR*5.0; //左声道电平转换结果。原理同上边左声道
  338.                 if(voR>2000) numR=14;               
  339.                 else if(voR>1635) numR=13;               
  340.                 else if(voR>1432) numR=12;        
  341.                 else if(voR>1270) numR=11;               
  342.                 else if(voR>1130) numR=10;        
  343.                 else if(voR>1006) numR=9;               
  344.                 else if(voR>895) numR=8;        
  345.                 else if(voR>797) numR=7;                                
  346.                 else if(voR>709) numR=6;        
  347.                 else if(voR>650) numR=5;               
  348.                 else if(voR>400) numR=4;               
  349.                 else if(voR>262) numR=3;               
  350.                 else if(voR>159) numR=2;
  351.                 else if(voR>70) numR=1;                                                                                       
  352.                 else numR=0;
  353.                
  354.                 if(pfR<=numR)
  355.                 {
  356.                         pfR=numR+1;
  357.                         biaozhiR=0;
  358.                         xuantingR=10;               
  359.                 }
  360.                 else
  361.                 {
  362.                         biaozhiR=1;
  363.                 }
  364.                 displayR();           //显示右声道具体电平值的段
  365.         }
  366. }

  367. void timer0() interrupt 1             //定时器0中断程序
  368. {
  369.       TH0=0xb1;
  370.       TL0=0xe0;
  371.       tt0++;

  372.       if (tt0>=1)                     //20ms转换一次.
  373.      {
  374.            tt0=0;
  375.            ADC_resultL = ad_zhuanhuan(0); //P1.0 为 A/D 当前通道, 测量结果存ADC_result0
  376.            ADC_resultR = ad_zhuanhuan(1); //P1.1 为 A/D 当前通道, 测量结果存ADC_result7                          
  377.            
  378.      }
  379. }

  380. void timer1() interrupt 3  //定时器1中断程序
  381. {
  382.                            //再装一次初值
  383.         TH1=0xd8;
  384.         TL1=0xf0;
  385.         
  386.         tt1++;
  387.         if(tt1>=1)
  388.         {
  389.                 if(biaozhiL)
  390.                 {
  391.                         ttL++;
  392.                         if(ttL>7)    //改变此值可以设定左漂浮物下降速度
  393.                         {
  394.                                 if(xuantingL==0)
  395.                                         pfL--;
  396.                                 else if(xuantingL>0)
  397.                                         xuantingL--;                                
  398.                                 ttL=0;                        
  399.                         }                        
  400.                 }
  401.                                           
  402.                 if(biaozhiR)
  403.                 {
  404.                         ttR++;
  405.                         if(ttR>7)   //改变此值可以设定右漂浮物下降速度
  406.                         {
  407.                                 if(xuantingR==0)
  408.                                         pfR--;
  409.                                 else if(xuantingR>0)
  410.                                         xuantingR--;                                
  411.                                 ttR=0;                        
  412.                         }                        
  413.                 }                  

  414.                 tt1=0;
  415.         }
  416. }
复制代码

附件只包含上面代码的Keil工程(如上图):
电平指示.rar (94.75 KB, 下载次数: 62)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:123083 发表于 2023-1-18 11:37 | 只看该作者
非常不错,仿一个试试!
回复

使用道具 举报

板凳
ID:1033105 发表于 2023-2-22 09:42 | 只看该作者
是不是可以把所有的IO口组成30段的LED电平表,单片机的IO口同时接左右声道的灯珠,然后灯组的接地用三极管驱动,单片机分时控制LR声道。或者干脆用几个595驱动,同理LR分时控制。再或者用可编程LED组做。
回复

使用道具 举报

地板
ID:996773 发表于 2023-2-22 10:21 | 只看该作者
51老鹰 发表于 2023-2-22 09:42
是不是可以把所有的IO口组成30段的LED电平表,单片机的IO口同时接左右声道的灯珠,然后灯组的接地用三极管 ...

12c5a60一共有32个口,可以30全推灯珠,不需要三极管驱动,编程时候处理可以分时点亮,因为30个口不可能同时亮。595也不需要
回复

使用道具 举报

5#
ID:1033105 发表于 2023-2-22 17:05 | 只看该作者
hi等你 发表于 2023-2-22 10:21
12c5a60一共有32个口,可以30全推灯珠,不需要三极管驱动,编程时候处理可以分时点亮,因为30个口不可能 ...

我的意思是可以组成双30段的电平表。另外双30段电平表的pcb不怎么好布线,pcb会很宽,不好看。用595的话是不是可以穿起来使用,配合地线分时控制线路会简单一点。其实线路最简单的恐怕就是可编程的LED了,只要串接数据口就可以了。
回复

使用道具 举报

6#
ID:996773 发表于 2023-2-24 09:28 | 只看该作者
51老鹰 发表于 2023-2-22 17:05
我的意思是可以组成双30段的电平表。另外双30段电平表的pcb不怎么好布线,pcb会很宽,不好看。用595的话 ...

30个左右的布线在狭小的板子上还是能做到的,正反两面,设计原则上能少用元件达到目的情况下不要用595

595本身也会占据大量板子面积,一片595占据的面积上下足够可以走七八条线了,只有在驱动上百更多个LED才

会动用串行输出到595
回复

使用道具 举报

7#
ID:996773 发表于 2023-2-24 09:40 | 只看该作者
51老鹰 发表于 2023-2-22 17:05
我的意思是可以组成双30段的电平表。另外双30段缙奖淼膒cb不怎么好布线,pcb会很宽,不好看。用595的话 ...

12c5a的io口配置输出有讲究的,如果采用共阴方案,每个io口配置成弱上拉,再用两个io口分别做左右声道

拉低LED共阴,如果30个全亮,每个灯分配到0.8ma,一共也就只有25ma左右电流,足够的,不需要三极管

驱动拉低,
回复

使用道具 举报

8#
ID:1093862 发表于 2023-11-10 13:47 | 只看该作者
LIN,  RIN两个输入口不用定义吗
回复

使用道具 举报

9#
ID:195496 发表于 2023-11-14 13:56 | 只看该作者
LED显示很直观
回复

使用道具 举报

10#
ID:688460 发表于 2023-11-14 18:32 | 只看该作者
邪门,我的怎么编译不通过呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表