蓝桥杯单片机——at24c02、PCF8591

前言

比赛时会提供驱动文件,包含IIC初始化函数,IIC写入函数,IIC读取函数,发送应答信号函数,接收应答信号函数·。对于at24c02需要写一个读取函数和写入函数,PCF8591需要adc转换函数和一个dac转换函数。

代码

iic.c

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/


#include "intrins.h"
#include "iic.h"

#define DELAY_TIME 5


/*   引脚定义,需要自己补充的部分    */
sbit sda = P2^1;  /* 数据线 */
sbit scl = P2^0;  /* 时钟线 */


//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		    I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		    I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		    I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}



/********************* at24c02  **************************/

/***   读取函数,参数为要读取的地址  ***/
unsigned char iic_eeprom_read(unsigned char add)
{
	unsigned char dat;
	I2CStart();//初始化iic总线
	I2CSendByte(0xa0);//发送从机 (写) 地址
	I2CWaitAck();//等待从机答应信号
	I2CSendByte(add);//写入要访问的地址
	I2CWaitAck();	//等待从机答应信号
	I2CStop();//结束本轮通讯
	
	I2CStart();//重新初始化iic总线
	I2CSendByte(0xa1);//发送从机 (读) 地址
	I2CWaitAck();//等待从机答应信号
	dat = I2CReceiveByte();//读取地址中的数据
	I2CSendAck(1);//发送答应信号
	I2CStop();//结束通讯
	
	return dat;
}

/***   写入函数,参数1为要写入的地址,参数1要写入的数据  ***/
/***   注意连续写入时要加10ms延时确保等到上一字节数据写入在写入下一字节  ***/
void iic_eeprom_write(unsigned char add,unsigned char dat)
{
	I2CStart();//初始化iic总线
	I2CSendByte(0xa0);//发送从机 (写) 地址
	I2CWaitAck();//等待从机答应信号
	I2CSendByte(add);//写入要访问的地址
	I2CWaitAck();//等待从机答应信号
	
	I2CSendByte(dat);//向访问地址写入数据
	I2CWaitAck();	//等待从机答应信号
	I2CStop();//结束通讯
}


/********************* adc\dac  **************************/

/* PCF8591AD转换函数,channel为模拟输入的通道  3光敏、1电位器、0 A/D  */
unsigned char  PCF8591_AD_Conversion(unsigned char channel )
{
    unsigned char dat = 0;
    I2CStart();//初始化iic总线
    I2CSendByte(0x90);//写入从机PCF8591的(写)地址,
    I2CWaitAck();  //等待从机应答信号

    I2CSendByte(0x00 | channel); //写入控制指令,单端输入,AD转换,选择通道channel
    I2CWaitAck(); //这一步不能少,否则读出来一直是255
    I2CStop(); //结束本次通信,改变收发方向
    
    I2CStart();//初始化iic总线
    I2CSendByte(0x91);//写入从机PCF8591的 (读) 地址,
    I2CWaitAck();
    dat = I2CReceiveByte();//读取AD转换出的数字量 
    I2CSendAck(1);//不应答

    I2CStop();//结束通信

    return dat;
}

/*   PCF8591DA转换函数,dat为输入的数字量  */
void PCF8591_DA_Conversion(unsigned  char dat)
{
    I2CStart();        //iic通信开始
    I2CSendByte(0x90);   //写入PCF8591的写地址
	I2CWaitAck(); 
	
    I2CSendByte(0x40);     //写入控制指令,DA转换
    I2CWaitAck();      //等待应答
	
	I2CSendByte(dat);      //写入数字量
	I2CWaitAck();      //等待应答
	I2CStop();         //结束通信
}




iic.h

#ifndef _IIC_H
#define _IIC_H

#include <STC15F2K60S2.H>


void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 




/*      自己写的程序   */
unsigned char iic_eeprom_read(unsigned char add);
void iic_eeprom_write(unsigned char add,unsigned char dat);

unsigned char  PCF8591_AD_Conversion(unsigned char channel );
void PCF8591_DA_Conversion(unsigned  char dat);

#endif

main.c

#include <hc138_hs.H>
#include "iic.h"

/*    应用      */
void main(void)
{
	unsigned int  adc1,adc2,dac1 = 255;
    char at24c02_data = 0;
	//iic_eeprom_write(0x01,0);//将这个地址的数据清零(初始化的时候调用一次)

	
	at24c02_data = iic_eeprom_read(0x01);//读取at24c02地址 0x01 中的数据
	iic_eeprom_write(0x01,++at24c02_data);//将数值加一再写回去,记录单片机的开机次数	

	while(1)
	{
		 //使用数码管1、2位显示开机次数
        smg_SetOne(1,at24c02_data/10);	
        smg_SetOne(2,at24c02_data%10);	

		//adc、dac
		adc1 = PCF8591_AD_Conversion(1);//读取光敏电阻分压的电压的数字量
		adc1 = adc1*50/255; //电压计算,放大10倍 ( 5v ->  50 )
		
		
		adc2 = PCF8591_AD_Conversion(3);//读取电位器上分压的电压的数字量
		
		PCF8591_DA_Conversion(adc2);//将读取到的电压值再用dac输出
		
	    adc2 = adc2*50/255;//电压计算,放大10倍 ( 5v ->  50 )
		
		//数码管显示敏电阻分压的电压
		smg_SetOne(4,adc1/10 +10);//加10,为带点的段码
		smg_SetOne(5,adc1%10);
		
		//数码管显示电位器上分压的电压
		smg_SetOne(7,adc2/10 +10);//加10,为带点的段码
		smg_SetOne(8,adc2%10);
		
		
	}
}

效果

 

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值