iic与24c02

偶做人间客 2019-01-06 05:55:25
这个程序是按键显示数字并且写进24c02芯片里,每次启动的时候读取,但是我只能保存一个数据,没办法保存8个数据,麻烦大佬帮忙看看


#include "reg52.h"
#include "intrins.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}


#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^0; /* 数据线 */
sbit SCL = P2^1; /* 时钟线 */


//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}

//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}

//应答位控制
void IIC_Ack(bit ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}

//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;

for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}


#include<reg51.h>
#include"iic.h"
#include "intrins.h"

sbit dula=P2^6;
sbit wela=P2^7;
sbit n=P1^0;


unsigned char duan[]={0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段选码1~9
unsigned char wei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位选码
unsigned char key_buf[]={0xee,0xde,0xbe,0xed,0xdd,0xbd,0xeb,0xdb,0xbb}; //键值
unsigned char key_scan[]={0xef,0xdf,0xbf}; //键盘扫描码
unsigned char led[8];
unsigned char buf=0;
unsigned char state=0;
unsigned char t=0;
unsigned char key=0;


unsigned char read_eeprom(unsigned char add)
{
unsigned char d;
IIC_Start();
IIC_SendByte(0xa0);
n=IIC_WaitAck();
IIC_SendByte(add);
n=IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
n=IIC_WaitAck();
d=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return d;
}

void write_eeprom(unsigned char add,unsigned char d)
{
IIC_Start();
IIC_SendByte(0xa0);
n=IIC_WaitAck();
IIC_SendByte(add);
n=IIC_WaitAck();
IIC_SendByte(d);
n=IIC_WaitAck();
IIC_Stop();
}

void delay(unsigned int a) //1ms
{
unsigned int j=0;
for(;a>0;a--)
for(j=0;j<125;j++);
}

void show(unsigned char i) //显示第i位数
{

dula=0;
P0=led[i];
dula=1;
dula=0;

wela=0;
P0=wei[i];
wela=1;
wela=0;
}


void initial() //定时器初始化
{
TMOD=0x01;
TH0=(65536-2500)/256; //2.5ms
TL0=(65536-2500)%256;
EA=1;
ET0=1;
TR0=1;
}

void timer0() interrupt 1 //中断函数
{
TH0=(65536-2500)/256;
TL0=(65536-2500)%256;
t++;
if(t==8)
t=0;
show(t); //每次中断显示一位数
}


char getkey(void)
{
char i=0;
char j=0;
char m=0;
for(;i<3;i++)
{
P3=key_scan[i];
if((P3&0x07)!=0x07)
{
delay(10);
if((P3&0x07)!=0x07)
if(state==0)
{
{
for(;j<9;j++)
{
if(key_buf[j]==P3)
{state++;return j;}
}
}
}

if(state==1)
{
for(;m<120;m++)
{
if((P3&0x07)!=0x07)
m=0;
}
state=0;
}
}
}
return -1;
}

void run(unsigned char a)
{
led[7]=led[6];
led[6]=led[5];
led[5]=led[4];
led[4]=led[3];
led[3]=led[2];
led[2]=led[1];
led[1]=led[0];
led[0]= duan[a];
}


#include<reg51.h>
#include"iic.h"
#include"fun.h"
#include"intrins.h"

sbit ledx=P1^2;
unsigned char num;

void main()
{
unsigned char i;
initial();
for(i=0;i<8;i++)
{
led[i]=read_eeprom(30+i);
}
while(1)
{
num=getkey();
if(num!=-1)
{
run(num);
for(i=0;i<8;i++)
{
write_eeprom(30+i,led[i]);
}
}
}
}
...全文
523 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
wdzastimber 2019-03-23
  • 打赏
  • 举报
回复
引用 3 楼 foolish_smile的回复:
加了延时,好像也没有用,还是写不进去,读也有问题,不知道错在哪
你看下是不是读的太快了,加个延时试试
Peter_GGG 2019-03-07
  • 打赏
  • 举报
回复
引用 10 楼 Peter_GGG 的回复:
要加延时10ms
还有waitack要改下
Peter_GGG 2019-03-07
  • 打赏
  • 举报
回复
要加延时10ms
皮皮涵 2019-01-10
  • 打赏
  • 举报
回复
楼主好好查一查时序吧
偶做人间客 2019-01-09
  • 打赏
  • 举报
回复
加了延时,好像也没有用,还是写不进去,读也有问题,不知道错在哪
诺水城子 2019-01-09
  • 打赏
  • 举报
回复
我写过日志,你可以参考 https://blog.csdn.net/ggggyj/article/details/84098957
诺水城子 2019-01-09
  • 打赏
  • 举报
回复
给你看看我用的代码
void E2prom_Write_Byte(uint32_t addr, uint8_t dat)
{
uint8_t u8Temp = 0;

if(addr > 0xFFFF)
{
u8Temp = 0x08;
}

E2prom_I2C_Start();
E2prom_I2C_Send_Byte(CTRL_CODE|u8Temp);
if(E2prom_I2C_Check_Ack() != 1)
{
return ;
}

E2prom_I2C_Send_Byte(addr&0x00FF);
if(E2prom_I2C_Check_Ack() != 1)
{
return;
}

E2prom_I2C_Send_Byte(dat);
if(E2prom_I2C_Check_Ack() != 1)
{
return;
}

E2prom_I2C_Stop();
DelayUs(20000);
}
void E2prom_Write_Bytes(uint32_t addr, uint8_t *pdat, uint8_t cnt)
{
uint8_t i;

for(i = 0; i < cnt; i++)
{
E2prom_Write_Byte(addr++, *pdat++);
}
}
偶做人间客 2019-01-09
  • 打赏
  • 举报
回复
我用的bst-v51的开发板,eprom是24c02
偶做人间客 2019-01-09
  • 打赏
  • 举报
回复
时序应该没问题吧,我把程序改成写一次,读一次,是能正常读取显示的,但是主函数改成连续8次读写就出问题了,实在看不出问题在哪
yishumei 2019-01-09
  • 打赏
  • 举报
回复
引用 3 楼 foolish_smile 的回复:
加了延时,好像也没有用,还是写不进去,读也有问题,不知道错在哪
IIC的硬件电路是典型电路吗?还有晶振要保证somenop的时间大于5us。如果这些都没问题,那楼主就好好查查时序吧。
yishumei 2019-01-08
  • 打赏
  • 举报
回复
用函数write_eeprom保存8个数据的话,需要每写入一个BYTE后延时10ms。这些数据手册里都有,楼主可以在网上查找阅读。 for(i=0;i<8;i++) { write_eeprom(30+i,led[i]); 延时10ms; }
fly 100% 2019-01-07
  • 打赏
  • 举报
回复
抓个波形放上来看看吧

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