IO口模拟I2C的要点:
- 数据帧符合标准的I2C协议
- 分的清楚ACK与NACK的区别,是那个设备下拉。
- 数据位时间符合要求
项目合作开发,吹牛扯蛋、交朋友 ,请联系:18665321219
#include "iic_p.h" #include <ny8.h> #include "main.h" #include <ny8_constant.h> #include <stdint.h> #define sda_out() IOSTA=(IOSTA & ((uint8_t)(~ C_PA6_Input))) //输出 #define sda_in() IOSTA=(IOSTA | C_PA6_Input) //输入 #define sda PORTAbits.PA6 //sda输出高 #define scl PORTAbits.PA4 //scl输出高,写程序注意默认让其保持高电平 void delayus(uint8_t tim) { while(tim--) //2.4us周期 clk_8M { NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); } } void i2c_stop(void) { scl = 0; delayus(1); sda = 0; sda_out(); delayus(2); scl = 1; delayus(1); sda = 1; } void i2c_start(void) { sda = 1; // delayus(1); scl = 1; //发送停止位后将SCL及SDA置位 delayus(1); sda = 0; delayus(1); } //测试ok void trandata(uint8_t data) { //IOSTB=(IOSTB & ((uint8_t)(~ C_PB2_Input))); //输出 uint8_t i; //scl = 0; for( i = 0;i<8;i++ ) { scl = 0; delayus(1); if((data & 0x80) == 0x80) { sda = 1; } else { sda = 0; } data <<=1; delayus(2); scl = 1; delayus(3); } //scl = 0; //delayus(3); //sda = 0; //因该把IO输出禁止,不然slaver无法下拉 } //测试ok void revdata(uint8_t *data) { uint8_t i; //sda_in(); for(i=0;i<8;i++) { scl = 0; delayus(3); scl = 1; delayus(1); *data <<= 1; if(sda==1) { *data |= 0x01; //首位置为一 } else { *data &= 0xfe; } delayus(2); } } //测试ok void i2c_nack(void) { scl = 0; delayus(1); sda = 1; sda_out(); delayus(2); scl = 1; delayus(3); } //测试ok uint8_t i2c_dectack(void) { uint8_t ackflg; scl = 0; delayus(1); sda_in(); delayus(2); scl = 1; delayus(1); if(sda ==1) { ackflg = 0; //为接收到应答 } else { ackflg = 1; //接收到应答 } delayus(2); return ackflg; } //测试ok 3ms uint8_t i2c_wtdata(uint8_t address,uint8_t data) { uint8_t temp,errflg=0; i2c_start(); temp = 0xa0; //地址位赋值1010add(R/W) trandata(temp); if(i2c_dectack() == 0) { errflg = 1; //未接收到应答数据 } scl = 0; delayus(1); sda = 1; sda_out(); temp = address; trandata(temp); if(i2c_dectack() == 0) { errflg = 1; //未接收到应答数据 } scl = 0; delayus(1); sda = 1; sda_out(); trandata(data); if(i2c_dectack() == 0) { errflg = 1; //未接收到应答数据 } // scl = 0; // delayus(3); // sda = 0; // sda_out(); i2c_stop(); return errflg; } //测试ok //测试不稳定 uint8_t curddata(uint8_t *data) { uint8_t temp,errflg=0; i2c_start(); temp = 0xa1; //地址位赋值1010add(R/W) trandata(temp); if(i2c_dectack() == 0) { errflg = 1; //未接收到应答数据 } //sda_out(); revdata(data); i2c_nack(); i2c_stop(); return errflg; } //测试ok 4ms uint8_t i2c_rddata(uint8_t address,uint8_t *pdata) { uint8_t temp,errflg=0; i2c_start(); temp = 0xa0; //地址位赋值1010000(R/W) trandata(temp); if(i2c_dectack() == 0) { errflg = 1; //未接收到应答数据 } scl = 0; delayus(1); sda = 1; //默认为上拉 sda_out(); temp = address; trandata(temp); if(i2c_dectack() == 0) { errflg = 1; //未接收到应答数据 } scl = 0; delayus(1); sda = 1; sda_out(); if(curddata(pdata) == 1) { errflg = 1; } return errflg; } /* //写数据遵守写入读出 void i2cbus_wt(uint8_t address,uint8_t data) { uint8_t temp; do { while(i2c_wtdata(address,data) == 1); //写入数据 while(curddata(&temp) == 1); //读出数据 } while(data != temp); //比较通过视为写入成功 } */