单片机-蓝桥杯 用光敏电阻测量光照强度并显示在数码管上。

简介: 单片机-蓝桥杯 用光敏电阻测量光照强度并显示在数码管上。

先给大家看下效果

数码管会随光照强度而变化,可以拿手电筒照射 光敏电阻看数码管数值变化

项目工程如下

首配置一下IIC协议 这个比较基础代码如下:

首先是.c文件

1. #include "iic.h"
2. 
3. #define DELAY_TIME 5
4. 
5. //I2C总线内部延时函数
6. void IIC_Delay(unsigned char i)
7. {
8.     do{_nop_();}
9.     while(i--);        
10. }
11. 
12. //I2C总线启动信号
13. void IIC_Start(void)
14. {
15.     SDA = 1;
16.     SCL = 1;
17.     IIC_Delay(DELAY_TIME);
18.     SDA = 0;
19.     IIC_Delay(DELAY_TIME);
20.     SCL = 0;  
21. }
22. 
23. //I2C总线停止信号
24. void IIC_Stop(void)
25. {
26.     SDA = 0;
27.     SCL = 1;
28.     IIC_Delay(DELAY_TIME);
29.     SDA = 1;
30.     IIC_Delay(DELAY_TIME);
31. }
32. 
33. //等待应答
34. bit IIC_WaitAck(void)
35. {
36. bit ackbit;
37. 
38.     SCL  = 1;
39.     IIC_Delay(DELAY_TIME);
40.     ackbit = SDA;
41.     SCL = 0;
42.     IIC_Delay(DELAY_TIME);
43. return ackbit;
44. }
45. 
46. //I2C总线发送一个字节数据
47. void IIC_SendByte(unsigned char byt)
48. {
49.     unsigned char i;
50. 
51. for(i=0; i<8; i++)
52.     {
53.         SCL  = 0;
54.         IIC_Delay(DELAY_TIME);
55. if(byt & 0x80) SDA  = 1;
56. else SDA  = 0;
57.         IIC_Delay(DELAY_TIME);
58.         SCL = 1;
59.         byt <<= 1;
60.         IIC_Delay(DELAY_TIME);
61.     }
62.     SCL  = 0;  
63. }
64. 
65. //I2C总线接收一个字节数据
66. unsigned char IIC_RecByte(void)
67. {
68.     unsigned char i, da;
69. for(i=0; i<8; i++)
70.     {   
71.       SCL = 1;
72.   IIC_Delay(DELAY_TIME);
73.   da <<= 1;
74.   if(SDA) da |= 1;
75.   SCL = 0;
76.   IIC_Delay(DELAY_TIME);
77.     }
78. return da;    
79. }
80. 
81. 
82. 
83. // pcf8591内有四个通道,如下:
84. // 0:AIN0电压输入(0x00)
85. // 1:光敏电阻(0x01)
86. // 2:运算放大器(0x02)
87. // 3:滑动变阻器(0x03)
88. //---------------------------------------
89. // AD转换:直接读取pcf8591内寄存器数据(不依赖EEPROM)
90. unsigned char ad_read(unsigned char add){
91.   unsigned char temp;
92. 
93.   IIC_Start();
94.   IIC_SendByte(0x90); // 选中8591芯片,写指令
95.   IIC_WaitAck();
96.   IIC_SendByte(add); // 配置寄存器,选择哪个通道
97.   IIC_WaitAck();
98.   IIC_Stop();
99. 
100.  IIC_Start();
101.  IIC_SendByte(0x91); // 选中8591,读指令
102.  IIC_WaitAck();
103.  temp=IIC_RecByte();
104.  IIC_Stop();
105. 
106.  return temp;
107. }
108. 
109. //-------------------------------------------
110. // 读取数据
111. unsigned char eeprom_read(unsigned char add){
112.  unsigned char temp;
113. 
114.  IIC_Start();
115.  IIC_SendByte(0xA0); // 选中eeprom芯片,写指令
116.  IIC_WaitAck();
117.  IIC_SendByte(add); // 选择哪个地址
118.  IIC_WaitAck();
119.  IIC_Stop();
120. 
121.  IIC_Start();
122.  IIC_SendByte(0xA1); // 选中eeprom,读指令
123.  IIC_WaitAck();
124.  temp=IIC_RecByte();
125.  IIC_Stop();
126. 
127.  return temp;
128. }
129. 
130. // 写入数据
131. void eeprom_write(unsigned char add, unsigned char dat){
132.  IIC_Start();
133.  IIC_SendByte(0xA0);
134.  IIC_WaitAck();
135.  IIC_SendByte(add);
136.  IIC_WaitAck();
137.  IIC_SendByte(dat);
138.  IIC_Stop();
139. }

