九齐MCUio⼝模拟I2C IO⼝模拟I2C的要点:
2. 分的清楚ACK与NACK的区别,是那个设备下拉。
3. 数据位时间符合要求
激光投影键盘项⽬合作开发,吹⽜扯蛋、交朋友,请联系:186******** #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();
ilvs
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)
{
}
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); //⽐较通过视为写⼊成功
}
*/