找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5316|回复: 1
收起左侧

PIC16F873A单片机的照度测量项目原理图与源代码

[复制链接]
ID:275894 发表于 2018-1-14 17:05 | 显示全部楼层 |阅读模式
基于PIC16F873A的照度测量C语言代码。
可以使用Labview以RS232接口和PC通信,并获取实时数据
1.png
2.png 0.png

单片机源程序如下:

  1. #include <pic.h>           //调用PIC16F87XA单片机的头文件


  2. __CONFIG(HS&WDTDIS&LVPDIS);

  3. #define U5A  RC0           //4位数码管单元的U5(74HC138)的A脚接在RB0口上
  4. #define U5B  RC1           //4位数码管单元的U5(74HC138)的B脚接在RB1口上
  5. #define U5C  RC2           //4位数码管单元的U5(74HC138)的C脚接在RB2口上

  6. unsigned char temp1;
  7. unsigned char temp2;

  8. const unsigned char LED[28]=
  9. {
  10. 0x3F,/*0*/        
  11. 0x06,/*1*/        
  12. 0x5B,/*2*/        
  13. 0x4F,/*3*/        
  14. 0x66,/*4*/        
  15. 0x6D,/*5*/        
  16. 0x7D,/*6*/        
  17. 0x07,/*7*/        
  18. 0x7F,/*8*/        
  19. 0x6F,/*9*/        
  20. 0x77,/*A*/        
  21. 0x7C,/*b*/        
  22. 0x39,/*C*/        
  23. 0x58,/*c*/        
  24. 0x5E,/*d*/        
  25. 0x79,/*E*/        
  26. 0x71,/*F*/        
  27. 0x76,/*H*/        
  28. 0x74,/*h*/        
  29. 0x38,/*L*/        
  30. 0x54,/*n*/        
  31. 0x37,/*N*/        
  32. 0x5C,/*o*/        
  33. 0x73,/*P*/        
  34. 0x50,/*r*/        
  35. 0x78,/*t*/        
  36. 0x3E,/*U*/        
  37. 0x40,/*-*/
  38. };
  39. //---------------------------------------
  40. //A/D转换用寄存器设置
  41. unsigned int  ADbuf;   //设置16位的unsigend int型寄存器用来暂存转换结果
  42. unsigned int adcbuf[16];


  43. void main(void)            //主函数,单片机开机后就是从这个函数开始运行
  44. {
  45.         unsigned char buf;   
  46.         unsigned char USARTbuf;

  47.     unsigned char c=0;     //定义一个char型变量,做延时用
  48.     unsigned char e=0;     //定义一个char型变量,做延时用

  49.         unsigned char i;
  50.         unsigned char b;
  51.         unsigned char d=0;     //定义一个char型变量,控制显示位置
  52.     TRISA=0B11111111;      //初始化RA5-RA0的输出方向
  53.    TRISC=0B11111000;           //RB0-3设置为输出
  54.         TRISB=0B00000000;           //RD设置为输出
  55.     PORTA=0B00000000;      //初始化RA5-RA0数值
  56.     PORTB=0B00000000;      //初始化RB7-RB0的数值
  57.     PORTB=0B00000000;      //初始化RD7-RD0的数值


  58.     //****A/D模块初始化****
  59.     //ADCON1=0B10001110;     //RA0为A/D输入口;ADFM=1,转换后数据右移,ADRESL为低8位数据
  60.      ADCON1=0B10001111;     //RA0为A/D输入口;ADFM=1,转换后数据右移,ADRESL为低8位数据
  61. //设置RA2=Vref-(GND),RA3=Vref+
  62. /*
  63. 详细分析该设置:
  64. ADFM=1,结果右移,ADRESH寄存器的高六位读作“0”
  65. bit6~4未用,以0设置
  66. bit3~0 RA0作为模拟信号输入端,其余引脚(RA1~7)都是数字信号输入端

  67. */

  68.     ADIE=0;                //禁止A/D中断
  69.     //*********************

  70.         //*****USART串口初始化*****
  71.     SPBRG=25;              //设置波特率为9600,误差0.16%
  72.     BRGH=1;                //设置高速波特率
  73.     SYNC=0;                //SYNC=0为异步模式,SYNC=1为同步模式
  74.     SPEN=1;                //允许串口操作
  75.     CREN=1;                //CREN=0禁止连续接收,CREN=1允许连续接收
  76.     TXIE=0;                //禁止发送中断
  77.     RCIE=0;                //禁止接收中断
  78.     TX9=0;                 //TX9=0为8位发送,TX9=1为9位发送
  79.     RX9=0;                 //RX9=0为8位接收,RX9=1为9位接收
  80.     TXEN=1;                //TXEN=0为禁止发送,TXEN=1为允许发送
  81.    

  82.     while(1)               //死循环,单片机初始化后,将一直运行这1个死循环
  83.     {
  84.                 for(i=0;i<16;i++)  //连续采样16次,然后取平均数
  85.                 {
  86.     //***启动一次A/D转换***
  87.                 ADCON0=0B00000001;     //选择AN0通道准备进行A/D转换,启动A/D模块
  88. /*
  89. 详细分析该设置:
  90. ADCS1:ADCS0=00,fosc/2;4MHz/2=2MHz?
  91. CHS2:CHS0=000,选择模拟通道RA0
  92. GO/DONE=0,未进行A/D转换,A/D转换完成后该位自动清零
  93. bit1=0,该位未用
  94. ADON=1,打开A/D转换器的工作状态
  95. */
  96.                 asm("NOP");            //略做延时
  97.                 asm("NOP");            //略做延时
  98.                 asm("NOP");            //略做延时
  99.                 asm("NOP");            //略做延时
  100.                 ADGO=1;                //开始进行A/D转换
  101.                 while(ADGO) continue;  //等待A/D转换结束
  102.                 adcbuf[i]=ADRESH*256+ADRESL;  
  103.            
  104.     //*********************   
  105.                 }
  106.                 ADbuf=0;
  107.                 for(i=0;i<16;i++)            
  108.                 {
  109.                         ADbuf+=adcbuf[i];           //把连续转换了16次的AD值加在一起
  110.                 }
  111.                 ADbuf=ADbuf/16;                 //除以16,算16次采样的平均值
  112.         
  113.                 ADbuf=(int)(((float)ADbuf/1023)*1000);            //将0-1023换算成电压值000-1000

  114.             temp1=ADbuf/100;
  115.             temp2=ADbuf%100;

  116.       if(ADbuf<999)
  117. {  

  118.          PORTB=0;           //关一次显示,以免显示出鬼影
  119.                if(++d>3) d=0;     //先将d加1,然后判断是否大于3,大于3归零
  120.                if(d==0)           //如果d=0,显示千位
  121.                {
  122.            U5A=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
  123.            U5B=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
  124.            U5C=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
  125.            PORTB=LED[(ADbuf%10000)/1000];       //将要显示的f的千位提取出来查表后送显示
  126.                }
  127.                else if(d==1)      //如果d=1,显示百位
  128.                {
  129.            U5A=1;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
  130.            U5B=0;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
  131.            U5C=0;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
  132.            PORTB=LED[(ADbuf%1000)/100]; //将要显示的f的百位提取出来查表后送显示
  133.                }
  134.                else if(d==2)      //如果d=2,显示十位
  135.                {
  136.            U5A=0;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
  137.            U5B=1;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
  138.            U5C=0;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
  139.            PORTB=LED[(ADbuf%100)/10];   //将要显示的f的十位提取出来查表后送显示
  140.                }
  141.                else if(d==3)      //如果d=3,显示个位
  142.                {
  143.            U5A=1;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
  144.            U5B=1;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
  145.            U5C=0;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
  146.            PORTB=LED[ADbuf%10];         //将要显示的f的个位提取出来查表后送显示
  147.                }
  148.   }   

  149. if(ADbuf>999)
  150. {
  151.          PORTB=0;           //关一次显示,以免显示出鬼影
  152.                if(++d>3) d=0;     //先将d加1,然后判断是否大于3,大于3归零
  153.                if(d==0)           //如果d=0,显示千位
  154.                {
  155.            U5A=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
  156.            U5B=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
  157.            U5C=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
  158.            PORTB=LED[15];       //将要显示的f的千位提取出来查表后送显示
  159.                }
  160.                else if(d==1)      //如果d=1,显示百位
  161.                {
  162.            U5A=1;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
  163.            U5B=0;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
  164.            U5C=0;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
  165.            PORTB=LED[15]; //将要显示的f的百位提取出来查表后送显示
  166.                }
  167.                else if(d==2)      //如果d=2,显示十位
  168.                {
  169.            U5A=0;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
  170.            U5B=1;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
  171.            U5C=0;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
  172.            PORTB=LED[0];   //将要显示的f的十位提取出来查表后送显示
  173.                }
  174.                else if(d==3)      //如果d=3,显示个位
  175.                {
  176.            U5A=1;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
  177.            U5B=1;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
  178.            U5C=0;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
  179.            PORTB=LED[10];         //将要显示的f的个位提取出来查表后送显示
  180. ……………………

  181. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
illuminometer.rar (176.22 KB, 下载次数: 45)
回复

使用道具 举报

ID:606233 发表于 2020-5-25 07:09 | 显示全部楼层
谢谢分享
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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