iic.h文件如下:

1. #ifndef __IIC__H__
2. #define __IIC__H__
3. 
4. #include "stc15f2k60s2.h"
5. #include "intrins.h"
6. 
7. sbit SDA = P2^1;
8. sbit SCL = P2^0;
9. 
10. void IIC_Start(void); 
11. void IIC_Stop(void);  
12. bit IIC_WaitAck(void);  
13. void IIC_SendAck(bit ackbit); 
14. void IIC_SendByte(unsigned char byt); 
15. unsigned char IIC_RecByte(void); 
16. 
17. unsigned char ad_read(unsigned char add);
18. unsigned char eeprom_read(unsigned char add);
19. void eeprom_write(unsigned char add, unsigned char dat);
20. 
21. #endif

然后在建一个use.c文件来放置各种函数方便直接在主函数main中调用

1. #include "use.h"
2. 
3. // 第0到9位是数字0到9, 第10到18位是带小数点的0到9,最后是关闭显示
4. uchar code tab[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0xff};
5. uchar dspbuf[8]={20, 20, 20, 20, 20, 20, 20, 20};
6. uchar dspcom=0;
7. 
8. void system_init(void){
9.  hc138(1, 0x00);  //关闭蜂鸣器
10.   hc138(2, 0xff);  //关闭LED
11.   timer_init();
12. }
13. 
14. void timer_init(void){
15.   TMOD=0x01; //定时器1 12分频
16. 
17.   TH0=(65536-1000)/256;  //1ms
18.   TL0=(65536-1000)%256;
19. 
20.   TR0=1;
21.   ET0=1;
22.   EA=1;
23. }
24. 
25. void hc138(uchar mode, uchar dat){
26.   P0=dat;
27.   switch(mode){
28.     case 1:P2=P2&0x1f|0xa0;break;// 蜂鸣器
29.     case 2:P2=P2&0x1f|0x80;break;// LED
30.     case 3:P2=P2&0x1f|0xe0;break;// 数码管段选
31.     case 4:P2=P2&0x1f|0xc0;break;// 数码管位选
32.   }
33.   P2&=0x1f;
34. }
35. 
36. void re_dsp(uchar *arr){
37.   uchar i;
38.   for(i=0;i<8;i++){
39.     *(dspbuf+i)=*(arr+i);//更新数码表
40.   }
41. }
42. 
43. void digital(void){
44.   hc138(3, 0xff);
45.   hc138(4, 1<<dspcom);
46.   hc138(3, tab[dspbuf[dspcom]]); //刷新数码管
47.   if(++dspcom>=8){
48.     dspcom=0;
49.   }
50. }

然后是use.h

1. #ifndef __USE__H__
2. #define __USE__H__
3. 
4. #include<stdio.h>
5. #include<intrins.h>
6. #include<stc15f2k60s2.h>
7. #include<iic.h>
8. 
9. typedef unsigned char uchar;
10. typedef unsigned int uint;
11. typedef unsigned long ulong;
12. 
13. void system_init(void);
14. void timer_init(void);
15. void hc138(uchar mode, uchar dat);
16. void re_dsp(uchar *arr);
17. void digital(void);
18. 
19. #endif

