#include<intrins.h>//程序虽然长,但是不是很复杂,关键在于理解IIC的工作机理
#define uchar unsigned char
#define uint unsigned int
#define DELAY5US _nop_()_nop_()_nop_()_nop_()_nop_()
sbit VSDA = P1^0
sbit VSCL = P1^1
sbit LED = P1^7
uchar SLAW
void STA() //发现:24C02C 是 256字节*8位的串行EEPROM存储器芯片,注意是ROM只读的
{ //但是这个例子将0-255这些数据写入到了ROM当中,怎么写的,是烧进去的,
VSDA = 1 //这个不是很理解啊
VSCL = 1
DELAY5US
VSDA = 0
DELAY5US
VSCL = 0
}
void STOP()
{
VSDA = 0
VSCL = 1
DELAY5US
VSDA = 1
VSCL = 1
DELAY5US
}
void MACK()
{
VSDA = 0
VSCL = 1
DELAY5US
VSCL = 0
}
void MNACK()
{
VSDA = 1
VSCL = 1
DELAY5US
VSCL = 0
}
void CACK()
{
VSDA = 1
VSCL = 1
F0 = 0
if ( 1 == VSDA )
{
F0 = 1
}
VSCL = 0
}
void WRBYTE(uchar idata *p)
{
uchar idata n = 8, temp
temp = *p
while(n--)
{
if ( 0x80 == (temp&0x80) )
{
VSDA = 1
VSCL = 1
DELAY5US
VSCL = 0
}
else
{
VSDA = 0
VSCL = 1
DELAY5US
VSCL = 0
}
temp = temp<<1
}
}
void RDBYTE(uchar idata *p)
{
uchar idata n = 8, temp = 0
while(n--)
{
VSDA = 1
VSCL = 1
temp = temp<<1
if ( 1 == VSDA )
temp = temp|0x01
else
temp = temp&0xfe
VSCL = 0
}
*p = temp
}
void delayMoreThan5ms()
{
uint i
for ( i = 0i <1000i++ )
{
DELAY5US
}
}
int main()
{
uchar ch, *p
uint i
SLAW = 0xA2//0xA0是slave write地址字节(写),A是1010是器件地址,由厂家决定
for ( i = 0i <= 255i++ ) //1010(A)是24C02C所属系列的器件地址
{ //0000是自己决定的,前3个0由24C02C芯片的A0A1A2决定
STA() //最后一个0是写的意思,1则为读
p = &SLAW //4个(器件地址),3个(引脚地址),一个(读写选择位)。
WRBYTE(p) //应答信号是关键啊
CACK() //发送对应写, 接收对应读
if ( 1 == F0 )
{
LED = 0
while(1)
}
ch = i
p = &ch
WRBYTE(p)
CACK()
if ( 1 == F0 )
{
LED = 0
while(1)
}
WRBYTE(p)
CACK()
STOP()
delayMoreThan5ms()
}
while(1)
return 0
}
你确定你外部电路没有接错么?24c02只有256字节,所以不需要用到高8位地址;只要000h-0ffh就可以直接访问,24c04就需要用P2连接高8位地址,不然是无法正常访问0ffh以上的地址的。#include<reg51.h>#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define Delay4us() {_nop_()_nop_()_nop_()_nop_()}
sbit SCL=P1^0
sbit SDA=P1^1
//数码管段码
uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}
//三位数显示缓冲
uchar DISP_Buffer[]={0,0,0}
uchar Count=0
//延时
void DelayMS(uint ms)
{
uchar i
while(ms--) for(i=0i<120i++)
}
//IIC启动
void Start()
{
SDA=1SCL=1Delay4us()SDA=0Delay4us()SCL=0
}
//IIC停止
void Stop()
{
SDA=0SCL=0Delay4us()SCL=1Delay4us()SDA=1
}
//读取应答
void RACK()
{
SDA=1Delay4us()SCL=1Delay4us()SCL=0
}
//发送非应答信号
void NO_ACK()
{
SDA=1SCL=1Delay4us()SCL=0SDA=0
}
//向24C04中写一个字节数据
void Write_A_Byte(uchar byte)
{
uchar i
for(i=0i<8i++)
{
byte<<=1SDA=CY_nop_()SCL=1Delay4us()SCL=0
}
RACK()
}
//向指定地址写数据
void Write_Random_Adress_Byte(uchar addr,uchar dat)
{
Start()
Write_A_Byte(0xa0)Write_A_Byte(addr)Write_A_Byte(dat)
Stop()
DelayMS(10)
}
//从24C04中读一个字节数据
uchar Read_A_Byte()
{
uchar i,b
for(i=0i<8i++)
{
SCL=1b<<=1b|=SDASCL=0
}
return b
}
//从当前地址读取数据
uchar Read_Current_Address_Data()
{
uchar dat
Start()
Write_A_Byte(0xa1)dat=Read_A_Byte()NO_ACK()
Stop()
return dat
}
//从任意地址读取数据
uchar Random_Read(uchar addr)
{
Start()
Write_A_Byte(0xa0)Write_A_Byte(addr)
Stop()
return Read_Current_Address_Data()
}
//数据转换与显示
void Convert_And_Display()
{
DISP_Buffer[2]=Count/100
DISP_Buffer[1]=Count%100/10
DISP_Buffer[0]=Count%100%10
if(DISP_Buffer[2]==0) //高位为0不显示
{
DISP_Buffer[2]=10
if(DISP_Buffer[1]==0) //高位为0,次高位为0也不显示
DISP_Buffer[1]=10
}
P0=0xff
P2=0x80 //个位
P0=DSY_CODE[DISP_Buffer[0]]
DelayMS(2)
P0=0xff
P2=0x40 //十位
P0=DSY_CODE[DISP_Buffer[1]]
DelayMS(2)
P0=0xff
P2=0x20 //百位
P0=DSY_CODE[DISP_Buffer[2]]
DelayMS(2)
}
//主程序
void main()
{
Count=Random_Read(0x00)+1 //从24C04的0x00地址读取数据并递增
Write_Random_Adress_Byte(0x00,Count) //将递增后的计数值写入24C04
while(1) Convert_And_Display() //转换并持续刷新数码管显示
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)