锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

AD(I2C通信)光敏电阻控制LED的单片机源码

时间:2023-11-05 23:37:01 光敏电阻加什么能控制灯

#include

#include

#define MAIN_Fosc 11059200UL //宏定义主时钟HZ

#define PCF8591_ADDR 0x90 //PCF8591地址

#define DACOUT_EN 0x40 //DAC输出使能

/*====================================

定制类型名

====================================*/

typedef unsigned char INT8U;

typedef unsigned char uchar;

typedef unsigned int INT16U;

typedef unsigned int uint;

/*====================================

声明硬件接口位置

====================================*/

sbit SDA = P2^0; //I2C串行数据

sbit SCL = P2^1; //I2C串行时钟

sbit DU= P2^6; ///数码管段选择

sbit WE= P2^7; ///数码管位选择

sbit LED1= P1^0; //读取AD值是否成功(亮成功,灭失败)

sbit LED2= P1^1; //DAC成功输出(亮成功,灭失败)

sbit BEEP= P2^3; ///蜂鸣器引脚定义

uchar AD_Value; //存储AD转换回的数字量

/*====================================

选择共阴极数码管段的代码

====================================*/

uchar code table[]={

//0 1 2 3 4 5 6 7 8

0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,

//9 A B C D E F - . 关显示

0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00

};

/*====================================

数码管位选码

====================================*/

//第1位 2位 3位 4位 5位 6位 7位 8位

uchar code T_COM[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};///数字管位码

/*====================================

函数:void Delay_Ms(INT16U ms)

参数:ms,毫秒延时形参

描述:12T 51单片机适应主时钟毫秒延迟函数

====================================*/

void Delay_Ms(INT16U ms)

{

INT16U i;

do{

i = MAIN_Fosc / 96000;

while(--i); //96T per loop

}while(--ms);

}

/*====================================

函数:void Delay5us()

描述:12T 51单片机5微秒延迟函数自适应时钟(11.0592M,12M,22.1184M)

====================================*/

void Delay5us()

{

#if MAIN_Fosc == 11059200

_nop_();

#elif MAIN_Fosc == 12000000

_nop_();

#elif MAIN_Fosc == 22118400

_nop_(); _nop_(); _nop_();

#endif

}

/*====================================

函数:void Display(INT8U Value)

参数:Value,显示值 取值0-255

描述:共阴极数字管显示函数可显示字节数

====================================*/

void Display(INT8U Value)

{

//------------------------------

DU = 1;

P0 = table[Value/100]; //管显示100位

DU = 0;

P0 = 0xff; ///清除断码

WE = 1;

P0 = T_COM[0]; ///第一位数码管

WE = 0;

Delay_Ms(5);

//-------------------------------

DU = 1;

P0 = table[Value0/10]; //显示十位

DU = 0;

P0 = 0xff; &nsp; //清除断码

WE = 1;

P0 = T_COM[1];                          //第二位数码管

WE = 0;

Delay_Ms(5);

//-------------------------------

DU = 1;

P0 = table[Value%10];                //显示个位

DU = 0;

P0 = 0xff;                                        //清除断码

WE = 1;

P0 = T_COM[2];                                //第三位数码管

WE = 0;

Delay_Ms(5);

}

/*====================================

函数:I2C_init()

描述:I2C总线初始化

====================================*/

void I2C_init()

{

SDA = 1;   //数据总线高

_nop_();

SCL = 1;   //时钟总线高

_nop_();

}

/*====================================

函数:I2C_Start()

描述:I2C起始信号

====================================*/

void I2C_Start()

{

SCL = 1;

_nop_();

SDA = 1;

Delay5us();

SDA = 0;

Delay5us();

}

/*====================================

函数:I2C_Stop()

描述:I2C停止信号

====================================*/

void I2C_Stop()

{

SDA = 0;

_nop_();

SCL = 1;

Delay5us();

SDA = 1;

Delay5us();

}

/*====================================

函数:Master_ACK(bit i)

参数:i 为0时发送非应答 为1时发送应答

描述:I2C主机发送应答

====================================*/

void Master_ACK(bit i)

{

SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化

_nop_(); // 让总线稳定

if (i)         //如果i = 1 那么拉低数据总线 表示主机应答

{

SDA = 0;

}

else

{

SDA = 1;         //发送非应答

}

_nop_();//让总线稳定

SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号

_nop_();

SCL = 0;//拉低时钟总线, 占用总线继续通信

_nop_();

SDA = 1;//释放SDA数据总线。

_nop_();

}

/*====================================

函数:Test_ACK()

返回:0为非应答 1为应答

描述:I2C检测从机应答

====================================*/

bit Test_ACK()         // 检测从机应答

{

SCL = 1;//时钟总线为高电平期间可以读取从机应答信号

Delay5us();

if (SDA)

{

SCL = 0;

I2C_Stop();

return(0);

}

else

{

SCL = 0;

return(1);

}

}

/*====================================

函数:I2C_send_byte(uchar byte)

参数:byte 要发送的字节

描述:I2C发送一个字节

====================================*/

void I2C_send_byte(uchar byte)

{

uchar i;

for(i = 0 ; i < 8 ; i++)

{

SCL = 0;

_nop_();

if (byte & 0x80)        //

{

SDA = 1;

_nop_();

}

else

{

SDA = 0;

_nop_();

}

SCL = 1;

_nop_();

byte <<= 1;

}

SCL = 0;

_nop_();

SDA = 1;

_nop_();

}

/*====================================

函数:I2C_read_byte()

返回:读取的字节

描述:I2C读一个字节

====================================*/

uchar I2C_read_byte()

{

uchar i, dat;

SCL = 0 ;

_nop_();

SDA = 1;

_nop_();

for(i = 0 ; i < 8 ; i++)

{

SCL = 1;

_nop_();

dat <<= 1;

if (SDA)

{

dat |= 0x01;

}

_nop_();

SCL = 0;

_nop_();

}

return(dat);

}

/*DAC输出*/

bit DAC_OUT(uchar DAT)

{

I2C_Start();

I2C_send_byte(PCF8591_ADDR+0);         //发送PCF8591地址加读写方向位0(写)

if (!Test_ACK())                                //检测是否发送成功(应答)

{

return(0);

}

I2C_send_byte(DACOUT_EN);        //DA输出使能

if (!Test_ACK())

{

return(0);

}

I2C_send_byte(DAT);

if (!Test_ACK())

{

return(0);

}

I2C_Stop();

return(1);

}

/*读AD数据*/

bit ADC_Read(uchar CON)

{

I2C_Start();

I2C_send_byte(PCF8591_ADDR+0);

if (!Test_ACK())

{

return(0);

}

I2C_send_byte(CON);                        //发送控制字节

Master_ACK(0);                                //发送非应答

I2C_Start();

I2C_send_byte(PCF8591_ADDR+1);                   //改变读写方向(读)

if (!Test_ACK())                                        //检测是否发送成功(应答)

{

return(0);

}

AD_Value = I2C_read_byte();

Master_ACK(0);                                                //主机发送非应答

I2C_Stop();

return(1);                                                         //成功返回1

}

void main()

{

I2C_init();

while(1)

{

//单端输入,读出通道2的值

if (ADC_Read(0x02))        LED1 = 0;

else        LED1 = 1;

//把AD转换得的数量在送给PCF8591转为模拟量控制模拟量输出口的小灯

if (DAC_OUT(AD_Value))        LED2 = 0;

else        LED2 = 1;

Display(AD_Value);         //显示读出的模拟量

if (AD_Value > 150)        BEEP = 0;

else        BEEP = 1;

Delay_Ms(5);

}

}

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章