joyrus 发表于 2012-7-6 21:17:24

我的第四个单片机开源项目——通过PIC单片机的I2C读写EEPROM

本帖最后由 joyrus 于 2012-7-8 11:28 编辑

项目设计目的:通过PIC单片机的I2C同步串行接口读写EEPROM

本项目使用C语言编写使用PICC(Hitech C),同时为项目三还未完成的PC段软件的编写打基础。

先学习I2C的技术资料。

joyrus 发表于 2012-7-7 20:25:57

还是先通过对张明峰先生撰写的《PIC单片机入门与实战》的阅读和学习,摘录了其中部分的代码,并用C语言改写作为这次我的开源项目的开始。

基本上和书籍上的汇编语言的思路一致,实现了I2C口发数据到EEPROM再读回数据验证。用C语言代码的输入工作量减少了,但是也牺牲了一些代码效率。之后慢慢说来。

joyrus 发表于 2012-7-8 11:23:04

C语言程序如下,由于我沿用了汇编的编程方法,所以并没有将C语言的内存管理优势完全发挥出来,比如程序中还是直接沿用了STATUS寄存器中的进位位C来传递是否有应答信号等。另外函数也没有使用局部变量和返回结果,造成函数无法通用性,对建立自己的函数库造成一定的困难。对于使用函数内的局部变量这一点我还是由一些担忧,因为之前我做了一些测试代码发现在某些情况下不同的局部变量会使用完全相同的地址,换而言之就是其中一个被另一个覆盖了!这在《16位单片机C语言编程-基于PIC24》书籍中提到过“静态覆盖”的技术,这样可以提高内存的使用效率,但也可能造成一些问题。

joyrus 发表于 2012-7-8 11:26:42

/**********************************************************************
*程序功能说明
*本程序通过单片机SSP/I2C端口读写EEPROM,程序由本人用C语言改编自张明峰先生撰写的《PIC单片机入门与实战》中的程序
*本人联系方法:沈毅;joyrus@163.net,www.joyrus.com,QQ:15953321
**********************************************************************/


#include <pic.h>       //调用头文件
//__CONFIG(0x3F32);         //芯片配置字

typedef unsigned int uint;
typedef unsigned char uchar;
////////函数申明///////
void I2cStart(void);      //I2C开始符
void I2cStop(void);       //I2C停止符
void I2cRestart(void);    //I2C重复开始符
void I2cDataOut(void);    //I2C数据发送
void I2cDataIn(void);   //I2C连续数据接收
void I2cDataInLast(void); //I2C接收最后一个数据
void OnError(void)       //错误处理
{
}
///////////////////变量申明//////////////////////////
volatile uchar eeAddr_L=0x00, //EEPROM 内部16位地址码低8位
    eeAddr_H=0x00, //EEPROM 内部16位地址码高8位
    eeData=0x00;   //EEPROM 寻址指令码与8位数据码

////////////////////主程序/////////////////////////
void main(void)
{
// Bank1 初始化I2C设置
SSPSTAT=0x0;
TRISC=0b00011000;
SSPADD=9;
SSPIE=0;
////////////////应本人实验板的PORTD输出需要而设置//
    TRISD=0X00;   //PORTD口设为输出驱动控制LED
TRISE2=0;   //74HC573锁存引脚对应IO口RE2设为输出
///////////////////////////////////////////////////
// Bank0 初始化I2C设置
SSPCON=0b00101000;
INTCON=0x0;
////////////////应本人实验板的PORTD输出需要而设置//
RE2=1;      //设置74HC573锁存引脚为高电平
PORTD=0XFF;   //PORTD输出低电平(74HC573为反向输出)
///////////////////////////////////////////////////

while(1)
{ ////////////写数据//////////////////
I2cStart(); //启动数据发送
eeData=0b10100000;   //发送寻址码
I2cDataOut();
if(CARRY){OnError();} //error
eeData=eeAddr_H=0x00;//发送高位地址码
I2cDataOut();
if(CARRY){OnError();} //error
eeData=eeAddr_L=0x40;//发送低位地址码
I2cDataOut();
if(CARRY){OnError();} //error
eeData=0x55;//发送一个字节数据
I2cDataOut();
if(CARRY){OnError();} //error

I2cStop();   //结束一个字节数据发送
RD0=0;//显示EEPROM开始内部写过程
CARRY=1;
while(CARRY)
{
   I2cStart(); //启动数据发送
   eeData=0b10100000;   //发送寻址码
   I2cDataOut();
   I2cStop();   //结束一个字节数据发送
}//end
RD0=1;   //显示EEPROM开始内部写完成
////////////读数据//////////////
I2cStart(); //启动数据发送
eeData=0b10100000;   //发送寻址码
I2cDataOut();
eeData=eeAddr_H=0x00;//发送高位地址码
I2cDataOut();
if(CARRY){OnError();} //error
eeData=eeAddr_L=0x40;//发送低位地址码
I2cDataOut();
if(CARRY){OnError();} //error
/////////////读数据////////////////////
I2cRestart();         //重复启动数据发送
eeData=0b10100001;   //发送寻址码
I2cDataOut();
if(CARRY){OnError();} //error
I2cDataInLast();
I2cStop();
if(eeData==0x55){RD0=0; } //数据正确则显示成功PORTD0灯亮
asm("nop"); //加一条nop用于设置程序调试断点
}//while(1) end
}//main end
////////////子程序//////////////
void I2cStart(void)
{
SEN=1;
while(!SSPIF){}
SSPIF=0;
return;
}//end
void I2cStop(void)
{
PEN=1;
while(!SSPIF){}
SSPIF=0;
return;
}//end
void I2cRestart(void)
{
RSEN=1;
while(!SSPIF){}
SSPIF=0;
return;
}//end
void I2cDataOut(void)
{
SSPBUF=eeData;
while(!SSPIF){}
SSPIF=0;
CARRY=0;
if(ACKSTAT){CARRY=1;}
return;
}//end
void I2cDataIn(void)
{
RCEN=1;
while(!SSPIF){}
SSPIF=0;
ACKDT=0;
ACKEN=1;
while(!SSPIF){}
SSPIF=0;
eeData=SSPBUF;
return;
}//end
void I2cDataInLast(void)
{
RCEN=1;
while(!SSPIF){}
SSPIF=0;
ACKDT=1;
ACKEN=1;
while(!SSPIF){}
SSPIF=0;
eeData=SSPBUF;
return;
}//end
页: [1]
查看完整版本: 我的第四个单片机开源项目——通过PIC单片机的I2C读写EEPROM