打印
[其他产品]

PIC16F877A单片机 (IIC总线+AT24C02芯片)

[复制链接]
1029|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tfqi|  楼主 | 2022-6-23 13:28 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
1 基本原理1.1 IIC总线













需要注意的是,高四位对于同种芯片而言,都是一样的。例如AT24C02芯片的高四位固定为1010。


1.2 AT24C02芯片




2 源代码


/*---------------------函数功能:
                IIC总线 AT24C02

-----------------------------------------*/


#include<pic.h>// 调用PIC16f87XA单片机的头文件
#include"delay.h"//调用延时子函数的头文件



__CONFIG(0xFF32);//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关
//__CONFIG(HS&WDTDIS&LVPDIS);



/*-----------宏定义--------------*/
#define  uint  unsigned int
#define  uchar unsigned char
#define  SDA     RC4                        // IIC的数据线
#define  SCL     RC3                        // IIC的时钟线



/*-----------子函数声明--------------*/
void IIC_start(void);                // IIC启动信号函数
void IIC_end(void);                        // IIC终止信号函数

void write_1Byte(uchar buf);//向IIC总线写一个字节的函数
char read_1Byte();                        //从IIC总线读一个字节的函数

void write_AT24C02(char address,char databuf);        //向AT24C02芯片的指定地址写一个字节的数据
char read_AT24C02(char address);                                //从AT24C02芯片的指定地址读一个字节的数据



/*-----------主函数--------------*/
void main()
{
        char bufdata;

        // data direction register is TRISA.
        // Setting  a TRISA bit (= 1) will make the corresponding PORTA pi an input.
        // Clearing a TRISA bit (= 0) will make the corresponding PORTA pin an output.
        TRISD=0x00;                        //RD作为输出口,作为LED灯的显示
        PORTD=0x00;                        //LED的初值为0
        delay(1000);

        while(1)
        {
                bufdata=read_AT24C02(0x18);// 从AT24C02中地址0x18读出数据
                PORTD=bufdata;
                delay(1000);


                bufdata=bufdata+1;
                PORTD=bufdata;
                delay(1000);


                write_AT24C02(0x18,bufdata);//将+1的数据保存在0x18中
        }
       
}








/*************IIC启动信号函数***************/
void IIC_start(void)
{
        //为什么这样写,见IIC的时序图
        SDA=1;
        SCL=1;
        asm("NOP");
        asm("NOP");

        SDA=0;
        asm("NOP");
        asm("NOP");

        SCL=0;
        asm("NOP");
        asm("NOP");

}




/*************IIC终止信号函数***************/
void IIC_end(void)
{
        SDA=0;
        SCL=0;
        asm("NOP");
        asm("NOP");

        SCL=1;
        asm("NOP");
        asm("NOP");

        SDA=1;
        asm("NOP");
        asm("NOP");

        SCL=0;//拉低
        asm("NOP");
        asm("NOP");

}




/*************向IIC总线写一个字节(8 bit)的函数***************/
void write_1Byte(uchar buf)
{
        int k=0;
        for(k=0;k<8;k++)
        {
                //将最高位写到SDA总线上去
                //SDA=buf&0x80;                // 等价于下面的if语句
                if(buf&0x80)                // 提取buf的最高位数据
                        SDA=1;                        //如果buf的最高位为1,就写1
                else
                        SDA=0;                        //如果buf的最高位为0,就写0
                asm("NOP");
                asm("NOP");
               
                SCL=1;
                asm("NOP");

                SCL=0;                                //时钟信号归零
                asm("NOP");

                buf=buf<<1;                        //左移一位,准备提取下一个待写的数据
        }


        // 每接收到一个字节的数据后,从机必须产生一个应答信号给主机。
        // 应答器件在第9个时钟周期将SDA线拉低,表示已经接收了一个八位数据
        TRISC4=1;                                //RC4作为输入,SDA引脚接的是RC4口   开始读数据,读SDA的值
        asm("NOP");

        SCL=1;       
        asm("NOP");
        asm("NOP");
        //if(RC4=0)                         //说明SDA=0,即成功接收
        SCL=0;
        TRISC4=0;
}




