PIC IIC & 24c02

2019-04-15 14:27发布


#include       //调用头文件,可以去PICC18软件下去查找PIC18FXX2.H __CONFIG(1,XT) ;         //晶振为外部4M __CONFIG(2,WDTDIS) ;      //看门狗关闭 __CONFIG(4,LVPDIS) ;     //禁止低电压编程 #define uint unsigned int #define uchar unsigned char #define nop NOP() #define scl RC3 //时钟线 #define sda RC4 //数据线
char shuma[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uint count=0; uchar sec;
void usdelay() { nop; //其实在用IIC对EEPROM操作时,它反应很快,延时可以很短,但必须延时,只要一个NOP()就可以了 }
void init_24c() //初始化24C,就是把两根线拉高 { TRISC4=0; scl=1; sda=1; usdelay(); }
PIC <wbr>IIC <wbr>& <wbr>24c02

void start() //开始信号,根据时序图(sx) { TRISC4=0; scl=1; usdelay(); sda=1; usdelay(); sda=0; }
void stop() //结束信号 sx { TRISC4=0; scl=1; usdelay(); sda=0; usdelay(); sda=1; }
void ack() //不知道为什么,在PIC中不能用ack,好像一用就会出错= =? { uchar i; TRISC4=0; sda=1; nop; TRISC4=1; scl=1; nop; while(sda==1&&i<10)i++; scl=0; }
PIC <wbr>IIC <wbr>& <wbr>24c02

void write_byte(uchar dat) //写字节 sx 由于不仅要写数据,还要写地址,所以只能先写字节的最高位R7,最后写最低位R0 { uchar i; TRISC4=0; sda=0; scl=0; nop; for(i=0;i<=8;i++) { sda=(dat&0x80)>>7; nop; scl=1; nop; scl=0; dat<<=1; nop; } }
uchar read_byte() //读字节 sx 先读高位R7,最后读地位R0 { uchar i,dat=0; TRISC4=1; sda=0; usdelay(); scl=1; usdelay(); for(i=0;i<8;i++) { dat<<=1; usdelay(); scl=1; nop; dat=dat|sda; nop; scl=0; usdelay(); } return dat; }
PIC <wbr>IIC <wbr>& <wbr>24c02
PIC <wbr>IIC <wbr>& <wbr>24c02

void write_add(uchar add,uchar dat) //写数据到地址 sx 注意不要用ack { start(); write_byte(0xa0);
write_byte(add);
write_byte(dat);
stop(); } PIC <wbr>IIC <wbr>& <wbr>24c02



PIC <wbr>IIC <wbr>& <wbr>24c02

uchar read_add(uchar add) //从地址读数据 sx 注意不要用ack { uchar dat; start(); write_byte(0xa0);
write_byte(add);
start(); write_byte(0xa1);
dat=read_byte();
stop(); return dat; }


void interrupt kaito() //定时器中断0 { if(TMR0IF==1) { TMR0IF=0; TMR0=0xff13; count++; if(count==4000) { count=0; sec++; if(sec>9) sec=0; write_add(0x10,sec); //每次要显示的数据发生变化,就写入到24c02中存起来,方便断电后保留 } } }
void main(void) { sec=0; ADCON1=0X06;  TRISD=0x00; TRISC3=0; TRISC4=0;
init_24c();
GIE=1; IPEN=0; TMR0IE=1; TMR0IF=0; T0CON=0x88; TMR0=0xff13; GIE=1;
sec=read_add(0x10); while(1) { PORTD=shuma[sec]; } }


就是感觉很奇怪,为什么不能用attack,时序图上明明有,可是一写上就是错的= =?
达到效果,定时器计数,数码管显示,如果关机或者复位,数码管从关机前的数开始继续计数。
如果对一个地址以前没有用过,它里面存的是出厂时设置在里面的数据,很多是ff,如果不对它做正确的写入,读出的数据就会是ff,如果用1602来显示,要取十位和个位,都是f,在加上显示时的0x30,就变成0x59,和0x35,显示出来的就是I5
还有在定时器中断中要写入多个数据,必须按照条件分开写入,同时写入的话会有几条语句可能写入失败。