最后就是main函数

1. #include "use.h"
2. 
3. bit show_flag=0;
4. bit adc_flag=0;
5. 
6. uchar dsp[8]={20, 20, 20, 20, 20, 20, 20, 20};
7. 
8. uchar light=0;
9. 
10. void show(void);
11. 
12. void main(void){
13.   system_init();
14.   while(1){
15.     if(show_flag==1){
16.       show_flag=0;
17.       show();
18.     }
19.     if(adc_flag==1){
20.       adc_flag=0;
21.       light=ad_read(0x01);//读取光敏电压
22.       light=ad_read(0x01);
23.       if(light<=80){
24.         eeprom_write(0x00, 0);
25.       }else{
26.         eeprom_write(0x00, 1);
27.       }
28.     }
29.     re_dsp(dsp);
30.   }
31. }
32. 
33. void show(void){
34. //更新数码表
35.   uchar cache_light=light;
36. 
37.   cache_light=(float)cache_light/255*500;
38.   dsp[0]=cache_light/100+10;
39.   dsp[1]=cache_light%100/10;
40.   dsp[2]=cache_light%10;
41.   dsp[3]=dsp[4]=dsp[5]=dsp[6]=20;
42.   dsp[7]=eeprom_read(0x00);
43. }
44. 
45. void timer_0(void) interrupt 1 {
46.   static uint count=0, adc_cnt=0;
47. 
48.   TH0=(65536-1000)/256;
49.   TL0=(65536-1000)%256;
50. 
51.   digital();//刷新数码管
52. 
53.   if(++adc_cnt>=200){  //0.2s读取光敏电压
54.     adc_cnt=0;
55.     adc_flag=1;
56.   }
57.   if(++count>=500){  //0.5s更新数码表
58.     count=0;
59.     show_flag=1;
60.   }
61. }

最后呢将程序烧录进去就行啦!

目录
相关文章
|
4月前
【51单片机】独立按键,每个按键不同功能,数码管数值的加减,控制流水灯模式,包含按键消抖,数码显示,流水灯
【51单片机】独立按键,每个按键不同功能,数码管数值的加减,控制流水灯模式,包含按键消抖,数码显示,流水灯
356 1
|
7月前
|
存储
【期末不挂科-单片机考前速过系列P3】(第三章:13题MOV&MOVX&MOVC&数码管速过)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P3】(第三章:13题MOV&MOVX&MOVC&数码管速过)经典例题盘点(带图解析)
|
4月前
51单片机汇编语言点亮一位数码管,并计时(超详细分析汇编语言)
51单片机汇编语言点亮一位数码管,并计时(超详细分析汇编语言)
222 0
|
4月前
【51单片机】开发板上矩阵键盘键码在数码管上的显示,按下键盘在数码管上显示对应段码
【51单片机】开发板上矩阵键盘键码在数码管上的显示,按下键盘在数码管上显示对应段码
160 0
|
4月前
|
算法
51单片机不用定时器的数码管倒计时
51单片机不用定时器的数码管倒计时
|
5月前
蓝桥杯之单片机学习(终)——关于之前文章的错误及更正(附:第十四届蓝桥杯单片机赛题)
蓝桥杯之单片机学习(终)——关于之前文章的错误及更正(附:第十四届蓝桥杯单片机赛题)
【51单片机】自定义动态数码管显示(设计思路&原理&代码演示)
【51单片机】自定义动态数码管显示(设计思路&原理&代码演示)
【51单片机】自定义静态数码管显示(设计思路&代码演示)
【51单片机】自定义静态数码管显示(设计思路&代码演示)
【51单片机】静态数码管显示(设计思路&原理&代码演示)
【51单片机】静态数码管显示(设计思路&原理&代码演示)
|
7月前
|
芯片 数据格式
【51单片机】要实现动静态数码管,你首先需要知道这些【数码管项目前置知识】
【51单片机】要实现动静态数码管,你首先需要知道这些【数码管项目前置知识】