/*************向IIC总线读一个字节(8 bit)的函数***************/
char read_1Byte()
{
        int k=0;
        char t_byte=0x00;

        TRISC4=1;                                        //RC4作为输入,SDA引脚接的是RC4口     开始读数据,读SDA的值

        for(k=0;k<8;k++)
        {
                t_byte=t_byte<<1;                //左移一位
                SCL=1;
                asm("NOP");
                asm("NOP");

                //读 SDA的值
                if(SDA=1)
                        t_byte=t_byte|0x01;//写1 只对最低位有影响
                else
                        t_byte=t_byte&0xfe;//写0

                SCL=0;
                asm("NOP");
                asm("NOP");
        }

        TRISC4=0;

        return t_byte;                // 返回的是一个字节 eg:0x3f
}





/*************向AT24C02芯片的指定地址写一个字节的数据***************/
void write_AT24C02(char address,char databuf)
{
        IIC_start();                        //发送起始信号

        //AT24C02芯片寄存器: 1010 A2 A1 A0 R/W_n  AT24C02芯片的高四位固定为1010
        // A2A1A0:从机选择,一共可以接八个AT24C02芯片。  A2A1A0=000,选择第一个芯片。  R/W_n:读/写

        //选择某一个从器件(确定用哪一个芯片)
        write_1Byte(0xa0);                //发送从器件地址000,选择第一个芯片。R/W_n=0,表示写
        //指定该器件内部的某一个地址(确定芯片内部地址)
        write_1Byte(address);        //指定该芯片内部的某一个地址(一共有256个地址)
        //向该芯片的指定地址里面写数据
        write_1Byte(databuf);        //向指定地址发送数据

        IIC_end();                                //发送结束信号
}




/*************从AT24C02芯片的指定地址读一个字节的数据***************/
char read_AT24C02(char address)
{
        char buf;

        //AT24C02芯片寄存器: 1010 A2 A1 A0 R/W_n  AT24C02芯片的高四位固定为1010
        // A2A1A0:从机选择,一共可以接八个AT24C02芯片。  A2A1A0=000,选择第一个芯片。  R/W_n:读/写
       

        IIC_start();                        //发送起始信号
        //选择某一个从器件(确定用哪一个芯片)
        write_1Byte(0xa0);                //发送从器件地址000,选择第一个芯片。R/W_n=0,表示写
        //指定该器件内部的某一个地址(确定芯片内部地址)
        write_1Byte(address);        //指定该芯片内部的某一个地址(一共有256个地址)




        //在传输过程中,当需要改变传送方向时(写<->读),起始信号IIC_start()和从机地址write_1Byte(0xa1)都被重复产生一次
        //由于写变成读,所以需要下面两条指令
        IIC_start();                        //再次启动
        //选择某一个从器件(确定用哪一个芯片)  此时要准备读数据
        write_1Byte(0xa1);                //发送从器件地址,选择第一个芯片。R/W_n=1,表示读
        //读出该芯片指定地址的数据
        buf=read_1Byte();               


        IIC_end();                                //发送结束信号



        return buf;                                // 返回的是一个字节 eg:0x3f
}



使用特权

评论回复
沙发
yiyigirl2014| | 2022-6-24 21:35 | 只看该作者
理论基础扎实,比什么都重要。

使用特权

评论回复
板凳
pl202| | 2022-7-9 12:17 | 只看该作者
iic学习一下。   

使用特权

评论回复
地板
cashrwood| | 2022-7-9 13:23 | 只看该作者
可以驱动flash芯片吗  

使用特权

评论回复
5
10299823| | 2022-11-3 21:44 | 只看该作者
这个PIC16F877A有硬件iic吗?

使用特权

评论回复
6
Jacquetry| | 2022-11-4 19:45 | 只看该作者
这个的硬件iic好用吗?

使用特权

评论回复
7
sanfuzi| | 2022-11-5 10:18 | 只看该作者
PIC16F877A还不如挂载一个flash芯片。

使用特权

评论回复
8
robertesth| | 2022-11-5 10:38 | 只看该作者
可以通过宏定义操作IIC总线的。

使用特权

评论回复
9
sheflynn| | 2022-11-5 11:46 | 只看该作者
PIC16F877A多大iic读取速度可以到多少?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

57

主题

3317

帖子

4

粉丝