PIC16F877A单片机 (IIC总线+AT24C02芯片)
2022-01-10 来源:eefocus
1 基本原理
1.1 IIC总线
需要注意的是,高四位对于同种芯片而言,都是一样的。例如AT24C02芯片的高四位固定为1010。
1.2 AT24C02芯片
2 源代码
/*---------------------函数功能:
IIC总线 AT24C02
-----------------------------------------*/
#include #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 }
- 将DHT11与PIC16F877A连接进行温度和湿度的测量
- 基于PIC16F877A的呼吸灯的实现+Proteus的仿真
- PIC16F877A单片机 (中断与定时器Timer0)
- PIC16F877A单片机 (中断与定时器Timer1)
- PIC16F877A单片机 (中断与定时器Timer2)
- PIC16F877A单片机 (外部中断)
- PIC16F877A单片机 (外部中断与定时器Timer0的综合使用)
- PIC16F877A单片机 (ADC)
- PIC16F877A单片机 (IIC总线+PCF8563芯片)
- 英飞凌与西门子将嵌入式汽车软件平台与微控制器结合 为下一代SDV提供所需功能