给大家分享一个 stm8单片机用IIC总线方式读写24c02存储芯片 里面是自己写的程序
完整源码下载:
4.I2C 24C02.rar
(396.59 KB, 下载次数: 85)
下面是部分文件预览:
- #include"i2c.h"
- uint8_t receive[N],send[N]; //全局数组变量
- void I2C_Start() //发送起始信号——在SCL为高电平期间,SDA由高拉低
- {
- SDA_OUT;
- SDA_1;
- SCL_1;
- Delay_us(3);
- SDA_0;
- Delay_us(5);
- SCL_0;
- Delay_us(1);
- }
- void I2C_Stop() //结束信号——在SCL为高电平期间,SDA由低拉高
- {
- SDA_OUT;
- SDA_0;
- SCL_0;
- Delay_us(1);
- SCL_1;
- Delay_us(3);
- SDA_1;
- Delay_us(5);
- SCL_0;
- Delay_us(1);
- }
- void I2C_Ack() //检测应答——第9个时钟周期时,由24C16将SDA拉低
- {
- SDA_1;
- Delay_us(3);
- SDA_IN;
- Delay_us(1);
- SCL_1;
- Delay_us(2);
- SCL_0;
- Delay_us(3);
- }
- uint8_t I2C_Ack2() //检测应答2
- {
- SDA_1;
- Delay_us(3);
- SDA_IN;
- Delay_us(2);
- SCL_1;
- Delay_us(2);
- // while(SDA); //很快能完成应答,不需要等待,防止硬件故障导致出错
- SCL_0;
- Delay_us(2);
- return SDA;
- }
- uint8_t I2C_Send(uint8_t buffer) //发送1个字节的数据
- {
- uint8_t temp = 0;
- uint8_t BitCnt = 7;
-
- SDA_OUT; //SDA为输出
- Delay_us(1);
- if((buffer&0x80)==0) //由高位开始发送
- SDA_0;
- else
- SDA_1;
- Delay_us(1);
- SCL_1;
- Delay_us(1);
- temp = buffer<<1;
- buffer = temp;
- while(BitCnt)
- {
- if((buffer&0x80)==0)
- {
- SCL_0;
- SDA_0;
- }
- else
- {
- SCL_0;
- SDA_1;
- }
- Delay_us(3);
- SCL_1;
- Delay_us(2);
- temp = buffer<<1;
- buffer = temp;
- BitCnt--;
- }
- SCL_0;
- if(I2C_Ack2()) //发送8位数据后,检测应答 0:无应答 1:有应答
- return 0;
- else
- return 1;
- }
- uint8_t I2C_Receive() //接收一个字节的数据
- {
- uint8_t ReceiveData,i;
- SDA_IN; //SDA为输入
- Delay_us(1);
- for(i=0;i<8;i++) //SCL高电平时,记录SDA,由高位开始
- {
- SCL_1;
- Delay_us(2); //延时的时间
- if(SDA==0)
- ReceiveData &= 0xfe;
- else
- ReceiveData |= 0x01;
- if(i<7)
- ReceiveData = ReceiveData<<1;
-
- SCL_0;
- Delay_us(1);
- }
- return ReceiveData;
- }
- void I2C_NoAck() //接收数据后不发送应答
- {
- SDA_1;
- SDA_OUT;
- SDA_1;
- Delay_us(1);
- SCL_1;
- Delay_us(2);
- SCL_0;
- Delay_us(2);
- SDA_0;
- Delay_us(2);
- }
- void I2C_SendAck() //接收数据后发送应答,由主机发送,告知24C16已经接收到一个字节的数据
- {
- SDA_OUT;
- SDA_0;
- Delay_us(1);
- SCL_1;
- Delay_us(3);
- SCL_0;
- SDA_0;
- Delay_us(2);
- }
- void I2C_Write_Byte(uint8_t addr,uint8_t data) //向24C06写入数据——单字节写
- {
- I2C_Start(); //起始信号
- I2C_Send(0xa0); //发送器件地址
- I2C_Send(addr); //发送字节地址
- I2C_Send(data); //发送数据
- I2C_Stop(); //结束信号
- }
- void I2C_Write_Page(uint8_t addr,uint8_t data) //向24C06写入数据——页写 16个字节
- {
- uint8_t i,j,k,p;
-
- if((N/16)==0) //判断N是否小于16 是:一次页写即可完成 否:需要多次页写
- {
- I2C_Start(); //起始信号
- I2C_Send(0xa0); //发送器件地址
- I2C_Send(addr); //发送字节地址
- for(j=0;j<N;j++)
- {
- send[j] = data+j;
- I2C_Send(send[j]); //发送数据
- }
- I2C_Stop(); //结束信号
- Delay_ms(5);
- }
- else //多次页写
- {
- for(i=0;i<(N/16);i++) //i次页写
- {
- I2C_Start(); //起始信号
- I2C_Send(0xa0); //发送器件地址
- I2C_Send(addr+i*16); //发送字节地址
- for(j=0;j<16;j++)
- {
- send[i*16+j] = data+i*16+j;
- I2C_Send(send[i*16+j]); //发送数据
- }
- I2C_Stop(); //结束信号
- Delay_ms(5);
- }
-
- if(N%16) //写剩余的数据
- {
- p=N-(N%16);
- I2C_Start(); //起始信号
- I2C_Send(0xa0); //发送器件地址
- I2C_Send(addr+p); //发送字节地址
- for(k=0;k<(N%16);k++)
- {
- send[i*16+k] = data+i*16+k;
- I2C_Send(send[i*16+k]); //发送数据
- }
- I2C_Stop(); //结束信号
- Delay_ms(5);
- }
- }
- }
- void I2C_Read2(uint8_t add_start)//连续读
- {
- uint8_t i;
-
- I2C_Start(); //起始信号
- I2C_Send(0xa0); //发送器件地址——写
- I2C_Send(add_start); //发送字节地址
- I2C_Start(); //起始信号
- I2C_Send(0xa1); //发送器件地址——读
- for(i=0;i<N-1;i++)
- {
- receive[i]=I2C_Receive();
- I2C_SendAck(); //主机发送应答,继续读
- }
- receive[i]=I2C_Receive();
- I2C_NoAck(); //第九个周期发送不应答
- I2C_Stop(); //停止信号
- // return receive;
- }
-
- uint8_t I2C_Read(uint8_t addr) //从24C06读出数据
- {
- uint8_t receive;
- I2C_Start(); //起始信号
- I2C_Send(0xa0); //发送器件地址——写
- I2C_Send(addr); //发送字节地址
- I2C_Start(); //起始信号
- I2C_Send(0xa1); //发送器件地址——读
- receive=I2C_Receive(); //读出数据
- I2C_Stop(); //停止信号,结束读数据操作
- return receive;
- }
- void I2C_Ack_Check() //应答查询
- {
- I2C_Start();
- I2C_Send(0xa0);
- I2C_Ack2();
- }
- /*
- void test_1(uint8_t add,uint8_t data) //单次测试
- {
- uint8_t test=0;
- I2C_Write_Byte(add,data);
- Delay_ms(5);
- test = I2C_Read(add);
- if(test==data)
- LED = LED1;
- else
- LED = LED2;
- }
- void test_write(uint8_t add,uint8_t data) //测试_写
- {
-
- I2C_Write_Byte(add,data);
- Delay_ms(5);
- }
- uint8_t test_read(uint8_t add) //测试_读
- {
- uint8_t test=0;
- test = I2C_Read(add);
- return test;
- }
- void test1(uint8_t add_start) //测试函数1
- {
- uint8_t read[N]={0},write[N]={0},i,k=0;
-
- for(i=0;i<N;i++)
- {
- write[i]=0x02+i;
- test_write(add_start+i,write[i]);
- }
-
- for(i=0;i<N;i++)
- {
- read[i]=test_read(add_start+i);
- }
- for(i=0;i<N;i++)
- {
- if(write[i]==read[i])
- k+=1;
- }
- if(k==N)
- LED = LED1;
- else
- LED = LED2;
- }
- */
- void test2(uint8_t add_start,uint8_t data) //测试函数2
- {
- uint8_t i,k=0;
- I2C_Write_Page(add_start,data);
- I2C_Read2(add_start);
- for(i=0;i<N;i++)
- {
- if(receive[i]==send[i])
- k+=1;
- }
- if(k==N)
- LED = LED1;
- else
- LED = LED2;
- for(i=0;i<N;i++)
- {
- receive[i]=0;
- send[i]=0;
- }
-
- }
- #pragma vector=5 //PA口的中断服务函数
- __interrupt void PORTA_IRQHandler(void)
- {
- Delay_ms(20); //软件消抖
- if(!(PA_IDR&0x04))
- {
- Delay_ms(20);
- while(!(PA_IDR&0x04));
- test2(0x00,0x06);
- }
- }
复制代码
|