先给大家看下效果
数码管会随光照强度而变化,可以拿手电筒照射 光敏电阻看数码管数值变化
项目工程如下:
首配置一下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. }
最后呢将程序烧录进去就行啦!